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

Module: Okapi


  
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
Author Message
joaquimandrade
Veteran Member
Join Date: Dec 2008
Location: Portugal
Old 02-07-2014 , 02:51   Module: Okapi
Reply With Quote #1

Hello. I've spent the last weeks working a new module built around a new idea to avoid using signatures.
I've also took the chance to add it features based on the experience with the making of orpheu.
So this module should be more funnier to use but more powerful than orpheu.

The new idea, is about to identify a function, in an easy manner, hopefully resistant to game updates.
It consists on the following notions:

Half-Life functions are an interconnected tree around a core of engine and dll functions.
Each function has a great chance of being connected to the core functions, and for each connection,
there is a minimal length path between the points.
The idea is to identify a function, based on a group of minimal path length between that function and the core functions.
The tree is built with simple parsing of the assembly call instructions (for example, indirect calls are not parsed)
in the libraries, but the results are solid, from my testing. Trees vary a great deal between mod's and operative systems but
for the main purpose of providing a way of identifying a function in a manner resistant to game updates, they seem quite ok.

So let's see an example. Remember that the purpose of this kind of identifier is to resist to game updates, so I will use and old version
of half life dedicated server, against the latest version. This is to see if identifiers for one of them, find the same function on the other and vice-versa.
I don't know if there is a legal way of testing this for an old cs server, but if you know I would like you to tell me.

I had to pick a name for this identifier and I chose "treemap". From now on I will use this name to refer to them.

hlds versions used:
Code:
Protocol version 46, Exe version 4.1.1.1, Exe build: 10:25:33 Apr 30 2003 (2379)
Protocol version 48, Exe version 1.1.2.2 (valve), Exe build: 13:13:29 Aug 29 2013 (6153)
Now I will take a "random" function and use it to exemplify how treemaps work.

This is a function present in the engine library of the old HLDS server:



Below, it has this portion that will make easy to identify it, in the other HLDS, to verify that we are dealing with the same function.





The first step now is to get it's treemap. This is done executing in the console the command:

Code:
okapi desc 0x550F0


This part:

Code:
Map values {4,4,4,4,4,5,5,4,4,5,6,4,6,6,4,4,4,4,4,5,4,0,4,2,4,6,5,5,5,3,4,5,5,5,5,5,4,3,5,4,0,4,5,5,5,6,3,3,3,3,3,3,3,3,3,3,0,6,5,5,5,3,4,5,0,4,0,6,0,0,0,3,4,0,4,0,0,4,4,4,4,4,5,4,4,4,4,4,0,4,4,4,4,5,4,4,4,4,6,5,0,4,4,4,4,0,4,6,3,5,5,5,4,0,4,5,5,0,5,4,4,4,4,4,4,4,0,5,5,5,0,4,4,0,0,0,0,5,4,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0}
is the group of minimal distances that our function 0x550F0, takes to each of engine library core functions.

This:

Code:
"jp='.BU*&.B8u{.N#,#.Q'Z$.z=F'.uYU{.#dJ$. 2I$.T\F'.-)V{.Mp/$.RXS{.00}&.;WU{.!eu{.u~V{.UP_(.c:B.+5 &. 8u{.7,V{.*+w&.j+w&...&~3"
It's the same information, compressed in a string. That is what we will use in plugins.
This string is what I refer to as "treemap".

Now, we will use try to use it as identifier to search it in the new hlds.

Code:
okapi search "jp='.BU*&.B8u{.N#,#.Q'Z$.z=F'.uYU{.#dJ$. 2I$.T\F'.-)V{.Mp/$.RXS{.00}&.;WU{.!eu{.u~V{.UP_(.c:B.+5 &. 8u{.7,V{.*+w&.j+w&...&~3"


In this image we can see a order list of the function that best match the given treemap.
The wanted case is that the first one is the same function in this hlds version as 0x550F0 is in the old one.

We can verify that it is the case in IDA:





Now we can do the inverse:




Now I will exemplify the use of a treemap in CS, with the InstallGameRules functions.
This would be the code to use the treemap, and create and hook the function.

PHP Code:
public OnInstallGameRules()
{
         new 
obj okapi_get_orig_return()
}

