Arkshine / CSBotEnabler

Enable CSBot on Counter-Strike 1.6
46 stars 10 forks source link

2023 Offsets #12

Open ClaudiuHKS opened 9 months ago

ClaudiuHKS commented 9 months ago
#define CS_BOTS 0xE8, '*', '*', '*', '*'

#ifdef WIN32

#define CS_BOTS_W CS_BOTS, 0x83, 0xC4, 0x04, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'

unsigned char CS_BOTS_RADIO[]{ CS_BOTS_W, '*', '*', 0xE8, '*', '*', '*', '*', 0x83, }; // phraseMan

unsigned char CS_BOTS_PROFILES[]{ CS_BOTS_W, 0x57, 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, };
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_W, 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, };
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_W, 0x8B, '*', 0x8B, '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', 0x8B, '*', 0x8B, '*', 0x68, };
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_W, 0x56, 0x8B, '*', '*', 0xB9, '*', '*', '*', '*', 0x8B, '*', 0x0F, };
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_W, 0xC6, '*', '*', '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x74, '*', 0x68, };
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_W, '*', '*', 0x83, '*', '*', 0x75, '*', 0x8B, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, }; // addBot

unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x83, '*', '*', 0x80, '*', '*', '*', 0x74, '*', 0x8B, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0x6A, '*', 0x6A, '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0xFF, }; // clientPrint #Game_radio_loc...

#else

#define CS_BOTS_L CS_BOTS, 0x83, 0xC4, 0x10, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'

unsigned char CS_BOTS_RADIO[]{ CS_BOTS_L, 0x83, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x83, '*', '*', 0x31, '*', 0xE9, }; // phraseMan

unsigned char CS_BOTS_PROFILES[]{ CS_BOTS, 0x84, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, };
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_L, 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0xFF, };
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_L, '*', 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x58, 0x8B, '*', 0x5A, 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x59, 0x58, 0x8B, };
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_L, '*', '*', 0xBF, '*', '*', '*', '*', 0xB9, '*', '*', '*', '*', 0xF3, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0xBF, };
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_L, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xA1, };
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_L, 0x83, '*', '*', 0x89, '*', 0x8B, '*', '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x0F, }; // addBot

unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x80, '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', 0x31, '*', 0xBB, '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0x89, }; // clientPrint #Game_radio_loc...

#endif

Use Orpheu to patch void CHostage::IdleThink(void).

The \steamapps\common\Half-Life\cstrike\addons\amxmodx\configs\orpheu\functions\CHostage\IdleThink file.

{
    "name"          : "IdleThink",
    "class"         : "CHostage",
    "library"       : "mod",
    "identifiers"   :
    [
        {
            "os"    : "windows",
            "mod"   : "cstrike",
            "value" : "?IdleThink@CHostage@@QAEXXZ"
        },
        {
            "os"    : "linux",
            "mod"   : "cstrike",
            "value" : "_ZN8CHostage9IdleThinkEv"
        }
    ]
}
#pragma tabsize 0
#pragma semicolon 0
#pragma ctrlchar '\'
#pragma dynamic 4194304

#include <amxmodx>

#tryinclude <amxmisc>

/// #include <fun>
/// #include <csx>
/// #include <json>
/// #include <sqlx>
/// #include <geoip>
/// #include <regex>
/// #include <engine>
/// #include <nvault>
/// #include <cstrike>
/// #include <sockets>
/// #include <fakemeta>
/// #include <hamsandwich>

#include <orpheu>

#tryinclude <orpheu_memory>

public plugin_init()
{
    register_plugin("CS Block Hostage Think", __DATE__, "Hattrick HKS (Caramel)");

    return PLUGIN_CONTINUE;
}

public plugin_precache()
{
    new OrpheuFunction: eOnHostageIdleThink = OrpheuGetFunction("IdleThink", "CHostage");

    if (OrpheuInvalidFunction != eOnHostageIdleThink)
    {
        OrpheuRegisterHook(eOnHostageIdleThink, "OnHostageIdleThink_PRE", OrpheuHookPre);
    }

    return PLUGIN_CONTINUE;
}

public OrpheuHookReturn: OnHostageIdleThink_PRE(nHostage)
{
    return OrpheuSupercede;
}

Wasn't able to test the Linux signatures. EDIT: Tested, working.

void CHostage::IdleThink(void) L/ W Signatures (To Block This Function)

