main函数的识别
来源:互联网 发布:base64 c语言 编辑:程序博客网 时间:2024/04/30 06:52
一般来说,用IDA反汇编程序时,IDA会自动识别出main函数。如果我们不是用IDA反汇编,那又怎么识别main函数呢?
1、WinMain函数的识别
先来看看WinMain函数的原型:
int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // pointer to command line int nCmdShow // show state of window);
1)首先在大多数情况下下,WinMain看起来是启动代码中参数最丰富的函数;
2)其次,放在堆栈中的最后一个变量hInstance是最可能即时能过调用GetModuleHandleA函数进行获取的。例如,在启动代码中,在遇到一个CALL GetMoudleHandleA类型的语句以后,就可以十分自信地断言,接在函数后面的一定是WinMain函数;
3)最后,对WinMain的调用通常放在启动函数代码结尾部分附近,它后面通常跟有诸如exit或者XcptFilter之类的两到三个函数。
我们来看看实例:
00401921 |> \6A 0A push 0A00401923 |. 58 pop eax00401924 |> 50 push eax00401925 |. 56 push esi00401926 |. 53 push ebx00401927 |. 53 push ebx ; /pModule00401928 |. FF15 00204000 call dword ptr [<&KERNEL32.GetModuleH>; \GetModuleHandleA0040192E |. 50 push eax0040192F |. E8 5E000000 call 0040199200401934 |. 8945 98 mov dword ptr [ebp-68], eax00401937 |. 50 push eax ; /status00401938 |. FF15 B0214000 call dword ptr [<&MSVCRT.exit>] ; \exit0040193E |. 8B45 EC mov eax, dword ptr [ebp-14]00401941 |. 8B08 mov ecx, dword ptr [eax]00401943 |. 8B09 mov ecx, dword ptr [ecx]00401945 |. 894D 88 mov dword ptr [ebp-78], ecx00401948 |. 50 push eax00401949 |. 51 push ecx0040194A |. E8 15000000 call <jmp.&MSVCRT._XcptFilter>0040194F |. 59 pop ecx00401950 |. 59 pop ecx00401951 \. C3 retn
再来看看call 00401992处的代码:
00401992 /$ FF7424 10 push dword ptr [esp+10]00401996 |. FF7424 10 push dword ptr [esp+10]0040199A |. FF7424 10 push dword ptr [esp+10]0040199E |. FF7424 10 push dword ptr [esp+10]004019A2 |. E8 43000000 call <jmp.&MFC42.#1576_AfxWinMain>004019A7 \. C2 1000 retn 10
2、DllMain函数的识别:
识别DllMain比WinMain困难得多,首先,DllMain的原型相对来说不那么复杂,并且不包含任何特别的内容:
BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to DLL module DWORD fdwReason, // reason for calling function LPVOID lpvReserved // reserved);
其次,对它的调用来自一个令人十分难忘的函数__DllMainCRTStartup的深处,并且没有办法容易地确定这就是我们需要的调用。
不过,调用里面还是存在一些蛛丝马迹。当初始化失败时,DllMain会返回FALSE。__DllMainCRTStartup的代码会对该值班进行检查,并且跳转到函数的发问也是可能的。在启动函数的函数体内包含的这类跳转分支非常少,而且其中仅有一个分支通常会连接到接受三个参数的那个函数。
我们来看看实例:
1003DEDF 57 push edi1003DEE0 56 push esi1003DEE1 53 push ebx1003DEE2 E8 D9C8FCFF call 1000A7C01003DEE7 8945 E4 mov dword ptr [ebp-1C], eax1003DEEA 83FE 01 cmp esi, 11003DEED 75 24 jnz short 1003DF131003DEEF 85C0 test eax, eax1003DEF1 75 20 jnz short 1003DF13
3、main函数的识别:
main函数是在mainCRTStartup函数中调用的。main函数仅仅接受两个参数:
int main (int argc, char **argv)
这并不足以将它与别的函数区分开。然而,命令的关键字不仅能够通过参数进行访问,而且能够通过全局变量__argc与__argv进行存取。(全局变量通过直接对内存进行寻址而即刻使自己暴露无遗。换句话说,对全局变量的引用是以诸如MOV EAX,[401066]的形式完成的,其中,0x401066是全局变量的地址)。由此可知,针对main进行的调用通常是如下形式的:
00403BF8 |. A1 B4014100 mov eax, dword ptr [4101B4]00403BFD |. A3 B8014100 mov dword ptr [4101B8], eax00403C02 |. 50 push eax00403C03 |. FF35 AC014100 push dword ptr [4101AC] ;-->全局变量00403C09 |. FF35 A8014100 push dword ptr [4101A8] ;-->全局变量00403C0F |. E8 ECD3FFFF call 0040100000403C14 |. 83C4 0C add esp, 0C00403C17 |. 8945 E4 mov dword ptr [ebp-1C], eax00403C1A |. 50 push eax00403C1B |. E8 39160000 call 00405259
main函数返回的结果被传递给紧接在它之后的那个函数(通常,这就是结束程序的函数)。我们进入到call 00405259内部,一步步步进,可进入到退出的程序:
0040527B /$ 57 push edi0040527C |. 6A 01 push 10040527E |. 5F pop edi0040527F |. 393D D4014100 cmp dword ptr [4101D4], edi00405285 |. 75 11 jnz short 0040529800405287 |. FF7424 08 push dword ptr [esp+8] ; /ExitCode0040528B |. FF15 20B04000 call dword ptr [<&KERNEL32.GetCurrent>; |[GetCurrentProcess00405291 |. 50 push eax ; |hProcess00405292 |. FF15 1CB04000 call dword ptr [<&KERNEL32.TerminateP>; \TerminateProcess00405298 |> 837C24 0C 00 cmp dword ptr [esp+C], 00040529D |. 53 push ebx0040529E |. 8B5C24 14 mov ebx, dword ptr [esp+14]004052A2 |. 893D D0014100 mov dword ptr [4101D0], edi004052A8 |. 881D CC014100 mov byte ptr [4101CC], bl004052AE |. 75 3C jnz short 004052EC004052B0 |. A1 F0064100 mov eax, dword ptr [4106F0]004052B5 |. 85C0 test eax, eax004052B7 |. 74 22 je short 004052DB004052B9 |. 8B0D EC064100 mov ecx, dword ptr [4106EC]004052BF |. 56 push esi004052C0 |. 8D71 FC lea esi, dword ptr [ecx-4]004052C3 |. 3BF0 cmp esi, eax004052C5 |. 72 13 jb short 004052DA004052C7 |> 8B06 /mov eax, dword ptr [esi]004052C9 |. 85C0 |test eax, eax004052CB |. 74 02 |je short 004052CF004052CD |. FFD0 |call eax004052CF |> 83EE 04 |sub esi, 4004052D2 |. 3B35 F0064100 |cmp esi, dword ptr [4106F0]004052D8 |.^ 73 ED \jnb short 004052C7004052DA |> 5E pop esi004052DB |> 68 88D04000 push 0040D088004052E0 |. 68 80D04000 push 0040D080004052E5 |. E8 2A000000 call 00405314004052EA |. 59 pop ecx004052EB |. 59 pop ecx004052EC |> 68 94D04000 push 0040D094004052F1 |. 68 8CD04000 push 0040D08C004052F6 |. E8 19000000 call 00405314004052FB |. 59 pop ecx004052FC |. 59 pop ecx004052FD |. 85DB test ebx, ebx004052FF |. 5B pop ebx00405300 |. 75 10 jnz short 0040531200405302 |. FF7424 08 push dword ptr [esp+8] ; /ExitCode00405306 |. 893D D4014100 mov dword ptr [4101D4], edi ; |0040530C |. FF15 0CB04000 call dword ptr [<&KERNEL32.ExitProces>; \ExitProcess00405312 |> 5F pop edi00405313 \. C3 retn
- main函数的识别
- 用zxing 识别二维码的main函数
- IDA如何识别ARM的main函数
- main函数的参数
- main函数的参数
- Main 函数的参数
- main()函数的参数
- main函数的参数
- main函数的参数
- main函数的参数
- main函数的规范
- main函数的参数
- main函数的参数
- main函数的参数
- main函数的参数
- main函数的参数
- main函数的参数
- main函数的参数
- 数字化口岸电子中间件应用
- 重写与重载
- Oracle11g 开始,创建DG更便捷了,有木有?
- (转)iOS App 自定义 URL Scheme 设计
- 二叉树中两个节点的最近公共父节点 使用二叉排序树
- main函数的识别
- 数据库默认端口和驱动总结
- 名企一览表——我要统统面试一遍
- 无聊的apache错误(.htaccess pcfg_openfile)
- Uva OJ 850 - Crypt Kicker II
- ArcGIS for Server 10.1 注册postsql SDE提示the data Item is inaccessible
- Oracle正则表达式的用法
- 通过 Applet使用BEA WebLogic JMS
- [多媒体、图形、动画] 通过VIew生成图片