예제 #1
0
//==================================================================
// Constructor
//==================================================================
CByteArray::CByteArray( int size )
{
	// Allocate space
	m_codeBytes = (unsigned char *)malloc( size );

	if( m_codeBytes )
	{
		m_totalSize = size;

		// Fill with nops
		fill_nop(m_codeBytes, size);

		// Allow patching / execution
		SetMemPatchable(m_codeBytes, size);

		// Set index to 0
		m_curIndex = 0;

		// This was not an existing piece of memory.
		m_bExisting = false;
	}

	else
	{
		printf("Couldn't malloc space for CByteArray!\n");
		return;
	}

}
예제 #2
0
void PlayerSlots::Patch()
{
#if defined PLATFORM_WINDOWS
    bool firstTime = !(humanLimitSig && lobbyConnectSig);
#else
    bool firstTime = !(lobbyConnectSig);
#endif
    L4D_DEBUG_LOG("PlayerSlots - Patching ...");

    /*
    Server patch
    ** Needed on windows only. On Linux, this called GetMaxHumanPlayers
    L4DToolZ doesn't patch this anymore?
    */

#if defined PLATFORM_WINDOWS
    if(firstTime)
    {
        if (!g_pGameConf->GetMemSig("HumanPlayerLimitReached", &humanLimitSig) || !humanLimitSig)
        {
            g_pSM->LogError(myself, "PlayerSlots -- Could not find 'HumanPlayerLimitReached' signature");
            return;
        }
    }
    //code pages can't be written to by default, so ApplyPatch changes that ;)

    /*
    jl around the string "Human player limit reached (%d/%d)"

    	jl -> jmp (Windows)
    	jle -> nop (Linux)

    we never check if the human player limit has been reached
    */
    patch_t humanLimitPatch;

//#if defined PLATFORM_WINDOWS
    humanLimitPatch.bytes = 1;
    humanLimitPatch.patch[0] = OP_JMP_REL8;
//#else //PLATFORM_LINUX
//	humanLimitPatch.bytes = OP_JLE_REL8_SIZE;
//	fill_nop(humanLimitPatch.patch, humanLimitPatch.bytes);
//#endif


    ApplyPatch(humanLimitSig, /*offset*/0, &humanLimitPatch, firstTime ? &humanLimitRestore : NULL);

    L4D_DEBUG_LOG("PlayerSlots -- 'HumanPlayerLimitReached' jl(e) patched to jmp");
#endif

    /*
    Engine patch
    */
    if (!g_pGameConf->GetMemSig("ConnectClientLobbyCheck", &lobbyConnectSig) || !lobbyConnectSig)
    {
        g_pSM->LogError(myself, "PlayerSlots -- Could not find 'ConnectClientLobbyCheck' signature");
        return;
    }
#if defined PLATFORM_WINDOWS

    /*
    jz around the string "#Valve_Reject_Server_Full"

    	jz -> nop (linux or windows)

     do not skip to the server is full code when sv_allow_lobby_connect is 0
    */
    patch_t lobbyConnectPatch;
    lobbyConnectPatch.bytes = OP_JZ_REL8_SIZE;
    fill_nop(lobbyConnectPatch.patch, OP_JZ_REL8_SIZE);
    ApplyPatch(lobbyConnectSig, /*offset*/0, &lobbyConnectPatch, firstTime ? &lobbyConnectRestore : NULL);

    unsigned char oldValue2 = lobbyConnectRestore.patch[0];
    L4D_DEBUG_LOG("PlayerSlots -- 'ConnectClientLobbyCheck' jz(%x) patched to 2 nops", oldValue2);
#endif
}
예제 #3
0
void PlayerSlots::PatchSlotCheckOnly()
{
    if(!lobbyConnectSig) return; //avoid a null dereference if we failed to lookup the sig

    bool firstTime = (serverFullOffset == -1);

    if(firstTime)
    {
        //////////////////////////
        //valve reject server full

        if (!g_pGameConf->GetOffset("ValveRejectServerFullFirst", &serverFullOffset))
        {
            g_pSM->LogError(myself, "PlayerSlots -- Could not find 'ValveRejectServerFullFirst' offset");
            return;
        }

        //the offset should point to the cmp eax, [esi+180h]... first byte incorrect => wrong offset

        if(*((uint8_t*)lobbyConnectSig + serverFullOffset) != OP_CMP_R32_RM32)
        {
            g_pSM->LogError(myself, "PlayerSlots -- Offset for 'ValveRejectServerFullFirst' is incorrect");
            return;
        }
    }

    /*
    cmp around the string "#Valve_Reject_Server_Full"

     cmp eax, [esi+180h] -> cmp eax, IMM32(PLAYER_SLOTS_MAX)        (Windows)
     cmp esi, [ebx+17Ch] -> cmp esi, IMM32(PLAYER_SLOTS_MAX)        (Linux)

    we effectively change how many max players we allow
    */

    patch_t serverFullPatch;

#if defined PLATFORM_LINUX
    serverFullPatch.bytes  = OP_CMP_RM32_IMM32_SIZE;
    serverFullPatch.patch[0] = OP_CMP_RM32_IMM32;
    serverFullPatch.patch[MODRM_BYTE] = MODRM_MOD_DIRECT | OP_CMP_RM32_IMM32_MODRM_DIGIT | MODRM_RM_ESI; //0xFF
    *(uint32_t*)(serverFullPatch.patch+MODRM_BYTE+sizeof(uint8_t)) = (uint32_t)PLAYER_SLOTS_MAX;

#else //PLATFORM_WINDOWS
    serverFullPatch.bytes = OP_CMP_R32_RM32_SIZE;

    //replace the first part of cmp eax, [esi+180h] with cmp eax, IMM32(player_slots_max)

    serverFullPatch.patch[0] = OP_CMP_EAX_IMM32;
    *(uint32_t*)(serverFullPatch.patch+sizeof(uint8_t)) = (uint32_t)PLAYER_SLOTS_MAX;

    //fill in the rest of the patch size with nops

    fill_nop(serverFullPatch.patch + OP_CMP_EAX_IMM32_SIZE, OP_CMP_R32_RM32_SIZE - OP_CMP_EAX_IMM32_SIZE);
#endif

    if(firstTime)
    {
        ApplyPatch(lobbyConnectSig, serverFullOffset, &serverFullPatch, &serverFullRestore);
    }
    else
    {
        ApplyPatch(lobbyConnectSig, serverFullOffset, &serverFullPatch, /*restore*/NULL);
    }
    L4D_DEBUG_LOG("PlayerSlots -- 'ValveRejectServerFullFirst' patched to CMP eax, %d", PLAYER_SLOTS_MAX);
//	L4D_DEBUG_LOG("PlayerSlots -- CBaseServer player limit: %d", *(unsigned int *)((int)g_pServer+ 0x17C));
}