L/ 57 56 53 83 ?? ?? 81 ?? ?? ?? ?? ?? ?? ?? ?? ?? 8B ?? ?? ?? 0F ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 85 ?? 0F
W/ 55 8B ?? 6A ?? 68 ?? ?? ?? ?? 64 ?? ?? ?? ?? ?? 50 83 ?? ?? 53 56 57 A1 ?? ?? ?? ?? 33 ?? 50 8D ?? ?? 64 ?? ?? ?? ?? ?? 8B ?? 83 ?? ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 75 ?? 85 ?? 74 ?? 8B ?? 6A ?? FF

[Update on Dec. 17, 2013] Patching void CHostage::IdleThink(void)/ blocking its execution will cause hostages to not work anymore. So:

#define CS_BOTS 0xE8, '*', '*', '*', '*'

#ifdef WIN32

#define CS_BOTS_W CS_BOTS, 0x83, 0xC4, 0x04, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'

unsigned char CS_BOTS_RADIO[]{ CS_BOTS_W, '*', '*', 0xE8, '*', '*', '*', '*', 0x83, };                                                                                                                                          /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __cdecl BotPhraseManager::Initialize (BotPhraseManager * this, char * a2, int a3)` ( LINUX )

unsigned char CS_BOTS_PROFILES[]{ CS_BOTS_W, 0x57, 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, };                                                                                                                 /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl BotProfileManager::Init (BotProfileManager * const this, char * filename, unsigned int * checksum)` ( LINUX )
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_W, 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, };                                                                                        /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void Bot_RegisterCvars (void)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_W, 0x8B, '*', 0x8B, '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', 0x8B, '*', 0x8B, '*', 0x68, };                                                                                 /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::AddServerCommands (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_W, 0x56, 0x8B, '*', '*', 0xB9, '*', '*', '*', '*', 0x8B, '*', 0x0F, };                                                                                                           /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `unsigned int __cdecl CCSBotManager::ServerCommand (CCSBotManager * this, const char * a2)` ( LINUX )
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_W, 0xC6, '*', '*', '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x74, '*', 0x68, };                                                                                        /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::ValidateMapData (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_W, '*', '*', 0x83, '*', '*', 0x75, '*', 0x8B, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xFF, };                                                                              /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __usercall CCSBotManager::AddBot @ <eax> (int a1 @ <edi>, BotProfile * this, const BotProfile * a3)` ( LINUX )

unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x83, '*', '*', 0x80, '*', '*', '*', 0x74, '*', 0x8B, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0x6A, '*', 0x6A, '*', 0xFF, '*', '*', '*', '*', '*', 0x6A, '*', 0xFF, };    /// `void __cdecl ClientPrint (entvars_t * client, int msg_dest, const char * msg_name, const char * param1, const char * param2, const char * param3, const char * param4)` CALL WITH "#Game_radio_location" PARAMETER INSIDE FUNCTION `void __cdecl CBasePlayer::Radio (CBasePlayer * const this, const char * msg_id, const char * msg_verbose, __int16 pitch, bool showIcon)` ( LINUX )

