lørdag den 16. juni 2012

CSGO: Chickens

 Shooting chickens is loads of fun in CSGO so I decided to code some stuff for it;
Chickens have 28 hitboxes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
enum EChickenHitboxes
{
 HITBOX_CHICKEN_PELVIS,
 HITBOX_CHICKEN_LEFTKNEE,
 HITBOX_CHICKEN_LEFTANKLE,
 HITBOX_CHICKEN_LEFTBACKTOE,
 HITBOX_CHICKEN_LEFTTOE,
 HITBOX_CHICKEN_RIGHTKNEE,
 HITBOX_CHICKEN_RIGHTANKLE,
 HITBOX_CHICKEN_RIGHTBACKTOE,
 HITBOX_CHICKEN_RIGHTTOE,
 HITBOX_CHICKEN_TAIL,
 HITBOX_CHICKEN_TAIL1,
 HITBOX_CHICKEN_TAIL2,
 HITBOX_CHICKEN_CLAVICAL, // gg misspell valve?
 HITBOX_CHICKEN_RIGHTBREAST,
 HITBOX_CHICKEN_RIGHTSHOULDER,
 HITBOX_CHICKEN_RIGHTELBOW,
 HITBOX_CHICKEN_RIGHTWRIST,
 HITBOX_CHICKEN_RIGHTTIP,
 HITBOX_CHICKEN_LEFTBREAST,
 HITBOX_CHICKEN_LEFTSHOULDER,
 HITBOX_CHICKEN_LEFTELBOW,
 HITBOX_CHICKEN_LEFTWRIST,
 HITBOX_CHICKEN_LEFTTIP,
 HITBOX_CHICKEN_NECK1,
 HITBOX_CHICKEN_NECK2,
 HITBOX_CHICKEN_NECK3,
 HITBOX_CHICKEN_HEAD,
 HITBOX_CHICKEN_WOBBLER
};

The chickens all have the clientclass CDynamicProp, and you can check wether it's a chicken or not by checking model name; Ex:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 bool CEntity::IsChicken( void )
{
 const model_t *model = GetModel();
 
 if ( !model )
 {
  LOG_ERROR( "model_t was 0" );
  return false;
 }
 
 
 studiohdr_t *studioHeader = g_InterfaceManager->ModelInfo()->GetVTable<IVModelInfo>()->GetStudiomodel( model );
 
 if ( !studioHeader )
 {
  LOG_ERROR( "studiohdr_t was 0" );
  return false;
 }
 
 
 return strstr( studioHeader->name, "chicken" );
}
  The pelvis hitbox is very big, almost like a bounding box tbh. and the height of the chickens hull is ~23;

A video of the result:

torsdag den 14. juni 2012

Networked Variables in the Source engine

I needed a way to hook networked props/get offsets simply in the source engine, so I implemented ghetto's/altimor's recursive solution in my netvars class.

 netvars.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#pragma once
 
 
#include "main.h"
 
 
class CNetworkedVariableManager
{
public:
 
    // stores all tables, and all props inside those
    CNetworkedVariableManager( void );
 
 
    // calls GetProp wrapper to get the absolute offset of the prop
    int GetOffset( const char *tableName, const char *propName );
 
 
    // calls GetProp wrapper to get prop and sets the proxy of the prop
    bool HookProp( const char *tableName, const char *propName, RecvVarProxyFn function );
 
 
private:
 
    // wrapper so we can use recursion without too much performance loss
    int GetProp( const char *tableName, const char *propName, RecvProp **prop = 0 );
 
 
    // uses recursion to return a the relative offset to the given prop and sets the prop param
    int GetProp( RecvTable *recvTable, const char *propName, RecvProp **prop = 0 );
 
 
    RecvTable *GetTable( const char *tableName );
 
 
    std::vector<RecvTable*>    m_tables;
};
 
 
extern CNetworkedVariableManager *g_NetworkedVariableManager;

