View Single Post
Author Message
kadet.89
Veteran Member
Join Date: Nov 2012
Location: Serbia
Old 12-21-2020 , 09:22   CSGO correct usage of manual hooks
Reply With Quote #1

I have a manual hook in my extension declared this way:

PHP Code:
SH_DECL_MANUALHOOK2_void(CPlayer_PlayerRunCmd000CUserCmd*, void*)

CPlayer::CPlayer(CBaseEntityentity)
{
    
SH_ADD_MANUALHOOK(CPlayer_PlayerRunCmdGetBaseEntity(), SH_MEMBER(this, &CPlayer::OnPlayerRunCmd), false);
}

CPlayer::~CPlayer(void)
{
    
SH_REMOVE_MANUALHOOK(CPlayer_PlayerRunCmdGetBaseEntity(), SH_MEMBER(this, &CPlayer::OnPlayerRunCmd), false);
}

void CPlayer::OnPlayerRunCmd(CUserCmd *cmdvoid *moveHelper)
{
    const 
int pressedButtons GetButtonPressed();
    if(
pressedButtons IN_RELOAD)
    {
        
CBaseEntityactiveWeapon GetActiveWeaponPointer();
        if(!
activeWeapon || strcmp(activeWeapon->GetClassName(), "weapon_knife") != 0)
            
RETURN_META(MRES_IGNORED);

        
CBaseEntityak47 GetWeaponByClassname("weapon_ak47");
        if(!
ak47)
            
RETURN_META(MRES_IGNORED);

        
SH_MCALL(GetBaseEntity(), CPlayer_Weapon_Switch)(ak470);
    }

    
RETURN_META(MRES_IGNORED);

This works, but quite often crashes the server. On in the crashstack I always see the same funtion name and the same stack:

PHP Code:
 0  server.so 0x5d5463
 1  server
.so 0x760f0b
 2  server
.so 0x767b7a
 3  server
.so 0xb8f9e7
 4  sdkhooks
.ext.2.csgo.so 0x1bdfe
 5  server
.so 0x77c1d3
 6  server
.so 0x77c951
 7  server
.so 0x75f47c
 8  server
.so 0xb8c335
 9  extension18
.ext.2.csgo.so 0x35f91
10  server
.so 0x777a94
11  server
.so 0x734db5 
The function where crash begins (extension18.ext.2.csgo.so + 0x35f91) Scroll to the comment (// Crashes here)

PHP Code:
int __cdecl __SourceHook_MFHCls_CPlayer_PlayerRunCmd::Func(int a1int a2int a3)
{
  
int v3// eax@1
  
int v4// ebx@1
  
int (__cdecl *v5)(intintint); // edx@2
  
int v6// eax@3
  
int (__cdecl *v7)(intintint); // edx@10
  
int v8// eax@11
  
int v10// [sp+8h] [bp-28h]@1
  
int v11// [sp+Ch] [bp-24h]@1
  
int v12// [sp+10h] [bp-20h]@1
  
void (__cdecl *v13)(intintint); // [sp+14h] [bp-1Ch]@1

  
v12 0;
  
v3 = (*(int (__cdecl **)(intintintintvoid (__cdecl **)(intintint), int *, int *, int *, _DWORD_DWORD))(*(_DWORD *)g_SHPtr 76))(
         
g_SHPtr,
         
__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_HI,
         *(
_DWORD *)(a1 + *(_DWORD *)&__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_MFI[12])
       + 
* *(_DWORD *)&__SourceHook_MFHCls_CPlayer_PlayerRunCmd::ms_MFI[8],
         
a1,
         &
v13,
         &
v12,
         &
v11,
         &
v10,
         
0,
         
0);
  
v11 0;
  
v4 v3;
  while ( 
)
  {
    
v6 = (**(int (__cdecl ***)(_DWORD))v4)(v4);
    if ( !
v6 )
      break;
    
v10 0;
    
v5 = *(int (__cdecl **)(intintint))(*(_DWORD *)v6 8);
    if ( 
v5 == __SourceHook_MFHCls_CPlayer_PlayerRunCmd::CMyDelegateImpl::Call )
    {
      
v5 = *(int (__cdecl **)(intintint))(v6 8);
      
v6 = *(_DWORD *)(v6 4) + *(_DWORD *)(v6 12);
      if ( (
unsigned __int8)v5 )
        
v5 = *(int (__cdecl **)(intintint))((char *)v5 + *(_DWORD *)v6 1);
    }
    
v5(v6a2a3);
    
v11 v10;
    if ( 
v10 v12 )
      
v12 v10;
  }
  if ( 
v12 != && (unsigned __int8)(*(int (__cdecl **)(int))(*(_DWORD *)v4 12))(v4) )
  {
    if ( (
unsigned __int8)v13 )
      (*(
void (__cdecl **)(intintint))((char *)v13 + *(_DWORD *)a1 1))(a1a2a3);
    else
      
v13(a1a2a3); // Crashes here
  
}
  
v11 0;
  while ( 
)
  {
    
v8 = (**(int (__cdecl ***)(_DWORD))v4)(v4);
    if ( !
v8 )
      break;
    
v10 0;
    
v7 = *(int (__cdecl **)(intintint))(*(_DWORD *)v8 8);
    if ( 
v7 == __SourceHook_MFHCls_CPlayer_PlayerRunCmd::CMyDelegateImpl::Call )
    {
      
v7 = *(int (__cdecl **)(intintint))(v8 8);
      
v8 = *(_DWORD *)(v8 4) + *(_DWORD *)(v8 12);
      if ( (
unsigned __int8)v7 )
        
v7 = *(int (__cdecl **)(intintint))((char *)v7 + *(_DWORD *)v8 1);
    }
    
v7(v8a2a3);
    
v11 v10;
    if ( 
v10 v12 )
      
v12 v10;
  }
  return (*(
int (__cdecl **)(intint))(*(_DWORD *)g_SHPtr 80))(g_SHPtrv4);

Can somebody give me some advice what it could be?
There are some other hooks which I removed from the example: SetTransmit, OnTakeDamage, Weapon_Switch, Weapon_Equip. None of them crashes, but PlayerRunCmd couses crashes in all my extensions. And I don't see any difference.
I thought that it could be not removed CPlayer instance when the CBaseEntity of the attached player stops existing, but the tests show that CPlayer is always deleted before the attached entity is deleted. If I use GameFrame hook instead, then the crashes go away.
kadet.89 is offline
Send a message via Skype™ to kadet.89