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 add eax, 0Ch jmp short loc_11767 loc_1174B: mov esi, [eax+3Ch] shr esi, 1 add eax, 5Eh jmp short loc_11767 loc_11755: mov esi, [eax+3Ch] shr esi, 1 add eax, 44h jmp short loc_11767 loc_1175F: mov esi, [eax+3Ch] shr esi, 1 add eax, 40h 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 */ };
No comments :
Post a Comment