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