summaryrefslogtreecommitdiff
path: root/sysmap/src/mapper/pe.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysmap/src/mapper/pe.h')
-rw-r--r--sysmap/src/mapper/pe.h118
1 files changed, 118 insertions, 0 deletions
diff --git a/sysmap/src/mapper/pe.h b/sysmap/src/mapper/pe.h
new file mode 100644
index 0000000..9841cb2
--- /dev/null
+++ b/sysmap/src/mapper/pe.h
@@ -0,0 +1,118 @@
+#pragma once
+
+#include <linuxpe>
+
+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<std::string, export_data_t> exports;
+ std::vector<win::section_header_t> sections;
+
+ image_t() : base{ 0 } { }
+ image_t(uintptr_t b) : base{ b } {
+ auto image = reinterpret_cast<win::image_x64_t*>(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<win::export_directory_t*>(export_dir);
+
+ if (exp->num_functions == 0) return;
+
+ auto names = reinterpret_cast<uint32_t*>(b + exp->rva_names);
+ auto funcs = reinterpret_cast<uint32_t*>(b + exp->rva_functions);
+ auto ords = reinterpret_cast<uint16_t*>(b + exp->rva_name_ordinals);
+
+ if (!names || !funcs || !ords) return;
+
+ for (size_t i{}; i < exp->num_names; i++) {
+ std::string name = reinterpret_cast<const char*>(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<char*>(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<std::string, std::vector<import_data_t>> imports;
+ std::unordered_map<uintptr_t, std::vector<win::reloc_entry_t>> relocs;
+ std::vector<win::section_header_t> sections;
+
+ raw_image_t(std::vector<u8>& buffer) {
+ auto image = reinterpret_cast<win::image_x64_t*>(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<win::import_directory_t>(import_rva);
+
+ for (uint32_t i = 0; i < desc->rva_name; i = desc->rva_name, ++desc) {
+ std::string mod = image->rva_to_ptr<char>(desc->rva_name);
+
+ auto thunk = image->rva_to_ptr<win::image_thunk_data_x64_t>(desc->rva_original_first_thunk);
+
+ for (uint32_t index = 0; thunk->address; index += sizeof(u64), ++thunk) {
+ auto named_import = image->rva_to_ptr<win::image_named_import_t>(thunk->address);
+
+ if (!thunk->is_ordinal) {
+ std::transform(mod.begin(), mod.end(), mod.begin(), ::tolower);
+
+ imports[mod].emplace_back(import_data_t{ reinterpret_cast<const char*>(named_import->name), desc->rva_first_thunk + index });
+ }
+ }
+ }
+
+ auto reloc_dir = image->rva_to_ptr<win::reloc_directory_t>(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);
+ }
+ }
+ }
+ };
+}; \ No newline at end of file