手动确定IAT的地址与大小

点击ImportREC的“IAT AutoSearch”按钮,一般情况下ImportREC可以自动识别出IAT地址与大小。但如果不能自动识别,就必须手动确定IAT地址与大小,然后将IAT的RVA与Size填进ImportREC,点击“Get Import”按钮就可得到输入表。

    还是用上一节实例演示,用OD打开notepad.upx.exe,来到OEP处:

手动确定IAT的地址与大小_第1张图片

 

    随便找一个API函数调用语句,如:

004010D3    FF15 E4634000   call    [4063E4]          ; kernel32.GetCommandLineA

 

   其中地址4063E4就是IAT中的一部分,在数据窗口下命令:D 4063E4,显示如下:

 

手动确定IAT的地址与大小_第2张图片

 

  上图每一组数据都是指向一个API函数,如 8D 2C 81 7C 就是地址:7C812C8D,在OD里按Ctrl+G,输入7C812C8D跳到这个地址就会发现是kernel32.GetCommandLineA函数:

 

手动确定IAT的地址与大小_第3张图片

 

 

   IAT是一块连续排列的数据,因此在数据窗口向上翻屏,直到出现00数据,寻找IAT起始地址:

 

手动确定IAT的地址与大小_第4张图片

 

然后向下翻屏,寻找IAT结束地址:

 

手动确定IAT的地址与大小_第5张图片

 

为了直观些,你也可以这样让数据窗口直接显示这些API函数,以确定IAT是否正确,在数据窗口点击鼠标右键:

 

手动确定IAT的地址与大小_第6张图片

 

调整显示格式后的数据窗口:

 

手动确定IAT的地址与大小_第7张图片

 

这样就直观了,IAT中每组数据指向一个API函数,各DLL之间是以000000分开的。

 

因此IAT范围:0x4062E4~0x406524 ,大小为0x406524-0x4062E4=0x240 

 

如果IAT加密了,此时IAT中的地址不是指向系统DLL中的API函数了,可能指向外壳。这就十分有必要找到外壳处理IAT的代码了,前面己说过,外壳加载时,会模拟Windows加载器,向IAT里填充当前操作系统API函数的实际地址。所以,在IAT里设个内存写断点,就可中断到这段代码处。

重新加载notepad.upx.exe,在IAT某个地址下内存写断点,这里选择0x4062E4这个地址设内存写断点,先在数据窗口下命令:D 4062E4

 

手动确定IAT的地址与大小_第8张图片

 

然后选择一个地址,点击鼠标右键,下“内存写断点”。

 

手动确定IAT的地址与大小_第9张图片

 

此时只要有数据写入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    .^\75 F7         jnz     short 0040E96D

 

这段还不是处理IAT,按F9继续执行程序,会中断这里:

 

0040E9E9    > /8A07          mov     al, [edi]

0040E9EB    . |47            inc     edi

0040E9EC    . |08C0          or      al, al

0040E9EE    .^|74 DC         je      short 0040E9CC

0040E9F0    . |89F9          mov     ecx, edi

0040E9F2    . |57            push    edi                        // 函数名字符串  

0040E9F3    . |48            dec     eax

0040E9F4    .  F2:AE         repne   scas byte ptr es:[edi]

0040E9F6    . |55            push    ebp                        // DLL模块句柄

0040E9F7    .  FF96 A4EC0000 call    [esi+ECA4]                 ;  kernel32.GetProcAddress

0040E9FD    . |09C0          or      eax, eax

0040E9FF    . |74 07         je      short 0040EA08

0040EA01    . |8903          mov     [ebx], eax                // EBX指向IAT,将取得的API地址填充进IAT

0040EA03    . |83C3 04       add     ebx, 4                    // 指向下一个地址

0040EA06    .^\EB E1         jmp     short 0040E9E9

0040EA08    >  FF96 A8EC0000 call    [esi+ECA8]

 

上面这段就是UPX外壳填充IAT的全过程,感兴趣的,动态跟踪一下就明白了。这里用GetProcAddress函数获得函数地址:

 

FARPROC GetProcAddress(

  HMODULE hModule,    // DLL模块句柄

  LPCSTR lpProcName   // 函数名

);

你可能感兴趣的:(手动确定IAT的地址与大小)