unsigned char CS_BOTS_HOSTAGE[]{ 0x55, 0x8B, '*', 0x6A, '*', 0x68, '*', '*', '*', '*', 0x64, '*', '*', '*', '*', '*', 0x50, 0x83, '*', '*', 0x53, 0x56, 0x57, 0xA1, '*', '*', '*', '*', 0x33, '*', 0x50, 0x8D, '*', '*',        /// `void __thiscall CHostage::IdleThink (CHostage * this)` FUNCTION ( WINDOWS )
0x64, '*', '*', '*', '*', '*', 0x8B, '*', 0x83, '*', '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x75, '*', 0x85, '*', 0x74, '*', 0x8B, '*', 0x6A, '*', 0xFF, };                                                    /// `void __cdecl CHostage::IdleThink (CHostage * const this)` FUNCTION ( LINUX )

unsigned char CS_BOTS_IMPROV[]{ 0x53, 0x8B, '*', 0x83, '*', '*', 0x83, '*', '*', 0x83, '*', '*', 0x55, 0x8B, '*', '*', 0x89, '*', '*', '*', 0x8B, '*', 0x6A, '*', 0x68, '*', '*', '*', '*', 0x64, '*', '*', '*', '*', '*',      /// `int * __userpurge sub_1004DBB0 @ <eax> (int * a1 @ <ecx>, int a2 @ <edi>, int a3 @ <esi>, int a4)` FUNCTION ( WINDOWS )
0x50, 0x53, 0x83, '*', '*', 0x56, 0x57, 0xA1, '*', '*', '*', '*', 0x33, '*', 0x50, 0x8D, '*', '*', 0x64, '*', '*', '*', '*', '*', 0x8B, '*', 0x89, '*', '*', 0xC7, };                                                           /// `void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity)` FUNCTION ( LINUX )

unsigned char CS_BOTS_NEW[]{ CS_BOTS, 0x83, '*', '*', 0x89, '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0x85, '*', 0x74, '*', 0x57, 0x8B, '*', 0xE8, '*', '*', '*', '*', 0xEB, };                                             /// `void * __cdecl operator new (unsigned size)` CALL INSIDE FUNCTION `void __cdecl CHostage::IdleThink (CHostage * const this)` ( LINUX )

#else

#define CS_BOTS_L CS_BOTS, 0x83, 0xC4, 0x10, 0x84, 0xC0, '*', '*', '*', '*', '*', '*'

unsigned char CS_BOTS_RADIO[]{ CS_BOTS_L, 0x83, '*', '*', 0xFF, '*', '*', '*', '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x83, '*', '*', 0x31, '*', 0xE9, };                                                /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __cdecl BotPhraseManager::Initialize (BotPhraseManager * this, char * a2, int a3)` ( LINUX )

unsigned char CS_BOTS_PROFILES[]{ CS_BOTS, 0x84, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xE9, };                           /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl BotProfileManager::Init (BotProfileManager * const this, char * filename, unsigned int * checksum)` ( LINUX )
unsigned char CS_BOTS_CON_VARS[]{ CS_BOTS_L, 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xFF, '*', '*', '*', '*', '*', 0xC7, '*', '*', '*', '*', '*', '*', 0xFF, };                                                              /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void Bot_RegisterCvars (void)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_REG[]{ CS_BOTS_L, '*', 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x58, 0x8B, '*', 0x5A, 0x68, '*', '*', '*', '*', 0x53, 0xFF, '*', '*', 0x59, 0x58, 0x8B, };                               /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::AddServerCommands (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_CON_CMDS_EXEC[]{ CS_BOTS_L, '*', '*', 0xBF, '*', '*', '*', '*', 0xB9, '*', '*', '*', '*', 0xF3, '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0xBF, };                               /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `unsigned int __cdecl CCSBotManager::ServerCommand (CCSBotManager * this, const char * a2)` ( LINUX )
unsigned char CS_BOTS_MAP_NAV[]{ CS_BOTS_L, '*', '*', '*', 0xE8, '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x68, '*', '*', '*', '*', 0xE8, '*', '*', '*', '*', 0xA1, };                     /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `void __cdecl CCSBotManager::ValidateMapData (CCSBotManager * this)` ( LINUX )
unsigned char CS_BOTS_MANAGER[]{ CS_BOTS_L, 0x83, '*', '*', 0x89, '*', 0x8B, '*', '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x85, '*', 0x0F, '*', '*', '*', '*', '*', 0x83, '*', '*', 0x0F, };                         /// `int __cdecl UTIL_IsGame (const char * gameName)` CALL INSIDE FUNCTION `int __usercall CCSBotManager::AddBot @ <eax> (int a1 @ <edi>, BotProfile * this, const BotProfile * a3)` ( LINUX )

unsigned char CS_BOTS_DISPLAY[]{ CS_BOTS, 0x80, '*', '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', 0x31, '*', 0xBB, '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x89, '*', '*', '*', 0x89, };            /// `void __cdecl ClientPrint (entvars_t * client, int msg_dest, const char * msg_name, const char * param1, const char * param2, const char * param3, const char * param4)` CALL WITH "#Game_radio_location" PARAMETER INSIDE FUNCTION `void __cdecl CBasePlayer::Radio (CBasePlayer * const this, const char * msg_id, const char * msg_verbose, __int16 pitch, bool showIcon)` ( LINUX )

unsigned char CS_BOTS_HOSTAGE[]{ 0x57, 0x56, 0x53, 0x83, '*', '*', 0x81, '*', '*', '*', '*', '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', 0x0F, '*', '*', '*', '*', '*', 0x8B, '*', '*', '*', '*', '*', 0x85, '*', 0x0F, };    /// `void __cdecl CHostage::IdleThink (CHostage * const this)` FUNCTION ( LINUX )

unsigned char CS_BOTS_IMPROV[]{ 0x57, 0x31, '*', 0x66, '*', '*', '*', 0x56, 0xBA, '*', '*', '*', '*', 0x53, 0xB9, '*', '*', '*', '*', 0x83, '*', '*', 0xBF, '*', '*', '*', '*', 0x8B, '*', '*', '*', 0x0F, '*', '*', '*', '*',  /// `int * __userpurge sub_1004DBB0 @ <eax> (int * a1 @ <ecx>, int a2 @ <edi>, int a3 @ <esi>, int a4)` FUNCTION ( WINDOWS )
'*', '*', 0x8B, '*', '*', '*', 0x0F, '*', '*', '*', 0x0F, '*', '*', '*', 0xF3, '*', '*', '*', '*', '*', '*', '*', 0x89, '*', '*', '*', '*', '*', 0xB8, };                                                                       /// `void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity)` FUNCTION ( LINUX )

unsigned char CS_BOTS_NEW[]{ CS_BOTS, 0x89, '*', '*', '*', 0x89, '*', '*', 0x89, '*', 0xE8, '*', '*', '*', '*', 0x89, '*', '*', '*', '*', '*', 0xE9, };                                                                         /// `void * __cdecl operator new (unsigned size)` CALL INSIDE FUNCTION `void __cdecl CHostage::IdleThink (CHostage * const this)` ( LINUX )

#endif
  1. Should block void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity) function. On Windows, it's a int * function. Not void. So in Windows, return nullptr; is needed.

  2. Should block void * __cdecl operator new (unsigned size) call inside function void __cdecl CHostage::IdleThink (CHostage * const this). On Windows and Linux, return nullptr; is needed. The void * __cdecl operator new (unsigned size) function is a void * function.

  3. Warning, void __cdecl CHostageImprov::CHostageImprov (CHostageImprov * const this, CHostage * entity) is a main function, not a sub-function which resides inside a main function (like the others are). Perhaps this needs a different hook method.

  4. No need to hook/ block void __cdecl CHostage::IdleThink (CHostage * const this) anymore. Can still be hooked but call the original function into the hook.

unsigned char* Hook_LoadFileForMe(const char* pcszFileName, int* pnLength) noexcept
{
    static bool bShouldBlock{ };

    if (!::g_strGameDir.empty())
    {
        if (!::g_strGameDir.compare("cstrike"))
        {
            if (pcszFileName)
            {
                if (*pcszFileName)
                {
                    if (::std::strcmp("tutordata.txt", pcszFileName))
                    {
                        if (::std::strcmp("BotChatter.db", pcszFileName))
                        {
                            if (!::std::strstr(pcszFileName, "sound\\radio\\bot\\"))
                            {
                                if (!::std::strstr(pcszFileName, "sound/radio/bot/"))
                                {
                                    bShouldBlock = { };
                                }

                                else
                                {
                                    bShouldBlock = true;
                                }
                            }

                            else
                            {
                                bShouldBlock = true;
                            }
                        }

                        else
                        {
                            bShouldBlock = true;
                        }
                    }

                    else
                    {
                        bShouldBlock = true;
                    }
                }

                else
                {
                    bShouldBlock = { };
                }
            }

            else
            {
                bShouldBlock = { };
            }
        }

        else
        {
            bShouldBlock = { };
        }
    }

    else
    {
        bShouldBlock = { };
    }

    if (!::g_bNoReturn)
    {
        do
        {
            ::gpMetaGlobals->mres = ((bShouldBlock) ? (::MRES_SUPERCEDE) : (::MRES_IGNORED));

            if (((::gpMetaGlobals)->orig_ret))
            {
                if (bShouldBlock)
                {
                    return { };
                }

                return (*(unsigned char**) ::gpMetaGlobals->orig_ret);
            }

            else
            {
                return { };
            }

            return { };
        }

        while (false);
    }

    else
    {
        return { };
    }

    return { };
}

I use bot_chatter off setting and I don't need talkable bots. I use this Meta Mod hook above as is. And return false; into the custom hook for: int __cdecl UTIL_IsGame(const char * gameName) call inside function int __cdecl BotPhraseManager::Initialize (BotPhraseManager * this, char * a2, int a3).

To hook functions (not sub-functions) on Windows/ Linux you can use https://github.com/Zeex/subhook To hook functions (not sub-functions) on Windows you can use https://github.com/microsoft/Detours

Hedwig7s commented 9 months ago

This should really be a pull request