我正在分析一个可执行文件的格式,我在image_optional_header
中发现了基址重定位表,这个基址重定位表是什么?
我正在分析一个可执行文件的格式,我在image_optional_header
中发现了基址重定位表,这个基址重定位表是什么?
有2个重定位表:COFF重定位表只存在于.obj文件中,其中包含所有指令访问对象文件中的本地/外部链接符号的rip相对偏移字节的地址及其对应的符号表中索引符号表条目。
该节的COFF重定位表由COFF头后的段表中相应节的段头指向。
typedef struct {
unsigned long r_vaddr; /* address of relocation */
unsigned long r_symndx; /* symbol we're adjusting for */
unsigned short r_type; /* type of relocation */
} RELOC; //COFF relocation table entry
*UNDEF*
条目(部分编号将是*UNDEF*
区域),从*UNDEF*
区域的偏移量始终为0。对于已定义的符号,在符号表中它会有正确的段以及相应段内的正确偏移量,如果符号名称无法内联到字符串表条目中,则它指向符号名称的字符串表索引。链接器将使用这些段+偏移量用于静态符号和包含的外部符号的段+偏移量,以计算从r_vaddr
末尾到符号的段+偏移量的正确偏移量。然后,它将地址r_vaddr
替换为该值,即它将call -1
或call 0
替换为正确的相对值。BaseRelocationTable
指向,通常在.reloc
中。如果加载程序映像的地址不是链接器选择并放置在PE头中的ImageBase,则需要应用基本重定位表中的补丁。基本重定位表由基本重定位块组成,每个块描述了4 KiB页。块标头包含页面的RVA和块结构的大小。块的其余部分包含一个2字节字段数组,其中前2字节的第4位表示重定位类型,后12位表示需要应用重定位的页RVA到偏移量。这将是指令中地址字段的偏移量。为了进行重定位,加载程序只需计算ImageBase和PEB中进程实际基地址之间的差异,并从地址中添加或减去它。由于代码中的大多数符号使用寄存器间接rip相对寻址(用于mov和dllimport调用)和直接相对寻址(用于常规调用),因此不会有太多的基本重定位。在COFF对象中,相对地址和绝对地址都需要重定位,在PE可执行文件中,只需要重定位绝对地址。typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress; //Page RVA
DWORD SizeOfBlock;
WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION; //base relocation table