首页
社区
课程
招聘
[旧帖] [原创]为什么需要导入段 0.00雪花
发表于: 2009-4-24 14:15 2116

[旧帖] [原创]为什么需要导入段 0.00雪花

2009-4-24 14:15
2116
网上有很多介绍PE文件的..但是大部都是说怎么找输入表...究竟PE文件为什么要用输入表呢...我想了很久.把所想的东西写下来...也不知道对否..请高手指点...

1.为什么需要导入段?

要回答这个问题... 我们得了解可执行文件执行的过程..

启动一个可执行模块的时候(通常是EXE文件..).操作系统的加载程序(以后简称加载程序)会先创建一个进程,然后通

过内存映射文件.把整个exe文件映射到这个进程空间的地址空间中(通常是4GB).初始位置可能是0x40000000..

(0x40000000前面的虚拟内存干什么用呢..这个加载程序可能会把dll加载到这一部分..也可能闲着不用..如果你需要

使用,就自己用吧..)0x80000000后面通常是操作系统的范围了..就是一些系统dll和内核代码了...

②.之后,加载程序会检查exe文件的导入段...(因为导入段中包含有dll的相关信息..比如dll名称..要调用该dll的函

数名称..等还有时间戳等...)把每个dll都加载到这个进程的地址空间..

③.对于②这个过程可能会是循环的..比如某个dll中又调用的其它的dll中的函数..同样.这个其它dll中的导入段也

会包含相关dll的一些信息..加载程序同样也要把其加载进来...例如.a.dll .调用了b.dll 中的add函数..加载程序

在加载a.dll的时候.也会加载b.dll... ..(DLL.和exe文件格式是完全一样 ...),你不用担心,,这个过程不会导致死

循环..加载程序会记载每个加载过的dll的....如果已经加载了..是不会再加载的..

④.当加载程序把所有的模块都加载完毕后..就开始修复对导入符号的引用了..(为什么要修复..先把这个过程弄完,

再说...)对导入段中列出的每个符号(即函数)..加载程序会检查对应dll中的导出表...看该函数是否存在..如果存在

,那么加载程序会取得该函数的RVA(相对虚拟地址..(DLL.中函数的地址是相对的..通常是相对于0X10000000这个地址

的..另外DLL.中保存的也是相对的虚拟地址..))取得地址后..加载程序通过计算(把rva.加上该DLL被加载的基址)就

得到了该函数在进程空间里边的绝对的虚拟地址...这里..如果DLL重定位了(就是没有被载入默认的基址.这个位置已

经被占用了)...还要通过更复杂的算法了...(算法是这样的..).它会把当前映射的基址减默认的基址 再加上当前加

符号的地址...
接着.加载程序就把这个地址保存在了导入段中了(可能会同时修改代码中所有对该符号引用的地址.这一点我不清

楚...没有办法证明..因为我看到的汇编代码都是修复好的...(就是显示是的绝对的虚拟地址))..好像是什么

firstThunk吧...刚开始的时候用的是orignalthunk//
吧..我对PE文件格式不是很熟悉...

⑤.之后呢..加载程序就完成了使命了...我们代码中如果调用了..某个函数..的时候..导入段中已经有了这个函数的

地址了...就能正确的被访问了...

最后一个问题.就是为什么要修复呢...当然不修复也行...能找到符号的地址就不用导入段了...比方说函数的正确地

址硬编码到指令中..这个是不可能的...比方说系统DLL.但是,每次..系统启动的时候.映射的位置就不同的...听说这

是VISTA.的一个特性.ASLR (地址空间布局随机化..)...那xp呢..可能没有问题(同一个XP版本 比如同是SP3).如果

XPSP2..这个地址一般不会相同的.....程序肯定不能运行 ...所以硬编码肯定不行(程序的移植性更打折扣)..那通常

我们写程序的时候...都是调用那个符号,其实编译器是把符号的地址写进去了.....编译器需要根据lib文件..(lib文

件中有dll中的函数的相对地址)....中的函数地址址,把我们的符号给替换掉....

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//