reversing the return address check in 2.5.4.42940 menu

User Tag List

Results 1 to 2 of 2
  1. #1
    thateuler's Avatar Member
    Reputation
    8
    Join Date
    May 2019
    Posts
    29
    Thanks G/R
    22/7
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    reversing the return address check in 2.5.4.42940

    here's a cleanish c implementation that is easier to understand.

    the return address check starts at 0x1422BAE10 (base 0x140000000)


    Code:
    /*
      - TBC 2.5.4.42940
      - imagebase is 0x140000000
      - returns:
        1:  if the arg is a valid return address
        0:  if not
     */
    
    int
    check_retaddr(uint8_t *ret)
    {
            uint8_t *mem = 0;
    
            /* check 1. return address is inside .text */
            if (ret < (uint8_t*)0x14001000 || ret > (uint8_t*)0x142400B75)
                    return 0;
    
            /* check 2. invoked from a call.  rop check? */
            /* patterns: 0xe8, 0xff 0x1x, 0xff 0x5x, 0xff 0x9x, 0xff 0xdx */
            int iscall = 0; 
            uint64_t reti = (uint64_t)ret;
    
            if (mem[reti-5] == 0xe8) // call off4
                    iscall = 1;
            if (mem[reti-6] == 0xff && (((mem[reti-5] & 0x38) - 16 ) & 0xf7) == 0) // call [reg + off4]
                    iscall = 1;
            if (mem[reti-3] == 0xff && (((mem[reti-2] & 0x38) - 16 ) & 0xf7) == 0) // call [reg + off1]
                    iscall = 1;
            if (mem[reti-2] == 0xff && (((mem[reti-1] & 0x38) - 16 ) & 0xf7) == 0) // call reg, call [reg]
                    iscall = 1;
    
            if (! iscall)
                    return 0;
    
    
            /* check 3. the return address is on the good list */
    
            /* step 1. get the array of good return addresses */
            uint32_t *rettab = (void*)0x01400BBC84;
            uint64_t ret_offset = (uint64_t)ret - 0x140000000;
            uint32_t array_offset = rettab[ret_offset / 0x4000];
            if (array_offset == 0)
                    return 0;
    
            /* step 2. traverse the array. check if this address is listed */
            uint32_t *pgoodaddr = (uint32_t *)&rettab[array_offset/4];
            while (*pgoodaddr > 0) { 
                    if ( (*pgoodaddr - ret_offset) <= 64)
                            return 1;
                    pgoodaddr++;
            }
    
            return 0;
    }

    reversing the return address check in 2.5.4.42940
  2. Thanks Sacred, gdfsxwy, barthen (3 members gave Thanks to thateuler for this useful post)
  3. #2
    doityourself's Avatar ★ Elder ★
    Reputation
    1424
    Join Date
    Nov 2008
    Posts
    843
    Thanks G/R
    35/448
    Trade Feedback
    0 (0%)
    Mentioned
    6 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by thateuler View Post
    here's a cleanish c implementation that is easier to understand.

    the return address check starts at 0x1422BAE10 (base 0x140000000)


    Code:
    /*
      - TBC 2.5.4.42940
      - imagebase is 0x140000000
      - returns:
        1:  if the arg is a valid return address
        0:  if not
     */
    
    int
    check_retaddr(uint8_t *ret)
    {
            uint8_t *mem = 0;
    
            /* check 1. return address is inside .text */
            if (ret < (uint8_t*)0x14001000 || ret > (uint8_t*)0x142400B75)
                    return 0;
    
            /* check 2. invoked from a call.  rop check? */
            /* patterns: 0xe8, 0xff 0x1x, 0xff 0x5x, 0xff 0x9x, 0xff 0xdx */
            int iscall = 0; 
            uint64_t reti = (uint64_t)ret;
    
            if (mem[reti-5] == 0xe8) // call off4
                    iscall = 1;
            if (mem[reti-6] == 0xff && (((mem[reti-5] & 0x38) - 16 ) & 0xf7) == 0) // call [reg + off4]
                    iscall = 1;
            if (mem[reti-3] == 0xff && (((mem[reti-2] & 0x38) - 16 ) & 0xf7) == 0) // call [reg + off1]
                    iscall = 1;
            if (mem[reti-2] == 0xff && (((mem[reti-1] & 0x38) - 16 ) & 0xf7) == 0) // call reg, call [reg]
                    iscall = 1;
    
            if (! iscall)
                    return 0;
    
    
            /* check 3. the return address is on the good list */
    
            /* step 1. get the array of good return addresses */
            uint32_t *rettab = (void*)0x01400BBC84;
            uint64_t ret_offset = (uint64_t)ret - 0x140000000;
            uint32_t array_offset = rettab[ret_offset / 0x4000];
            if (array_offset == 0)
                    return 0;
    
            /* step 2. traverse the array. check if this address is listed */
            uint32_t *pgoodaddr = (uint32_t *)&rettab[array_offset/4];
            while (*pgoodaddr > 0) { 
                    if ( (*pgoodaddr - ret_offset) <= 64)
                            return 1;
                    pgoodaddr++;
            }
    
            return 0;
    }
    Additional little comment: You will see multiple versions and functions of the return address checks in the binary. Sometimes inlined, sometimes not. Sometimes without the check in the array and sometimes without.

Similar Threads

  1. [Live] About the integrity check in live
    By youyanruyu in forum WoW Memory Editing
    Replies: 10
    Last Post: 11-09-2021, 03:30 PM
  2. Replies: 12
    Last Post: 06-29-2021, 10:13 AM
  3. [Selling] Selling my account in the future. (price-check plz)
    By Manimal in forum WoW-US Account Buy Sell Trade
    Replies: 1
    Last Post: 05-14-2013, 12:19 PM
  4. [Selling] WoW Gold on EU Servers! Check in the cheap prices! [Private Seller]
    By Mammuten in forum World of Warcraft Buy Sell Trade
    Replies: 3
    Last Post: 12-30-2012, 07:40 AM
  5. Reversing the DB2 struct in memory
    By JuJuBoSc in forum WoW Memory Editing
    Replies: 4
    Last Post: 07-29-2012, 11:41 AM
All times are GMT -5. The time now is 05:10 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search