Monday, November 12, 2018

Practical Reverse Engineering - Chapter 1 pg 25 - Author's Challenge Solution

Question: Take the example shown on page 24 and decompile it further to make it look more "natural"


Solution:

char * sub_1000AE3B(char * aStr){
    signed int length = lstrlenA(aStr);
    signed int counter1 = 0;
    signed int counter2 = 0;
    if(length != 0){
        while(counter2 < length){
            aStr[counter1] = aStr[counter2];
            counter2 += 3;
            counter1 += 1;
        }
    }
    aStr[counter1] = '\x00';
    return aStr;
}

Additional Notes

The disassembly on page 25 of the edition I am reading is incorrect. In the example given the authors provide an example whose assembly is as follows:
01 mov ecx, edx
02 loc_CFB8F:
03     lodsd
04     not eax
05     stosd
06     loop loc_CFB8F
They then state that this is the corresponding disassembly to C:
while (ecx != 0) {
     eax = *edi
     edi++;
     *esi = ~eax;
      esi++;
      ecx--;
}
If one refers back to their earlier remarks about how lodsd works, one will see that this command actually loads into EAX the DWORD at the location pointed to by ESI (refer to http://faydoc.tripod.com/cpu/lodsd.htm or the x86 instruction manual by Intel if you need further confirmation). Similarly, stosd actually stores the value at EAX into EDI, not ESI as shown above (see http://faydoc.tripod.com/cpu/stosd.htm).

Therefore the rough C code should actually be:
while (ecx != 0) {
     eax = *esi
     esi++;
     *edi = ~eax;
      edi++;
      ecx--;
}
Aka a simple switch of the ESI and EDI registers in the example C code provided.