绑定输入和延迟载入,本质上都是为了程序的快速运行而考虑的。
绑定导入的结构,每一个绑定输入的DLL都对应于一个IMAGE_BOUND_IMPORT_DESCRIPTOR结构
typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
DWORD TimeDateStamp;
WORD OffsetModuleName;
WORD NumberOfModuleForwarderRefs;
} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR;
TimeDateStamp,这里的时间戳是比较有用的,在Loader加载的时候,会对时间戳进行一个比对操作,若是一个stale时间戳,则会从输入表加载该DLL。
OffsetModuleName,对应该绑定导入的DLL的名称的偏移,注意这里的偏移量不是RVA,而是首个IMAGE_BOUND_IMPORT_DESCRIPTOR的地址。
NumberOfModuleForwarderRefs,后面IMAGE_BOUND_FORWARDER_REF结构的数量,即转发链机制,这里是表示转发的模块数量。
再来看下IMAGE_BOUND_FORWARDER_REF结构
typedef struct _IMAGE_BOUND_FORWARDER_REF {
DWORD TimeDateStamp;
WORD OffsetModuleName;
WORD Reserved;
} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;
可以看到除了最后一项被保留外,其余项跟IMAGE_BOUND_IMPORT_DESCRIPTOR结构相同。
下面实战下:
这里LordPe有点问题,看到绑定导入的RVA是0x250
转到绑定导入的地方
第一项是时间戳,0x4802bda2,第二项是绑定的DLL名称的偏移,这里是0x58,加上0x250,所指向的是0x2A8,也就是ccmdlg32.dll,其转向的DLL项数是0,可以看到转发的DLL是很少的。
只有这里有一项转发,这里的偏移是0xA3,加上0x250,也就是0x2f3,转发的数量为1,所以后面有一项IMAGE_BOUND_FORWARDER_REF结构,后面一项的偏移是0xB0,也就是0x300
可以看到Kernrl32.dll的函数转发到ntdll.dll的相应函数。