From 49c8efdc6dc827e28ed004923d67b645b6f0dd8e Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Mon, 4 May 2015 17:38:34 -0500 Subject: [PATCH] XexGetProcedureAddress by name implemented. --- src/xenia/kernel/objects/xkernel_module.cc | 5 ++ src/xenia/kernel/objects/xkernel_module.h | 1 + src/xenia/kernel/objects/xmodule.h | 1 + src/xenia/kernel/objects/xuser_module.cc | 11 ++++ src/xenia/kernel/objects/xuser_module.h | 1 + src/xenia/kernel/util/xex2.cc | 59 ++++++++++++++++++++++ src/xenia/kernel/util/xex2.h | 10 ++++ src/xenia/kernel/util/xex2_info.h | 14 ++++- 8 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/objects/xkernel_module.cc b/src/xenia/kernel/objects/xkernel_module.cc index 91d8470fb..e46e88e16 100644 --- a/src/xenia/kernel/objects/xkernel_module.cc +++ b/src/xenia/kernel/objects/xkernel_module.cc @@ -34,5 +34,10 @@ void* XKernelModule::GetProcAddressByOrdinal(uint16_t ordinal) { return NULL; } +void* XKernelModule::GetProcAddressByName(const char* name) { + XELOGE("GetProcAddressByName not implemented"); + return NULL; +} + } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/objects/xkernel_module.h b/src/xenia/kernel/objects/xkernel_module.h index 98691f41d..a4117032c 100644 --- a/src/xenia/kernel/objects/xkernel_module.h +++ b/src/xenia/kernel/objects/xkernel_module.h @@ -24,6 +24,7 @@ class XKernelModule : public XModule { virtual ~XKernelModule(); virtual void* GetProcAddressByOrdinal(uint16_t ordinal); + virtual void* GetProcAddressByName(const char* name); protected: Emulator* emulator_; diff --git a/src/xenia/kernel/objects/xmodule.h b/src/xenia/kernel/objects/xmodule.h index 0abe66931..225a80987 100644 --- a/src/xenia/kernel/objects/xmodule.h +++ b/src/xenia/kernel/objects/xmodule.h @@ -27,6 +27,7 @@ class XModule : public XObject { const std::string& name() const { return name_; } virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0; + virtual void* GetProcAddressByName(const char *name) = 0; virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data, uint32_t* out_section_size); diff --git a/src/xenia/kernel/objects/xuser_module.cc b/src/xenia/kernel/objects/xuser_module.cc index dc7dc0c1e..86ecb025a 100644 --- a/src/xenia/kernel/objects/xuser_module.cc +++ b/src/xenia/kernel/objects/xuser_module.cc @@ -148,6 +148,17 @@ void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) { return NULL; } +void* XUserModule::GetProcAddressByName(const char* name) { + PEExport export; + int ret = xe_xex2_lookup_export(xex_, name, export); + + // Failure. + if (ret) + return NULL; + + return (void *)export.addr; +} + X_STATUS XUserModule::GetSection(const char* name, uint32_t* out_section_data, uint32_t* out_section_size) { auto header = xe_xex2_get_header(xex_); diff --git a/src/xenia/kernel/objects/xuser_module.h b/src/xenia/kernel/objects/xuser_module.h index 590a0a5b4..19edc0c3b 100644 --- a/src/xenia/kernel/objects/xuser_module.h +++ b/src/xenia/kernel/objects/xuser_module.h @@ -33,6 +33,7 @@ class XUserModule : public XModule { X_STATUS LoadFromMemory(const void* addr, const size_t length); virtual void* GetProcAddressByOrdinal(uint16_t ordinal); + virtual void* GetProcAddressByName(const char* name); virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data, uint32_t* out_section_size); diff --git a/src/xenia/kernel/util/xex2.cc b/src/xenia/kernel/util/xex2.cc index c2dfcb40b..d645e6adb 100644 --- a/src/xenia/kernel/util/xex2.cc +++ b/src/xenia/kernel/util/xex2.cc @@ -49,6 +49,8 @@ typedef struct xe_xex2 { size_t count; xe_xex2_import_info_t *infos; } library_imports[16]; + + xe_xex2_export_table *export_table; } xe_xex2_t; int xe_xex2_read_header(const uint8_t *addr, const size_t length, @@ -237,6 +239,11 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length, case XEX_HEADER_DEFAULT_HEAP_SIZE: header->exe_heap_size = opt_header->value; break; + case XEX_HEADER_EXPORTS_BY_NAME: { + // IMAGE_DATA_DIRECTORY (w/ offset from PE file base) + header->export_table_offset = xe::load_and_swap(pp); + // size = xe::load_and_swap(pp + 0x04); + } break; case XEX_HEADER_IMPORT_LIBRARIES: { const size_t max_count = xe::countof(header->import_libraries); size_t count = xe::load_and_swap(pp + 0x08); @@ -869,6 +876,20 @@ int xe_xex2_load_pe(xe_xex2_ref xex) { xex->sections->push_back(section); } + if (header->export_table_offset) { + // This table is located inside of the PE (for some reason) + xe_xex2_export_table *table = (xe_xex2_export_table *)xex->memory->TranslateVirtual(xex->header.loader_info.export_table); + xex->export_table = table; + // cmp magic... + + table->base = xe::load_and_swap(&table->base); + table->imagebaseaddr = xe::load_and_swap(&table->imagebaseaddr); + table->count = xe::load_and_swap(&table->count); + for (int i = 0; i < table->count; i++) { + table->ordOffset[i] = xe::load_and_swap(&table->ordOffset[i]); + } + } + // DumpTLSDirectory(pImageBase, pNTHeader, (PIMAGE_TLS_DIRECTORY32)0); // DumpExportsSection(pImageBase, pNTHeader); return 0; @@ -982,3 +1003,41 @@ int xe_xex2_get_import_infos(xe_xex2_ref xex, *out_import_infos = xex->library_imports[library_index].infos; return 0; } + +int xe_xex2_lookup_export(xe_xex2_ref xex, const char *name, + PEExport &peexport) { + auto header = xe_xex2_get_header(xex); + + // no exports :( + if (!header->export_table_offset) { + return 1; + } + + uint64_t loadaddr = (uint64_t)xex->memory->TranslateVirtual(header->loader_info.load_address); + IMAGE_EXPORT_DIRECTORY *e = (PIMAGE_EXPORT_DIRECTORY)(loadaddr + header->export_table_offset); + + // e->AddressOfX RVAs are relative to the IMAGE_EXPORT_DIRECTORY! + uint32_t* function_table = (uint32_t*)((uint64_t)e + e->AddressOfFunctions); // Functions relative to base + uint32_t* name_table = (uint32_t*)((uint64_t)e + e->AddressOfNames); // Names relative to directory + uint16_t* ordinal_table = (uint16_t*)((uint64_t)e + e->AddressOfNameOrdinals); // Table of ordinals + + const char* mod_name = (const char*)((uint64_t)e + e->Name); + + for (int i = 0; i < e->NumberOfNames; i++) { + const char *fn_name = (const char *)((uint64_t)e + name_table[i]); + uint16_t ordinal = ordinal_table[i]; + uint64_t addr = (uint64_t)(loadaddr + function_table[ordinal]); + + if (!strcmp(name, fn_name)) { + // We have a match! + peexport.name = fn_name; + peexport.addr = addr; + peexport.ordinal = ordinal; + + return 0; + } + } + + // No match + return 1; +} \ No newline at end of file diff --git a/src/xenia/kernel/util/xex2.h b/src/xenia/kernel/util/xex2.h index 212badb7c..dbea70cf5 100644 --- a/src/xenia/kernel/util/xex2.h +++ b/src/xenia/kernel/util/xex2.h @@ -43,6 +43,13 @@ class PESection { uint32_t flags; // kXEPESection* }; +struct PEExport { + const char *name; + uint32_t ordinal; + + uint64_t addr; // Function address +}; + xe_xex2_ref xe_xex2_load(xe::Memory* memory, const void* addr, const size_t length, xe_xex2_options_t options); void xe_xex2_dealloc(xe_xex2_ref xex); @@ -55,4 +62,7 @@ int xe_xex2_get_import_infos(xe_xex2_ref xex, xe_xex2_import_info_t** out_import_infos, size_t* out_import_info_count); +int xe_xex2_lookup_export(xe_xex2_ref xex, const char *name, + PEExport &peexport); + #endif // XENIA_KERNEL_UTIL_XEX2_H_ diff --git a/src/xenia/kernel/util/xex2_info.h b/src/xenia/kernel/util/xex2_info.h index 5256fa5cd..6109bd963 100644 --- a/src/xenia/kernel/util/xex2_info.h +++ b/src/xenia/kernel/util/xex2_info.h @@ -295,6 +295,17 @@ typedef struct { xe_xex2_approval_type approval; } xe_xex2_static_library_t; +// credits: some obscure pastebin (http://pastebin.com/ZRvr3Sgj) +typedef struct { + uint32_t magic[3]; + uint32_t modulenumber[2]; + uint32_t version[3]; + uint32_t imagebaseaddr; // must be <<16 to be accurate + uint32_t count; + uint32_t base; + uint32_t ordOffset[1]; // ordOffset[0] + (imagebaseaddr << 16) = function offset of ordinal 1 +} xe_xex2_export_table; + typedef enum { XEX_ENCRYPTION_NONE = 0, XEX_ENCRYPTION_NORMAL = 1, @@ -397,7 +408,7 @@ typedef struct { uint8_t import_table_digest[20]; uint8_t media_id[16]; uint8_t file_key[16]; - uint32_t export_table; + uint32_t export_table; // address of the export table uint8_t header_digest[20]; xe_xex2_region_flags game_regions; xe_xex2_media_flags media_flags; @@ -434,6 +445,7 @@ typedef struct { xe_xex2_tls_info_t tls_info; size_t import_library_count; xe_xex2_import_library_t import_libraries[32]; + size_t export_table_offset; // PE Export Directory size_t static_library_count; xe_xex2_static_library_t static_libraries[32]; xe_xex2_file_format_info_t file_format_info;