#pragma once #include namespace pe { struct export_data_t { uintptr_t func_rva; std::string f_mod; std::string f_func; }; struct image_t { uintptr_t base; std::unordered_map exports; std::vector sections; image_t() : base{ 0 } { } image_t(uintptr_t b) : base{ b } { auto image = reinterpret_cast(b); auto nt = image->get_nt_headers(); for (auto &sec : nt->sections()) { sections.emplace_back(sec); } auto export_dir = b + nt->optional_header.data_directories.export_directory.rva; auto export_size = nt->optional_header.data_directories.export_directory.size; auto exp = reinterpret_cast(export_dir); if (exp->num_functions == 0) return; auto names = reinterpret_cast(b + exp->rva_names); auto funcs = reinterpret_cast(b + exp->rva_functions); auto ords = reinterpret_cast(b + exp->rva_name_ordinals); if (!names || !funcs || !ords) return; for (size_t i{}; i < exp->num_names; i++) { std::string name = reinterpret_cast(b + names[i]); export_data_t ret; ret.func_rva = funcs[ords[i]]; uintptr_t proc_addr = b + funcs[ords[i]]; if (proc_addr > export_dir && proc_addr < export_dir + export_size) { std::string forwarded_name = reinterpret_cast(proc_addr); size_t delim = forwarded_name.find('.'); if (delim == std::string::npos) continue; ret.f_mod = forwarded_name.substr(0, delim + 1); ret.f_mod.append("dll"); std::transform(ret.f_mod.begin(), ret.f_mod.end(), ret.f_mod.begin(), ::tolower); ret.f_func = forwarded_name.substr(delim + 1); } exports[name] = ret; } } }; struct import_data_t { std::string name; uintptr_t rva; }; struct raw_image_t { win::nt_headers_x64_t* nt; std::unordered_map> imports; std::unordered_map> relocs; std::vector sections; raw_image_t(std::vector& buffer) { auto image = reinterpret_cast(buffer.data()); nt = image->get_nt_headers(); for (auto& sec : nt->sections()) { sections.emplace_back(sec); } auto import_rva = nt->optional_header.data_directories.import_directory.rva; auto desc = image->rva_to_ptr(import_rva); for (uint32_t i = 0; i < desc->rva_name; i = desc->rva_name, ++desc) { std::string mod = image->rva_to_ptr(desc->rva_name); auto thunk = image->rva_to_ptr(desc->rva_original_first_thunk); for (uint32_t index = 0; thunk->address; index += sizeof(u64), ++thunk) { auto named_import = image->rva_to_ptr(thunk->address); if (!thunk->is_ordinal) { std::transform(mod.begin(), mod.end(), mod.begin(), ::tolower); imports[mod].emplace_back(import_data_t{ reinterpret_cast(named_import->name), desc->rva_first_thunk + index }); } } } auto reloc_dir = image->rva_to_ptr(nt->optional_header.data_directories.basereloc_directory.rva); for (auto* block = &reloc_dir->first_block; block->base_rva; block = block->next()) { for (auto& entry : *block) { relocs[block->base_rva].emplace_back(entry); } } } }; };