Raised This Month: $12 Target: $400
 3% 

Hooking BaseEntity Functions in CSGO


Post New Thread Reply   
 
Thread Tools Display Modes
spidershift
Member
Join Date: Oct 2014
Old 10-28-2014 , 13:31   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #11

donrevan, thank you for taking the time to write up that assembly. I just gave it a try and it unfortunately crashed once I fired that first bullet. I really wish I could offer some help but I don't really know assembly. Once psychonic told me about LTCG in the signatures thread, I knew things would quickly start to get over my head. I understand that some arguments are being passed through registers, which therefore changes the arguments themselves, but doubt I could construct any of those move instructions as you did.

I'll see if I can make any progress for the time being by hooking CBaseEntity::FireBullets(...) since that's what SDKHooks does. I doubt it's going to work out as intended because CCSPlayer::FireBullet(...) and FX_FireBullets(...) have a lot of their own custom functionality, but I guess there's no harm in trying.

Finally, do you think perhaps any of these issues we're running into are because of CSWeaponID and WeaponSound_t? I had to manually copy their definitions into my headers because I could not find public definitions anywhere, but they are just enums, so shouldn't they technically be no different than (and could even be replaced by) an int instead? Or could they be the arguments contributing to these crashes?
spidershift is offline
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 10-28-2014 , 18:24   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #12

Quote:
Originally Posted by spidershift View Post
Finally, do you think perhaps any of these issues we're running into are because of CSWeaponID and WeaponSound_t? I had to manually copy their definitions into my headers because I could not find public definitions anywhere, but they are just enums, so shouldn't they technically be no different than (and could even be replaced by) an int instead? Or could they be the arguments contributing to these crashes?
Yup they'll be replaced by int's(most-likely).
I just spotted a mistake in my snippet(I moved iPlayerId to a wrong register, esi instead of ecx) - I updated my post. Please try it again.
Anyway, if that doesn't work I'll setup a CS:GO server because this made me curious

Last edited by donrevan; 10-28-2014 at 18:24.
donrevan is offline
spidershift
Member
Join Date: Oct 2014
Old 10-28-2014 , 19:20   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #13

I tried it again and unfortunately it still crashed.
spidershift is offline
spidershift
Member
Join Date: Oct 2014
Old 10-30-2014 , 08:46   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #14

So here's a small update. I tried to see what would happen if I changed the values of the parameters:

PHP Code:
Vector *ptr3;
ptr3 = (Vector*)( &a3 );
*
ptr3 Vector(000);
QAngle *ptr4;
ptr4 = (QAngle*)( &a4 );
*
ptr4 QAngle(000); 
With everything else commented out, this doesn't crash or anything. Outputting the values of a3 and a4 shows they were changed, but it doesn't have any effect on the bullets themselves. So with this, and the fact that bullets are still being shot even with the static call commented out (which still crashes no matter what I try), it seems as though the static detour is being called like a post hook. Isn't the expected behavior of the detour to stop the original FX_FireBullets(...) from being called?

Also as a sanity check, removing the first two parameters is definitely correct as was described, because the logged values of a3 and a4 are correct when they are not included, and completely wrong when they are.
spidershift is offline
spidershift
Member
Join Date: Oct 2014
Old 10-30-2014 , 09:43   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #15

So after logging iPlayerId and definitionIndex, I saw that it was always logging 0 for the iPlayerId, even for bots.

I also noticed once I put bots on the map that no hit detection is registering when I detour the function. However, tracer animations, bullet decals, and so on are all still displayed (which is what lead me to believe that FX_FireBullets(...) was still being called before I put bots on the map), but now I'm just confused. After all this, I don't really have any kind of an idea what is going on with relation to the original function call.
spidershift is offline
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 10-30-2014 , 15:35   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #16

