View Single Post
Author Message
API
Veteran Member
Join Date: May 2006
Old 04-12-2007 , 20:09   [EXTENSION] Signature Scan Extension with example
Reply With Quote #1

Hey guys,

For those of you that do not know what signature scanning is, please reference the following: http://wiki.alliedmods.net/Signature_Scanning

Quote:
Sigscanning is a multi-step process involving extracting function signatures from a binary and then scanning for them at run-time to locate an otherwise-hidden function. A signature for a function is a set of bytes unique to a function. These bytes are the instructions a program uses to operate. These sets of bytes are what make up functions (or subroutines as they are called in Assembly). When we have enough of these bytes to form a unique set, we can then match them again to the function in memory.

Why is this useful for plugins? Each time Valve releases an update for their mods, they may change classes such as CBaseEntity used by many plugin coders to interact with a player’s entity. Due to the fact that we do not have the appropriate class headers for each of these changes, we may be using virtual functions that now exist at different addresses. This would cause a crash at run-time. To avoid this, the following solutions are available:

* rely on manual offsets into the class' vtable
* modify the provided class headers by inserting dummy virtual functions to fix the offsets
* sigscanning

Each have their pros and cons, but it turns out that although sigscanning is the most tedious out of the three, it is the most reliable. The first two choices are typically broken by updates.
So, how does this benefit a SourceMod coder? Simple, you can call functions from the server dll such as CBaseAnimating::Ignite, and watch people burn! Obviously there is a lot more than you can do. Like I said, reference the above link for help with practical usage.

Credit
Thanks to everyone in IRC, especially BAILOPAN, cybermind, and sawce

Installation
1. Extract 'sigoffset.ext.dll' and 'sigoffset.ext.so' to the 'addons/sourcemod/extensions' folder.
2. Extract 'sigoffset.inc' to the 'addons/sourcemod/scripting/include' folder.

Functions
There are 4 functions that you can use in your plugins.
First is SignatureScanFind.
Quote:
/**
* Scans for a function in the memory and returns an index used to call it
*
* @param functionname The name of the function (E.G. CBaseAnimating::Ignite)
* @param address Signature address to scan for
* @param mask Signature mask
* @param len Length of the signature in bytes
* @param linuxaddress The linux symbol name used for the function
* @return Index for calling, -1 means a failure in the scan
*/
native SignatureScanFind(const String:functionname[], const String:address[], const String:mask[], len, const String:linuxaddress[]);
This function basically scans for the function and returns the index that you can use to call it, for more information on the parameters, reference the link above.

Next, SignatureScanCall.
Quote:
/**
* Call a previously scanned function using the returned index from SignatureScanFind
*
* @param functionindex What SignatureScanFind spat out at you
* @param playerindex The playerindex associated with the function
* @param functiontype The classtype for function, see SigFuncType
* @param[x] argtype Datatype of argument, see SigEnum
* @param[y] arg Argument for function
* The last to arguments (argtype and arg) repeat for how many arguments the function actually requires
* If you want to use cbase stuff, provide the type and an ent index
* @return If there was a failure in the function, it will return -1, otherwise, 1
*/
native SignatureScanCall(functionindex, playerindex, functiontype, any:...);
This function calls the function you have previously scanned for, using the function index you stored before.

And last, SignatureScanCall_NoIndex:
Quote:
/**
* Call a previously scanned function using the returned index from SignatureScanFind, but without an index for a specific entity
*
* @param functionindex What SignatureScanFind spat out at you
* @param[x] argtype Datatype of argument, see SigEnum
* @param[y] arg Argument for function
* The last to arguments (argtype and arg) repeat for how many arguments the function actually requires
* If you want to use cbase stuff, provide the type and an ent index
* @return If there was a failure in the function, it will return -1, otherwise, 1
*/
native SignatureScanCall_NoIndex(functionindex,any:. ..);
Allows you to call a signature function that doesn't use an index for entity, example would be UTIL_SetModel.

Quote:
native SignatureScan_HandleToIndex(Handle:hand);
With a handle return value from calling a signature scanned function, it will return the entity index.

Here is a small example on usage of the functions.
This function is called on plugin init.
Code:
ignite_index=SignatureScanFind("CBaseAnimating::Ignite","\x56\x8B\xF1\x8B\x86\xBC\x00\x00\x00\xC1\xE8\x1B\xA8\x01\x0F\x85\x9A\x00\x00\x00\x8B\x16\xFF\x92\xF0\x00\x00\x00\x80\x7C\x24\x0C\x00\x74\x08\x84\xC0\x0F\x84\x83\x00\x00\x00\x3C\x01\x75\x20\x80\x7C\x24\x14\x00\x75\x19\x8B\xCE\xE8\x83\x1A\x01\x00\x85\xC0\x74\x0E\x8B\x10\x8B\xC8\xFF\x92\x08\x05\x00\x00\x84\xC0\x74\x5F\x57\x6A\x01\x56\xE8\x48\xEA\x07\x00\x8B\xF8\x83\xC4\x08\x85\xFF\x74\x3D\x8B\x44\x24\x0C\x50\x8B\xCF\xE8\x83\xE5\x07\x00\x68\x00\x00\x00\x08\x8B\xCE","xxx?????????????????xxx????????????xx??????xx??xxxxx??xxx????????xxxxx?????xx??xxxxx????xxxxxxx??xxxxxxxx????xxxxxxx",116,"_ZN14CBaseAnimating6IgniteEfbfb");
If the example above has any spaces, they are not supposed to be there, I think it is a forum problem.

Next, this is called where ever wanted.
Code:
SignatureScanCall(ignite_index,player_index,SIGTYPE_CBASEANIMATING,PARAM_FLOAT,20.0,PARAM_INT,0,PARAM_FLOAT,10.0,PARAM_INT,0);
There is a 13 param limit for Call and 15 param limit for Call_NoIndex.
Have fun.

Also, I have updated the source code.
Attached Files
File Type: zip sigoffset_handletoindex.zip (242.2 KB, 1647 views)
File Type: zip sigoffset_src_june132007.zip (18.8 KB, 1005 views)

Last edited by API; 06-13-2007 at 22:08. Reason: added HandleToIndex and cleaned code a bit
API is offline
Send a message via AIM to API