netvars.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "main.h"
 
 
CNetworkedVariableManager *g_NetworkedVariableManager = 0;
 
 
CNetworkedVariableManager::CNetworkedVariableManager( void )
{
    m_tables.clear();
 
 
    ClientClass *clientClass = g_InterfaceManager->Client()->GetOriginalMethod<GetAllClasses_t>( INDEX_GETALLCLASSES )( g_InterfaceManager->Client()->thisptr() );
 
    if ( !clientClass )
    {
        LOG_ERROR( "ClientClass was not found" );
        return;
    }
 
 
    while ( clientClass )
    {
        RecvTable *recvTable = clientClass->m_pRecvTable;
 
 
        m_tables.push_back( recvTable );
 
 
        clientClass = clientClass->m_pNext;
    }
}
 
 
// calls GetProp wrapper to get the absolute offset of the prop
int CNetworkedVariableManager::GetOffset( const char *tableName, const char *propName )
{
    int offset = GetProp( tableName, propName );
 
    if ( !offset )
    {
        LOG_ERROR( "Failed to find offset for prop: %s from table: %s", propName, tableName );
        return 0;
    }
 
 
    return offset;
}
 
 
// calls GetProp wrapper to get prop and sets the proxy of the prop
bool CNetworkedVariableManager::HookProp( const char *tableName, const char *propName, RecvVarProxyFn function )
{
    RecvProp *recvProp = 0;
    GetProp( tableName, propName, &recvProp );
 
 
    if ( !recvProp )
    {
        LOG_ERROR( "Failed to hook prop: %s from table: %s", propName, tableName );
        return false;
    }
 
 
    recvProp->m_ProxyFn = function;
 
    return true;
}
 
 
// wrapper so we can use recursion without too much performance loss
int CNetworkedVariableManager::GetProp( const char *tableName, const char *propName, RecvProp **prop )
{
    RecvTable *recvTable = GetTable( tableName );
 
    if ( !recvTable )
    {
        LOG_ERROR( "Failed to find table: %s", tableName );
        return 0;
    }
 
 
    int offset = GetProp( recvTable, propName, prop );
 
    if ( !offset )
    {
        LOG_ERROR( "Failed to find prop: %s from table: %s", propName, tableName );
        return 0;
    }
 
 
    return offset;
}
 
 
// uses recursion to return a the relative offset to the given prop and sets the prop param
int CNetworkedVariableManager::GetProp( RecvTable *recvTable, const char *propName, RecvProp **prop )
{
    int extraOffset = 0;
 
    for ( int i = 0; i < recvTable->m_nProps; ++i )
    {
        RecvProp *recvProp = &recvTable->m_pProps[i];
 
 
        RecvTable *child = recvProp->m_pDataTable;
 
        if ( child
            && ( child->m_nProps > 0 ) )
        {
            int tmp = GetProp( child, propName, prop );
 
            if ( tmp )
            {
                extraOffset += ( recvProp->m_Offset + tmp );
            }
        }
 
 
        if ( stricmp( recvProp->m_pVarName, propName ) )
        {
            continue;
        }
 
 
        if ( prop )
        {
            *prop = recvProp;
        }
 
        return ( recvProp->m_Offset + extraOffset );
    }
 
    return extraOffset;
}
 
 
RecvTable *CNetworkedVariableManager::GetTable( const char *tableName )
{
    if ( m_tables.empty() )
    {
        LOG_ERROR( "Failed to find table: %s (m_tables is empty)", tableName );
        return 0;
    }
 
 
    for each ( RecvTable *table in m_tables )
    {
        if ( !table )
        {
            continue;
        }
 
 
        if ( stricmp( table->m_pNetTableName, tableName ) == 0 )
        {
            return table;
        }
    }
 
    return 0;
}

example usages:
1
2
3
4
5
// we need to construct this manually
g_NetworkedVariableManager = new CNetworkedVariableManager();
 
// hook netvar proxy
g_NetworkedVariableManager->HookProp( "DT_CSPlayer", "m_angEyeAngles[0]", CSPlayer_EyeAnglesX );
1
2
3
4
5
Vector CPlayer::GetViewOffset( void )
{
 static int offset = g_NetworkedVariableManager->GetOffset( "DT_BasePlayer", "m_vecViewOffset[0]" );
 return *Member<Vector*>( this, offset );
}

lørdag den 9. juni 2012

CTraceFilterSkipTwoEntities

[I WON'T GO INTO DETAILS WITH THIS]
This isn't anything special, but since there always seems to be alot of drama going on when there has been an update, I figured I'll post some code here and simple instructions on how to find it. If you will be using Olly, you need the SigMaker plugin, by p47r!ck: Sig Maker 0.4


This tracefilter(CTraceFilterSkipTwoEntities) which is used in peoples tracing code, can be found alot of places, but my preferred location is inside the CSPlayer::FireBullet function, which contains a neat little string which we can follow: "gunshotsplash".
The call to CTraceFilterSkipTwoEntities's constructor is almost at the top of the function and should look something like this(raw copy paste from Olly):

54227F7C   6A 00            PUSH 0
54227F7E   57               PUSH EDI
54227F7F   56               PUSH ESI
54227F80   8D8D 9CFDFFFF    LEA ECX,DWORD PTR SS:[EBP-264]
54227F86   E8 E54BFCFF      CALL client.541ECB70
Just follow that call and make a signature/get the relative offset for it. Please note that this is achievable in IDA aswell, but Olly is my preferred tool.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
void Aimbot::GetTraceFilterSkipTwoEntities( CSPlayer *first, CSPlayer *second, DWORD* thisptr )
{
 typedef void ( __thiscall *TraceFilterSkipTwoEntities_t )( void *thisptr, const CSPlayer *first, const CSPlayer *second, int group );
 static TraceFilterSkipTwoEntities_t traceFilterskiptwoentities = (TraceFilterSkipTwoEntities_t)memory::FindPattern( GetModuleHandle( "client.dll" ), "\x55\x8B\xEC\x8B\x55\x10\x8B\xC1\x8B\x4D\x08\x89\x48\x04\x8B\x4D\x0C\x89\x50\x08\xC7\x40" );
 
 if ( !traceFilterskiptwoentities )
 {
  LOG_ERROR( "TraceFilterSkipTwoEntities not found" );
 }
 
 
 traceFilterskiptwoentities( thisptr, first, second, 0 );
}
ex. usage: 
1
2
3
DWORD traceFilter[5]; // 20 or 0x14 bytes
GetTraceFilterSkipTwoEntities( m_localPlayer, skipPlayer, traceFilter );
TraceRay( ray, 0x4600400B, (ITraceFilter*)&traceFilter, &traceData );