This is what I've now:
PHP Code:
DETOUR_DECL_STATIC10(Detour_FXFireBulletsvoidVector const&, vOriginQAngle const&, vAnglesintweaponIdintmodeintseedfloatflSpreadfloata9floata10floata11inta12)
{
    
int iPlayerId;
    
__asm mov iPlayerIdecx
    int definitionIndex
;
    
__asm mov definitionIndexedx

    
// Trick the compiler into thinking that we're using ESI(to preserve it - just to be sure).
    
__asm mov esiesi;

    
printf("playerID: %d\n"iPlayerId);
    
printf("definitionIndex: %d\n"definitionIndex);
    
printf("wpnId: %d\n"weaponId);
    
printf("mode: %d\n"mode);
    
printf("seed: %d\n"seed);
    
printf("spread: %f\n"flSpread);

    
/* Call original function.
     * I had to manually 'construct' this call because the compiler was destroying register content while pushing the args. */
    
void *addr DETOUR_STATIC_CALL(Detour_FXFireBullets);
    
__asm {
        
push a12
        push a11
        push a10
        push a9
        push flSpread
        push seed
        push mode
        push weaponId
        push vAngles
        push vOrigin
        mov edx
definitionIndex
        mov ecx
iPlayerId
        call addr
        add esp
0x28
    
}

Excuse the huge mess but I had to use inline assembly to call the function because the compiler would destroy the contents of edx, ecx if I call it via DETOUR_STATIC_CALL..

If you remove the call to the original function no bullets/shots will be networked, however you can still kill people with knife/nades.

iPlayerID has correct values, dunno about definitionIndex

Last edited by donrevan; 10-30-2014 at 15:39.
donrevan is offline
spidershift
Member
Join Date: Oct 2014
Old 10-31-2014 , 03:15   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #17

I really appreciate all your help, and can't thank you enough. I'm so eager to get this working and it's killing me cause I can see that you're so close to making this work. I feel bad to inform you that after trying what you have there, it unfortunately crashed. To be on the safe side, here is the signature that I'm using:

PHP Code:
\x55\x8B\xEC\x83\xE4\x2A\x81\xEC\x2A\x2A\x2A\x2A\x89\x54\x2A\x2A\x89\x4C\x2A\x2A\x56\x57 
Aside from that, I used exactly what you provided, and even tried it with the printf()s commented out as well.
spidershift is offline
spidershift
Member
Join Date: Oct 2014
Old 10-31-2014 , 04:37   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #18

You mentioned the compiler was destroying your assembly. Perhaps I need to change some compiler settings of some kind to match yours? Were you able to get that snippet working in game?

Last edited by spidershift; 10-31-2014 at 04:37.
spidershift is offline
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 10-31-2014 , 07:30   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #19

Yes, I tested the snippet and it's working.
I'm using the same signature and the SM sample extension. Attach a debugger to srcds.exe so we can see why it is crashing.

Last edited by donrevan; 10-31-2014 at 07:30.
donrevan is offline
spidershift
Member
Join Date: Oct 2014
Old 10-31-2014 , 10:57   Re: Hooking BaseEntity Functions in CSGO
Reply With Quote #20

Unhandled exception at 0x1707E1BF (dbi.sqlite.ext.dll) in srcds.exe: Fatal program exit requested.

extension.h
PHP Code:
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_

/**
 * @file extension.h
 * @brief Sample extension code header.
 */

#include "smsdk_ext.h"
#include "CDetour/detours.h"

#define DETOUR_DECL_STATIC10(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name, p10type, p10name) \
ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type, p10type) = NULL; \
ret name(p1type p1namep2type p2namep3type p3namep4type p4namep5type p5namep6type p6namep7type p7namep8type p8namep9type p9namep10type p10name)

bool CreateFXFireBulletsDetour();

/**
 * @brief Sample implementation of the SDK Extension.
 * Note: Uncomment one of the pre-defined virtual functions in order to use it.
 */
class Sample : public SDKExtension, public IPluginsListener
{
public:
    
/**
     * @brief This is called after the initial loading sequence has been processed.
     *
     * @param error        Error message buffer.
     * @param maxlength    Size of error message buffer.
     * @param late        Whether or not the module was loaded after map load.
     * @return            True to succeed loading, false to fail.
     */
    
virtual bool SDK_OnLoad(char *errorsize_t maxlengthbool late);
    
    
/**
     * @brief This is called right before the extension is unloaded.
     */
    
virtual void SDK_OnUnload();

    
/**
     * @brief This is called once all known extensions have been loaded.
     * Note: It is is a good idea to add natives here, if any are provided.
     */
    //virtual void SDK_OnAllLoaded();

