mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Mach-o MH_EXECUTE rewrite; work-in-progress
On amd64, otool and lldb accept the results. The entry point points to the unfilter and uncompress routines. Somehow _start has been lost. modified: p_mach.cpp modified: p_mach.h modified: p_mach_enum.h modified: stub/amd64-darwin.macho-entry.h modified: stub/src/amd64-darwin.macho-entry.S modified: stub/src/amd64-darwin.macho-upxmain.c modified: stub/src/i386-darwin.macho-upxmain.c modified: stub/src/powerpc-darwin.macho-upxmain.c modified: stub/tmp/amd64-darwin.macho-entry.bin.dump
This commit is contained in:
parent
e633c51b50
commit
4f6979967d
238
src/p_mach.cpp
238
src/p_mach.cpp
|
@ -570,20 +570,13 @@ void PackMachBase<T>::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
|||
super::pack4(fo, ft);
|
||||
|
||||
if (Mach_header::MH_EXECUTE == my_filetype) {
|
||||
upx_uint64_t const zero = 0;
|
||||
unsigned const len = fo->getBytesWritten();
|
||||
fo->write(&zero, 7& (0u-len));
|
||||
unsigned len = fo->getBytesWritten();
|
||||
char page[~PAGE_MASK]; memset(page, 0, sizeof(page));
|
||||
fo->write(page, ~PAGE_MASK & (0u - len));
|
||||
len += ~PAGE_MASK & (0u - len) ;
|
||||
|
||||
unsigned const eofcmpr = fo->getBytesWritten();
|
||||
if (Mach_header::CPU_TYPE_X86_64 == my_cputype) {
|
||||
// sneak in a little below 4GiB
|
||||
segTEXT.vmaddr = segZERO.vmaddr + segZERO.vmsize;
|
||||
}
|
||||
else {
|
||||
// ::pack1 set segTEXT.vmaddr to be va_hi: no conflict
|
||||
}
|
||||
segTEXT.filesize = eofcmpr;
|
||||
segTEXT.vmsize += eofcmpr; // utilize GAP + NO_LAP + sz_unc - sz_cpr
|
||||
segTEXT.filesize = len;
|
||||
segTEXT.vmsize = len; // FIXME? utilize GAP + NO_LAP + sz_unc - sz_cpr
|
||||
secTEXT.offset = overlay_offset - sizeof(linfo);
|
||||
secTEXT.addr = segTEXT.vmaddr + secTEXT.offset;
|
||||
secTEXT.size = segTEXT.filesize - secTEXT.offset;
|
||||
|
@ -593,7 +586,13 @@ void PackMachBase<T>::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
|||
}
|
||||
secXHDR.addr += secXHDR.offset;
|
||||
unsigned offLINK = segLINK.fileoff;
|
||||
segLINK.vmaddr = segTEXT.vmaddr + offLINK;
|
||||
|
||||
|
||||
segLINK.fileoff = len; // must be in the file
|
||||
segLINK.vmaddr = len + segTEXT.vmaddr;
|
||||
fo->write(page, 16); len += 16;
|
||||
segLINK.vmsize = 16;
|
||||
segLINK.filesize = 16;
|
||||
|
||||
// Get a writeable copy of the stub to make editing easier.
|
||||
ByteArray(upxstub, sz_stub_main);
|
||||
|
@ -602,7 +601,6 @@ void PackMachBase<T>::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
|||
Mach_header *const mhp = (Mach_header *)upxstub;
|
||||
mhp->cpusubtype = my_cpusubtype;
|
||||
char *tail = (char *)(1+ mhp);
|
||||
Mach_segment_command *segtxt = 0; // in temp for output
|
||||
Mach_section_command *sectxt = 0; // in temp for output
|
||||
unsigned txt_addr = 0;
|
||||
char *const lcp_end = mhdro.sizeofcmds + tail;
|
||||
|
@ -612,7 +610,6 @@ void PackMachBase<T>::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
|||
//unsigned cmdsize = mhdro.sizeofcmds;
|
||||
unsigned delta = 0;
|
||||
|
||||
unsigned va_next = 0;
|
||||
for (unsigned j = 0; j < ncmds; ++j) {
|
||||
unsigned skip = 0;
|
||||
unsigned sz_cmd = lcp->cmdsize;
|
||||
|
@ -622,94 +619,19 @@ void PackMachBase<T>::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
|||
case Mach_command::LC_SEGMENT: // fall through
|
||||
case Mach_command::LC_SEGMENT_64: {
|
||||
Mach_segment_command *const segptr = (Mach_segment_command *)lcp;
|
||||
if (!strcmp("__PAGEZERO", segptr->segname)) {
|
||||
if (pagezero_vmsize < 0xF0000000ull) {
|
||||
segptr->vmsize = pagezero_vmsize;
|
||||
}
|
||||
}
|
||||
if (!strcmp("__TEXT", segptr->segname)) {
|
||||
segtxt = segptr; // remember base for appending
|
||||
sectxt = (Mach_section_command *)(1+ segptr);
|
||||
txt_addr = sectxt->addr;
|
||||
// Collapse into 1 section by appending onto the first section.
|
||||
unsigned off_hi = sectxt->size + sectxt->offset;
|
||||
Mach_section_command const *scpk = 1+ sectxt;
|
||||
for (unsigned k = 1; k < segptr->nsects; ++scpk, ++k) {
|
||||
if (off_hi == scpk->offset || scpk->size==0) {
|
||||
off_hi += scpk->size;
|
||||
sectxt->size += scpk->size;
|
||||
}
|
||||
else {
|
||||
if (!(Mach_header::CPU_TYPE_POWERPC == my_cputype
|
||||
&& 12==(unsigned)scpk->size
|
||||
&& !strcmp("__cstring", (char const *)&scpk->sectname))) {
|
||||
printWarn(fi->getName(), "Unexpected .text section %s size=%u\n",
|
||||
(char const *)&scpk->sectname, (unsigned)scpk->size);
|
||||
}
|
||||
// Assume the maximum size: to end of the page.
|
||||
sectxt->size = (segptr->vmsize + segptr->vmaddr) - sectxt->addr;
|
||||
// Try to stop the cascade of errors.
|
||||
off_hi = scpk->size + scpk->offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int const d = (-1+ segptr->nsects) * sizeof(secTEXT);
|
||||
if (0 < d) {
|
||||
segptr->nsects = 1;
|
||||
sz_cmd -= d;
|
||||
segptr->cmdsize -= d;
|
||||
mhp->sizeofcmds -= d;
|
||||
}
|
||||
if (Mach_header::CPU_TYPE_I386 == my_cputype
|
||||
|| Mach_header::CPU_TYPE_POWERPC == my_cputype ) {
|
||||
// Avoid overlap by moving to va_hi.
|
||||
upx_uint64_t const delt2 = segTEXT.vmaddr - segptr->vmaddr;
|
||||
segptr->vmaddr += delt2;
|
||||
sectxt->addr += delt2;
|
||||
}
|
||||
memcpy(&segTEXT, segptr, sizeof(segTEXT));
|
||||
memcpy(&secTEXT, sectxt, sizeof(secTEXT));
|
||||
va_next = segTEXT.vmsize + segTEXT.vmaddr;
|
||||
break;
|
||||
}
|
||||
if (!strcmp("__DATA", segptr->segname) && !segptr->vmsize) {
|
||||
// __DATA with no pages.
|
||||
// Use the space as Mach_segment_command for new segXHDR, or elide.
|
||||
segXHDR.cmdsize = sizeof(segXHDR); // no need for sections
|
||||
segXHDR.vmaddr = segTEXT.vmsize + segTEXT.vmaddr; // XXX FIXME
|
||||
segXHDR.vmsize = offLINK - segTEXT.vmsize;
|
||||
segXHDR.fileoff = segTEXT.filesize + segTEXT.fileoff; // XXX FIXME: assumes no __DATA in stub
|
||||
segXHDR.filesize = offLINK - segTEXT.filesize; // XXX FIXME: assumes no __DATA in stub;
|
||||
segXHDR.maxprot = Mach_command::VM_PROT_READ;
|
||||
segXHDR.nsects = 0;
|
||||
if (!segtxt) { // replace __DATA with segXHDR
|
||||
va_next = segXHDR.vmsize + segXHDR.vmaddr;
|
||||
memcpy(tail, &segXHDR, sizeof(segXHDR));
|
||||
tail += sizeof(segXHDR);
|
||||
goto next;
|
||||
}
|
||||
else { // append to .text
|
||||
segtxt->vmsize = offLINK;
|
||||
segtxt->filesize = offLINK;
|
||||
sectxt->size = offLINK - (~PAGE_MASK & sectxt->offset);
|
||||
va_next = segtxt->vmsize + segtxt->vmaddr;
|
||||
skip = 1;
|
||||
}
|
||||
sz_cmd = (segTEXT.nsects * sizeof(secTEXT)) + sizeof(segTEXT);
|
||||
memcpy(tail, &segTEXT, sz_cmd); tail += sz_cmd;
|
||||
goto next;
|
||||
}
|
||||
if (!strcmp("__LINKEDIT", segptr->segname)) {
|
||||
segLINK.initprot = Mach_command::VM_PROT_READ
|
||||
| Mach_command::VM_PROT_EXECUTE;
|
||||
segLINK.initprot = Mach_command::VM_PROT_READ;
|
||||
delta = offLINK - segptr->fileoff; // relocation constant
|
||||
|
||||
// Update the __LINKEDIT header
|
||||
segLINK.filesize = eofcmpr - offLINK;
|
||||
segLINK.vmsize = PAGE_MASK64 & (~PAGE_MASK64 + eofcmpr - offLINK);
|
||||
if (Mach_header::CPU_TYPE_I386 == my_cputype) {
|
||||
segLINK.fileoff = offLINK; // otherwise written by ::pack3
|
||||
}
|
||||
segLINK.vmaddr = va_next;
|
||||
memcpy(tail, &segLINK, sizeof(segLINK));
|
||||
tail += sizeof(segLINK);
|
||||
sz_cmd = sizeof(segLINK);
|
||||
memcpy(tail, &segLINK, sz_cmd); tail += sz_cmd;
|
||||
goto next;
|
||||
}
|
||||
} break;
|
||||
|
@ -808,6 +730,7 @@ next:
|
|||
unsigned const sz_threado = threado_size();
|
||||
mhp->ncmds += 1;
|
||||
mhp->sizeofcmds += sz_threado;
|
||||
sz_mach_headers += sz_threado;
|
||||
fo->seek(0, SEEK_SET);
|
||||
fo->rewrite(mhp, tail - (char *)mhp);
|
||||
threado_rewrite(fo);
|
||||
|
@ -826,7 +749,8 @@ next:
|
|||
}
|
||||
}
|
||||
|
||||
// At 2013-02-03 part of the source for codesign was // http://opensource.apple.com/source/cctools/cctools-836/libstuff/ofile.c
|
||||
// At 2013-02-03 part of the source for codesign was:
|
||||
// http://opensource.apple.com/source/cctools/cctools-836/libstuff/ofile.c
|
||||
|
||||
template <class T>
|
||||
void PackMachBase<T>::pack4dylib( // append PackHeader
|
||||
|
@ -1023,22 +947,16 @@ off_t PackMachBase<T>::pack3(OutputFile *fo, Filter &ft) // append loader
|
|||
fo->write(&zero, 3& (0u-len));
|
||||
len += (3& (0u-len));
|
||||
|
||||
disp = len - sz_mach_headers;
|
||||
disp = len; // backward offset to Mach_header
|
||||
fo->write(&disp, sizeof(disp));
|
||||
len += sizeof(disp);
|
||||
|
||||
if (Mach_header::MH_DYLIB != my_filetype) {
|
||||
// Why does MH_EXECUTE do this?
|
||||
char page[~PAGE_MASK]; memset(page, 0, sizeof(page));
|
||||
fo->write(page, ~PAGE_MASK & (0u - len));
|
||||
len += ~PAGE_MASK & (0u - len);
|
||||
segLINK.fileoff = len;
|
||||
}
|
||||
disp = len - sz_mach_headers; // backward offset to start of compressed data
|
||||
fo->write(&disp, sizeof(disp));
|
||||
len += sizeof(disp);
|
||||
threado_setPC(entryVMA= len + segTEXT.vmaddr);
|
||||
|
||||
threado_setPC(entryVMA= len + segTEXT.vmaddr); /* entry address */
|
||||
super::pack3(fo, ft);
|
||||
fo->write(&zero, 7& (0u-len)); // FIXME: align(4) ?
|
||||
return segTEXT.vmsize = len = fo->getBytesWritten();
|
||||
return segTEXT.vmsize = super::pack3(fo, ft);
|
||||
}
|
||||
|
||||
off_t PackDylibI386::pack3(OutputFile *fo, Filter &ft) // append loader
|
||||
|
@ -1359,7 +1277,7 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
|||
strncpy((char *)segTEXT.segname, "__TEXT", sizeof(segTEXT.segname));
|
||||
if (my_filetype==Mach_header::MH_EXECUTE) {
|
||||
int k; // must ignore zero-length segments, which sort last
|
||||
for (k=n_segment; --k>=0; )
|
||||
for (k=1 /*n_segment*/; --k>=0; )
|
||||
if (msegcmd[k].vmsize!=0)
|
||||
break;
|
||||
segTEXT.vmaddr = PAGE_MASK64 & (~PAGE_MASK64 +
|
||||
|
@ -1408,12 +1326,11 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
|||
segLINK.cmdsize = sizeof(segLINK);
|
||||
strncpy((char *)segLINK.segname, "__LINKEDIT", sizeof(segLINK.segname));
|
||||
segLINK.nsects = 0;
|
||||
segLINK.initprot = Mach_command::VM_PROT_READ
|
||||
| Mach_command::VM_PROT_EXECUTE;
|
||||
segLINK.initprot = Mach_command::VM_PROT_READ;
|
||||
// Adjust later: .vmaddr .vmsize .fileoff .filesize
|
||||
|
||||
if (my_filetype == Mach_header::MH_EXECUTE) {
|
||||
unsigned cmdsize = mhdro.sizeofcmds - sizeof(segXHDR);
|
||||
unsigned cmdsize = mhdro.sizeofcmds;
|
||||
Mach_header const *const ptr0 = (Mach_header const *)stub_main;
|
||||
Mach_command const *ptr1 = (Mach_command const *)(1+ ptr0);
|
||||
for (unsigned j = 0; j < mhdro.ncmds -1; ++j, (cmdsize -= ptr1->cmdsize),
|
||||
|
@ -1433,13 +1350,11 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
|||
// Mach_command before __LINKEDIT
|
||||
pos += (char const *)ptr1 - (char const *)(1+ ptr0);
|
||||
fo->write((1+ ptr0), (char const *)ptr1 - (char const *)(1+ ptr0));
|
||||
pos += sizeof(segXHDR);
|
||||
fo->write(&segXHDR, sizeof(segXHDR));
|
||||
|
||||
// Mach_command __LINKEDIT and after
|
||||
pos += cmdsize;
|
||||
fo->write((char const *)ptr1, cmdsize);
|
||||
// Contents before __LINKEDIT; put non-headers at same offset in file
|
||||
fo->write(&stub_main[pos], segptr->fileoff - pos);
|
||||
|
||||
sz_mach_headers = fo->getBytesWritten();
|
||||
break;
|
||||
}
|
||||
|
@ -1824,6 +1739,9 @@ int PackMachBase<T>::canUnpack()
|
|||
|
||||
return true;
|
||||
}
|
||||
#define WANT_MACH_SEGMENT_ENUM
|
||||
#define WANT_MACH_SECTION_ENUM
|
||||
#include "p_mach_enum.h"
|
||||
|
||||
template <class T>
|
||||
bool PackMachBase<T>::canPack()
|
||||
|
@ -1972,10 +1890,10 @@ bool PackMachBase<T>::canPack()
|
|||
{CPU_TYPE_X86_64, MH_EXECUTE,
|
||||
sizeof(stub_amd64_darwin_macho_entry),
|
||||
sizeof(stub_amd64_darwin_macho_fold),
|
||||
sizeof(stub_amd64_darwin_macho_upxmain_exe),
|
||||
0, //sizeof(stub_amd64_darwin_macho_upxmain_exe),
|
||||
stub_amd64_darwin_macho_entry,
|
||||
stub_amd64_darwin_macho_fold,
|
||||
stub_amd64_darwin_macho_upxmain_exe
|
||||
0 // stub_amd64_darwin_macho_upxmain_exe
|
||||
},
|
||||
{CPU_TYPE_X86_64, MH_DYLIB,
|
||||
sizeof(stub_amd64_darwin_dylib_entry), 0, 0,
|
||||
|
@ -2024,6 +1942,86 @@ bool PackMachBase<T>::canPack()
|
|||
stub_fold = stub_list[j].stub_fold;
|
||||
sz_stub_main = stub_list[j].sz_stub_main;
|
||||
stub_main = stub_list[j].stub_main;
|
||||
if (!stub_main) { // development stub
|
||||
static struct {
|
||||
Mach_header mhdri;
|
||||
Mach_segment_command segZERO;
|
||||
Mach_segment_command segTEXT;
|
||||
Mach_section_command secTEXT;
|
||||
Mach_segment_command segLINK;
|
||||
Mach_version_min_command cmdVERMIN;
|
||||
Mach_source_version_command cmdSRCVER;
|
||||
} fsm; // fake_stub_main
|
||||
fsm.mhdri = mhdri;
|
||||
fsm.mhdri.ncmds = 5;
|
||||
fsm.mhdri.sizeofcmds = sizeof(fsm) - sizeof(fsm.mhdri);
|
||||
fsm.mhdri.flags = MH_NOUNDEFS | MH_PIE;
|
||||
|
||||
fsm.segZERO.cmd = LC_SEGMENT + (fsm.mhdri.cputype >> 24)
|
||||
* (LC_SEGMENT_64 - LC_SEGMENT);
|
||||
fsm.segZERO.cmdsize = sizeof(Mach_segment_command);
|
||||
strncpy(fsm.segZERO.segname, "__PAGEZERO", sizeof(fsm.segZERO.segname));
|
||||
fsm.segZERO.vmaddr = 0;
|
||||
fsm.segZERO.vmsize = (4<<16);
|
||||
if (8==sizeof(void *)) fsm.segZERO.vmsize <<= (32 - 18);
|
||||
fsm.segZERO.fileoff = 0;
|
||||
fsm.segZERO.filesize = 0;
|
||||
fsm.segZERO.maxprot = 0;
|
||||
fsm.segZERO.initprot = 0;
|
||||
fsm.segZERO.nsects = 0;
|
||||
fsm.segZERO.flags = 0;
|
||||
|
||||
fsm.segTEXT.cmd = fsm.segZERO.cmd;
|
||||
fsm.segTEXT.cmdsize = sizeof(Mach_segment_command)
|
||||
+ sizeof(Mach_section_command);
|
||||
strncpy(fsm.segTEXT.segname, "__TEXT", sizeof(fsm.segTEXT.segname));
|
||||
fsm.segTEXT.vmaddr = fsm.segZERO.vmsize; // dummy?
|
||||
fsm.segTEXT.vmsize = 0;
|
||||
fsm.segTEXT.fileoff = 0;
|
||||
fsm.segTEXT.filesize = fsm.segTEXT.vmsize; // dummy
|
||||
fsm.segTEXT.maxprot = VM_PROT_EXECUTE | VM_PROT_READ;
|
||||
fsm.segTEXT.initprot = VM_PROT_EXECUTE | VM_PROT_READ;
|
||||
fsm.segTEXT.nsects = 1;
|
||||
fsm.segTEXT.flags = 0;
|
||||
|
||||
strncpy(fsm.secTEXT.sectname, "__text", sizeof(fsm.secTEXT.sectname));
|
||||
memcpy(fsm.secTEXT.segname, fsm.segTEXT.segname, sizeof(fsm.secTEXT.segname));
|
||||
unsigned const d = 400 + fsm.mhdri.sizeofcmds;
|
||||
fsm.secTEXT.addr = fsm.segTEXT.vmaddr + d; // dummy
|
||||
fsm.secTEXT.size = fsm.segTEXT.vmsize - d; // dummy
|
||||
fsm.secTEXT.offset = d; // dummy
|
||||
fsm.secTEXT.align = 3; // (1<<2)
|
||||
fsm.secTEXT.reloff = 0;
|
||||
fsm.secTEXT.nreloc = 0;
|
||||
fsm.secTEXT.flags = S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
|
||||
fsm.secTEXT.reserved1 = 0;
|
||||
fsm.secTEXT.reserved2 = 0;
|
||||
|
||||
fsm.segLINK = fsm.segTEXT;
|
||||
fsm.segLINK.cmdsize = sizeof(Mach_segment_command);
|
||||
strncpy(fsm.segLINK.segname, "__LINKEDIT", sizeof(fsm.segLINK.segname));
|
||||
fsm.segLINK.vmaddr = fsm.segTEXT.vmaddr + fsm.segTEXT.vmsize; // dummy
|
||||
fsm.segLINK.vmsize = 0x1000; // dummy
|
||||
fsm.segLINK.fileoff = fsm.segTEXT.fileoff + fsm.segTEXT.filesize;
|
||||
fsm.segLINK.filesize = fsm.segLINK.vmsize;
|
||||
fsm.segLINK.maxprot = VM_PROT_READ;
|
||||
fsm.segLINK.initprot = VM_PROT_READ;
|
||||
fsm.segLINK.nsects = 0;
|
||||
|
||||
fsm.cmdVERMIN.cmd = LC_VERSION_MIN_MACOSX; // LC_VERSION_MIN_IPHONEOS
|
||||
fsm.cmdVERMIN.cmdsize = 4*4;
|
||||
fsm.cmdVERMIN.version = (10<<16)|(12<<8);
|
||||
fsm.cmdVERMIN.sdk = fsm.cmdVERMIN.version;
|
||||
|
||||
fsm.cmdSRCVER.cmd = LC_SOURCE_VERSION;
|
||||
fsm.cmdSRCVER.cmdsize = 4*4;
|
||||
fsm.cmdSRCVER.version = 0;
|
||||
fsm.cmdSRCVER.__pad = 0;
|
||||
|
||||
sz_stub_main = sizeof(fsm);
|
||||
stub_main = (unsigned char const *)&fsm;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -336,6 +336,7 @@ __packed_struct(Mach_source_version_command)
|
|||
Word cmd; // LC_SOURCE_VERSION
|
||||
Word cmdsize; // 16
|
||||
Word version;
|
||||
Word __pad; // to 0 mod 8
|
||||
__packed_struct_end()
|
||||
|
||||
template <class TMachITypes>
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
enum { // cputype
|
||||
CPU_TYPE_I386 = 7,
|
||||
CPU_TYPE_X86_64 = 0x01000007,
|
||||
CPU_TYPE_ARM = 12,
|
||||
CPU_TYPE_ARM = 0x0000000c,
|
||||
CPU_TYPE_ARM64 = 0x0100000c,
|
||||
CPU_TYPE_POWERPC = 0x00000012,
|
||||
CPU_TYPE_POWERPC64 = 0x01000012,
|
||||
CPU_TYPE_POWERPC64LE = 0x01000021
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,23 +31,99 @@
|
|||
;
|
||||
*/
|
||||
|
||||
NBPW= 8
|
||||
|
||||
#include "arch/amd64/macros.S"
|
||||
#include "arch/amd64/regs.h"
|
||||
|
||||
mlc_cmd = 0
|
||||
mlc_cmdsize = 4
|
||||
|
||||
mseg_segname = 8
|
||||
mseg_vmsize = 4+4+16+NBPW
|
||||
mseg_initprot = 4+4+16+(4*NBPW)+4
|
||||
|
||||
/*************************************************************************
|
||||
// program entry point
|
||||
// see glibc/sysdeps/amd64/elf/start.S
|
||||
**************************************************************************/
|
||||
|
||||
MAP_FIXED = 0x10
|
||||
MAP_PRIVATE = 0x02
|
||||
MAP_ANON = 0x1000
|
||||
PROT_READ = 1
|
||||
PROT_WRITE = 2
|
||||
PROT_EXEC = 4
|
||||
MAP_ANON_FD = -1
|
||||
|
||||
SYS_mmap =0xc5
|
||||
SYS_mprotect =0x4a
|
||||
SYS_munmap =0x49
|
||||
|
||||
#define __c4(a,b,c,d) (((a)<<(0*8)) | ((b)<<(1*8)) | ((c)<<(2*8)) | ((d)<<(3*8)))
|
||||
#define __c8(a,b,c,d,e,f,g,h) (__c4(a,b,c,d) | (__c4(e,f,g,h) << 32))
|
||||
|
||||
section AMD64BXX
|
||||
0: .word 9f - 0b
|
||||
#include "arch/amd64/bxx.S"
|
||||
9:
|
||||
|
||||
// FYI: Following the env[] vector there is another vector apple[] of strings.
|
||||
// Contents from one actual instance on MacOS 10.13 HighSierra:
|
||||
// "executable_path=<rooted_path>"
|
||||
// "pfz=0x7ffffff84000"
|
||||
// "stack_guard=0x850795b0f36900c2"
|
||||
// "malloc_entropy=0x94a87434eb9e2c1,0xf6814219485392e8"
|
||||
// "main_stack=0x7ffeefc00000,0x800000,0x7ffeebc00000,0x4000000"
|
||||
// "executable_file=0x1000008,0x2209ce"
|
||||
// when %rsp was 0x7ffeefbffaf0.
|
||||
|
||||
section MACHMAINX
|
||||
_start: .globl _start
|
||||
// int3
|
||||
lea -2*4+_start(%rip),%rbp; movl (%rbp),%eax; sub %rax,%rbp // &Mach_header64
|
||||
mov mhdr_ncmds(%rbp),%r12d
|
||||
lea sz_Mach_header64(%rbp),%rbx // ptr
|
||||
L20:
|
||||
cmpl $LC_SEGMENT_64,mlc_cmd(%rbx); jne L50
|
||||
cmpl $__c4('T','E','X','T'),2+mseg_segname(%rbx); jne L40
|
||||
sub %arg1l,%arg1l // 0 addr
|
||||
mov %arg1,%arg6 // 0 off_t
|
||||
lea -1(%rdi),%arg5 // MAP_ANON_FD
|
||||
mov $MAP_PRIVATE|MAP_ANON,%sys4l
|
||||
mov $PROT_WRITE|PROT_READ,%arg3l
|
||||
mov mseg_vmsize(%rbx),%arg2
|
||||
mov $SYS_mmap,%eax; syscall
|
||||
mov %rax,%r15 // vmaddr
|
||||
|
||||
movq mseg_vmsize(%rbx),%arg3
|
||||
movq mseg_vmaddr(%rbx),%arg2
|
||||
mov %rax,%arg1
|
||||
call memcpy
|
||||
|
||||
movl mseg_initprot,%arg3l
|
||||
movq mseg_vmsize(%rbx),%arg2
|
||||
mov %rax,%arg1
|
||||
mov $SYS_mprotect,%eax; syscall
|
||||
|
||||
sub 2*NBPW(%rsp),%r15 // reloc
|
||||
call goto_clone
|
||||
jmp L50
|
||||
|
||||
goto_clone:
|
||||
addq %r15,(%rsp) // retaddr += reloc
|
||||
ret
|
||||
memcpy:
|
||||
mov %arg3,%rcx; shr $3,%rcx; rep movsq
|
||||
ret
|
||||
|
||||
L40:
|
||||
movabsq $__c8('L','I','N','K','E','D','I','T'),%rcx; cmp %rcx,2+mseg_segname(%rbx); jne L50
|
||||
|
||||
L50:
|
||||
mov mlc_cmdsize(%rbx),%eax; add %rax,%rbx
|
||||
sub $1,%ebp; jne L20
|
||||
|
||||
call main // push &decompress
|
||||
ret_main:
|
||||
|
||||
|
|
|
@ -29,10 +29,11 @@
|
|||
<jreiser@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define __WORDSIZE 64
|
||||
#include "include/darwin.h"
|
||||
|
||||
typedef unsigned char * Addr;
|
||||
|
||||
#ifndef DEBUG /*{*/
|
||||
#define DEBUG 0
|
||||
#endif /*}*/
|
||||
|
@ -184,16 +185,16 @@ done:
|
|||
|
||||
typedef struct {
|
||||
size_t size; // must be first to match size[0] uncompressed size
|
||||
void *buf;
|
||||
Addr buf;
|
||||
} Extent;
|
||||
|
||||
DEBUG_STRCON(STR_xread, "xread %%p(%%x %%p) %%p %%x\\n")
|
||||
DEBUG_STRCON(STR_xreadfail, "xreadfail %%p(%%x %%p) %%p %%x\\n")
|
||||
|
||||
static void
|
||||
xread(Extent *x, void *buf, size_t count)
|
||||
xread(Extent *x, Addr buf, size_t count)
|
||||
{
|
||||
unsigned char *p=x->buf, *q=buf;
|
||||
Addr p=x->buf, q=buf;
|
||||
size_t j;
|
||||
DPRINTF((STR_xread(), x, x->size, x->buf, buf, count));
|
||||
if (x->size < count) {
|
||||
|
@ -285,7 +286,7 @@ unpackExtent(
|
|||
// compressible and is stored in its uncompressed form.
|
||||
|
||||
// Read and check block sizes.
|
||||
xread(xi, (unsigned char *)&h, sizeof(h));
|
||||
xread(xi, (Addr)&h, sizeof(h));
|
||||
if (h.sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||
if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic
|
||||
err_exit(2);
|
||||
|
@ -328,7 +329,7 @@ ERR_LAB
|
|||
}
|
||||
|
||||
static void
|
||||
upx_bzero(unsigned char *p, size_t len)
|
||||
upx_bzero(Addr p, size_t len)
|
||||
{
|
||||
if (len) do {
|
||||
*p++= 0;
|
||||
|
@ -484,8 +485,8 @@ typedef union {
|
|||
#define MAP_ANON_FD -1
|
||||
#define MAP_FAILED ((void *) -1)
|
||||
|
||||
extern void *mmap(void *, size_t, unsigned, unsigned, int, off_t);
|
||||
ssize_t pread(int, void *, size_t, off_t);
|
||||
extern void *mmap(void *, size_t, unsigned, unsigned, int, off_t_upx_stub);
|
||||
ssize_t pread(int, void *, size_t, off_t_upx_stub);
|
||||
extern void bswap(void *, unsigned);
|
||||
|
||||
DEBUG_STRCON(STR_mmap,
|
||||
|
@ -496,7 +497,7 @@ DEBUG_STRCON(STR_do_xmap,
|
|||
static uint64_t // entry address
|
||||
do_xmap(
|
||||
Mach_header64 const *const mhdr,
|
||||
off_t const fat_offset,
|
||||
off_t_upx_stub const fat_offset,
|
||||
Extent *const xi,
|
||||
int const fdi,
|
||||
Mach_header64 **mhdrpp,
|
||||
|
@ -514,12 +515,12 @@ do_xmap(
|
|||
fdi, mhdr, xi, (xi? xi->size: 0), (xi? xi->buf: 0), f_unf));
|
||||
|
||||
for ( j=0; j < mhdr->ncmds; ++j,
|
||||
(sc = (Mach_segment_command const *)(sc->cmdsize + (void const *)sc))
|
||||
(sc = (Mach_segment_command const *)(sc->cmdsize + (unsigned char const *)sc))
|
||||
) if (LC_SEGMENT_64==sc->cmd && sc->vmsize!=0) {
|
||||
Extent xo;
|
||||
size_t mlen = xo.size = sc->filesize;
|
||||
unsigned char *addr = xo.buf = base + (unsigned char *)sc->vmaddr;
|
||||
unsigned char *haddr = sc->vmsize + addr;
|
||||
Addr addr = xo.buf = base + (Addr)sc->vmaddr;
|
||||
Addr haddr = sc->vmsize + addr;
|
||||
size_t frag = (int)(uint64_t)addr &~ PAGE_MASK;
|
||||
addr -= frag;
|
||||
mlen += frag;
|
||||
|
@ -531,10 +532,10 @@ do_xmap(
|
|||
unsigned const flags = (addr ? MAP_FIXED : 0) | MAP_PRIVATE |
|
||||
((xi || 0==sc->filesize) ? MAP_ANON : 0);
|
||||
int const fdm = ((0==sc->filesize) ? MAP_ANON_FD : fdi);
|
||||
off_t const offset = sc->fileoff + fat_offset;
|
||||
off_t_upx_stub const offset = sc->fileoff + fat_offset;
|
||||
|
||||
DPRINTF((STR_mmap(), addr, mlen3, prot, flags, fdm, offset));
|
||||
unsigned char *mapa = mmap(addr, mlen3, prot, flags, fdm, offset);
|
||||
Addr mapa = (Addr)mmap(addr, mlen3, prot, flags, fdm, offset);
|
||||
if (MAP_FAILED == mapa) {
|
||||
err_exit(8);
|
||||
}
|
||||
|
@ -593,7 +594,7 @@ ERR_LAB
|
|||
return entry;
|
||||
}
|
||||
|
||||
static off_t
|
||||
static off_t_upx_stub
|
||||
fat_find(Fat_header *fh) // *fh suffers bswap()
|
||||
{
|
||||
Fat_arch *fa = (Fat_arch *)(1+ fh);
|
||||
|
@ -628,11 +629,11 @@ upx_main(
|
|||
)
|
||||
{
|
||||
uint64_t entry;
|
||||
off_t fat_offset = 0;
|
||||
off_t_upx_stub fat_offset = 0;
|
||||
Extent xi, xo, xi0;
|
||||
xi.buf = CONST_CAST(unsigned char *, 1+ (struct p_info const *)(1+ li)); // &b_info
|
||||
xi.buf = CONST_CAST(Addr, 1+ (struct p_info const *)(1+ li)); // &b_info
|
||||
xi.size = sz_compressed - (sizeof(struct l_info) + sizeof(struct p_info));
|
||||
xo.buf = (unsigned char *)mhdr;
|
||||
xo.buf = (Addr)mhdr;
|
||||
xo.size = ((struct b_info const *)(void const *)xi.buf)->sz_unc;
|
||||
xi0 = xi;
|
||||
|
||||
|
@ -650,7 +651,7 @@ upx_main(
|
|||
unsigned j;
|
||||
|
||||
for (j=0; j < mhdr->ncmds; ++j,
|
||||
(lc = (Mach_load_command const *)(lc->cmdsize + (void const *)lc))
|
||||
(lc = (Mach_load_command const *)(lc->cmdsize + (unsigned char const *)lc))
|
||||
) if (LC_LOAD_DYLINKER==lc->cmd) {
|
||||
char const *const dyld_name = ((Mach_lc_str const *)(1+ lc))->offset +
|
||||
(char const *)lc;
|
||||
|
@ -694,6 +695,15 @@ typedef struct {
|
|||
uint32_t data[2]; // because cmdsize >= 16
|
||||
} Mach_command; // generic prefix
|
||||
|
||||
// Go to the clone.
|
||||
extern void goto_clone(ptrdiff_t reloc);
|
||||
//{
|
||||
// add %arg1,(%rsp) // relocate return address
|
||||
// ret
|
||||
//}
|
||||
|
||||
extern void *memcpy(void *, void const *, size_t);
|
||||
|
||||
//
|
||||
// Build on Mac OS X: (where gcc is really clang)
|
||||
// gcc -o amd64-darwin.macho-upxmain.exe \
|
||||
|
@ -718,6 +728,7 @@ main(int argc, char *argv[])
|
|||
|
||||
Mach_header64 const *mhdr0 = (Mach_header64 const *)((~0ul<<16) & (unsigned long)&main);
|
||||
Mach_command const *ptr = (Mach_command const *)(1+ mhdr0);
|
||||
ptrdiff_t reloc = 0;
|
||||
f_unfilter *f_unf;
|
||||
f_expand *f_exp;
|
||||
char *payload;
|
||||
|
@ -728,11 +739,22 @@ main(int argc, char *argv[])
|
|||
ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr))
|
||||
if (LC_SEGMENT_64==ptr->cmd) {
|
||||
Mach_segment_command const *const seg = (Mach_segment_command const *)ptr;
|
||||
// Compare 8 characters
|
||||
// Compare 4 bytes
|
||||
if (*(int const *)(&"__TEXT"[2]) == *(int const *)(&seg->segname[2])) {
|
||||
Addr const vmaddr = (Addr)mmap(0, seg->vmsize, PROT_WRITE | PROT_READ,
|
||||
MAP_PRIVATE | MAP_ANON, MAP_ANON_FD, 0);
|
||||
memcpy(vmaddr, (void const *)seg->vmaddr, seg->vmsize);
|
||||
mprotect(vmaddr, seg->vmsize, seg->initprot);
|
||||
reloc = vmaddr - (Addr)mhdr0;
|
||||
ptr = (Mach_command const *)(reloc + (Addr)ptr);
|
||||
goto_clone(reloc);
|
||||
} else
|
||||
// Compare 8 bytes
|
||||
if (*(long const *)(&"__LINKEDIT"[2]) == *(long const *)(&seg->segname[2])) {
|
||||
f_unf = (f_unfilter *)(sizeof(unsigned short) + seg->vmaddr);
|
||||
f_exp = (f_expand *)(*(unsigned short const *)seg->vmaddr + seg->vmaddr);
|
||||
unsigned const *q = (unsigned const *)seg->vmaddr;
|
||||
Addr const vm2 = (Addr)(seg->vmaddr + reloc);
|
||||
f_unf = (f_unfilter *)(sizeof(unsigned short) + vm2);
|
||||
f_exp = (f_expand *)(*(unsigned short const *)vm2 + vm2);
|
||||
unsigned const *q = (unsigned const *)vm2;
|
||||
while (!(paysize = *--q)) /*empty*/ ;
|
||||
payload = (char *)(-paysize + (char const *)q);
|
||||
break;
|
||||
|
@ -743,8 +765,8 @@ main(int argc, char *argv[])
|
|||
(Mach_header64 *)mhdr, sizeof(mhdr),
|
||||
f_exp, f_unf, (Mach_header64 **)&argv[-2]);
|
||||
|
||||
munmap(payload, paysize); // leaving __LINKEDIT
|
||||
argv[-1] = (char *)(long)argc;
|
||||
munmap(payload, paysize); // leaving __LINKEDIT
|
||||
asm("lea -2*8(%1),%%rsp; jmp *%0" : : "r" (entry), "r" (argv));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<jreiser@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#define __WORDSIZE 32
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "include/darwin.h"
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<jreiser@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#define __WORDSIZE 32
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "include/darwin.h"
|
||||
|
|
|
@ -3,19 +3,19 @@ file format elf64-x86-64
|
|||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn Flags
|
||||
0 AMD64BXX 0000004c 0000000000000000 0000000000000000 00000040 2**0 CONTENTS, READONLY
|
||||
1 MACHMAINX 00000005 0000000000000000 0000000000000000 0000008c 2**0 CONTENTS, RELOC, READONLY
|
||||
2 MACH_UNC 00000008 0000000000000000 0000000000000000 00000091 2**0 CONTENTS, READONLY
|
||||
3 NRV_HEAD 00000067 0000000000000000 0000000000000000 00000099 2**0 CONTENTS, READONLY
|
||||
4 NRV2E 000000b7 0000000000000000 0000000000000000 00000100 2**0 CONTENTS, RELOC, READONLY
|
||||
5 NRV2D 0000009e 0000000000000000 0000000000000000 000001b7 2**0 CONTENTS, RELOC, READONLY
|
||||
6 NRV2B 00000090 0000000000000000 0000000000000000 00000255 2**0 CONTENTS, RELOC, READONLY
|
||||
7 LZMA_ELF00 00000064 0000000000000000 0000000000000000 000002e5 2**0 CONTENTS, RELOC, READONLY
|
||||
8 LZMA_DEC10 000009f7 0000000000000000 0000000000000000 00000349 2**0 CONTENTS, READONLY
|
||||
9 LZMA_DEC20 000009f7 0000000000000000 0000000000000000 00000d40 2**0 CONTENTS, READONLY
|
||||
10 LZMA_DEC30 00000014 0000000000000000 0000000000000000 00001737 2**0 CONTENTS, READONLY
|
||||
11 NRV_TAIL 00000000 0000000000000000 0000000000000000 0000174b 2**0 CONTENTS, READONLY
|
||||
12 MACHMAINY 00000011 0000000000000000 0000000000000000 0000174b 2**0 CONTENTS, READONLY
|
||||
13 MACHMAINZ 00000041 0000000000000000 0000000000000000 0000175c 2**0 CONTENTS, READONLY
|
||||
1 MACHMAINX 000000b7 0000000000000000 0000000000000000 0000008c 2**0 CONTENTS, RELOC, READONLY
|
||||
2 MACH_UNC 00000008 0000000000000000 0000000000000000 00000143 2**0 CONTENTS, READONLY
|
||||
3 NRV_HEAD 00000067 0000000000000000 0000000000000000 0000014b 2**0 CONTENTS, READONLY
|
||||
4 NRV2E 000000b7 0000000000000000 0000000000000000 000001b2 2**0 CONTENTS, RELOC, READONLY
|
||||
5 NRV2D 0000009e 0000000000000000 0000000000000000 00000269 2**0 CONTENTS, RELOC, READONLY
|
||||
6 NRV2B 00000090 0000000000000000 0000000000000000 00000307 2**0 CONTENTS, RELOC, READONLY
|
||||
7 LZMA_ELF00 00000064 0000000000000000 0000000000000000 00000397 2**0 CONTENTS, RELOC, READONLY
|
||||
8 LZMA_DEC10 000009f7 0000000000000000 0000000000000000 000003fb 2**0 CONTENTS, READONLY
|
||||
9 LZMA_DEC20 000009f7 0000000000000000 0000000000000000 00000df2 2**0 CONTENTS, READONLY
|
||||
10 LZMA_DEC30 00000014 0000000000000000 0000000000000000 000017e9 2**0 CONTENTS, READONLY
|
||||
11 NRV_TAIL 00000000 0000000000000000 0000000000000000 000017fd 2**0 CONTENTS, READONLY
|
||||
12 MACHMAINY 00000011 0000000000000000 0000000000000000 000017fd 2**0 CONTENTS, READONLY
|
||||
13 MACHMAINZ 00000044 0000000000000000 0000000000000000 0000180e 2**0 CONTENTS, READONLY
|
||||
SYMBOL TABLE:
|
||||
0000000000000000 l d NRV_HEAD 0000000000000000 NRV_HEAD
|
||||
0000000000000000 l d LZMA_DEC30 0000000000000000 LZMA_DEC30
|
||||
|
@ -32,11 +32,20 @@ SYMBOL TABLE:
|
|||
0000000000000000 l d LZMA_DEC20 0000000000000000 LZMA_DEC20
|
||||
0000000000000000 l d NRV_TAIL 0000000000000000 NRV_TAIL
|
||||
0000000000000000 g MACHMAINX 0000000000000000 _start
|
||||
0000000000000000 *UND* 0000000000000000 mhdr_ncmds
|
||||
0000000000000000 *UND* 0000000000000000 sz_Mach_header64
|
||||
0000000000000000 *UND* 0000000000000000 LC_SEGMENT_64
|
||||
0000000000000000 *UND* 0000000000000000 mseg_vmaddr
|
||||
0000000000000011 g MACHMAINY 0000000000000000 end_decompress
|
||||
|
||||
RELOCATION RECORDS FOR [MACHMAINX]:
|
||||
OFFSET TYPE VALUE
|
||||
0000000000000001 R_X86_64_PC32 MACHMAINZ+0x0000000000000037
|
||||
0000000000000003 R_X86_64_PC32 _start+0xfffffffffffffff4
|
||||
0000000000000010 R_X86_64_32S mhdr_ncmds
|
||||
0000000000000017 R_X86_64_32S sz_Mach_header64
|
||||
000000000000001e R_X86_64_32 LC_SEGMENT_64
|
||||
0000000000000056 R_X86_64_32S mseg_vmaddr
|
||||
00000000000000b3 R_X86_64_PC32 MACHMAINZ+0x000000000000003a
|
||||
|
||||
RELOCATION RECORDS FOR [NRV2E]:
|
||||
OFFSET TYPE VALUE
|
||||
|
|
Loading…
Reference in New Issue
Block a user