- UID
- 41172
注册时间2007-12-14
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 开心 2022-4-18 15:36 |
---|
签到天数: 207 天 [LV.7]常住居民III
|
当我们找到OEP后,用ImportREC的“IATAutoSearch”按钮,一般情况下ImportREC可以自动识别出IAT地址与大小。但如果不能自动识别,就必须手动确定IAT地址与大小,然后将IAT的RVA与Size填进ImportREC,点击“GetImport”按钮就可得到输入表。
比如我们用OD打开一个notepad.upx.exe文件,来到OEP处:
随便找一个API函数调用语句,如:
004010D3 FF15E4634000 call [4063E4] ;kernel32.GetCommandLineA
其中地址4063E4就是IAT中的一部分,在数据窗口下命令:D4063E4,显示如下:
上图每一组数据都是指向一个API函数,如8D2C817C就是地址:7C812C8D,在OD里按Ctrl+G,输入7C812C8D跳到这个地址就会发现是kernel32.GetCommandLineA函数:
IAT是一块连续排列的数据,因此在数据窗口向上翻屏,直到出现00数据,寻找IAT起始地址:
然后向下翻屏,寻找IAT结束地址:
为了直观些,你也可以这样让数据窗口直接显示这些API函数,以确定IAT是否正确,在数据窗口点击鼠标右键:
调整显示格式后的数据窗口:
这样就直观了,IAT中每组数据指向一个API函数,各DLL之间是以000000分开的。
因此IAT范围:0x4062E4~0x406524,大小为0x406524-0x4062E4=0x240
如果IAT加密了,此时IAT中的地址不是指向系统DLL中的API函数了,可能指向外壳。这就十分有必要找到外壳处理IAT的代码了,前面己说过,外壳加载时,会模拟Windows加载器,向IAT里填充当前操作系统API函数的实际地址。所以,在IAT里设个内存写断点,就可中断到这段代码处。
重新加载notepad.upx.exe,在IAT某个地址下内存写断点,这里选择0x4062E4这个地址设内存写断点,先在数据窗口下命令:D4062E4
然后选择一个地址,点击鼠标右键,下“内存写断点”。
此时只要有数据写入4062E4地址处,OD就会中断,按F9运行OD,会中断这里:
0040E96D >/8A02 mov al,[edx]
0040E96F .|42 inc edx
0040E970 .|8807 mov [edi],al
0040E972 .|47 inc edi
0040E973 .|49 dec ecx
0040E974 .^75F7 jnz short0040E96D
这段还不是处理IAT,按F9继续执行程序,会中断这里:
0040E9E9 >/8A07 mov al,[edi]
0040E9EB .|47 inc edi
0040E9EC .|08C0 or al,al
0040E9EE .^|74DC je short0040E9CC
0040E9F0 .|89F9 mov ecx,edi
0040E9F2 .|57 push edi //函数名字符串
0040E9F3 .|48 dec eax
0040E9F4 . F2:AE repne scasbyteptres:[edi]
0040E9F6 .|55 push ebp //DLL模块句柄
0040E9F7 . FF96A4EC0000call [esi+ECA4] ; kernel32.GetProcAddress
0040E9FD .|09C0 or eax,eax
0040E9FF .|7407 je short0040EA08
0040EA01 .|8903 mov [ebx],eax //EBX指向IAT,将取得的API地址填充进IAT
0040EA03 .|83C304 add ebx,4 //指向下一个地址
0040EA06 .^EBE1 jmp short0040E9E9
0040EA08 > FF96A8EC0000call [esi+ECA8]
上面这段就是UPX外壳填充IAT的全过程,感兴趣的,动态跟踪一下就明白了。这里用GetProcAddress函数获得函数地址:
FARPROCGetProcAddress(
HMODULEhModule, //DLL模块句柄
LPCSTRlpProcName //函数名
); |
评分
-
查看全部评分
|