It’s my first day ever trying decomilation and IDA, so I don’t really understand what’s happening.
I have a following function in my disassembly:
IDA View
; =============== S U B R O U T I N E =======================================
CODE:004040FC
CODE:004040FC
CODE:004040FC ; int __usercall sub_4040FC@<eax>(int result@<eax>, char@<dl>, char)
CODE:004040FC sub_4040FC proc near ; CODE XREF: sub_403D94+7↑p
CODE:004040FC ; sub_40D984+A↓p ...
CODE:004040FC
CODE:004040FC arg_0 = byte ptr 4
CODE:004040FC
CODE:004040FC push edx
CODE:004040FD push ecx
CODE:004040FE push ebx
CODE:004040FF test dl, dl
CODE:00404101 jl short loc_404106
CODE:00404103 call dword ptr [eax-0Ch]
CODE:00404106
CODE:00404106 loc_404106: ; CODE XREF: sub_4040FC+5↑j
CODE:00404106 xor edx, edx
CODE:00404108 lea ecx, [esp+0Ch+arg_0]
CODE:0040410C mov ebx, fs:[edx]
CODE:0040410F mov [ecx], ebx
CODE:00404111 mov [ecx+8], ebp
CODE:00404114 mov dword ptr [ecx+4], offset sub_404125
CODE:0040411B mov [ecx+0Ch], eax
CODE:0040411E mov fs:[edx], ecx
CODE:00404121 pop ebx
CODE:00404122 pop ecx
CODE:00404123 pop edx
CODE:00404124 retn
CODE:00404124 sub_4040FC endp
Pseudocode
int __usercall sub_4040FC@<eax>(int result@<eax>, char a2@<dl>, char a3)
{
if ( a2 >= 0 )
result = (*(int (**)(void))(result - 12))();
__writefsdword(0, (unsigned int)&a3);
return result;
}
Seeing that negative offset in result-12
, I tried using __shifted
I created new struct
00000000 struct s20 // sizeof=0x10
00000000 {
00000000 void (*foo)(void);
00000004 _BYTE gap[8];
0000000C int i;
00000010 };
and then changed type of result
to int *__shifted(s20,0xC)
My function turns into variadic
int *__shifted(s20,0xC) __usercall sub_4040FC@<eax>(int *__shifted(s20,0xC) result@<eax>, char a2@<dl>, ...)
{
va_list va; // [esp+4h] [ebp+4h] BYREF
va_start(va, a2);
if ( a2 >= 0 )
result = (int *__shifted(s20,0xC))((int (*)(void))ADJ(result)->foo)();
__writefsdword(0, (unsigned int)va);
return result;
}
Notice that it has va_list and va_begin - but no va_end.
Ctrl+Z reverts type, but not it turning into variadic
int __usercall sub_4040FC@<eax>(int result@<eax>, char a2@<dl>, ...)
{
va_list va; // [esp+4h] [ebp+4h] BYREF
va_start(va, a2);
if ( a2 >= 0 )
result = (*(int (**)(void))(result - 12))();
__writefsdword(0, (unsigned int)va);
return result;
}
I feel stuck