7. 重定位表
一种重定位方法:
g_dwVar dd ?
call @F
@@:
pop ebx
sub ebx, offset @B ;运行时的eip减去编译时的eip,算出偏移
mov eax, [ebx + offset g_dwVar]
/DLL和/FIXED:NO选项都会产生重定位表,一般会多出一个.reloc的节
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress; //重定位块的RVA
DWORD SizeOfBlock; //包括本结构和所有要修正的页内偏移数组的大小
// WORD TypeOffset[1]; //紧接着是所有要修正的页内偏移,长度WORD,由于只需要12bit就能表示,高4bit在32位下一般为3或0,64位下一般为A或0。IMAGE_REL_BASED_HIGHLOW,IMAGE_REL_BASED_DIR64,IMAGE_REL_BASED_ABSOLUTE
} IMAGE_BASE_RELOCATION;
下图中是dll文件的重定位表,VirtualAddress为1000h,SizeOfBlock为10,TypeOffset数组分别为3003,3008,3064,0000,高4位表示IMAGE_REL_BASED_HIGHLOW,最后一个0000用来4字节对齐。
实际要重定位的地址分别是10001003,10001008,10001064。可以看出只有分页地址为1000h的地方要修。
再去看看10001003,10001008,10001064里是什么,前两个是字符串地址,最后一个是IAT中的一个项,确实需要修。可以发现命中在重定位表中的数据,调试器会加上下划线。