From fe4a8f33b1152bd624d5901351a03ad26ff66633 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Wed, 3 May 2017 08:30:21 -0700 Subject: [PATCH] Start on darwin.macho-dylib modified: p_mach.cpp modified: p_mach.h modified: packmast.cpp --- src/p_mach.cpp | 53 ++++++++++++++++++++++++++++++++---------------- src/p_mach.h | 4 ++-- src/packmast.cpp | 2 +- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/p_mach.cpp b/src/p_mach.cpp index f0bb8660..523b7260 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -104,8 +104,8 @@ PackMachBase::PackMachBase(InputFile *f, unsigned cputype, unsigned filetype, unsigned flavor, unsigned count, unsigned size) : super(f), my_cputype(cputype), my_filetype(filetype), my_thread_flavor(flavor), my_thread_state_word_count(count), my_thread_command_size(size), - n_segment(0), rawmseg(NULL), msegcmd(NULL), o_routines_cmd(0), - prev_init_address(0), pagezero_vmsize(0) + n_segment(0), rawmseg(NULL), msegcmd(NULL), o__mod_init_func(0), + prev_mod_init_func(0), pagezero_vmsize(0) { MachClass::compileTimeAssertions(); bele = N_BELE_CTP::getRTP((const BeLePolicy*) NULL); @@ -354,13 +354,13 @@ void PackMachI386::addStubEntrySections(Filter const *ft) void PackMachAMD64::addStubEntrySections(Filter const * /*ft*/) { - if (my_filetype!=Mach_header::MH_EXECUTE) { + if (my_filetype==Mach_header::MH_DYLIB) { addLoader("MACHMAINX", NULL); } else { addLoader("AMD64BXX", NULL); + addLoader("MACH_UNC", NULL); } - addLoader("MACH_UNC", NULL); //addLoader(getDecompressorSections(), NULL); addLoader( ( M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E,NRV_TAIL" @@ -876,10 +876,15 @@ void PackMachBase::pack4dylib( // append PackHeader (Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg); for ( ; seg < endseg; seg = (Mach_segment_command const *)( seg->cmdsize + (char const *)seg ) - ) switch (~Mach_segment_command::LC_REQ_DYLD & seg->cmd) { + ) switch (seg->cmd & ~Mach_segment_command::LC_REQ_DYLD) { default: // unknown if any file offset field must slide printf("Unrecognized Macho cmd offset=0x%lx cmd=0x%lx size=0x%lx\n", (unsigned long)((const char *)seg - (const char *)rawmseg), (unsigned long)seg->cmd, (unsigned long)seg->cmdsize); // fall through + case Mach_segment_command::LC_DYLD_INFO_ONLY & ~Mach_segment_command::LC_REQ_DYLD: + case Mach_segment_command::LC_VERSION_MIN_MACOSX: + case Mach_segment_command::LC_FUNCTION_STARTS: // points into __LINKEDIT + case Mach_segment_command::LC_DATA_IN_CODE: // points into __LINKEDIT + case Mach_segment_command::LC_SOURCE_VERSION: case Mach_segment_command::LC_THREAD: case Mach_segment_command::LC_UNIXTHREAD: case Mach_segment_command::LC_LOAD_DYLIB: @@ -1092,7 +1097,7 @@ void PackDylibI386::pack3(OutputFile *fo, Filter &ft) // append loader fo->write(&zero, 3& (0u-len)); len += (3& (0u-len)) + 4*sizeof(disp); - disp = prev_init_address; + disp = prev_mod_init_func; fo->write(&disp, sizeof(disp)); // user .init_address disp = sizeof(mhdro) + mhdro.sizeofcmds + sizeof(l_info) + sizeof(p_info); @@ -1119,7 +1124,7 @@ void PackDylibAMD64::pack3(OutputFile *fo, Filter &ft) // append loader disp64= len; fo->write(&disp64, sizeof(disp64)); // __mod_init_func - disp = prev_init_address; + disp = prev_mod_init_func; fo->write(&disp, sizeof(disp)); // user .init_address disp = sizeof(mhdro) + mhdro.sizeofcmds + sizeof(l_info) + sizeof(p_info); @@ -1142,7 +1147,7 @@ void PackDylibPPC32::pack3(OutputFile *fo, Filter &ft) // append loader fo->write(&zero, 3& (0u-len)); len += (3& (0u-len)) + 4*sizeof(disp); - disp = prev_init_address; + disp = prev_mod_init_func; fo->write(&disp, sizeof(disp)); // user .init_address disp = sizeof(mhdro) + mhdro.sizeofcmds + sizeof(l_info) + sizeof(p_info); @@ -1165,7 +1170,7 @@ void PackDylibPPC64LE::pack3(OutputFile *fo, Filter &ft) // append loader fo->write(&zero, 3& (0u-len)); len += (3& (0u-len)) + 4*sizeof(disp); - disp = prev_init_address; + disp = prev_mod_init_func; fo->write(&disp, sizeof(disp)); // user .init_address disp = sizeof(mhdro) + mhdro.sizeofcmds + sizeof(l_info) + sizeof(p_info); @@ -1824,7 +1829,6 @@ template bool PackMachBase::canPack() { unsigned const lc_seg = lc_segment[sizeof(Addr)>>3]; - unsigned const lc_rout = lc_routines[sizeof(Addr)>>3]; fi->seek(0, SEEK_SET); fi->readx(&mhdri, sizeof(mhdri)); @@ -1835,16 +1839,36 @@ bool PackMachBase::canPack() return false; my_cpusubtype = mhdri.cpusubtype; - rawmseg = (Mach_segment_command *)new char[(unsigned) mhdri.sizeofcmds]; + unsigned const sz_mhcmds = (unsigned)mhdri.sizeofcmds; + if (16384 < sz_mhcmds) { // somewhat arbitrary, but amd64-darwin.macho-upxmain.c + throwCantPack("16384 < Mach_header.sizeofcmds"); + } + rawmseg = (Mach_segment_command *)new char[sz_mhcmds]; fi->readx(rawmseg, mhdri.sizeofcmds); unsigned const ncmds = mhdri.ncmds; + if (256 < ncmds) { // arbitrary, but guard against garbage + throwCantPack("256 < Mach_header.ncmds"); + } msegcmd = new Mach_segment_command[ncmds]; unsigned char const *ptr = (unsigned char const *)rawmseg; for (unsigned j= 0; j < ncmds; ++j) { Mach_segment_command const *segptr = (Mach_segment_command const *)ptr; if (lc_seg == segptr->cmd) { msegcmd[j] = *segptr; + if (!strcmp("__DATA", segptr->segname)) { + for (Mach_section_command const *secptr = (Mach_section_command const *)(1+ segptr); + ((char const *)secptr - (char const *)segptr) < segptr->cmdsize; + ++secptr + ) { + if (sizeof(Addr) == secptr->size + && !strcmp("__mod_init_func", secptr->sectname)) { + o__mod_init_func = secptr->offset; + fi->seek(o__mod_init_func, SEEK_SET); + fi->readx(&prev_mod_init_func, sizeof(Addr)); + } + } + } } else { memcpy(&msegcmd[j], ptr, 2*sizeof(unsigned)); // cmd and size @@ -1867,14 +1891,9 @@ bool PackMachBase::canPack() memcpy(&cmdSRCVER, ptr, sizeof(cmdSRCVER)); } break; } - if (((Mach_segment_command const *)ptr)->cmd == lc_rout) { - o_routines_cmd = (const char *)ptr - (const char *)rawmseg; - prev_init_address = - ((Mach_routines_command const *)ptr)->init_address; - } ptr += (unsigned) ((const Mach_segment_command *)ptr)->cmdsize; } - if (Mach_header::MH_DYLIB==my_filetype && 0==o_routines_cmd) { + if (Mach_header::MH_DYLIB==my_filetype && 0==o__mod_init_func) { infoWarning("missing -init function"); return false; } diff --git a/src/p_mach.h b/src/p_mach.h index 35660046..fc034722 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -853,8 +853,8 @@ protected: upx_byte const *stub_main; Mach_segment_command *rawmseg; // as input, with sections Mach_segment_command *msegcmd; // LC_SEGMENT first, without sections - unsigned o_routines_cmd; // file offset to LC_ROUINTES - upx_uint64_t prev_init_address; + unsigned o__mod_init_func; // file offset to __DATA.__mod_init_func Mach_section_command + upx_uint64_t prev_mod_init_func; upx_uint64_t pagezero_vmsize; Mach_header mhdri; diff --git a/src/packmast.cpp b/src/packmast.cpp index ae921a08..78aca00d 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -216,6 +216,7 @@ Packer *PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const optio D(PackCom); // Mach (MacOS X PowerPC) + D(PackDylibAMD64); D(PackMachPPC32); D(PackMachPPC64LE); D(PackMachI386); @@ -227,7 +228,6 @@ Packer *PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const optio // assumes about .dylib file structure. // D(PackDylibI386); // D(PackDylibPPC32); - // D(PackDylibAMD64); return NULL; #undef D