用OD加载文件的时候,不会停留在main
函数上,如何确定main
的位置,这就需要对程序加载过程有个了解。
使用IDA就可以准确定位main
函数的起始位置。
控制台部分识别
console beta
void __cdecl start()
{
DWORD v0; // eax@1
int v1; // eax@4
v0 = GetVersion();
dword_4101A4 = BYTE1(v0);
dword_4101A0 = v0;
dword_41019C = BYTE1(v0) + (v0 << 8);
dword_410198 = v0 >> 16;
if ( !sub_4068EE(0) )
fast_error_exit(0x1Cu);
_ioinit();
dword_411704 = *GetCommandLineA*();
dword_41017C = __crtGetEnvironmentStringsA();
_setargv();
_setenvp();
_cinit();
dword_4101B8 = envp;
v1 = main(argc, argv, envp);
exit(v1);
}
可以看到,main函数开始之前,有很多的初始化工作。OD不会全部识别,唯一可以识别的函数是GetCommandLine
,在此函数执行之后,一般要再次调用4个函数__crtGetEnviromentStrings、setargv、setenvp、cinit
,此后才会执行main
函数。
因此,只要在GetCommandLine后跳过4个函数,一般就可以到达main
函数的位置。
如果你不想使用IDA加载程序来获得main函数位置,使用此方法可以快速找到main函数。是不是跳过4个,一般而言与编译器有很大的关系,所以,此方法只能算作经验积累。
window应用程序识别
windows程序常用start代码
void __cdecl start()
{
DWORD v0; // eax@1
signed int v1; // eax@4
HMODULE v2; // eax@7
int v3; // eax@7
int v4; // [sp-4h] [bp-78h]@6
CHAR *lpCmdLine; // [sp+10h] [bp-64h]@3
struct _STARTUPINFOA StartupInfo; // [sp+18h] [bp-5Ch]@3
CPPEH_RECORD ms_exc; // [sp+5Ch] [bp-18h]@3
v0 = GetVersion();
dword_405528 = BYTE1(v0);
dword_405524 = (unsigned __int8)v0;
dword_405520 = BYTE1(v0) + ((unsigned __int8)v0 << 8);
dword_40551C = v0 >> 16;
if ( !_heap_init(0) )
fast_error_exit(0x1Cu);
ms_exc.registration.TryLevel = 0;
_ioinit();
dword_405A18 = (int)GetCommandLineA();
dword_405504 = (void *)__crtGetEnvironmentStringsA();
_setargv();
_setenvp();
_cinit();
StartupInfo.dwFlags = 0;
GetStartupInfoA(&StartupInfo);
lpCmdLine = (CHAR *)_wincmdln();
if ( StartupInfo.dwFlags & 1 )
v1 = StartupInfo.wShowWindow;
else
v1 = 10;
v4 = v1;
v2 = GetModuleHandleA(NULL);
v3 = WinMain(v2, NULL, lpCmdLine, v4);
exit(v3);
}
可以看到,windows应用程序比控制台程序又多了GetStartupInfo,GetModuleHandle
,所以此时就应该跳过6个。
好在OD可以识别GetModuleHandle
,所以在此函数之后,就是winmain
函数。当然,从压入的4个参数也能够看出来。