    /**
     * @brief Called when the pause state is changed.
     */
    //virtual void SDK_OnPauseChange(bool paused);

    /**
     * @brief this is called when Core wants to know if your extension is working.
     *
     * @param error        Error message buffer.
     * @param maxlength    Size of error message buffer.
     * @return            True if working, false otherwise.
     */
    //virtual bool QueryRunning(char *error, size_t maxlength);
public:
#if defined SMEXT_CONF_METAMOD
    /**
     * @brief Called when Metamod is attached, before the extension version is called.
     *
     * @param error            Error buffer.
     * @param maxlength        Maximum size of error buffer.
     * @param late            Whether or not Metamod considers this a late load.
     * @return                True to succeed, false to fail.
     */
    //virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);

    /**
     * @brief Called when Metamod is detaching, after the extension version is called.
     * NOTE: By default this is blocked unless sent from SourceMod.
     *
     * @param error            Error buffer.
     * @param maxlength        Maximum size of error buffer.
     * @return                True to succeed, false to fail.
     */
    //virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);

    /**
     * @brief Called when Metamod's pause state is changing.
     * NOTE: By default this is blocked unless sent from SourceMod.
     *
     * @param paused        Pause state being set.
     * @param error            Error buffer.
     * @param maxlength        Maximum size of error buffer.
     * @return                True to succeed, false to fail.
     */
    //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
#endif
    
void OnPluginLoaded(IPlugin *plugin);
    
void OnPluginUnloaded(IPlugin *plugin);
private:
    
bool m_FXFireBulletsDetourEnabled;
};

#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ 
extension.cpp
PHP Code:
#include "extension.h"

/**
 * @file extension.cpp
 * @brief Implement extension code here.
 */

Sample g_Sample;        /**< Global singleton for extension's main interface */

SMEXT_LINK(&g_Sample);

IGameConfig *g_pGameConf NULL;

CDetour  *DFXFireBullets NULL;
IForward *g_pFireBullet  NULL;

DETOUR_DECL_STATIC10(DetourFXFireBulletsvoidVector const&, vOriginQAngle const&, vAnglesintweaponIdintmodeintseedfloatflSpreadfloata9floata10floata11inta12)
{
    
int iPlayerId;
    
__asm mov iPlayerIdecx
    int definitionIndex
;
    
__asm mov definitionIndexedx

    
// Trick the compiler into thinking that we're using ESI(to preserve it - just to be sure).
    
__asm mov esiesi;

    
/*cell_t result = Pl_Continue;
    g_pFireBullet->PushCell(iPlayerId);
    g_pFireBullet->Execute(&result);

    printf("playerID: %d\n", iPlayerId);
    printf("definitionIndex: %d\n", definitionIndex);
    printf("wpnId: %d\n", weaponId);
    printf("mode: %d\n", mode);
    printf("seed: %d\n", seed);
    printf("spread: %f\n", flSpread);*/

    /*Vector *ptr3;
    
    ptr3  = (Vector*)( &vOrigin );
    *ptr3 =  Vector(vOrigin.x, vOrigin.y, vOrigin.z);
    
    QAngle *ptr4;
    
    ptr4  = (QAngle*)( &vAngles );
    *ptr4 =  QAngle(vAngles.x, vAngles.y, vAngles.z);*/

    /* Call original function.
     * I had to manually 'construct' this call because the compiler was destroying register content while pushing the args. */
    
void *addr DETOUR_STATIC_CALL(DetourFXFireBullets);
    
__asm {
        
push a12
        push a11
        push a10
        push a9
        push flSpread
        push seed
        push mode
        push weaponId
        push vAngles
        push vOrigin
        mov edx
definitionIndex
        mov ecx
iPlayerId
        call addr
        add esp
0x28
    
}
}

