Apple codesign now works.
modified: p_mach.cpp
This commit is contained in:
+105
-124
@@ -805,48 +805,38 @@ void PackMachAMD64::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
|||||||
unsigned char upxstub[sizeof(stub_amd64_darwin_macho_upxmain_exe)];
|
unsigned char upxstub[sizeof(stub_amd64_darwin_macho_upxmain_exe)];
|
||||||
memcpy(upxstub, stub_amd64_darwin_macho_upxmain_exe, sizeof(upxstub));
|
memcpy(upxstub, stub_amd64_darwin_macho_upxmain_exe, sizeof(upxstub));
|
||||||
|
|
||||||
Mach_header *const ptr0 = (Mach_header *)upxstub;
|
Mach_header *const mhp = (Mach_header *)upxstub;
|
||||||
Mach_command *ptr1 = (Mach_command *)(1+ ptr0);
|
char *tail = (char *)(1+ mhp);
|
||||||
unsigned cmdsize = mhdro.sizeofcmds - sizeof(segXHDR);
|
char *const lcp_end = mhdro.sizeofcmds + tail;
|
||||||
|
Mach_command *lcp = (Mach_command *)(1+ mhp);
|
||||||
|
Mach_command *lcp_next;
|
||||||
unsigned const ncmds = mhdro.ncmds;
|
unsigned const ncmds = mhdro.ncmds;
|
||||||
|
//unsigned cmdsize = mhdro.sizeofcmds;
|
||||||
unsigned delta = 0;
|
unsigned delta = 0;
|
||||||
for (unsigned j = 0; j < ncmds -1; ++j,
|
|
||||||
(cmdsize -= ptr1->cmdsize),
|
for (unsigned j = 0; j < ncmds; ++j) {
|
||||||
ptr1 = (Mach_command *)(ptr1->cmdsize + (char *)ptr1))
|
unsigned skip = 0;
|
||||||
next:
|
unsigned sz_cmd = lcp->cmdsize;
|
||||||
switch (ptr1->cmd) {
|
lcp_next = (Mach_command *)(sz_cmd + (char *)lcp);
|
||||||
|
|
||||||
|
switch (lcp->cmd) {
|
||||||
case Mach_segment_command::LC_SEGMENT_64: {
|
case Mach_segment_command::LC_SEGMENT_64: {
|
||||||
Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr1;
|
Mach_segment_command *const segptr = (Mach_segment_command *)lcp;
|
||||||
if (!strcmp("__TEXT", segptr->segname)) {
|
if (!strcmp("__TEXT", segptr->segname)) {
|
||||||
|
if (0) { // Why is codesign unhappy with this?
|
||||||
|
int const d = (-1+ segptr->nsects) * sizeof(secTEXT);
|
||||||
|
if (0 < d) {
|
||||||
|
segptr->nsects = 1;
|
||||||
|
segptr->cmdsize -= d;
|
||||||
|
sz_cmd -= d;
|
||||||
|
}
|
||||||
|
}
|
||||||
memcpy(&segTEXT, segptr, sizeof(segTEXT));
|
memcpy(&segTEXT, segptr, sizeof(segTEXT));
|
||||||
Mach_section_command const *const secptr = (Mach_section_command const *)(1+ segptr);
|
Mach_section_command const *const secptr = (Mach_section_command const *)(1+ segptr);
|
||||||
memcpy(&secTEXT, secptr, sizeof(secTEXT));
|
memcpy(&secTEXT, secptr, sizeof(secTEXT));
|
||||||
// // Put f_unf and f_exp before compiled C code:
|
break;
|
||||||
// // steal space from -Wl,-headerpadsize
|
|
||||||
//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("__DATA", segptr->segname) && !segptr->vmsize) {
|
if (!strcmp("__DATA", segptr->segname) && !segptr->vmsize) {
|
||||||
goto omit;
|
|
||||||
}
|
|
||||||
if (!strcmp("__LINKEDIT", segptr->segname)) {
|
|
||||||
segLINK.initprot = Mach_segment_command::VM_PROT_READ
|
|
||||||
| Mach_segment_command::VM_PROT_EXECUTE;
|
|
||||||
delta = offLINK - segptr->fileoff; // relocation constant
|
|
||||||
|
|
||||||
//// The contents for __LINKEDIT remain the same,
|
|
||||||
//// but move to a different offset in the file
|
|
||||||
//fo->seek(offLINK, SEEK_SET);
|
|
||||||
//fo->write(&stub_amd64_darwin_macho_upxmain_exe[segLINK.fileoff], segLINK.filesize);
|
|
||||||
|
|
||||||
// Mach_segment_command for new segXHDR
|
// Mach_segment_command for new segXHDR
|
||||||
segXHDR.cmdsize = sizeof(segXHDR); // no need for sections
|
segXHDR.cmdsize = sizeof(segXHDR); // no need for sections
|
||||||
segXHDR.vmaddr = segTEXT.vmsize + segTEXT.vmaddr; // XXX FIXME
|
segXHDR.vmaddr = segTEXT.vmsize + segTEXT.vmaddr; // XXX FIXME
|
||||||
@@ -855,62 +845,66 @@ next:
|
|||||||
segXHDR.filesize = offLINK - segTEXT.filesize; // XXX FIXME: assumes no __DATA in stub;
|
segXHDR.filesize = offLINK - segTEXT.filesize; // XXX FIXME: assumes no __DATA in stub;
|
||||||
segXHDR.maxprot = Mach_segment_command::VM_PROT_READ;
|
segXHDR.maxprot = Mach_segment_command::VM_PROT_READ;
|
||||||
segXHDR.nsects = 0;
|
segXHDR.nsects = 0;
|
||||||
fo->seek((char const *)ptr1 - (char const *)ptr0, SEEK_SET);
|
memcpy(tail, &segXHDR, sizeof(segXHDR));
|
||||||
fo->rewrite(&segXHDR, sizeof(segXHDR));
|
tail += sizeof(segXHDR);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
if (!strcmp("__LINKEDIT", segptr->segname)) {
|
||||||
|
segLINK.initprot = Mach_segment_command::VM_PROT_READ
|
||||||
|
| Mach_segment_command::VM_PROT_EXECUTE;
|
||||||
|
delta = offLINK - segptr->fileoff; // relocation constant
|
||||||
|
|
||||||
// Update the __LINKEDIT header
|
// Update the __LINKEDIT header
|
||||||
segLINK.filesize = eofcmpr - offLINK;
|
segLINK.filesize = eofcmpr - offLINK;
|
||||||
segLINK.vmsize = PAGE_MASK64 & (~PAGE_MASK64 + eofcmpr - offLINK);
|
segLINK.vmsize = PAGE_MASK64 & (~PAGE_MASK64 + eofcmpr - offLINK);
|
||||||
segLINK.fileoff = segXHDR.filesize + segXHDR.fileoff;
|
segLINK.fileoff = segXHDR.filesize + segXHDR.fileoff;
|
||||||
segLINK.vmaddr = segXHDR.vmsize + segXHDR.vmaddr;
|
segLINK.vmaddr = segXHDR.vmsize + segXHDR.vmaddr;
|
||||||
fo->rewrite(&segLINK, sizeof(segLINK));
|
memcpy(tail, &segLINK, sizeof(segLINK));
|
||||||
|
tail += sizeof(segLINK);
|
||||||
|
goto next;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_DYLD_INFO_ONLY: {
|
case Mach_segment_command::LC_DYLD_INFO_ONLY: {
|
||||||
N_Mach::Mach_dyld_info_only_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
N_Mach::Mach_dyld_info_only_command *p = (N_Mach::Mach_dyld_info_only_command *)lcp;
|
||||||
if (blk.rebase_off) blk.rebase_off += delta;
|
if (p->rebase_off) p->rebase_off += delta;
|
||||||
if (blk.bind_off) blk.bind_off += delta;
|
if (p->bind_off) p->bind_off += delta;
|
||||||
if (blk.lazy_bind_off) blk.lazy_bind_off += delta;
|
if (p->lazy_bind_off) p->lazy_bind_off += delta;
|
||||||
if (blk.export_off) blk.export_off += delta;
|
if (p->export_off) p->export_off += delta;
|
||||||
// But we don't want any exported symbols.
|
// But we don't want any exported symbols.
|
||||||
blk.export_off = 0;
|
p->export_off = 0;
|
||||||
blk.export_size = 0;
|
p->export_size = 0;
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
skip = 1;
|
||||||
fo->rewrite(&blk, sizeof(blk));
|
|
||||||
goto omit; // try omitting this
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_SYMTAB: {
|
case Mach_segment_command::LC_SYMTAB: {
|
||||||
Mach_symtab_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
// Apple codesign requires that string table is last in the file.
|
||||||
if (blk.symoff) blk.symoff += delta;
|
Mach_symtab_command *p = (Mach_symtab_command *)lcp;
|
||||||
if (blk.stroff) blk.stroff += delta;
|
p->symoff = segLINK.filesize + segLINK.fileoff;
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
p->nsyms = 0;
|
||||||
fo->rewrite(&blk, sizeof(blk));
|
p->stroff = segLINK.fileoff;
|
||||||
goto omit; // try omitting this
|
p->strsize = segLINK.filesize;
|
||||||
|
skip = 1;
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_DYSYMTAB: {
|
case Mach_segment_command::LC_DYSYMTAB: {
|
||||||
Mach_dysymtab_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
Mach_dysymtab_command *p = (Mach_dysymtab_command *)lcp;
|
||||||
if (blk.tocoff) blk.tocoff += delta;
|
if (p->tocoff) p->tocoff += delta;
|
||||||
if (blk.modtaboff) blk.modtaboff += delta;
|
if (p->modtaboff) p->modtaboff += delta;
|
||||||
if (blk.extrefsymoff) blk.extrefsymoff += delta;
|
if (p->extrefsymoff) p->extrefsymoff += delta;
|
||||||
if (blk.indirectsymoff) blk.indirectsymoff += delta;
|
if (p->indirectsymoff) p->indirectsymoff += delta;
|
||||||
if (blk.extreloff) blk.extreloff += delta;
|
if (p->extreloff) p->extreloff += delta;
|
||||||
if (blk.locreloff) blk.locreloff += delta;
|
if (p->locreloff) p->locreloff += delta;
|
||||||
// But we don't want any symbols.
|
// But we don't want any symbols.
|
||||||
blk.ilocalsym = 0;
|
p->ilocalsym = 0;
|
||||||
blk.nlocalsym = 0;
|
p->nlocalsym = 0;
|
||||||
blk.iextdefsym = 0;
|
p->iextdefsym = 0;
|
||||||
blk.nextdefsym = 0;
|
p->nextdefsym = 0;
|
||||||
blk.iundefsym = 0;
|
p->iundefsym = 0;
|
||||||
blk.nundefsym = 0;
|
p->nundefsym = 0;
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
skip = 1;
|
||||||
fo->rewrite(&blk, sizeof(blk));
|
|
||||||
goto omit; // adds full path as another agrument?
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_FUNCTION_STARTS: {
|
case Mach_segment_command::LC_FUNCTION_STARTS: {
|
||||||
N_Mach::Mach_function_starts_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
N_Mach::Mach_function_starts_command *p = (N_Mach::Mach_function_starts_command *)lcp;
|
||||||
if (blk.dataoff) blk.dataoff += delta;
|
if (p->dataoff) p->dataoff += delta;
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
skip = 1;
|
||||||
fo->rewrite(&blk, sizeof(blk));
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_MAIN: {
|
case Mach_segment_command::LC_MAIN: {
|
||||||
// Change to LC_UNIX_THREAD; known to be contiguous with last
|
// Change to LC_UNIX_THREAD; known to be contiguous with last
|
||||||
@@ -921,69 +915,56 @@ next:
|
|||||||
threado.flavor = my_thread_flavor;
|
threado.flavor = my_thread_flavor;
|
||||||
threado.count = my_thread_state_word_count;
|
threado.count = my_thread_state_word_count;
|
||||||
memset(&threado.state, 0, sizeof(threado.state));
|
memset(&threado.state, 0, sizeof(threado.state));
|
||||||
threado.state.rip = ((N_Mach::Mach_main_command const *)ptr1)->entryoff + segTEXT.vmaddr;
|
threado.state.rip = ((N_Mach::Mach_main_command const *)lcp)->entryoff + segTEXT.vmaddr;
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
skip = 1;
|
||||||
fo->rewrite(&threado, sizeof(threado));
|
|
||||||
mhdro.sizeofcmds += sizeof(threado) - ((Mach_command const *)ptr1)->cmdsize;
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(&mhdro, sizeof(mhdro));
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_LOAD_DYLIB: {
|
case Mach_segment_command::LC_LOAD_DYLIB: {
|
||||||
// Remove this command; known to be contiguous with last
|
skip = 1;
|
||||||
N_Mach::Mach_load_dylib_command blk; memset(&blk, 0, sizeof(blk));
|
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
|
||||||
fo->rewrite(&blk, sizeof(blk));
|
|
||||||
mhdro.ncmds -= 1;
|
|
||||||
mhdro.sizeofcmds -= ((Mach_command const *)ptr1)->cmdsize;
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(&mhdro, sizeof(mhdro));
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_DATA_IN_CODE: {
|
case Mach_segment_command::LC_DATA_IN_CODE: {
|
||||||
N_Mach::Mach_data_in_code_command blk; memcpy(&blk, ptr1, sizeof(blk));
|
N_Mach::Mach_data_in_code_command *p = (N_Mach::Mach_data_in_code_command *)lcp;
|
||||||
if (blk.dataoff) blk.dataoff += delta;
|
if (p->dataoff) p->dataoff += delta;
|
||||||
memset(&blk, 0, sizeof(blk));
|
skip = 1;
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
|
||||||
fo->rewrite(&blk, sizeof(blk));
|
|
||||||
// Temporary test: remove this command; known to be last
|
|
||||||
mhdro.ncmds -= 1;
|
|
||||||
mhdro.sizeofcmds -= ((Mach_command const *)ptr1)->cmdsize;
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(&mhdro, sizeof(mhdro));
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_LOAD_DYLINKER: {
|
case Mach_segment_command::LC_LOAD_DYLINKER: {
|
||||||
// Try omitting this
|
skip = 1;
|
||||||
omit:
|
|
||||||
fo->seek(sizeof(mhdro) + mhdro.sizeofcmds - cmdsize, SEEK_SET);
|
|
||||||
Mach_command *ptr2 = ptr1;
|
|
||||||
unsigned const sz_omit = ptr1->cmdsize;
|
|
||||||
ptr1 = (Mach_command *)(sz_omit + (char *)ptr1);
|
|
||||||
cmdsize -= sz_omit;
|
|
||||||
|
|
||||||
fo->rewrite(ptr1, cmdsize); // slide in file TODO: clear the garbage
|
|
||||||
memmove(ptr2, ptr1, cmdsize); // overlapping slide lower
|
|
||||||
ptr1 = ptr2;
|
|
||||||
|
|
||||||
mhdro.ncmds -= 1;
|
|
||||||
mhdro.sizeofcmds -= sz_omit;
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(&mhdro, sizeof(mhdro));
|
|
||||||
if (++j < (ncmds -1))
|
|
||||||
goto next;
|
|
||||||
goto done;
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_SOURCE_VERSION: { // copy from saved original
|
case Mach_segment_command::LC_SOURCE_VERSION: { // copy from saved original
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
memcpy(lcp, &cmdSRCVER, sizeof(cmdSRCVER));
|
||||||
fo->rewrite(&cmdSRCVER, sizeof(cmdSRCVER));
|
|
||||||
memcpy(ptr1, &cmdSRCVER, sizeof(cmdSRCVER));
|
|
||||||
goto omit;
|
|
||||||
} break;
|
} break;
|
||||||
case Mach_segment_command::LC_VERSION_MIN_MACOSX: { // copy from saved original
|
case Mach_segment_command::LC_VERSION_MIN_MACOSX: { // copy from saved original
|
||||||
fo->seek(sizeof(segXHDR) + ((char const *)ptr1 - (char const *)ptr0), SEEK_SET);
|
memcpy(lcp, &cmdVERMIN, sizeof(cmdVERMIN));
|
||||||
fo->rewrite(&cmdVERMIN, sizeof(cmdVERMIN));
|
|
||||||
memcpy(ptr1, &cmdVERMIN, sizeof(cmdVERMIN));
|
|
||||||
} break;
|
} break;
|
||||||
} // end switch
|
} // end switch
|
||||||
done:
|
|
||||||
|
if (skip) {
|
||||||
|
mhp->ncmds -= 1;
|
||||||
|
mhp->sizeofcmds -= sz_cmd;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (tail != (char *)lcp) {
|
||||||
|
memmove(tail, lcp, sz_cmd);
|
||||||
|
}
|
||||||
|
tail += sz_cmd;
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
lcp = lcp_next;
|
||||||
|
} // end for
|
||||||
|
|
||||||
|
// Add LC_UNIX_THREAD
|
||||||
|
mhp->ncmds += 1;
|
||||||
|
mhp->sizeofcmds += sizeof(threado);
|
||||||
|
fo->seek(0, SEEK_SET);
|
||||||
|
fo->rewrite(mhp, tail - (char *)mhp);
|
||||||
|
fo->rewrite(&threado, sizeof(threado));
|
||||||
|
tail += sizeof(threado);
|
||||||
|
//
|
||||||
|
// Zero any remaining tail.
|
||||||
|
if (tail < lcp_end) {
|
||||||
|
unsigned sz_cmd = lcp_end - tail;
|
||||||
|
memset(tail, 0, sz_cmd);
|
||||||
|
fo->rewrite(tail, sz_cmd);
|
||||||
|
}
|
||||||
fo->seek(0, SEEK_END);
|
fo->seek(0, SEEK_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2022,7 +2003,7 @@ int PackMachBase<T>::canUnpack()
|
|||||||
if (i < 1 || !getPackHeader(buf + i, bufsize - i, true)) {
|
if (i < 1 || !getPackHeader(buf + i, bufsize - i, true)) {
|
||||||
// Breadcrumbs failed.
|
// Breadcrumbs failed.
|
||||||
// Pirates might overwrite the UPX! marker. Try harder.
|
// Pirates might overwrite the UPX! marker. Try harder.
|
||||||
upx_uint64_t const rip_off = rip - ptrTEXT->vmaddr;
|
upx_uint64_t const rip_off = ptrTEXT ? (rip - ptrTEXT->vmaddr) : 0;
|
||||||
if (ptrTEXT && rip && rip_off < ptrTEXT->vmsize) {
|
if (ptrTEXT && rip && rip_off < ptrTEXT->vmsize) {
|
||||||
fi->seek(ptrTEXT->fileoff + rip_off, SEEK_SET);
|
fi->seek(ptrTEXT->fileoff + rip_off, SEEK_SET);
|
||||||
fi->readx(buf, bufsize);
|
fi->readx(buf, bufsize);
|
||||||
|
|||||||
Reference in New Issue
Block a user