From 2635472896addee5fe6b0eba2942abac01be937f Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 5 Nov 2016 13:16:16 -0700 Subject: [PATCH] more unpacking for Mach-o (pre-3.91 ?) modified: p_mach.cpp modified: p_mach.h --- src/p_mach.cpp | 7 ++++-- src/p_mach.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 101941ae..8b8a887a 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -1617,9 +1617,12 @@ int PackMachBase::canUnpack() } } else if (Mach_segment_command::LC_UNIXTHREAD==ptr->cmd) { - rip = entryVMA; + rip = entryVMA = threadc_getPC(ptr); } - } + } + if (391==style && 0==offLINK && 2==ncmds) { // pre-3.91 ? + offLINK = ptrTEXT->fileoff + ptrTEXT->filesize; // fake __LINKEDIT at EOF + } if (0 == style || 0 == offLINK) { return false; } diff --git a/src/p_mach.h b/src/p_mach.h index 4ea7f635..921d705a 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -827,6 +827,8 @@ protected: static int __acc_cdecl_qsort compare_segment_command(void const *aa, void const *bb); + virtual upx_uint64_t threadc_getPC(void /*MachThreadCommand*/ const *) = 0; + upx_uint64_t entryVMA; unsigned my_cputype; unsigned my_filetype; @@ -937,6 +939,17 @@ protected: } void threado_rewrite(OutputFile *fo) { fo->rewrite(&threado, sizeof(threado)); } void threado_write(OutputFile *fo) { fo->write(&threado, sizeof(threado)); } + + upx_uint64_t threadc_getPC(void const *ptr) { + Mach_thread_command const *tc = (Mach_thread_command const *)ptr; + if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD + || tc->cmdsize!=sizeof(threado) + || tc->flavor!=my_thread_flavor + || tc->count!=my_thread_state_word_count) { + return ~0ull; + } + return tc->state.srr0; + } }; class PackMachPPC64LE : public PackMachBase @@ -978,6 +991,17 @@ protected: } void threado_rewrite(OutputFile *fo) { fo->rewrite(&threado, sizeof(threado)); } void threado_write(OutputFile *fo) { fo->write(&threado, sizeof(threado)); } + + upx_uint64_t threadc_getPC(void const *ptr) { + Mach_thread_command const *tc = (Mach_thread_command const *)ptr; + if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD + || tc->cmdsize!=sizeof(threado) + || tc->flavor!=my_thread_flavor + || tc->count!=my_thread_state_word_count) { + return ~0ull; + } + return tc->state64.srr0; + } }; class PackDylibPPC32 : public PackMachPPC32 @@ -1049,6 +1073,17 @@ protected: } void threado_rewrite(OutputFile *fo) { fo->rewrite(&threado, sizeof(threado)); } void threado_write(OutputFile *fo) { fo->write(&threado, sizeof(threado)); } + + upx_uint64_t threadc_getPC(void const *ptr) { + Mach_thread_command const *tc = (Mach_thread_command const *)ptr; + if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD + || tc->cmdsize!=sizeof(threado) + || tc->flavor!=my_thread_flavor + || tc->count!=my_thread_state_word_count) { + return ~0ull; + } + return tc->state.eip; + } }; class PackDylibI386 : public PackMachI386 @@ -1106,6 +1141,17 @@ protected: } void threado_rewrite(OutputFile *fo) { fo->rewrite(&threado, sizeof(threado)); } void threado_write(OutputFile *fo) { fo->write(&threado, sizeof(threado)); } + + upx_uint64_t threadc_getPC(void const *ptr) { + Mach_thread_command const *tc = (Mach_thread_command const *)ptr; + if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD + || tc->cmdsize!=sizeof(threado) + || tc->flavor!=my_thread_flavor + || tc->count!=my_thread_state_word_count) { + return ~0ull; + } + return tc->state.rip; + } }; class PackDylibAMD64 : public PackMachAMD64 @@ -1163,6 +1209,17 @@ protected: } void threado_rewrite(OutputFile *fo) { fo->rewrite(&threado, sizeof(threado)); } void threado_write(OutputFile *fo) { return fo->write(&threado, sizeof(threado)); } + + upx_uint64_t threadc_getPC(void const *ptr) { + Mach_thread_command const *tc = (Mach_thread_command const *)ptr; + if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD + || tc->cmdsize!=sizeof(threado) + || tc->flavor!=my_thread_flavor + || tc->count!=my_thread_state_word_count) { + return ~0ull; + } + return tc->state.pc; + } }; class PackMachARM64EL : public PackMachBase @@ -1205,6 +1262,17 @@ protected: } void threado_rewrite(OutputFile *fo) { fo->rewrite(&threado, sizeof(threado)); } void threado_write(OutputFile *fo) { fo->write(&threado, sizeof(threado)); } + + upx_uint64_t threadc_getPC(void const *ptr) { + Mach_thread_command const *tc = (Mach_thread_command const *)ptr; + if (tc->cmd!=Mach_segment_command::LC_UNIXTHREAD + || tc->cmdsize!=sizeof(threado) + || tc->flavor!=my_thread_flavor + || tc->count!=my_thread_state_word_count) { + return ~0ull; + } + return tc->state.pc; + } }; class PackMachFat : public Packer