bool Sample::SDK_OnLoad(char *errorsize_t maxlengthbool late)
{
    
char conf_error[255];
    if (!
gameconfs->LoadGameConfigFile("sample.games", &g_pGameConfconf_errorsizeof(conf_error)))
    {
        if (
error)
        {
            
snprintf(errormaxlength"Could not read sample.games.txt: %s"conf_error);
        }
        return 
false;
    }

    
sharesys->RegisterLibrary(myself"sample");

    
plsys->AddPluginsListener(this);

    
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
    
    
m_FXFireBulletsDetourEnabled false;
    
    
g_pFireBullet forwards->CreateForward("OnFireBullet"ET_Event1NULLParam_Cell);

    return 
true;
}
void Sample::SDK_OnUnload()
{
    
gameconfs->CloseGameConfigFile(g_pGameConf);
    
plsys->RemovePluginsListener(this);
    
forwards->ReleaseForward(g_pFireBullet);
}

void Sample::OnPluginLoaded(IPlugin *plugin)
{
    if(!
m_FXFireBulletsDetourEnabled)
    {
        
m_FXFireBulletsDetourEnabled CreateFXFireBulletsDetour();
    }
}
void Sample::OnPluginUnloaded(IPlugin *plugin)
{
    if(
m_FXFireBulletsDetourEnabled)
    {
        if(
DFXFireBullets != NULL)
        {
            
DFXFireBullets->Destroy();
            
DFXFireBullets NULL;
        }
        
m_FXFireBulletsDetourEnabled false;
    }
}

bool CreateFXFireBulletsDetour()
{
    
DFXFireBullets =  DETOUR_CREATE_STATIC(DetourFXFireBullets"FX_FireBullets");

    if(
DFXFireBullets != NULL)
    {
        
DFXFireBullets->EnableDetour();
        return 
true;
    }
    
g_pSM->LogError(myself"FX_FireBullets detour could not be initialized");
    return 
false;

PHP Code:
1707E15C  push        dword ptr [ebp+10h]  
1707E15F  push        0  
1707E161  push        dword ptr 
[ebp+8]  
1707E164  call        1707DEB0  
1707E169  push        dword ptr 
[ebp+18h]  
1707E16C  push        dword ptr [ebp+14h]  
1707E16F  call        1708489C  
1707E174  pop         ecx  
1707E175  pop         ecx  
1707E176  pop         ebp  
1707E177  ret  
1707E178  push        ebp  
1707E179  mov         ebp
,esp  
1707E17B  mov         edx
,dword ptr [ebp+0Ch]  
1707E17E  mov         eax,dword ptr ds:[1709C2B0h]  
1707E183  not         edx  
1707E185  mov         ecx
,dword ptr [ebp+8]  
1707E188  and         edx,eax  
1707E18A  
and         ecx,dword ptr [ebp+0Ch]  
1707E18D  or          edx,ecx  
1707E18F  mov         dword ptr ds
:[1709C2B0h],edx  
1707E195  pop         ebp  
1707E196  ret  
1707E197  call        1708503F  
1707E19C  test        eax
,eax  
1707E19E  je          1707E1A8  
1707E1A0  push        16h  
1707E1A2  call        17085068  
1707E1A7  pop         ecx  
1707E1A8  test        byte ptr ds
:[1709C2B0h],2  
1707E1AF  je          1707E1D2  
1707E1B1  push        17h  
1707E1B3  call        1708B1B8  
1707E1B8  test        eax
,eax  
1707E1BA  je          1707E1C1  
1707E1BC  push        7  
1707E1BE  pop         ecx  
1707E1BF  int         29h  
1707E1C1  push        1  
1707E1C3  push        40000015h  
1707E1C8  push        3  
1707E1CA  call        1707E1E7  
1707E1CF  add         esp
,0Ch  
1707E1D2  push        3  
1707E1D4  call        1708087B  
1707E1D9  int         3  
1707E1DA  push        ebp  
1707E1DB  mov         ebp
,esp  
1707E1DD  mov         eax
,dword ptr [ebp+8]  
1707E1E0  mov         dword ptr ds:[1709DD68h],eax  
1707E1E5  pop         ebp  
1707E1E6  ret 
spidershift is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 08:22.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode