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

The art of signature scanning


  
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Author Message
TheAvenger
Junior Member
Join Date: May 2012
Old 05-01-2012 , 16:30   The art of signature scanning
Reply With Quote #1

Hi!

I just joined this community, and even though it might not seem as the most
appropriate one (I'm only doing metamod extensions, which aren't related to amxx),
but I won't deny that it is flourishing (considering GoldSrc's age of 14 years)
and this seemed as the best place to find help.

I've noticed that signature scanning is highly appreciated since it is the most efficient
and dynamic way to get full access of the modifications that GoldSrc has to offer.

In my specific case, I'm trying to learn signature scanning to be used in my
Counter-Strike extension. Right now I do not have any specific goal nor does
my extension have a purpose, but I do want to master (or at least learn) the
art of signature scanning (I hate explicit offsets ).

Right now I'm testing signature scanning with the "StartDeathCam__11CBasePlayer" call,
which obviously is: void CBasePlayer::StartDeathCam(void) from player.h@Ln:1349.

I'm using the well spread method that is documented on the alliedmodders wiki.

The problem I am experiencing is simple, yet I have not been able to solve it. I do
my signature call (Note: I'm on linux so there's no interest for Windows atm) to find
the address of the "StartDeathCam" method.

After I've found out the position I create a pointer to the address (void (*StartDeathCam) (void*),
where as void* is a CBasePlayer pointer) which I then call in-game by user command (i.e 'say .test').

As mentioned here, I am calling this method by simple specifying a pvPrivateData
pointer as the void* (CBasePlayer*) since the 'this' pointer is the first one to be
pushed onto the stack under GCC.

This casues an instant crash (note: I've tried to use the command under several circumstances,
such as: dead, alive, round end, freezetime etc...) with no recovery, and this is where I am stuck.

This is the code that I am using (sigscanner.h):
PHP Code:
#ifndef SIGSCANNER_H
#define SIGSCANNER_H

// Include files
#include <extdll.h>
#include "global.h" // Just contains type defines such-as unsigned char = byte etc...

class SigScanner
{
public:
    
// Constructor
    
SigScanner(void);
    
    
// Public functions
    
bool Init(void pAddr);                        // Initialize signature scanner
    
void FindSignature(byte pSignaturesize_t sigLength);    // Finds a specified signature
    
private:
    
// Private variables
    
byte m_baseAddr;        // Base address to memory
    
size_t m_baseLength;        // Our base address length
};

#endif 
And this is the sigscanner implementation:
PHP Code:
// Header files
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>

// Our class header
#include "sigscanner.h"

SigScanner::SigScanner(void)
{
    
// Just reset variables
    
m_baseAddr null;
    
m_baseLength 0;
}

bool SigScanner::Init(void pAddr)
{
    
// Setup variables
    
Dl_info info;
    
struct stat buffer;
    
    
// Load our address
    
if(!dladdr(pAddr, &info))
        return 
false;
    
    if(!
info.dli_fbase || !info.dli_fname)
        return 
false;
    
    if(
stat(info.dli_fname, &buffer) != 0)
        return 
false;
    
    
// Success, setup variables
    
m_baseAddr = (byte*) info.dli_fbase;
    
m_baseLength buffer.st_size;
    
    
// Return...
    
return true;
}

void SigScanner::FindSignature(byte pSignaturesize_t sigLength)
{
    
// Setup our memory pointers
    
byte pBasePtr m_baseAddr;
    
byte pEndPtr m_baseAddr m_baseLength /* 0x100000 <-- Should this be used instead? */;
    
    
size_t i;
    
    
// Start searching memory
    
while(pBasePtr pEndPtr)
    {
        for(
0sigLengthi++)
        {
            if(
pSignature[i] != 0x2A && pSignature[i] != pBasePtr[i])
                    break;
        }
        
        
// Check for a match
        
if(== sigLength/* + 1 */)
        {
            
// Return our match
            
return (void*) pBasePtr;
        }
        
        
// Search memory in an aligned manner
        
pBasePtr += sizeof(byte*);
    }
    
    
// No success...
    
return (void*) null;

And this is how I use the sig-scanner implementation (read comments):
PHP Code:
// Global function pointer and type define
typedef void (*StartDeathCam)(void *);
StartDeathCam gRS null;

void Game::EventServerActivatePost(edict_t pEntListint /*edictCount*/int clientMax)
{
    
// Initializing some stuff first
    // ...

    // Here, I initialize my signature scanner (and specifies AddToFullPack as start address)
    
if(m_sigScanner.Init((void*) MDLL_AddToFullPack))
    {
        
// This is the Linux signature for StartDeathCam method
        
char signature[] = "StartDeathCam__11CBasePlayer";

        
// And this is where I am fetching the function pointer (note: it is valid, i.e the logs outputs success)
        
StartDeathCam gRS = (StartDeathCamm_sigScanner.FindSignature((byte*) signaturestrlen(signature));
        
        if(
gRS != null)
        {
            
m_debug->Log("We have found our signature!");
        }
        
        else 
m_debug->Log("Failed to find signature.");
    } else 
m_debug->Log("Failed to initialize SigScanner.");
}

void Game::EventClientCommand(edict_t pEnt)
{
    
// Sorting out all invalid objects and verifying commands
    // ....

    
if(strcmp(command".test") != 0)
        
Meta::Return(Meta::Ignored);

    
// This is where I am calling the function,
    // but it results in a server crash...
    
(gRS)(pEnt->pvPrivateData);

    
// Return as ignored...
    
Meta::Return(Meta::Ignored);

I'm sorry for the wall of code, but C++ code easily gets extensive.

I am also aware of the popular Orpheu module which uses signature
scanning, but it consists of _so_ much code that it is hardly extinguishable
from the rest (of the incurious code).

I do not know if I am to be expecting a reply since I presented everything
kinda sloppy, but I would appreciate any help/assistance that is offered!

EDIT: In case of interest I'm using g++ 4.6.3 @ Ubuntu 12.04 i386

Last edited by TheAvenger; 05-01-2012 at 16:35.
TheAvenger is offline
 



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 16:47.


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