public 
plugin_precache()
{
             new 
install_gamerules_ptr okapi_mod_get_symbol_ptr("_Z16InstallGameRulesv"
    
              if(!
install_gamerules_ptr)
                           
install_gamerules_ptr okapi_get_treemap_ptr("[TG.;nC'.pbG.sXQ.J=g(.;OS'.ueA.1/.*K}.`/F'. 8u{.s9s{.Ohi(.,lm{.s9s{.2/#&.*0J.lE>'.1`}&.-]}&.vMa(.zp='.<cN'.=j12")
     
              new 
okapi_func:install_game_rules okapi_build_function(install_gamerules_ptr,arg_int)
     
              
okapi_add_hook(install_game_rules,"OnInstallGameRules",1)

Note that calls to okapi_get_treemap_ptr can take like 1 to 2 seconds, because many calculations are involved but, the results are then cached so
it just takes that time when the server is put on.

I will extend the talk about treemaps on a later ocasion.

Now, to show more of the module, I will continue from the previous code to show how to generically hook virtual functions.

PHP Code:
public OnAllowFlashlight()
{
             
okapi_set_return(1)
             return 
okapi_ret_supercede
}

public 
OnInstallGameRules()
{
             new 
obj okapi_get_orig_return()
    
             new 
okapi_func:allow_flashlight okapi_build_vfunc_ptr(obj,3,arg_int)
    
             
okapi_add_hook(allow_flashlight,"OnAllowFlashlight")

Note that 3 is the offset of the function CHalfLifeMultiplay::FAllowFlashlight in the CHalfLifeMultiplay vtable.

The module supports also searching for signatures with the functions

PHP Code:
okapi_mod_find_sig(const sig[],count)
okapi_engine_find_sig(const sig[],count
You can read about those functions and many others in the includes. Everything is sufficiently documented and I believe it's easy to use.

The signatures should look like this:

Code:
{0x51,0x56,"𐌻","𐌻",0x8B,0x86}
{0x51,0x56,0xDEF,0xDEF,0x8B,0x86}
using the symbol "𐌻", or any value above 0xFF, means that the particular bit is to be skipped from comparisons.

You can hook any function that uses a combination of these types:

PHP Code:
enum okapi_arg
{
             
arg_void,
             
arg_int,
             
arg_cbase,
             
arg_float,
             
arg_vec,
             
arg_entvars,
             
arg_string,
             
arg_edict,
             
arg_vec_ptr

that represent: int,CBaseEntity*,float,Vector,entvars_s*,char *,edict_t*,Vector*

The only exceptions is that when the function return a Vector. That is because when the function returns a Vector, a pointer is passed
in the beginning of the stack, so to handle that situation I would have to make a messy code so I prefered to ignore it.
Still, if you really need to hook or use a function that returns a Vector, it can be made with some lines of code using some tricks.

use "int" for long or for any value that you want to ignore.

Other thing present in the module are natives to handle memory directly.
You can use them to change any value in memory and for example to use structures not exposed via an API like playermove_s.

Example of replacing a string that was painful to do with orpheu, now takes one line:

PHP Code:
public plugin_init()
{
             
okapi_engine_replace_string("#      name userid uniqueid frag time ping loss adr^n","stuff^n")

This will change the max value of money a player can hold (note that this is probably not safe to use since there can be values replaced not related to the money)

PHP Code:
public plugin_init()
{
             
okapi_mod_replace_int(16000,1337000)

The module ended up a little big so I will show more stuff about it later.

Notes:

I tested the module alone since I wanted to make it a surprise so I expect it to need some enhancements or have some bugs.
When you use signatures to use functions, after you attach the module to a function, it modifies the bytes of the functions.
That means that if you use the same signature twice, the second will fail. This means that if you use the same signature in two
plugins, it will fail in one. To avoid this you can as an example, just to signature search in plugin_precache and hooking in plugin_init.

Again, I invite you to check the include files, I'm sure you will find there information that you will put to good use.
Also check the server console commands available, within the command okapi.




Attached Files
File Type: zip okapi_bin.zip (168.1 KB, 3792 views)
File Type: zip okapi_src.zip (116.6 KB, 1589 views)
__________________
joaquimandrade 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 02:13.


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