TOC

基址重定位表中罗列了硬编码地址的偏移,读取这张表就能获得准确的硬编码地址偏移,基址重定位表就是IMAGE_BASE_RELOCATION的结构体数组。 结构体定义如下:

typedef struct _IMAGE_BASE_RELOCATION {
  DWORD VirtualAddress;  // 基准地址
  DWORD SizeOfBlock;  // 重定位块的大小
//    WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION; // 
typedef IMAGE_BASE_RELOCATION UNALIGNED *PIMAGE_BASE_RELOCATION;

#define IMAGE_SIZEOF_BASE_RELOCATION 8

#define IMAGE_REL_BASED_ABSOLUTE 0
#define IMAGE_REL_BASED_HIGH 1
#define IMAGE_REL_BASED_LOW 2
#define IMAGE_REL_BASED_HIGHLOW 3
#define IMAGE_REL_BASED_HIGHADJ 4
#define IMAGE_REL_BASED_MIPS_JMPADDR 5
#define IMAGE_REL_BASED_ARM_MOV32 5
#define IMAGE_REL_BASED_THUMB_MOV32 7
#define IMAGE_REL_BASED_MIPS_JMPADDR16 9
#define IMAGE_REL_BASED_IA64_IMM64 9
#define IMAGE_REL_BASED_DIR64 10

最后一项TypeOffset数组不是结构体成员,而是以注释的形式存在的,表示在该结构体之下会出现WORD类型的数组,并且该数组元素的值就是硬编码在程序中的地址偏移。TypeOffset是2字节16位,由4位Type和12位offser组成 IMAGE_BASE_RELOCATION 如图是基址重定位表,也就是一个IMAGE_BASE_RELOCATION的结构体数组,图中Page RVA即VirtualAddress, A2608位置处是第一个硬编码在程序中的地址偏移,这里的值为3800,Type是3,Offset是800,3表示IMAGE_REL_BASED_HIGHLOW,在64位PE+文件中常见的Type是A(IMAGE_REL_BASED_DIR64)。 在恶意代码中正常修改文件代码后,有时要修改指向相应区域的重定位表(为了略去PE装载器的重定位过程,常常把Type值修改为0(IMAGE_REL_BASED_ABSOLUTE))