Page 1 of 3 123 LastLast
Results 1 to 10 of 28

Thread: Pro tips for hooking up the function

  1. #1
    Private Whiskas's Avatar
    Join Date
    Jan 2015
    Posts
    84
    Thanks
    69
    Thanked 20 Times in 17 Posts

    Post Pro tips for hooking up the function

    I have an issue with seg faults. I would like to know more about the address where "magic" happens. The only way I know to learn something about my address is hooking it up in libcod and add some printfs to see what variables are there and how long function works until its death. To learn something about hooking up I checked few examples from libcod like these:

    http://pastebin.com/PNzExehb was hooked up as http://pastebin.com/4qbJNiYZ

    I was impressed that anyone could determine what address is "gentityaddress_to_num()". As I am newb at rewritting functions, I would like to ask you for any tips I should know before I start. Also I would be thankful if anyone could share the list (or database) of known functions (addresses).

    Thank you in advance

  2. #2
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,010
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    You don't need to let it crash, you can unhook a hooked function in itself, call itself, save the return value, rehook it and just return the saved value, so for the engine it's like nothing happened.

    Example from

    PHP Code:
    static int size_all 0;
    static 
    int i 0;
    cHook *hook_MSG_WriteBigString;
    void MSG_WriteBigString(int *MSGchar *s)
    {

        
    int len;

        
    len strlen(s);
        
    printf("i=%d size_all=%d len=%d MSG=%p %s\n"isize_alllenMSGs);

        
    size_all += len;
        
    i++;
        
        
    hook_MSG_WriteBigString->unhook();
        
        
    void (*sig)(int *MSGchar *s);
        *(
    int *)&sig 0x0806825E;
        
    sig(MSGs);
        
        
    hook_MSG_WriteBigString->hook();
        

    And instead of writing the hardcoded address (*(int *)&sig = 0x0806825E;), you can take the value of hook_MSG_WriteBigString->from.

    For finding stuff you want: e.g. at the start of libcod I wanted to find a script function ("closer" because it was easy to reimplement and I actually never used it) and I had no clue about anything, since cracking was totally new to me. I started with some C knowledge and WinHex, like this:

    At first I searched the plain string in WinHex: lets say it was at file offset 0x12345

    Then you go to that file address in IDA (some option in menu) and then IDA shows you the actual memory address of that file offset, lets say 0xaabbccdd is "closer". But the address wasn't linked anywhere, but it had to be linked somewhere I thought, so I searched the hex numbers of it in WinHex with no success, till I reversered them (0xddccbbaa), since x86 is using little-endianness. That way I found the actual table which hold the string->function address relations and I could slowly decompile all kind of glued C function to the script engine e.g.

    On the other hand you could just search an error string from anything in WinHex too and enter the file offset in IDA again. Since IDA has analyzed a lot from beginning, it can show all found function which point to the error message then.

    And don't forget all the GPL engines, RTCW, Quake 3 etc., which all have a lot of code in common.
    timescale 0.01

  3. The Following 3 Users Say Thank You to kung foo man For This Useful Post:

    maxdamage99 (3rd May 2016),serthy (19th August 2020),Whiskas (3rd May 2016)

  4. #3
    Corporal voron00's Avatar
    Join Date
    Nov 2014
    Posts
    248
    Thanks
    64
    Thanked 216 Times in 116 Posts
    I didn't fully understand the magic stuff and database thing but apparently you want to find what causes the segfault.

    When a program crashes it should generate a core dump file. For more or less modern systems it should be in /var/lib/systemd/coredump core.cod2_lnxded.1000.etc.

    Move this core dump to your home dir, if its compressed (lz4), unlz4 it (unlz4 filename.lz4), move the uncompressed core dump to your cod2_lnxded dir and start GDB like:
    PHP Code:
    gdb cod2_lnxded corefilename 
    You should see the crash now (if not, type 'bt'). The adress where it's crashed should be the toppest one. Search this adress in ida and it should point you the spot of the crash (proably will be inside of some sub).

    If you can't understand what exactly this function does you proably want to hook it.

    Hooking is quite easy, there are multiple ways to do it. Basicly you redirect this function, do some stuff e.g read it's params and call the original function. You can hook a function, function call or use a cHook class.

    For hooking a function, use the way kung posted above, for a function call there is alot of references in libcod.cpp just search cracking_hook_call but basicly it works like:

    PHP Code:
    cracking_hook_call(0x0812A3EC, (int)hook_test_func);


    void hook_test_func(int a1int a2) {

        
    printf("Test: %i, %i"a1a2);

        
    int (*Orig)(int a1int a2);
        *(
    int *)&Orig 0x0812A004// The real adress of a function you are trying to hook as a call

        
    Orig(a1a2);


    1. Hook the call
    2. Get stuff and do stuff
    3. Call the original

    You can find where the function e.g sub_812A004 is called by just searching it as text in IDA and you will find something like:

    PHP Code:
    .text:0812A3EC                 call    sub_812A004 
    Where 0812A3EC is the hook call adress.

    You don't have to call the original function if you are rewriting it as a reverse, for this you can also use cracking_hook_function but do NOT use craacking_hook_function if you are calling the original inside a hooked function. Reversing though can be a lot of pain in the arse. As kung said above you can look at q3 source to see some useful references.

    BTW: I had a segfaults with playFxOnTag() function, which was related to models without that tag in some way, also feel free to upload your coredump file, or share the code where that crash is so we can look for it aswell.
    Last edited by voron00; 4th May 2016 at 09:18.
    sudo apt-get rekt

  5. The Following User Says Thank You to voron00 For This Useful Post:

    Whiskas (6th May 2016)

  6. #4
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,010
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Quote Originally Posted by voron00 View Post

    Hooking is quite easy, there are multiple ways to do it. Basicly you redirect this function, do some stuff e.g read it's params and call the original function. You can hook a function, function call or use a cHook class (which can be more handy than usual cracking_hook_function, but does the same thing atm).
    Ye, but remember the "Original" function is still redirected, so when you call it without unhooking it, you are catched in a loop. Hence this little helper class:

    PHP Code:
    cHook::cHook(int fromint to) {
        
    this->from from;
        
    this->to to;
    }
    void cHook::hook() {
        
    memcpy((void *)oldCode, (void *)from5);
        
    cracking_hook_function(fromto);
    }
    void cHook::unhook() {
        
    memcpy((void *)from, (void *)oldCode5);

    It saves the first 5 bytes just to restore them later to call the original function.
    timescale 0.01

  7. The Following User Says Thank You to kung foo man For This Useful Post:

    Whiskas (6th May 2016)

  8. #5
    Private Whiskas's Avatar
    Join Date
    Jan 2015
    Posts
    84
    Thanks
    69
    Thanked 20 Times in 17 Posts
    My core dump looks like this:

    Code:
    Program terminated with signal SIGSEGV, Segmentation fault.
    #0  0x080e983d in ?? ()
    (gdb) bt
    #0  0x080e983d in ?? ()
    #1  0x0808f697 in ?? ()
    #2  0x0808fa6f in ?? ()
    #3  0x080943e1 in ?? ()
    #4  0x08061779 in ?? ()
    #5  0x08062451 in ?? ()
    #6  0x0806251d in ?? ()
    #7  0x080d2b22 in ?? ()
    #8  0xb73c5a83 in __libc_start_main (main=0x80d2990, argc=12, argv=0xbfc54ac4,
        init=0x8049b90, fini=0x8139b50, rtld_fini=0xb7760180 <_dl_fini>,
        stack_end=0xbfc54abc) at libc-start.c:287
    #9  0x0804a4d1 in ?? ()
    Address 0x080e983d belongs to this function:

    PHP Code:
    int __cdecl sub_80E97F0(int a1int a2)
    {
      
    int v3// [sp+Ch] [bp-Ch]@5
      
    char v4// [sp+17h] [bp-1h]@1

      
    v4 1;
      if ( !(
    unsigned __int8)sub_80E9758(a2) )
        
    v4 0;
      if ( !(
    unsigned __int8)sub_80D9E84(a1 1348a2) )
        
    v4 0;
      
    v3 sub_80E9270(a2);
      if ( !*(
    _DWORD *)(v3 132)
        && *(
    _BYTE *)(a1 1365) != a2
        
    && *(_BYTE *)(a1 1366) != a2
        
    && *(_DWORD *)(v3 876) != a2 )
      {
        
    v4 0;
      }
      return (
    unsigned __int8)v4;

    The problem seems to be in an IF statement as it's right after calling the sub_80E9270 function. Who knows, maybe this function doesn't return anything to v3 variable.

    Code:
    .text:080E9832                 call    sub_80E9270
    .text:080E9837                 mov     [ebp+var_C], eax
    .text:080E983A                 mov     eax, [ebp+var_C]
    .text:080E983D                 cmp     dword ptr [eax+84h], 0                  //HERE
    .text:080E9844                 jnz     short loc_80E987C
    .text:080E9846                 mov     eax, [ebp+var_C]
    .text:080E9849                 mov     eax, [eax+36Ch]
    If I want to hook up int __cdecl sub_80E97F0(int a1, int a2) function I should write in libcod address where the function begins?
    Code:
    .text:080E97F0 sub_80E97F0     proc near               ; CODE XREF: sub_808F510+182p
    Like this?:

    PHP Code:
    cracking_hook_call(0x080E97F0, (int)hook_my_Problem); 
    Then I just would like to know what params contain and v3 variable..

    PHP Code:
    int hook_my_Problem(int a1int a2)
    {
        
    printf("Param a1 == %i  Param a2 == %i  \n"a1a2);
        
    hook_my_Problem->unhook(); 

    How can I hook right after the call of sub_80E9270 to just print v3 variable?

    Something like this?

    PHP Code:
    int hook_my_Problem(int a1int a2)
    {
        
    printf("Param a1 == %i  Param a2 == %i  \n"a1a2);
        
    hook_my_Problem->unhook(); 
         
    int v3;
        
    void (*sig)(int a1itn a2); 
        *(
    int *)&sig 0x080E9832//the sub_80E9270 call
        
    sig(a1a2);

        
    hook_my_Problem->hook(); 
        
    v3 =  sub_80E9270(a2);
        
    printf("Param V3 == %i  \n"v3);

        
    hook_my_Problem->unhook(); 

    Btw. Should this function be void as it returns nothing? If so should I change aslo cracking_hook_call(0x080E97F0, (int)hook_my_Problem); to (viod)hook_my_Problem?

    Thanks for your help!
    Last edited by Whiskas; 4th May 2016 at 11:56.

  9. #6
    Corporal voron00's Avatar
    Join Date
    Nov 2014
    Posts
    248
    Thanks
    64
    Thanked 216 Times in 116 Posts
    Ok so the crash is in the BG_IsWeaponValid, which is (i guess ) related to weapons. You proably need to check them out. And this function is small so why not just revere it, going to be a piece of cake, here we go:

    PHP Code:
    cracking_hook_function(0x080E97F0, (int)hook_BG_IsWeaponValid);



    int hook_BG_IsWeaponValid(int a1int a2) {
        
        
    int v3;
        
    char v4;
        
        
    signed int (*sub_80E9758)(int a1);
        *(
    int *)&sub_80E9758 0x80E9758;
        
        
    int (*sub_80D9E84)(int a1signed int a2);
        *(
    int *)&sub_80D9E84 0x80D9E84;
        
        
    int (*sub_80E9270)(int a1);
        *(
    int *)&sub_80E9270 0x80E9270;

        
    v4 1;
        if ( !(
    unsigned int8_t)sub_80E9758(a2) )
            
    v4 0;
        if ( !(
    unsigned int8_t)sub_80D9E84(a1 1348a2) )
            
    v4 0;
        
    v3 sub_80E9270(a2);
        if ( !*(
    long *)(v3 132) && *(char *)(a1 1365) != a2 && *(char *)(a1 1366) != a2 && *(long *)(v3 876) != a2 )
            
    v4 0;
        
        
    // printf("Testcall\n");

        
    return (unsigned int8_t)v4;

    I have no idea why it segfaults though, and it's called from a SV_UserMove (possibly every player's frame). Try playing with this code, it could be that v3 e.g weapon + its somewhat parameter is broken or something.
    Last edited by voron00; 4th May 2016 at 13:01.
    sudo apt-get rekt

  10. The Following User Says Thank You to voron00 For This Useful Post:

    Whiskas (6th May 2016)

  11. #7
    Corporal voron00's Avatar
    Join Date
    Nov 2014
    Posts
    248
    Thanks
    64
    Thanked 216 Times in 116 Posts
    Also maybe put:
    PHP Code:
    printf("Last weapon used: %s\n", *(char**)(v3 0)); 
    To see which weapon has crashed the server (this would be the last message before the crash then). Have you tried reproducing it somehow? How does it happens anyway?
    sudo apt-get rekt

  12. The Following User Says Thank You to voron00 For This Useful Post:

    Whiskas (6th May 2016)

  13. #8
    Private Whiskas's Avatar
    Join Date
    Jan 2015
    Posts
    84
    Thanks
    69
    Thanked 20 Times in 17 Posts
    Quote Originally Posted by voron00 View Post
    PHP Code:
    int hook_BG_IsWeaponValid(int a1int a2) {
        
        
    int v3;
        
    char v4;
        
        
    signed int (*sub_80E9758)(int a1);
        *(
    int *)&sub_80E9758 0x80E9758;
        
        
    int (*sub_80D9E84)(int a1signed int a2);
        *(
    int *)&sub_80D9E84 0x80D9E84;
        
        
    int (*sub_80E9270)(int a1);
        *(
    int *)&sub_80E9270 0x80E9270;

        
    v4 1;
        if ( !(
    unsigned int8_t)sub_80E9758(a2) )
            
    v4 0;
        if ( !(
    unsigned int8_t)sub_80D9E84(a1 1348a2) )
            
    v4 0;
        
    v3 sub_80E9270(a2);
        if ( !*(
    long *)(v3 132) && *(char *)(a1 1365) != a2 && *(char *)(a1 1366) != a2 && *(long *)(v3 876) != a2 )
            
    v4 0;
        
        
    // printf("Testcall\n");

        
    return (unsigned int8_t)v4;

    Sooo for the short functions we can only change types of variables and it will work out anyway? Whoa.

    But where did it came from?

    PHP Code:
    signed int (*sub_80E9758)(int a1);
        *(
    int *)&sub_80E9758 0x80E9758;
        
        
    int (*sub_80D9E84)(int a1signed int a2);
        *(
    int *)&sub_80D9E84 0x80D9E84;
        
        
    int (*sub_80E9270)(int a1);
        *(
    int *)&sub_80E9270 0x80E9270
    My _weapons.gsc file is nothing special. I've only added function deleting machine guns and added precaching every rifle for every team. http://pastebin.com/yKg1RfBb

    I've added some prints to your hook function. It compiled properly (Thanks!). Just waiting for the server to become empty so I can implement new libcod.

  14. #9
    Private Whiskas's Avatar
    Join Date
    Jan 2015
    Posts
    84
    Thanks
    69
    Thanked 20 Times in 17 Posts
    Quote Originally Posted by voron00 View Post
    Also maybe put:
    PHP Code:
    printf("Last weapon used: %s\n", *(char**)(v3 0)); 
    To see which weapon has crashed the server (this would be the last message before the crash then). Have you tried reproducing it somehow? How does it happens anyway?
    Sorry as I was writting my last post there wasn't your second post.

    PHP Code:
    int hook_BG_IsWeaponValid(int a1int a2) {

        
    printf("hook_BG_IsWeaponValid -- Starting \n");
        
    printf("hook_BG_IsWeaponValid -- a1 == %i  a2 == %i \n"a1a2);
        
        
    int v3;
        
    char v4;
        
        
    signed int (*sub_80E9758)(int a1);
        *(
    int *)&sub_80E9758 0x80E9758;
        
        
    int (*sub_80D9E84)(int a1signed int a2);
        *(
    int *)&sub_80D9E84 0x80D9E84;
        
        
    int (*sub_80E9270)(int a1);
        *(
    int *)&sub_80E9270 0x80E9270;

        
    v4 1;
        if ( !(
    unsigned int8_t)sub_80E9758(a2) )
            
    v4 0;
        if ( !(
    unsigned int8_t)sub_80D9E84(a1 1348a2) )
            
    v4 0;
        
    v3 sub_80E9270(a2);
        
    printf("hook_BG_IsWeaponValid -- sub_80E9270(a2) = v3 == %i \n"v3);
        
    printf("hook_BG_IsWeaponValid -- Checking fi anything changed a1 == %i  a2 == %i \n"a1a2);
        if ( !*(
    long *)(v3 132) && *(char *)(a1 1365) != a2 && *(char *)(a1 1366) != a2 && *(long *)(v3 876) != a2 )
            
    v4 0;
        
        
    printf("Finished hook_BG_IsWeaponValid \n");

        return (
    unsigned int8_t)v4;

    Should I place your printf("Last weapon used: %s\n", *(char**)(v3 + 0)); right after v3 = sub_80E9270(a2); ? Why is it even a char? Mine prints are bad then?

    I wass trying to reproduce it by disconnecting the server with opened weapon menu, but no success. Seg fault is quite rare, about one per day, but I had none since 2 days now.

    There is nothing special when it happens.

    Code:
    ^9(GAME_AXIS)Lazlow B^7: QUICKMESSAGE_SORRY
    ^9(GAME_AXIS)Lazlow B^7: QUICKMESSAGE_SORRY
    Client 50 connecting with 100 challenge ping from 41.227.135.167:11431
    Going from CS_FREE to CS_CONNECTED for  (num 0 guid 0)
    ^9(GAME_AXIS)Lazlow B^7: QUICKMESSAGE_SORRY
    ^9(GAME_DEAD)Ndrecke24^7: SORRY JB
    ^9(GAME_AXIS)Lazlow B^7: QUICKMESSAGE_SORRY
    Segmentation fault (core dumped)
    Code:
    Client 11 connecting with 150 challenge ping from 39.32.79.134:28960
    Going from CS_FREE to CS_CONNECTED for  (num 2 guid 0)
    0: EXE_DISCONNECTED
    clientDownload: 2 : begining "whiskys.lair2/zzz_rifle_only.iwd"
    clientDownload: 2 : file "whiskys.lair2/zzz_rifle_only.iwd" completed
    clientDownload: 2 : begining "whiskys.lair2/zzz_modz.iwd"
    clientDownload: 2 : file "whiskys.lair2/zzz_modz.iwd" completed
    Client 12 connecting with 150 challenge ping from 41.111.108.187:15369
    Going from CS_FREE to CS_CONNECTED for  (num 0 guid 0)
    Segmentation fault (core dumped)

  15. #10
    Corporal voron00's Avatar
    Join Date
    Nov 2014
    Posts
    248
    Thanks
    64
    Thanked 216 Times in 116 Posts
    The prints are ok but you wont get any useful info from that as it will return the same integer its char becasue that will return the name of weapon e.g m1garand_mp, and ye it must be right after v3 = sub_80E9270(a2);
    sudo apt-get rekt

  16. The Following User Says Thank You to voron00 For This Useful Post:

    Whiskas (6th May 2016)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •