延迟导入表

延迟导入表,顾名思义就是有一些函数或模块,不需要再程序一启动就加载导入,而是等到真正用到的时候才进行导入的。

延迟导入表和导入表结构基本类似也存在IAT和INT,存在双桥结构,这里不再赘述,关于导入表请参考:导入表

先看一下延迟导入表的结构体。

typedef struct ImgDelayDescr {
    DWORD           grAttrs;        // attributes
    RVA             rvaDLLName;     // RVA to dll name
    RVA             rvaHmod;        // RVA of module handle
    RVA             rvaIAT;         // RVA of the IAT
    RVA             rvaINT;         // RVA of the INT
    RVA             rvaBoundIAT;    // RVA of the optional bound IAT
    RVA             rvaUnloadIAT;   // RVA of optional copy of original IAT
    DWORD           dwTimeStamp;    // 0 if not bound,
                                    // O.W. date/time stamp of DLL bound to (Old BIND)
} ImgDelayDescr, * PImgDelayDescr;
typedef const ImgDelayDescr *   PCImgDelayDescr;

grAttrs:用来区分版本,1是新版本,0是旧版本,旧版本中后续的rvaxxxxxx域使用的都是指针,而新版本中都用RVA,我们只讨论新版本。
rvaDLLName:一个RVA,指向导入DLL的名字。

rvaHmod:一个RVA,指向导入DLL的模块基地址,这个基地址在DLL真正被导入前是NULL,导入后才是实际的基地址。

rvaIAT:一个RVA,表示导入函数表,实际上指向IAT,在DLL加载前,IAT里存放的是一小段代码的地址,加载后才是真正的导入函数地址。

rvaINT:一个RVA,指向导入函数的名字表。

rvaUnloadIAT:延迟导入函数卸载表。

dwTimeStamp:延迟导入DLL的时间戳。


 我们根据这张图来了解一下延迟导入表的机制。

当执行某一个延迟导入的函数时,找到对应的IAT之后,其中的内容其实很简单,就是将自身地址放入eax中,然后跳转。

.text:75C7A363 __imp_load__InternetConnectA@32:        ; InternetConnectA(x,x,x,x,x,x,x,x)
.text:75C7A363                 mov     eax, offset __imp__InternetConnectA@32
.text:75C7A368                 jmp     __tailMerge_WININET

跳转到如下的位置,然后执行完毕之后IAT表中的值就变成了正确的函数地址,下次再调用就可以直接调用。

__tailMerge_WININET proc near           
.text:75C6BEF0                 push    ecx
.text:75C6BEF1                 push    edx
.text:75C6BEF2                 push    eax
.text:75C6BEF3                 push    offset __DELAY_IMPORT_DESCRIPTOR_WININET
.text:75C6BEF8                 call    __delayLoadHelper
.text:75C6BEFD                 pop     edx
.text:75C6BEFE                 pop     ecx
.text:75C6BEFF                 jmp     eax
.text:75C6BEFF __tailMerge_WININET endp

这个__delayLoadHelper只有两个参数,而没有当前函数的名称,那么它是如何完成的呢。

实际上eax中存的是IAT表中该函数的地址(address1),然后我们有__DELAY_IMPORT_DESCRIPTOR_WININET这个结构中有一个rvaIAT其中存的是IAT表的基址(address0),我们通过(address1-address0)/4 就可以得到该函数在INT表中偏移,从而获得函数的名称。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值