6#include <unordered_set>
15 BYTE* dimps_table = (BYTE*)((ULONGLONG) modulePtr + d_imps_dir->VirtualAddress);
17 if (d_imps_dir->Size < min_size) {
23 dir_size = d_imps_dir->Size;
32 CollectRelocs(BYTE* pe_buffer,
size_t buffer_size, IN
bool _is64bit, OUT std::unordered_set<ULONGLONG>& _relocs)
33 : RelocBlockCallback(_is64bit), relocs(_relocs),
34 peBuffer(pe_buffer), bufferSize(buffer_size)
38 virtual bool processRelocField(ULONG_PTR relocField)
40 ULONGLONG reloc_addr = (relocField - (ULONGLONG)peBuffer);
43 ULONGLONG* relocateAddr = (ULONGLONG*)((ULONG_PTR)relocField);
44 rva = (*relocateAddr);
47 DWORD* relocateAddr = (DWORD*)((ULONG_PTR)relocField);
48 rva = ULONGLONG(*relocateAddr);
55 std::unordered_set<ULONGLONG>& relocs;
62template <
typename T_FIELD,
typename T_IMAGE_THUNK_DATA>
64 BYTE* modulePtr,
const size_t moduleSize,
65 const ULONGLONG img_base,
67 const T_FIELD ordinal_flag,
70 const std::unordered_set<ULONGLONG> &reloc_values
74 LOG_ERROR(
"Invalid IMAGE_DELAYLOAD_DESCRIPTOR");
79 auto convert_va_to_rva = [&](ULONGLONG& addr) ->
bool {
80 if (reloc_values.find(addr) != reloc_values.end()) {
81 if (addr < img_base) {
82 LOG_ERROR(
"Invalid VA: 0x%llx cannot convert safely", addr);
93 if (!convert_va_to_rva(iat_addr) || !convert_va_to_rva(thunk_addr)) {
97 if (iat_addr > moduleSize || thunk_addr > moduleSize) {
101 LOG_INFO(
"iat_addr: 0x%llx, thunk_addr: 0x%llx", iat_addr, thunk_addr);
103 T_FIELD* record_va = (T_FIELD*)((ULONGLONG)modulePtr + iat_addr);
104 T_IMAGE_THUNK_DATA* thunk_va = (T_IMAGE_THUNK_DATA*)((ULONGLONG)modulePtr + thunk_addr);
106 for (; ; record_va++, thunk_va++) {
112 if (*record_va == 0)
break;
114 ULONGLONG iat_rva =
static_cast<ULONGLONG
>(*record_va);
115 if (!convert_va_to_rva(iat_rva))
return false;
117 LOG_DEBUG(
"IAT VA: 0x%llx RVA: 0x%llx",
static_cast<unsigned long long>(*record_va),
static_cast<unsigned long long>(iat_rva));
119 const T_FIELD* iat_record_ptr = (T_FIELD*)((ULONGLONG)modulePtr + iat_rva);
124 FARPROC hProc =
nullptr;
125 if (thunk_va->u1.Ordinal & ordinal_flag) {
126 T_FIELD raw_ordinal = thunk_va->u1.Ordinal & (~ordinal_flag);
127 LOG_DEBUG(
"ord: 0x%llx",
static_cast<unsigned long long>(raw_ordinal));
129 hProc = func_resolver->
resolve_func(lib_name, MAKEINTRESOURCEA(raw_ordinal));
133 ULONGLONG name_rva = thunk_va->u1.AddressOfData;
134 if (!convert_va_to_rva(name_rva))
return false;
136 PIMAGE_IMPORT_BY_NAME by_name = (PIMAGE_IMPORT_BY_NAME)((ULONGLONG)modulePtr + name_rva);
138 LOG_ERROR(
"Invalid pointer to IMAGE_IMPORT_BY_NAME");
142 LPSTR func_name =
reinterpret_cast<LPSTR
>(by_name->Name);
149 hProc = func_resolver->
resolve_func(lib_name, func_name);
155 *record_va = (T_FIELD) hProc;
156 LOG_DEBUG(
"Delayload Function resolved");
159 LOG_DEBUG(
"Delayload Function not resolved");
172 bool is_loader64 =
false;
176 if (is_64bit != is_loader64) {
177 LOG_ERROR(
"Loader/Payload bitness mismatch.");
183 if (!func_resolver) {
186 size_t table_size = 0;
193 std::unordered_set<ULONGLONG> reloc_values;
194 CollectRelocs callback(modulePtr, module_size,
peconv::is64bit(modulePtr), reloc_values);
197 LOG_DEBUG(
"Delay-import table found, table_size = %zu bytes.", table_size);
200 for (
size_t i = 0; i < max_count; i++) {
207 if (dll_name_rva > moduleBase) {
208 dll_name_rva -= moduleBase;
210 char* dll_name = (
char*)((ULONGLONG) modulePtr + dll_name_rva);
211 if (!
validate_ptr(modulePtr, module_size, dll_name,
sizeof(
char)))
continue;
212 LOG_DEBUG(
"Processing delayed imports for: %s", dll_name);
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name)=0
bool parse_delayed_desc(BYTE *modulePtr, const size_t moduleSize, const ULONGLONG img_base, LPSTR lib_name, const T_FIELD ordinal_flag, IMAGE_DELAYLOAD_DESCRIPTOR *desc, peconv::t_function_resolver *func_resolver, const std::unordered_set< ULONGLONG > &reloc_values)
Parsing and filling the Delayload Import Table.
struct _IMAGE_DELAYLOAD_DESCRIPTOR IMAGE_DELAYLOAD_DESCRIPTOR
Parsing and filling the Import Table.
#define LOG_DEBUG(fmt,...)
#define LOG_INFO(fmt,...)
#define LOG_ERROR(fmt,...)
bool load_delayed_imports(BYTE *modulePtr, const ULONGLONG moduleBase, t_function_resolver *func_resolver=nullptr)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
DWORD get_image_size(IN const BYTE *payload)
bool process_relocation_table(IN PVOID modulePtr, IN SIZE_T moduleSize, IN RelocBlockCallback *callback)
bool is64bit(IN const BYTE *pe_buffer)
bool is_valid_import_name(const PBYTE modulePtr, const size_t moduleSize, LPSTR lib_name)
IMAGE_DATA_DIRECTORY * get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty=false)
IMAGE_DELAYLOAD_DESCRIPTOR * get_delayed_imps(IN const BYTE *modulePtr, IN const size_t moduleSize, OUT size_t &dir_size)
Operating on PE file's relocations table.
DWORD ImportAddressTableRVA