基址重定位表中罗列了硬编码地址的偏移,读取这张表就能获得准确的硬编码地址偏移,基址重定位表就是IMAGE_BASE_RELOCATION的结构体数组。
结构体定义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| 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的结构体数组,图中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))