## Wednesday, January 7, 2015

### Practical Reverse Engineering p. 35 #8

Question number 8 on page 35 of Practical Reverse Engineering is as follows:

Sample H. Decompile sub_11732 and explain the most likely programming construct used in the original code.

The function's disassembly looks like the following:

```sub_1172E:
push    esi
mov     esi, [esp+8]
dec     esi
jz      short loc_1175F
dec     esi
jz      short loc_11755
dec     esi
jz      short loc_1174B
sub     esi, 9
jnz     short loc_1176B
mov     esi, [eax+8]
shr     esi, 1
jmp     short loc_11767

loc_1174B:
mov     esi, [eax+3Ch]
shr     esi, 1
jmp     short loc_11767

loc_11755:
mov     esi, [eax+3Ch]
shr     esi, 1
jmp     short loc_11767

loc_1175F:
mov     esi, [eax+3Ch]
shr     esi, 1

loc_11767:

mov     [ecx], esi
mov     [edx], eax

loc_1176B:
pop     esi
retn    4 ```

The function contains a switch. The calling convention is odd for x86 as there are three variables passed in a register, which means it was probably compiled as a static unit. There is a lot of repeated code, which means either the programmer or the compiler couldn't optimize the size in a logical way. Here is a more natural way to write the function:

```static struct *sub_1172E(struct *arg1, struct *arg2,
struct *arg3, int unknown_enum)
{
DWORD dwUnknown;

/* mov esi, [esp+8] */
switch (unknown_enum)
{
case 1:                 /* dec esi */
arg1 += 64;         /* add eax, 40h */
break;

case 2:                 /* dec esi */
arg1 += 68          /* add eax, 44h */
break;

case 3:                 /* dec esi */
arg1 += 94;         /* add eax, 5Eh */
break;

case 12:                /* sub esi, 9 */
arg1 += 12;         /* add eax, 0Ch */
break;

default:
return arg1;
}

dwUnknown = (unknown_enum == 12) ?
arg1->Unknown0x8 :  /* mov esi, [eax+8] */
arg1->Unknown0x3c;  /* mov esi, [eax+3Ch] */

dwUnknown /= 2;             /* shr esi, 1 */

*arg2 = dwUnknown;          /* mov [ecx], esi */
*arg3 = arg1;               /* mov [edx], eax */

return arg1;
}```

We can infer some of the struct in the first argument by where offsets were accessed:

```struct arg1 {
BYTE Unknown0x0[0x8];   /* 0x0 */
DWORD bigTwiceVal;      /* 0x8 */
BYTE Unknown0xc[0x30];  /* 0xc */
DWORD smallTwiceVal;    /* 0x3c */
};
```