9#define RELOC_32BIT_FIELD 3
10#define RELOC_64BIT_FIELD 0xA
23 ULONGLONG* relocateAddr = (ULONGLONG*)((ULONG_PTR)relocField);
24 ULONGLONG rva = (*relocateAddr) -
oldBase;
25 (*relocateAddr) = rva +
newBase;
28 DWORD* relocateAddr = (DWORD*)((ULONG_PTR)relocField);
29 ULONGLONG rva = ULONGLONG(*relocateAddr) -
oldBase;
30 (*relocateAddr) =
static_cast<DWORD
>(rva +
newBase);
42 if (entriesNum == 0) {
46 for (SIZE_T i = 0; i < entriesNum; i++) {
50 DWORD type = entry->
Type;
61 bool validate_reloc_field(PVOID modulePtr, SIZE_T moduleSize,
bool is64bit,
const DWORD reloc_field)
63 const size_t field_width =
is64bit ?
sizeof(ULONGLONG) : sizeof(DWORD);
64 const ULONG_PTR reloc_ptr = (ULONG_PTR)modulePtr + reloc_field;
71 if (entriesNum == 0) {
76 for (i = 0; i < entriesNum; i++) {
80 DWORD offset = entry->
Offset;
81 DWORD type = entry->
Type;
88 LOG_ERROR(
"Not supported relocation format at %d: %d.", (
int)i, (
int)type);
92 const DWORD reloc_field = page + offset;
93 if (!validate_reloc_field(modulePtr, moduleSize,
is64bit, reloc_field)) {
95 LOG_ERROR(
"Malformed reloc field: 0x%lx.", reloc_field);
102 LOG_ERROR(
"Failed processing reloc field at: 0x%lx.", reloc_field);
114 if (relocDir == NULL) {
118 if (!
validate_ptr(modulePtr, moduleSize, relocDir,
sizeof(IMAGE_DATA_DIRECTORY))) {
122 DWORD maxSize = relocDir->Size;
123 DWORD relocAddr = relocDir->VirtualAddress;
124 bool is64b =
is64bit((BYTE*)modulePtr);
126 IMAGE_BASE_RELOCATION* reloc = NULL;
128 DWORD parsedSize = 0;
129 while (parsedSize < maxSize) {
130 reloc = (IMAGE_BASE_RELOCATION*)(relocAddr + parsedSize + (ULONG_PTR)modulePtr);
131 if (!
validate_ptr(modulePtr, moduleSize, reloc,
sizeof(IMAGE_BASE_RELOCATION))) {
132 LOG_ERROR(
"Invalid address of relocations.");
135 if (reloc->SizeOfBlock < (2 *
sizeof(DWORD))) {
136 LOG_ERROR(
"Malformed relocation block: SizeOfBlock too small.");
139 const size_t entriesNum = (reloc->SizeOfBlock - 2 *
sizeof(DWORD)) /
sizeof(WORD);
140 const DWORD page = reloc->VirtualAddress;
144 LOG_ERROR(
"Invalid address of relocations block.");
148 if (!
process_reloc_block(block, entriesNum, page, modulePtr, moduleSize, is64b, callback)) {
153 parsedSize += reloc->SizeOfBlock;
160 const bool is64b =
is64bit((BYTE*)modulePtr);
167 if (modulePtr == NULL) {
173 LOG_DEBUG(
"New Base: 0x%llx Old Base: 0x%llx.", (
unsigned long long)newBase, (
unsigned long long)oldBase);
174 if (newBase == oldBase) {
175 LOG_DEBUG(
"Nothing to relocate: oldBase equals newBase.");
181 LOG_ERROR(
"Could not relocate the module.");
virtual bool processRelocField(ULONG_PTR relocField)
ApplyRelocCallback(bool _is64bit, ULONGLONG _oldBase, ULONGLONG _newBase)
RelocBlockCallback(bool _is64bit)
virtual bool processRelocField(ULONG_PTR relocField)=0
#define LOG_DEBUG(fmt,...)
#define LOG_ERROR(fmt,...)
ULONGLONG get_image_base(IN const BYTE *pe_buffer)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
bool process_relocation_table(IN PVOID modulePtr, IN SIZE_T moduleSize, IN RelocBlockCallback *callback)
bool is64bit(IN const BYTE *pe_buffer)
bool relocate_module(IN BYTE *modulePtr, IN SIZE_T moduleSize, IN ULONGLONG newBase, IN ULONGLONG oldBase=0)
struct peconv::_BASE_RELOCATION_ENTRY BASE_RELOCATION_ENTRY
IMAGE_DATA_DIRECTORY * get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty=false)
bool has_valid_relocation_table(IN const PBYTE modulePtr, IN const size_t moduleSize)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
bool process_reloc_block(BASE_RELOCATION_ENTRY *block, SIZE_T entriesNum, DWORD page, PVOID modulePtr, SIZE_T moduleSize, bool is64bit, RelocBlockCallback *callback)
#define RELOC_64BIT_FIELD
bool apply_relocations(PVOID modulePtr, SIZE_T moduleSize, ULONGLONG newBase, ULONGLONG oldBase)
bool is_empty_reloc_block(BASE_RELOCATION_ENTRY *block, SIZE_T entriesNum, DWORD page, PVOID modulePtr, SIZE_T moduleSize)
#define RELOC_32BIT_FIELD
Operating on PE file's relocations table.