2006年4月30日星期日

PE Loader 有所突破

想了一个办法,把 Loader 宿主程序的 ImageBase 在链接时设到不是 0x00400000 的地址,那么被运行的程序就可以在 0x00400000 安家了。

今天花了很多时间来修改导入表的程序段,加入了 Forwarder 导出函数(比如 WSock32.dll 中的导出函数 WSAStartup 其实只是 WS2_32.dll 中的 WSAStartup 的一个引用)的导入程序段,现在基本上可以保证所有导入函数能够被正确导入。

现在的问题是,即使被运行程序的 ImageBase 正确了,被导入的 DLL 们也无法保证他们的 ImageBase。一般来说,很多 DLL 的 ImageBase 都处在很高的内存段,而且相互之间很可能会重叠,遇到这些情况,被导入的 DLL 就必须挪位置。不幸的是,很多程序里面给出的访问地址就是以默认 ImageBase 的值为参照的,所以肯定会出错。我还想不到什么办法来解决这个问题。

更奇快的是,我现在一调试程序,整个 Windows (Windows XP SP1)的所有图标都没了,然后陷入半死机状态,所有程序无法运行。我发现是只要我一装载 exe 文件到 0x00400000,就会出现这个问题,完全让人摸不到头脑……

关于调试器,我找不到合适的、运行于 Windows 下的、开源的 exe 的调试器,而且我发现,就算是 OllyDbg,它也是通过 API 来装载好了一个 exe 后再进行调试的,而我需要的恰恰是在不调用任何关键 API 的情况下装载并运行 exe。看来后面的路还很长。

2006年4月25日星期二

PE Loader 遇到难题

开始做 PE Loader。我的思路是,在自己的宿主程序里读入一个 EXE 文件,将之映像(Image)复制到内存(当然是这个 Loader 宿主程序的内存空间里的某处),同时把相关 DLL 以同样的方式载入,最后跳转(JMP)到 EXE 程序的入口地址,将程序的控制权交给它。我还没有考虑到如果目标 EXE 程序结束后,程序运行指针会指向哪里,实在不行,用一个 CALL 来调用。

现在的进度是,能够将 EXE 读入内存(Section 正确对齐 SectionAlignment),能把所有相关 DLL 载入内存,找到导入函数入口地址并修改 FirstThunk 数组。由于 Loader 宿主程序的映像自己占据了 0x00400000(ImageBase 默认值),所以载入的 EXE 的 ImageBase 肯定会在其他地方。当我想 JMP 时,发现程序中很多地址还是以 0x00400000 作为 ImageBase,所以一访问这些地址就会出错。我现在想不到怎么解决这个问题,想不明白 Windows 的 PE Loader 是怎么考虑这个重定位的,而且我手动把一个 EXE 的 ImageBase 改到 0x00500000,程序一样无法运行。

最大嫌疑是在 IAT 表和 Relocation 表。但很多程序根本没有 Relocation 表,IAT 也在修正 FirstThunk 数组时改过了。网上关于 PE Loader 方面的资料真的很少,更多的都是讲 PE 文件结构(想来这几天把 Iczelion 和 LUEVELSMEYER 的 PE 教程看了不知道多少遍)。我想,很可能为这个 EXE 分配内存时不能用常规的 VirtualAlloc,在 Loader 宿主空间里申请,而应该类似虚拟机那样让其有一个独立的虚拟内存空间。

现在的打算是,有时间就研究一下类似 OllyDbg 的这些调试器,因为它们确实能做到 Load and Execute PE file.

2006年4月14日星期五

GRE 作文终于考完了

4月13日上午终于把 GRE 作文考了,题目比较容易。无论如何,解决一心头大患了(想想为了它规避了多少节课)。现在该准备笔试了。