📄 chap8-5-5-1.htm.primary
字号:
</tr>
<tr>
<td class="p8" width="21%" height="20"><span class="p9"> FirstThunk</span></td>
<td class="p8" width="5%" height="20"><span class="p9">dd 0</span></td>
<td class="p8" width="74%" height="20"><font color="#000000">⑤0002C070</font></td>
</tr>
<tr>
<td height="8" class="p8" colspan="3"><span class="p9">IMAGE_IMPORT_DESCRIPTOR
ends </span></td>
</tr>
</table>
<p class="p9">现在我们将<span class="p9"><span class="p9">image_import_descriptors结构</span></span>中每项的地址均显示分析一下:</p>
<p class="p9"><br>
<b>① <span class="p9">Name</span>选项</b>(我们定位Import表地址就是以此为依据的)</p>
<p class="p9">在这例Name项值为:<font color="#000000"><font color="#9999FF">④</font>0002DA8A</font><br>
<br>
下命令DD <font color="#000000">42DA8A (显示内存地址42DA8A的数据,其中42DA8A=<font color="#9999FF">④</font>0002DA8A</font><font color="#000000">+<span class="p9">Image
Base(基址)</span>)</font></p>
<table width="100%" cellspacing="0" align="center" bgcolor="#000000">
<tr>
<td class="p9"><font color="#00AF00">-----SHOWDEP!.rdata+1A8A--------------------------dword-------------PROT---<font color="#00FFFF">(0)<font color="#00AF00">--</font></font></font></td>
</tr>
<tr>
<td class="p9" height="18"><font color="#AFAFAF">0030:<font color="#FF3366">0042DA8A</font>
4E52454B 32334C45 4C4C442E 019A0000 KERNEL32.DLL.... ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042DA9A 64616F4C 73727543 0041726F
6F4C01AB LoadCursorA...Lo v</font></td>
</tr>
</table>
<div align="center"><span class="p9">(图二)</span> </div>
<p><span class="p9">想必大家己睁大眼睛了,发现什么有价值的东西?对,就是<font color="#FF3366"><b><i>KERNEL32.DLL</i></b><font color="#000000">!就是我们的突破口。</font></font></span></p>
<p class="p9">Import表装载的基本原理是:根据Import表的指示找到外部模块的文件名,再使用Win32 API函数GetModuleHandleA获得该模块在内存中的句柄。如果没在内存中就使用LoadLibraryA
API调用装入该模块。随后使用获得的模块句柄调用Win32 API函数GetProcAddress 获得该模块中Import表指定功能的实际地址,加上装入基址,并且填入Import表的FirstThunk所指的IMAGE_IMPORT_BY_NAME结构指针数组中,完成该模块的一个功能的人工装入填写。循环调用函数GetProcAddress以获得其他功能调用的地址,加上装入基址,并填入之,以完成一个外部模块的装入。再循环上述过程对其他模块进行装入。<br>
<br>
因此我们可以从函数LoadLibraryA入手,该函数会装入外部模块,我们监视这函数的入口参数是否为KERNEL32.DLL,以此来确定Import表的状况。即确定
<span class="p9"><span class="p9">image_import_descriptors结构中的name选项。</span></span></p>
<p class="p9">函数LoadLibrary:</p>
<table width="100%" cellspacing="0" align="center" bgcolor="#CCCCFF">
<tr>
<td class="p9">HINSTANCE LoadLibrary(<br>
LPCTSTR lpLibFileName // 执行模块的文件名和地址<br>
);</td>
</tr>
</table>
<p class="p9">只要函数LoadLibrary参数的模块名为KERNEL32.DLL,就会出现图二的情况,这时KERNEL32.DLL地址为<font color="#FF3366"><b>0042DA8A</b></font>。因此<span class="p9"><span class="p9">image_import_descriptors结构</span></span>中name为<font color="#000000">0042DA8A</font>—400000=<font color="#000000">2DA8A</font>,这时利用S命令在内存中查找字条串<font color="#FF3366">002DA8A</font>,就可确定import表的地址。<br>
</p>
<p class="p9"> (到这里我们就能确定Import表的地址了,下面几项可帮助我们大家更好理解Import表)</p>
<p class="p9"><b>②<span class="p9">riginalFirstThunk</span>项</b></p>
<p class="p9">在这里<span class="p9">riginalFirstThunk</span>项值为:<font color="#000000"><font color="#9999FF">①</font>0002D23C</font><br>
<br>
下命令DD <font color="#000000">42D23C (显示内存地址42D23C的数据,其中42DA8A=<font color="#9999FF">①</font>0002D23C+<span class="p9">Image
Base(基址)</span>)</font> </p>
<table width="100%" cellspacing="0" align="center" bgcolor="#000000">
<tr>
<td class="p9"><font color="#00AF00">-----SHOWDEP!.rdata+123C--------------------------dword-------------PROT---<font color="#00FFFF">(0)<font color="#00AF00">--</font></font></font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D23C <font color="#FF3366">0002D798
</font>0002D7A8 0002D7BE 0002D782 ................ ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D24C 0002D7CC 0002D7E0 0002D7F6
0002D80A ................ ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D25C 0002D81C 0002D830 0002D840
0002D854 ....0...@...T... v</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D26C 0002D868 0002D87C 0002D890
0002D8A0 h...|........... v</font></td>
</tr>
</table>
<div align="center"><span class="p9">(图三)</span> </div>
<p class="p9">图三是一个指针数组,其中每一个指针都指向一IMAGE_IMPORT_BY_NAME结构。</p>
<p><span class="p9">我们以第一个指<font color="#000000">针0002D798为例,显示它所指的IMAGE_IMPORT_BY_NAME结构.<br>
下命令:dd 42d798(注意:0002D798+<span class="p9">Image Base(基址)</span>)</font></span></p>
<table width="100%" cellspacing="0" align="center" bgcolor="#000000">
<tr>
<td class="p9"><font color="#00AF00">-----SHOWDEP!.rdata+1798--------------------------dword-------------PROT---<font color="#00FFFF">(0)<font color="#00AF00">--</font></font></font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:<font color="#FF6666">0042D798 </font>6547011B
636F4C74 69546C61 0000656D ..GetLocalTime.. ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D7A8 6F430025 6E69746E 65446575
45677562 %.ContinueDebugE ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D7B8 746E6576 022B0000 65736552
65764574 vent..+.ResetEve v</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042D7C8 0000746E 615702CB 6F467469
62654472 nt....WaitForDeb v</font></td>
</tr>
</table>
<div align="center"><span class="p9">(图四)</span> </div>
<p><b class="p9">③<span class="p9">FirstThunk</span>项</b></p>
<p><span class="p9">在这例,<span class="p9">FirstThunk</span>项的值为:<font color="#99CCFF">⑤</font><font color="#000000">0002C070<br>
</font></span></p>
<p><font color="#000000"><span class="p9">下命令dd 42c070 <span class="p9"><font color="#000000">(注意:0002c070+<span class="p9">Image
Base(基址)</span>):</font></span></span></font></p>
<table width="100%" cellspacing="0" align="center" bgcolor="#000000">
<tr>
<td class="p9"><font color="#00AF00">-----SHOWDEP!.rdata+0070--------------------------dword-------------PROT---<font color="#00FFFF">(0)<font color="#00AF00">--</font></font></font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:<font color="#FF6699">0042C070</font>
0002D798 0002D7A8 0002D7BE 0002D782 ................ ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042C080 0002D7CC 0002D7E0 0002D7F6
0002D80A ................ ^</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042C090 0002D81C 0002D830 0002D840
0002D854 ....0...@...T... v</font></td>
</tr>
<tr>
<td class="p9"><font color="#AFAFAF">0030:0042C0A0 0002D868 0002D87C 0002D890
0002D8A0 h...|........... v</font></td>
</tr>
</table>
<div align="center"><span class="p9">(图五)</span> </div>
<p class="p9">图五是一个指针数组(Image_thunk_data联合结构),大多数情况下,Image_thunk_data是指IMAGE_IMPORT_BY_NAME结构的指针。如果不是一个指针的话,那它就是该功能在DLL中的序号。不知你发现没有,图五的数据和图三完全相同,原因就是这个。</p>
<p class="p9"><b>二、确定Import表的地址和大小并修正Import表</b></p>
<p class="p9">通过上面的讲解,想必大家对Import表己比较熟悉了吧,现在以脱<span class="p9">ShowDep 4.0 beta
1</span>的壳为例,讲解定位Import表的位置和大小的几种方法。</p>
<p class="p9"><font color="#6699FF">方法一:通过idata来确定Import表的位置</font></p>
<p class="p9">大部分加壳程序的块表中都有.idata这一项,.idata包含其他外来DLL的函数及数据信息,也就是说Import表的起始地址就是.idata的地址。如是这种情况,脱壳就简单多了。</p>
<p class="p9">先dump取正确的Import表(假设取名为idata.bin),然后在解压入口点full dump取整个程序(假设取名为dump.exe),用
Procdump打开dump.exe文件, 察看.idata Section. 记下Raw Size和 Raw Offset的值。用HexWorkshop打开dump.exe,
将idata.bin拷贝/粘贴到 dump.exe(粘贴位置为Raw Offset, 大小为Raw Size). 再修正Entry Point和Import表的地址(此值就是.idata的RVA)
</p>
<p class="p9">具体操作参考后面几节的脱壳教学实例。</p>
<p class="p9"><font color="#6699FF">方法二:没.idata一项,利用bpx loadlibrarya来判断Import表的位置</font></p>
<p class="p9">由于<span class="p9">ShowDep 4.0 beta 1</span>没.idata一项,因此要确定Import表的位置和大小较困难,步骤如下:</p>
<p class="p9">①分析<span class="p9">ShowDep 4.0 beta 1</span>的文件PE头</p>
<p><span class="p9"> </span><span class="p9">运行 Procdump,点击pe-editor按钮,选中ShowDep.exe文件:</span></p>
<p><span class="p9">Size of image : 000A0000 ; 这个PE文件执行时分配的内存空间。<br>
Image Base : 00400000 ; 基址</span></p>
<p class="p9">②确定Import表的地址</p>
<p><span class="p9">a.先装载Icedump<br>
在这用Icedump 6.016版本,其命令操作形式完全和以前的版本不同。先在Icedump目录里运行相应SOFTICE版本的icedump.exe(我用的SOFTICE是4.05版,因此在win9x/405目录下运行icedump.exe),如Icedump装载成功,Icedump会返回如下信息:</span></p>
<table width="100%" cellspacing="0" align="center" bgcolor="#000000">
<tr>
<td><span class="p9"><font color="#CCCCCC">icedump v6.0.1.6 for winice v4.05
loader<br>
icedum<span class="p9">p unloaded<br>
icedump loaded </span></font><font color="#FFFFFF"><span class="p9"><font color="#66CC00">←出现这句话表示Icedump装载成功</font><br>
</span><br>
<span class="p8"><font color="#CCCCCC">C:> </font></span></font></span></td>
</tr>
</table>
<div align="center"><span class="p9">(图六)</span> </div>
<p><span class="p9"> b.再装载FrogsICE<br>
由于ShowDep能检测到SOFTICE的存在,因此装载Frogsice就可躲过。在我机子里:FrogsICE 1.00 Final和Icedump不能很好兼容工作,因此我将FrogsICE换成版本v0.43,hehe..它们配合的很好。双击FPloader.exe文件即可装载成功。<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -