revamp MH_EXECUTE: try to meet expectations of MacOSX 10.12 Sierra
changed src/p_mach.cpp changed src/stub/src/amd64-darwin.macho-upxmain.c
This commit is contained in:
parent
15d62f7b96
commit
3fefaa7362
214
src/p_mach.cpp
214
src/p_mach.cpp
@ -328,7 +328,13 @@ void PackMachI386::addStubEntrySections(Filter const *ft)
|
||||
|
||||
void PackMachAMD64::addStubEntrySections(Filter const * /*ft*/)
|
||||
{
|
||||
addLoader("MACHMAINX", NULL);
|
||||
if (my_filetype!=Mach_header::MH_EXECUTE) {
|
||||
addLoader("MACHMAINX", NULL);
|
||||
}
|
||||
else {
|
||||
addLoader("AMD64BXX", NULL);
|
||||
}
|
||||
addLoader("MACH_UNC", NULL);
|
||||
//addLoader(getDecompressorSections(), NULL);
|
||||
addLoader(
|
||||
( M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E,NRV_TAIL"
|
||||
@ -338,7 +344,10 @@ void PackMachAMD64::addStubEntrySections(Filter const * /*ft*/)
|
||||
: NULL), NULL);
|
||||
if (hasLoaderSection("CFLUSH"))
|
||||
addLoader("CFLUSH");
|
||||
addLoader("MACHMAINY,IDENTSTR,+40,MACHMAINZ,FOLDEXEC", NULL);
|
||||
addLoader("MACHMAINY,IDENTSTR,+40,MACHMAINZ", NULL);
|
||||
if (my_filetype!=Mach_header::MH_EXECUTE) {
|
||||
addLoader("FOLDEXEC", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void PackMachARMEL::addStubEntrySections(Filter const * /*ft*/)
|
||||
@ -457,11 +466,29 @@ PackMachI386::buildLoader(const Filter *ft)
|
||||
void
|
||||
PackMachAMD64::buildLoader(const Filter *ft)
|
||||
{
|
||||
if (my_filetype==Mach_header::MH_EXECUTE) {
|
||||
if (0 && my_filetype==Mach_header::MH_EXECUTE) {
|
||||
initLoader(NULL, 0);
|
||||
linker->addSection("UPXMAIN", stub_amd64_darwin_macho_upxmain_exe,
|
||||
sizeof(stub_amd64_darwin_macho_upxmain_exe), 0);
|
||||
addLoader("UPXMAIN", NULL);
|
||||
addStubEntrySections(ft);
|
||||
|
||||
defineSymbols(ft);
|
||||
relocateLoader();
|
||||
if (0) {
|
||||
Mach_command const *ptr1 = (Mach_command const *)(1+
|
||||
(Mach_header const *)stub_amd64_darwin_macho_upxmain_exe);
|
||||
for (unsigned j = 0; j < mhdro.ncmds; ++j,
|
||||
ptr1 = (Mach_command const *)(ptr1->cmdsize + (char const *)ptr1))
|
||||
switch (ptr1->cmd) {
|
||||
case Mach_segment_command::LC_SEGMENT_64: {
|
||||
Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr1;
|
||||
if (!strcmp("__TEXT", segptr->segname)) {
|
||||
Mach_section_command const *const secptr = (Mach_section_command const *)(1+ segptr);
|
||||
linker->addSection("UPXMAIN", &stub_amd64_darwin_macho_upxmain_exe[secptr->offset],
|
||||
secptr->size, 0);
|
||||
addLoader("UPXMAIN", NULL);
|
||||
}
|
||||
} break;
|
||||
} // end switch
|
||||
}
|
||||
}
|
||||
else {
|
||||
buildMachLoader(
|
||||
@ -748,25 +775,115 @@ void PackMachAMD64::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
||||
secXHDR.offset -= sizeof(linkitem);
|
||||
}
|
||||
secXHDR.addr += secXHDR.offset;
|
||||
unsigned foff1 = (PAGE_MASK & (~PAGE_MASK + segTEXT.filesize));
|
||||
if (foff1 < segTEXT.vmsize)
|
||||
foff1 += PAGE_SIZE; // codesign disallows overhang
|
||||
segLINK.fileoff = foff1;
|
||||
segLINK.vmaddr = segTEXT.vmaddr + foff1;
|
||||
fo->seek(foff1 - 1, SEEK_SET); fo->write("", 1);
|
||||
fo->seek(sizeof(mhdro), SEEK_SET);
|
||||
fo->rewrite(&segZERO, sizeof(segZERO));
|
||||
fo->rewrite(&segXHDR, sizeof(segXHDR));
|
||||
fo->rewrite(&secXHDR, sizeof(secXHDR));
|
||||
fo->rewrite(&segTEXT, sizeof(segTEXT));
|
||||
fo->rewrite(&secTEXT, sizeof(secTEXT));
|
||||
fo->rewrite(&cmdUUID, sizeof(cmdUUID));
|
||||
fo->rewrite(&segLINK, sizeof(segLINK));
|
||||
fo->rewrite(&threado, sizeof(threado));
|
||||
if (my_filetype==Mach_header::MH_EXECUTE) {
|
||||
fo->rewrite(&linkitem, sizeof(linkitem));
|
||||
unsigned offLINK = (PAGE_MASK & (~PAGE_MASK + segTEXT.filesize));
|
||||
if (offLINK < segTEXT.vmsize)
|
||||
offLINK += PAGE_SIZE; // codesign disallows overhang
|
||||
segLINK.fileoff = offLINK;
|
||||
segLINK.vmaddr = segTEXT.vmaddr + offLINK;
|
||||
if (0) {
|
||||
fo->seek(offLINK - 1, SEEK_SET); fo->write("", 1);
|
||||
fo->seek(sizeof(mhdro), SEEK_SET);
|
||||
fo->rewrite(&segZERO, sizeof(segZERO));
|
||||
fo->rewrite(&segXHDR, sizeof(segXHDR));
|
||||
fo->rewrite(&secXHDR, sizeof(secXHDR));
|
||||
fo->rewrite(&segTEXT, sizeof(segTEXT));
|
||||
fo->rewrite(&secTEXT, sizeof(secTEXT));
|
||||
fo->rewrite(&cmdUUID, sizeof(cmdUUID));
|
||||
fo->rewrite(&segLINK, sizeof(segLINK));
|
||||
fo->rewrite(&threado, sizeof(threado));
|
||||
if (my_filetype==Mach_header::MH_EXECUTE) {
|
||||
fo->rewrite(&linkitem, sizeof(linkitem));
|
||||
}
|
||||
fo->rewrite(&linfo, sizeof(linfo));
|
||||
}
|
||||
if (my_filetype == Mach_header::MH_EXECUTE) {
|
||||
unsigned cmdsize = mhdro.sizeofcmds - sizeof(segXHDR);
|
||||
Mach_header const *const ptr0 = (Mach_header const *)stub_amd64_darwin_macho_upxmain_exe;
|
||||
Mach_command const *ptr1 = (Mach_command const *)(1+ ptr0);
|
||||
unsigned delta = 0;
|
||||
for (unsigned j = 0; j < mhdro.ncmds -1; ++j,
|
||||
(cmdsize -= ptr1->cmdsize),
|
||||
ptr1 = (Mach_command const *)(ptr1->cmdsize + (char const *)ptr1))
|
||||
switch (ptr1->cmd) {
|
||||
case Mach_segment_command::LC_SEGMENT_64: {
|
||||
Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr1;
|
||||
if (!strcmp("__TEXT", segptr->segname)) {
|
||||
Mach_section_command const *const secptr = (Mach_section_command const *)(1+ segptr);
|
||||
memcpy(&secTEXT, secptr, sizeof(secTEXT));
|
||||
secTEXT.align = 0;
|
||||
unsigned const d = getLoaderSize();
|
||||
secTEXT.addr -= d;
|
||||
secTEXT.size += d;
|
||||
secTEXT.offset -= d;
|
||||
fo->seek((char const *)secptr - (char const *)ptr0, SEEK_SET);
|
||||
fo->rewrite(&secTEXT, sizeof(secTEXT));
|
||||
fo->seek(secTEXT.offset, SEEK_SET);
|
||||
fo->rewrite(getLoader(), d);
|
||||
fo->seek(0, SEEK_END);
|
||||
}
|
||||
if (!strcmp("__LINKEDIT", ((Mach_segment_command const *)ptr1)->segname)) {
|
||||
memcpy(&segLINK, segptr, sizeof(segLINK));
|
||||
delta = offLINK - segLINK.fileoff; // relocation constant
|
||||
|
||||
// Mach_command __LINKEDIT
|
||||
// The contents remain the same, but at a different offset in the file
|
||||
fo->seek(offLINK, SEEK_SET);
|
||||
fo->write(&stub_amd64_darwin_macho_upxmain_exe[segLINK.fileoff], segLINK.filesize);
|
||||
|
||||
// Update the __LINKEDIT header
|
||||
segLINK.vmaddr += delta;
|
||||
segLINK.fileoff = offLINK;
|
||||
fo->seek((char const *)ptr1 - (char const *)ptr0, SEEK_SET);
|
||||
fo->rewrite(&segLINK, sizeof(segLINK));
|
||||
|
||||
// Mach_segment_command for new segXHDR
|
||||
segXHDR.cmdsize = sizeof(segXHDR);
|
||||
segXHDR.nsects = 0;
|
||||
fo->rewrite(&segXHDR, sizeof(segXHDR));
|
||||
}
|
||||
} break;
|
||||
case Mach_segment_command::LC_DYLD_INFO_ONLY: {
|
||||
N_Mach::Mach_dyld_info_only_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
||||
if (blk.rebase_off) blk.rebase_off += delta;
|
||||
if (blk.bind_off) blk.bind_off += delta;
|
||||
if (blk.lazy_bind_off) blk.lazy_bind_off += delta;
|
||||
if (blk.export_off) blk.export_off += delta;
|
||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
||||
fo->rewrite(&blk, sizeof(blk));
|
||||
} break;
|
||||
case Mach_segment_command::LC_SYMTAB: {
|
||||
Mach_symtab_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
||||
if (blk.symoff) blk.symoff += delta;
|
||||
if (blk.stroff) blk.stroff += delta;
|
||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
||||
fo->rewrite(&blk, sizeof(blk));
|
||||
} break;
|
||||
case Mach_segment_command::LC_DYSYMTAB: {
|
||||
Mach_dysymtab_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
||||
if (blk.tocoff) blk.tocoff += delta;
|
||||
if (blk.modtaboff) blk.modtaboff += delta;
|
||||
if (blk.extrefsymoff) blk.extrefsymoff += delta;
|
||||
if (blk.indirectsymoff) blk.indirectsymoff += delta;
|
||||
if (blk.extreloff) blk.extreloff += delta;
|
||||
if (blk.locreloff) blk.locreloff += delta;
|
||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
||||
fo->rewrite(&blk, sizeof(blk));
|
||||
} break;
|
||||
case Mach_segment_command::LC_FUNCTION_STARTS: {
|
||||
N_Mach::Mach_function_starts_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
||||
if (blk.dataoff) blk.dataoff += delta;
|
||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
||||
fo->rewrite(&blk, sizeof(blk));
|
||||
} break;
|
||||
case Mach_segment_command::LC_DATA_IN_CODE: {
|
||||
N_Mach::Mach_data_in_code_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
||||
if (blk.dataoff) blk.dataoff += delta;
|
||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
||||
fo->rewrite(&blk, sizeof(blk));
|
||||
} break;
|
||||
} // end switch
|
||||
fo->seek(0, SEEK_END);
|
||||
}
|
||||
fo->rewrite(&linfo, sizeof(linfo));
|
||||
}
|
||||
|
||||
void PackMachARMEL::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
||||
@ -1444,13 +1561,10 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
||||
unsigned const lc_seg = lc_segment[sizeof(Addr)>>3];
|
||||
mhdro = mhdri;
|
||||
if (my_filetype==Mach_header::MH_EXECUTE) {
|
||||
mhdro.ncmds = 6; // __ZERO, __XHDR, __TEXT, UUID, __LINKEDIT, THREAD_STATE
|
||||
mhdro.sizeofcmds = sizeof(segZERO)
|
||||
+ sizeof(segXHDR) + sizeof(secXHDR)
|
||||
+ sizeof(segTEXT) + sizeof(secTEXT)
|
||||
+ sizeof(cmdUUID)
|
||||
+ sizeof(segLINK) + my_thread_command_size /* + sizeof(linkitem) */ ;
|
||||
mhdro.flags = Mach_header::MH_NOUNDEFS | Mach_header::MH_DYLDLINK;
|
||||
memcpy(&mhdro, stub_amd64_darwin_macho_upxmain_exe, sizeof(mhdro));
|
||||
mhdro.ncmds += 1; // we add LC_SEGMENT{,_64} for UPX_DATA
|
||||
mhdro.sizeofcmds += sizeof(segXHDR);
|
||||
mhdro.flags &= ~Mach_header::MH_PIE; // we require fixed address
|
||||
}
|
||||
fo->write(&mhdro, sizeof(mhdro));
|
||||
|
||||
@ -1501,13 +1615,15 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
||||
| Mach_section_command::S_ATTR_PURE_INSTRUCTIONS;
|
||||
|
||||
segXHDR = segTEXT;
|
||||
segXHDR.cmdsize = sizeof(segXHDR) + sizeof(secXHDR);
|
||||
segXHDR.vmaddr = segZERO.vmsize;
|
||||
segXHDR.vmsize = PAGE_SIZE;
|
||||
segXHDR.filesize = PAGE_SIZE;
|
||||
strncpy((char *)segXHDR.segname, "__XHDR", sizeof(segXHDR.segname));
|
||||
segXHDR.nsects = 1;
|
||||
strncpy((char *)segXHDR.segname, "UPX_DATA", sizeof(segXHDR.segname));
|
||||
|
||||
memset(&secXHDR, 0, sizeof(secXHDR));
|
||||
strncpy((char *)secXHDR.sectname, "__xhdr", sizeof(secXHDR.sectname));
|
||||
strncpy((char *)secXHDR.sectname, "upx_data", sizeof(secXHDR.sectname));
|
||||
memcpy(secXHDR.segname, segXHDR.segname, sizeof(secXHDR.segname));
|
||||
secXHDR.addr = segXHDR.vmaddr;
|
||||
secXHDR.size = 0; // empty so far
|
||||
@ -1520,7 +1636,33 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
||||
segLINK.initprot = Mach_segment_command::VM_PROT_READ;
|
||||
// Adjust later: .vmaddr .vmsize .fileoff .filesize
|
||||
|
||||
if (my_filetype==Mach_header::MH_EXECUTE) {
|
||||
if (my_filetype == Mach_header::MH_EXECUTE) {
|
||||
unsigned cmdsize = mhdro.sizeofcmds - sizeof(segXHDR);
|
||||
Mach_header const *const ptr0 = (Mach_header const *)stub_amd64_darwin_macho_upxmain_exe;
|
||||
Mach_command const *ptr1 = (Mach_command const *)(1+ ptr0);
|
||||
for (unsigned j = 0; j < mhdro.ncmds -1; ++j,
|
||||
(cmdsize -= ptr1->cmdsize),
|
||||
ptr1 = (Mach_command const *)(ptr1->cmdsize + (char const *)ptr1)) {
|
||||
Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr1;
|
||||
if (lc_seg == ptr1->cmd && !strcmp("__LINKEDIT", segptr->segname)) {
|
||||
// Mach_command before __LINKEDIT
|
||||
fo->write((1+ ptr0), (char const *)ptr1 - (char const *)(1+ ptr0));
|
||||
// Mach_command __LINKEDIT
|
||||
fo->write(segptr, segptr->cmdsize);
|
||||
// LC_SEGMENT_64 for payload; steal space from -Wl,-headerpadsize
|
||||
segXHDR.cmdsize = sizeof(segXHDR);
|
||||
segXHDR.nsects = 0;
|
||||
fo->write(&segXHDR, sizeof(segXHDR));
|
||||
// Mach_command after __LINKEDIT
|
||||
fo->write(ptr1->cmdsize + (char const *)ptr1, cmdsize - ptr1->cmdsize);
|
||||
// Contents before __LINKEDIT; put non-headers at same offset in file
|
||||
unsigned pos = sizeof(mhdro) + mhdro.sizeofcmds; // includes sizeof(segXHDR)
|
||||
fo->write(&stub_amd64_darwin_macho_upxmain_exe[pos], segptr->fileoff - pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // not MH_EXECUTE; thus MH_DYLIB
|
||||
fo->write(&segZERO, sizeof(segZERO));
|
||||
fo->write(&segXHDR, sizeof(segXHDR));
|
||||
fo->write(&secXHDR, sizeof(secXHDR));
|
||||
@ -1531,8 +1673,6 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
||||
pack1_setup_threado(fo);
|
||||
memset(&linkitem, 0, sizeof(linkitem));
|
||||
fo->write(&linkitem, sizeof(linkitem));
|
||||
}
|
||||
if (my_filetype==Mach_header::MH_DYLIB) {
|
||||
fo->write(rawmseg, mhdri.sizeofcmds);
|
||||
}
|
||||
sz_mach_headers = fo->getBytesWritten();
|
||||
@ -1608,7 +1748,7 @@ void PackMachBase<T>::unpack(OutputFile *fo)
|
||||
unsigned char const *ptr = (unsigned char const *)(1+mhdr);
|
||||
for (unsigned j= 0; j < ncmds; ++j) {
|
||||
memcpy(&msegcmd[j], ptr, umin(sizeof(Mach_segment_command),
|
||||
((Mach_segment_command const *)ptr)->cmdsize));
|
||||
((Mach_command const *)ptr)->cmdsize));
|
||||
ptr += (unsigned) ((Mach_segment_command const *)ptr)->cmdsize;
|
||||
if ((unsigned)(ptr - (unsigned char const *)mhdr) > ph.u_len) {
|
||||
throwCantUnpack("cmdsize");
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
<jreiser@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "include/darwin.h"
|
||||
|
||||
#ifndef DEBUG /*{*/
|
||||
@ -135,10 +136,10 @@ heximal(unsigned long x, char *ptr, int n)
|
||||
}
|
||||
|
||||
|
||||
#define DPRINTF(a) dprintf a
|
||||
#define DPRINTF(a) my_printf a
|
||||
|
||||
static int
|
||||
dprintf(char const *fmt, ...)
|
||||
my_printf(char const *fmt, ...)
|
||||
{
|
||||
char c;
|
||||
int n= 0;
|
||||
@ -397,11 +398,13 @@ typedef struct {
|
||||
unsigned cmdsize;
|
||||
} Mach_load_command;
|
||||
enum e4 {
|
||||
LC_REQ_DYLD = 0x80000000, // OR'ed ==> must not ignore
|
||||
LC_SEGMENT = 0x1,
|
||||
LC_SEGMENT_64 = 0x19,
|
||||
LC_THREAD = 0x4,
|
||||
LC_UNIXTHREAD = 0x5,
|
||||
LC_LOAD_DYLINKER = 0xe
|
||||
LC_LOAD_DYLINKER = 0xe,
|
||||
LC_MAIN = (0x28|LC_REQ_DYLD)
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -423,6 +426,27 @@ typedef struct {
|
||||
VM_PROT_EXECUTE = 4
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
uint64_t addr; /* memory address */
|
||||
uint64_t size; /* size in bytes */
|
||||
unsigned offset; /* file offset */
|
||||
unsigned align; /* power of 2 */
|
||||
unsigned reloff; /* file offset of relocation entries */
|
||||
unsigned nreloc; /* number of relocation entries */
|
||||
unsigned flags; /* section type and attributes */
|
||||
unsigned reserved1; /* for offset or index */
|
||||
unsigned reserved2; /* for count or sizeof */
|
||||
} Mach_section_command;
|
||||
|
||||
typedef struct {
|
||||
uint32_t cmd; // LC_MAIN; MH_EXECUTE only
|
||||
uint32_t cmdsize; // 24
|
||||
uint64_t entryoff; // file offset of main() [expected in __TEXT]
|
||||
uint64_t stacksize; // non-default initial stack size
|
||||
} Mach_main_command;
|
||||
|
||||
typedef struct {
|
||||
uint64_t rax, rbx, rcx, rdx;
|
||||
uint64_t rdi, rsi, rbp, rsp;
|
||||
@ -469,7 +493,7 @@ DEBUG_STRCON(STR_mmap,
|
||||
DEBUG_STRCON(STR_do_xmap,
|
||||
"do_xmap fdi=%%x mhdr=%%p xi=%%p(%%x %%p) f_unf=%%p\\n")
|
||||
|
||||
static Mach_AMD64_thread_state const *
|
||||
static uint64_t // entry address
|
||||
do_xmap(
|
||||
Mach_header64 const *const mhdr,
|
||||
off_t const fat_offset,
|
||||
@ -481,7 +505,8 @@ do_xmap(
|
||||
)
|
||||
{
|
||||
Mach_segment_command const *sc = (Mach_segment_command const *)(1+ mhdr);
|
||||
Mach_AMD64_thread_state const *entry = 0;
|
||||
Mach_segment_command const *segTEXT = 0;
|
||||
uint64_t entry = 0;
|
||||
unsigned j;
|
||||
|
||||
DPRINTF((STR_do_xmap(),
|
||||
@ -514,6 +539,7 @@ do_xmap(
|
||||
}
|
||||
if (xi && 0!=sc->filesize) {
|
||||
if (0==sc->fileoff /*&& 0!=mhdrpp*/) {
|
||||
segTEXT = sc;
|
||||
*mhdrpp = (Mach_header64 *)(void *)addr;
|
||||
}
|
||||
unpackExtent(xi, &xo, f_decompress, f_unf);
|
||||
@ -547,13 +573,18 @@ ERR_LAB
|
||||
Mach_thread_command const *const thrc = (Mach_thread_command const *)sc;
|
||||
if (AMD64_THREAD_STATE ==thrc->flavor
|
||||
&& AMD64_THREAD_STATE_COUNT==thrc->count ) {
|
||||
entry = &thrc->state;
|
||||
entry = thrc->rip;
|
||||
}
|
||||
else if (LC_MAIN==sc->cmd) {
|
||||
entry = ((Mach_main_command const *)sc)->entryoff;
|
||||
if (segTEXT->fileoff <= entry && entry < segTEXT->filesize) {
|
||||
entry += segTEXT->vmaddr;
|
||||
}
|
||||
// XXX FIXME TODO: if entry not in segTEXT
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// upx_main - called by our entry code
|
||||
//
|
||||
@ -563,7 +594,7 @@ DEBUG_STRCON(STR_upx_main,
|
||||
"upx_main szc=%%x f_dec=%%p f_unf=%%p "
|
||||
" xo=%%p(%%x %%p) xi=%%p(%%x %%p) mhdrpp=%%p\\n")
|
||||
|
||||
Mach_AMD64_thread_state const *
|
||||
uint64_t // entry address
|
||||
upx_main(
|
||||
struct l_info const *const li,
|
||||
size_t volatile sz_compressed, // total length
|
||||
@ -574,7 +605,7 @@ upx_main(
|
||||
Mach_header64 **const mhdrpp // Out: *mhdrpp= &real Mach_header64
|
||||
)
|
||||
{
|
||||
Mach_AMD64_thread_state const *entry;
|
||||
uint64_t entry;
|
||||
off_t fat_offset = 0;
|
||||
Extent xi, xo, xi0;
|
||||
xi.buf = CONST_CAST(unsigned char *, 1+ (struct p_info const *)(1+ li)); // &b_info
|
||||
@ -636,25 +667,56 @@ ERR_LAB
|
||||
return entry;
|
||||
}
|
||||
|
||||
f_expand *f_exp;
|
||||
f_unfilter *f_unf;
|
||||
void (*launch)(void const *, Mach_header64 **);
|
||||
typedef struct {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
uint32_t data[2]; // because cmdsize >= 16
|
||||
} Mach_command; // generic prefix
|
||||
|
||||
// Build on Mac OS X:
|
||||
// gcc -o amd64-darwin.macho-upxmain.exe \
|
||||
// -fPIC amd64-darwin.macho-upxmain.c -Wl,-pagezero_size,0xffff0000
|
||||
//
|
||||
// Build on Mac OS X: (where gcc is really clang)
|
||||
// gcc -o amd64-darwin.macho-upxmain.exe -fno-stack-protector \
|
||||
// -Os -fPIC amd64-darwin.macho-upxmain.c -Wl,-pagezero_size,0xffff0000 \
|
||||
// -Wl,-no_pie -Wl,-no_uuid -Wl,-no_function_starts -Wl,-headerpad,0x400
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Mach_header64 *mhdrp;
|
||||
unsigned long const base = 0xffff0000ul;
|
||||
size_t const len = *(size_t *)(base - sizeof(size_t));
|
||||
void const *const ptr = (void const *)(base - len);
|
||||
Mach_header64 const *mhdr0 = (Mach_header64 const *)((~0ul<<16) & (unsigned long)&main);
|
||||
Mach_command const *ptr = (Mach_command const *)(1+ mhdr0);
|
||||
f_unfilter *f_unf;
|
||||
f_expand *f_exp;
|
||||
unsigned char const *payload;
|
||||
size_t paysize;
|
||||
|
||||
unsigned j;
|
||||
for (j=0; j < mhdr0->ncmds; ++j,
|
||||
ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr))
|
||||
if (LC_SEGMENT_64==ptr->cmd) {
|
||||
Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr;
|
||||
//fprintf(stderr, "ptr=%p segptr=%p\n", ptr, segptr);
|
||||
if ((long)0x0000545845545f5ful == *(long const *)segptr->segname) { // "__TEXT"
|
||||
Mach_section_command const *const secptr = (Mach_section_command const *)(1+ segptr);
|
||||
//if ((long)0x0000747865745f5ful == *(long const *)secptr->sectname) { // "__text"
|
||||
f_unf = (f_unfilter *)(sizeof(unsigned short) + secptr->addr);
|
||||
f_exp = (f_expand *)((char const *)f_unf + ((unsigned short *)f_unf)[-1]);
|
||||
//fprintf(stderr, "f_unf=%p f_exp=%p\n", f_unf, f_exp);
|
||||
//}
|
||||
}
|
||||
if ((long)0x415441445f585055ul == *(long const *)segptr->segname) { // "UPX_DATA"
|
||||
payload = (unsigned char const *)(segptr->vmaddr);
|
||||
paysize = segptr->filesize;
|
||||
//fprintf(stderr, "payload=%p paysize=%lu\n", payload, paysize);
|
||||
}
|
||||
}
|
||||
char mhdr[2048];
|
||||
void const *entry = upx_main((struct l_info const *)ptr, len,
|
||||
(Mach_header64 *)&mhdr, sizeof(mhdr),
|
||||
//fprintf(stderr, "call upx_main(payload=%p paysize=%lu mhdr=%p f_exp=%p f_unf=%p mhdrp@%p)\n",
|
||||
//payload, paysize, mhdr, f_exp, f_unf, &mhdrp);
|
||||
uint64_t entry = upx_main((struct l_info const *)payload, paysize,
|
||||
(Mach_header64 *)mhdr, sizeof(mhdr),
|
||||
f_exp, f_unf, &mhdrp);
|
||||
launch(entry, &mhdrp);
|
||||
//fprintf(stderr, "return to launch\n");
|
||||
//launch(entry, &mhdrp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user