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:

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:
 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:
#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:
#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:
// we need to construct this manually
g_NetworkedVariableManager = new CNetworkedVariableManager();

// hook netvar proxy
g_NetworkedVariableManager->HookProp( "DT_CSPlayer", "m_angEyeAngles[0]", CSPlayer_EyeAnglesX );
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.
 
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: 
DWORD traceFilter[5]; // 20 or 0x14 bytes
GetTraceFilterSkipTwoEntities( m_localPlayer, skipPlayer, traceFilter );
TraceRay( ray, 0x4600400B, (ITraceFilter*)&traceFilter, &traceData );