.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Bot Coding (http://forums.bots-united.com/forumdisplay.php?f=24)
-   -   Fake bot ping (SV_CalcPing() function injecting) (http://forums.bots-united.com/showthread.php?t=8494)

Immortal_BLG 05-02-2011 14:20

Fake bot ping (SV_CalcPing() function injecting)
 
Code:

const unsigned char Pointer32Size (sizeof (void *));
const unsigned char WildCard (0x2A);        // Used for signature scanning.
const unsigned char Push32 (0x68);        // push '....' (encoding is <imm32>)
const unsigned char JumpImmediately32 (0xE9);        // jmp '....' (encoding is imm32)
const unsigned char JumpImmediately32Size (sizeof (JumpImmediately32) + Pointer32Size);        // size of the jump-to instruction

struct ModuleInformation_t
{
        void        *baseAddress;
        unsigned int  memorySize;

        inline ModuleInformation_t (void) :
                baseAddress (NULL),
                memorySize (0u)
        { /* VOID */ }
};
inline const bool GetModuleInformation (const void *const libraryPointer, ModuleInformation_t &dynamicLibraryInformation)
{
        // Get base address of the module (dynamicLibraryInformation.baseAddress) and get its ending offset (dynamicLibraryInformation.memorySize)

        // First - reset dynamic library information structure....
        dynamicLibraryInformation.baseAddress = NULL;
        dynamicLibraryInformation.memorySize = 0u;

        // Reliability check.
        if (libraryPointer == NULL)        // GetModuleInformation() failed!
                return false;

        MEMORY_BASIC_INFORMATION info;

        // Reliability check.
        if (VirtualQuery (libraryPointer, &info, sizeof (info)) == 0)
                return false;

        /// @note THIS CHECK IS ADDED FROM CSigMngr.cpp
        if (info.AllocationBase == NULL)
                return false;

        // All this is for our insane sanity checks :O
        const IMAGE_DOS_HEADER *const dos (static_cast <IMAGE_DOS_HEADER *> (info.AllocationBase));
        const IMAGE_NT_HEADERS *const pe (reinterpret_cast <IMAGE_NT_HEADERS *> (reinterpret_cast <unsigned int> (info.AllocationBase) + dos->e_lfanew));

        // Check PE magic and signature
        /// @note IsBadReadPtr() CHECKS ARE ADDED FROM CSigMngr.cpp
        if
        (
                IsBadReadPtr (dos, sizeof (IMAGE_DOS_HEADER)) ||
                dos->e_magic != IMAGE_DOS_SIGNATURE          ||
                IsBadReadPtr (pe, sizeof (IMAGE_NT_HEADERS))  ||        // pe points to a bad location?
                pe->Signature != IMAGE_NT_SIGNATURE          ||
                pe->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC
        )
                return false;

        /* Check architecture, which is 32-bit/x86 right now
        * Should change this for 64-bit if Valve gets their act together
        */
        if (pe->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
                return false;

        // Finally, we can do this
        dynamicLibraryInformation.baseAddress = info.AllocationBase;
        dynamicLibraryInformation.memorySize = pe->OptionalHeader.SizeOfImage;

        return true;
}
inline const bool CompareMemoryWithoutWildCard (const unsigned char *const startPointer, const unsigned char *const pattern, const unsigned char length)
{
        // Compare each byte, except wildcards....
        for (unsigned char index (0u); startPointer[index] == pattern[index]; /* Empty */)
                if ((index += sizeof (unsigned char)) == length)        // If 'index' reached the end, we know we have a match!
                        return true;        // Found a match.

        return false;
}
inline void *const FindPatternWithoutWildCard (void *startPointer, const unsigned int searchLength, const unsigned char *const pattern, const unsigned char length, const unsigned char stepSize = sizeof (unsigned char))
{
        // Scan for the signature in memory then return the starting position's address.

        // Reliability checks.
        if (startPointer == NULL || searchLength < length || length < 2u)
                return NULL;

        const unsigned char *const endPointer (static_cast <unsigned char *> (startPointer) + searchLength);        // prevent a crash maybe?

        do
        {
                // Compare each byte, except wildcards....
                if (CompareMemoryWithoutWildCard (static_cast <unsigned char *> (startPointer), pattern, length))
                        return startPointer;        // Found a match.
        } while ((reinterpret_cast <unsigned char *&> (startPointer) += stepSize/* search memory in an aligned manner, or not */) + length <= endPointer);        // prevent a crash maybe?

        return NULL;
}
inline const bool CompareMemory (const unsigned char *const startPointer, const unsigned char *const pattern, const unsigned char length, const unsigned char wildCard = WildCard)
{
        // Compare each byte, except wildcards....
        for (unsigned char index (0u); pattern[index] == wildCard || startPointer[index] == pattern[index]; /* Empty */)
                if ((index += sizeof (unsigned char)) == length)        // If 'index' reached the end, we know we have a match!
                        return true;        // Found a match.

        return false;
}
/**
* @brief Searches for a pattern of bytes within the memory of a dynamic library.
*
* @param startPointer:        Pointer to memory to search for.
* @param searchLength:        Length of sequence of memory to search for.
* @param pattern:                Pattern of bytes to search for. 0x2A can be used as a wildcard.
* @param length:                Size of the pattern in bytes.
* @return                                Pointer to pattern found in memory, NULL if not found.
*/
inline void *const FindPattern (void *startPointer, const unsigned int searchLength, const unsigned char *const pattern, const unsigned char length, const unsigned char stepSize = sizeof (unsigned char), const unsigned char wildCard = WildCard)
{
        // Scan for the signature in memory then return the starting position's address.

        // Reliability checks.
        if (startPointer == NULL || searchLength < length || length < 2u)
                return NULL;

        const unsigned char *const endPointer (static_cast <unsigned char *> (startPointer) + searchLength);        // prevent a crash maybe?

        do
        {
                // Compare each byte, except wildcards....
                if (CompareMemory (static_cast <unsigned char *> (startPointer), pattern, length, wildCard))
                        return startPointer;        // Found a match.
        } while ((reinterpret_cast <unsigned char *&> (startPointer) += stepSize/* search memory in an aligned manner, or not */) + length <= endPointer);        // prevent a crash maybe?

        return NULL;
}
inline void *const FindMemoryChunkReference32 (void *const startPointer, const unsigned int searchLength, const void *const address, const unsigned char instruction)
{
        const union /* Unnamed */
        {
                const void    *pointer;
                unsigned char  byte[Pointer32Size];
        } pointerToByte = {address/*, Do not initialize me! */};
        const unsigned char pattern[sizeof (instruction) + Pointer32Size] =
        {
                instruction, pointerToByte.byte[0u], pointerToByte.byte[1u], pointerToByte.byte[2u], pointerToByte.byte[3u]        // instruction 'address'
        };

        return FindPattern (startPointer, searchLength, pattern, sizeof (pattern));
}
inline void *const GetRealAddressOfRelativeAddress32 (const void *const relativeAddress)
{
        // Reliability check.
        if (relativeAddress == NULL)
                return NULL;

        return reinterpret_cast <void *> (static_cast <const unsigned int *const> (relativeAddress)[0u] + reinterpret_cast <const unsigned int> (relativeAddress) + Pointer32Size);
}

struct Client_t;
typedef const unsigned int (*SV_CalcPingFunction_t) (const Client_t *const client);

inline SV_CalcPingFunction_t GetSV_CalcPingFunction (void)
{
        ModuleInformation_t engineModuleInformation;

        if (!GetModuleInformation (gEngfuncs.pfnGetPlayerUserId, engineModuleInformation))
                return NULL;

        const unsigned char string[] = {"%4i %s\n"};        // From Host_Ping_f() function.
        unsigned char *address (static_cast <unsigned char *> (FindPatternWithoutWildCard (engineModuleInformation.baseAddress, engineModuleInformation.memorySize, string, sizeof (string) - sizeof ('\0'))));

        if (address == NULL)
                return NULL;

        address = static_cast <unsigned char *> (FindMemoryChunkReference32 (engineModuleInformation.baseAddress, engineModuleInformation.memorySize, address, Push32));

        if (address == NULL)
                return NULL;

        address -= sizeof ("\x4D\x93\x04\x00\x83\xC4\x04\x50") - sizeof ('\0');

        return static_cast <SV_CalcPingFunction_t> (GetRealAddressOfRelativeAddress32 (address));
}

inline const unsigned int SV_CalcPing_IfFakeClient (const Client_t *const fakeClient)
{
        edict_t *const fakeClientEdict (reinterpret_cast <edict_t **> (fakeClient)[4839u/* For 4554 build! */]);

        gEngfuncs.pfnServerPrint ("SV_CalcPing_IfFakeClient(%s): called!", STRING (fakeClientEdict->v.netname));

        return 999u;        // YOUR CODE HERE!!!!
}

#define CALL_SV_CalcPing_IfFakeClient_FUNCTION                                                                \
        { push eax }                                                /* just for safety */                                \
        { push ecx }                                                /* push the fake client pointer */        \
        { call SV_CalcPing_IfFakeClient }        /* call our function */                                \
        { add  esp, 8 }                                                /* correct stack */                                        \

inline const unsigned int __declspec (naked) SV_CalcPing_IfFakeClient_Gate_WithEpilogueOfListenServer (const Client_t *const fakeClient)
{
        __asm
        {
                CALL_SV_CalcPing_IfFakeClient_FUNCTION;

                pop  ebp;
                pop  ecx;

                retn;        // Return Near from Procedure
        }
}
inline const unsigned int __declspec (naked) SV_CalcPing_IfFakeClient_Gate_WithEpilogueOfDedicatedServer (const Client_t *const fakeClient)
{
        /// @todo THIS FUNCTION WORKS FINE, BUT I'M NOT SHURE....

        __asm
        {
                CALL_SV_CalcPing_IfFakeClient_FUNCTION;

                pop  esi;
                mov  esp, ebp;
                pop  ebp;

                retn;        // Return Near from Procedure
        }
}
inline void InjectInSV_CalcPingFunction (void)
{
        SV_CalcPingFunction_t SV_CalcPingFunction (GetSV_CalcPingFunction ());

        if (SV_CalcPingFunction == NULL)
        {
                gEngfuncs.pfnServerPrint ("InjectInSV_CalcPingFunction(): Can't find target function!");

                return;
        }

        const unsigned char signatureIfFakeClient[] = {"\x39\x2A\x48\x25\x00\x00"};        // cmp [ecx+2548h], (ebp/esi)        // Compare Two Operands (2548h - offset to Client_t::fakeclient member)
        unsigned char *addressIfFakeClient (static_cast <unsigned char *> (FindPattern (SV_CalcPingFunction, sizeof ("\x55\x8B\xEC\x51\x8B\x4D\x08\x56\x33\xF6\x39\xB1\x48\x25\x00\x00\x74\x07\x33\xC0\x5E\x8B\xE5\x5D\xC3") - sizeof ('\0')/* Signature from swds.dll (longer than in hw.dll) */, signatureIfFakeClient, sizeof (signatureIfFakeClient) - sizeof ('\0'))));

        // Reliability check.
        if (addressIfFakeClient == NULL)
                return;

        // Skip "cmp [ecx+2548h], (ebp/esi)" and "jz short loc_1D9B089" instructions....
        addressIfFakeClient += sizeof (signatureIfFakeClient) - sizeof ('\0') + sizeof ("\x74\x07")/* jz short loc_1D9B089 */ - sizeof ('\0');

        // Reliability checks.
        if (addressIfFakeClient[0u] != 0x33 || addressIfFakeClient[1u] != 0xC0)        // xor eax, eax        // Logical Exclusive OR
                return;

        unsigned long dummyOldProtectFlags;

        if (!VirtualProtect (addressIfFakeClient, JumpImmediately32Size, PAGE_EXECUTE_READWRITE, &dummyOldProtectFlags))
        {
                gEngfuncs.pfnServerPrint ("InjectInSV_CalcPingFunction(): VirtualProtect() filed!");

                return;
        }

        addressIfFakeClient[0u] = JumpImmediately32;

        reinterpret_cast <unsigned int *> (addressIfFakeClient + sizeof (JumpImmediately32))[0u] = reinterpret_cast <unsigned char *> (gEngfuncs.pfnIsDedicatedServer () ? SV_CalcPing_IfFakeClient_Gate_WithEpilogueOfDedicatedServer : SV_CalcPing_IfFakeClient_Gate_WithEpilogueOfListenServer) - addressIfFakeClient - JumpImmediately32Size;

        gEngfuncs.pfnServerPrint ("InjectInSV_CalcPingFunction(): Complete!");
}

It works fine for me!

P.S. 1 SORRY FOR BAD ENGLISH!
P.S. 2 With this method you can see fake ping for example in 'status' command
P.S. 3 I'm not good in ASM!!!
P.S. 4 If you need full Client_t structure I can post it. (But with changed names of structures)


All times are GMT +2. The time now is 07:19.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.