📄 p_mach.cpp
字号:
&& exe_filesize_max < msegcmd[k].filesize) { exe_filesize_max = msegcmd[k].filesize; } int nx = 0; for (k = 0; k < n_segment; ++k) if (Mach_segment_command::LC_SEGMENT==msegcmd[k].cmd && 0!=msegcmd[k].filesize ) { x.offset = msegcmd[k].fileoff; x.size = msegcmd[k].filesize; if (0 == nx) { // 1st LC_SEGMENT must cover Mach_header at 0==fileoffset unsigned const delta = mhdri.sizeofcmds; x.offset += delta; x.size -= delta; } bool const do_filter = (msegcmd[k].filesize==exe_filesize_max) && 0!=(Mach_segment_command::VM_PROT_EXECUTE & msegcmd[k].initprot); packExtent(x, total_in, total_out, (do_filter ? &ft : 0 ), fo, hdr_u_len ); if (do_filter) { exe_filesize_max = 0; } hdr_u_len = 0; ++nx; } for (k = 0; k < n_segment; ++k) { x.size = find_SEGMENT_gap(k); if (x.size) { x.offset = msegcmd[k].fileoff +msegcmd[k].filesize; packExtent(x, total_in, total_out, 0, fo); } } if ((off_t)total_in != file_size) throwEOFException(); segcmdo.filesize = fo->getBytesWritten();}#undef PAGE_MASK#undef PAGE_SIZE#define PAGE_MASK (~0u<<12)#define PAGE_SIZE -PAGE_MASKvoid PackMachPPC32::pack1_setup_threado(OutputFile *const fo){ threado.cmd = Mach_segment_command::LC_UNIXTHREAD; threado.cmdsize = sizeof(threado); threado.flavor = my_thread_flavor; threado.count = my_thread_state_word_count; memset(&threado.state, 0, sizeof(threado.state)); fo->write(&threado, sizeof(threado));}void PackMachI386::pack1_setup_threado(OutputFile *const fo){ threado.cmd = Mach_segment_command::LC_UNIXTHREAD; threado.cmdsize = sizeof(threado); threado.flavor = my_thread_flavor; threado.count = my_thread_state_word_count; memset(&threado.state, 0, sizeof(threado.state)); fo->write(&threado, sizeof(threado));}template <class T>void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate executable header{ mhdro = mhdri; mhdro.ncmds = 2; mhdro.sizeofcmds = sizeof(segcmdo) + my_thread_command_size; mhdro.flags = Mach_header::MH_NOUNDEFS; fo->write(&mhdro, sizeof(mhdro)); segcmdo.cmd = Mach_segment_command::LC_SEGMENT; segcmdo.cmdsize = sizeof(segcmdo); strncpy((char *)&segcmdo.segname, "__TEXT", sizeof(segcmdo.segname)); segcmdo.vmaddr = PAGE_MASK & (~PAGE_MASK + msegcmd[n_segment -1].vmsize + msegcmd[n_segment -1].vmaddr ); segcmdo.vmsize = 0; // adjust later segcmdo.fileoff = 0; segcmdo.filesize = 0; // adjust later segcmdo.initprot = segcmdo.maxprot = Mach_segment_command::VM_PROT_READ | Mach_segment_command::VM_PROT_WRITE | Mach_segment_command::VM_PROT_EXECUTE; segcmdo.nsects = 0; segcmdo.flags = 0; fo->write(&segcmdo, sizeof(segcmdo)); pack1_setup_threado(fo); sz_mach_headers = fo->getBytesWritten(); memset((char *)&linfo, 0, sizeof(linfo)); fo->write(&linfo, sizeof(linfo)); return;}template <class T>void PackMachBase<T>::unpack(OutputFile *fo){ overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + my_thread_command_size + sizeof(linfo); fi->seek(overlay_offset, SEEK_SET); p_info hbuf; fi->readx(&hbuf, sizeof(hbuf)); unsigned orig_file_size = get_native32(&hbuf.p_filesize); blocksize = get_native32(&hbuf.p_blocksize); if (file_size > (off_t)orig_file_size || blocksize > orig_file_size) throwCantUnpack("file header corrupted"); ibuf.alloc(blocksize + OVERHEAD); b_info bhdr; memset(&bhdr, 0, sizeof(bhdr)); fi->readx(&bhdr, sizeof(bhdr)); ph.u_len = get_native32(&bhdr.sz_unc); ph.c_len = get_native32(&bhdr.sz_cpr); ph.method = bhdr.b_method; ph.filter = bhdr.b_ftid; ph.filter_cto = bhdr.b_cto8; // Uncompress Macho headers fi->readx(ibuf, ph.c_len); Mach_header *const mhdr = (Mach_header *)new upx_byte[ph.u_len]; decompress(ibuf, (upx_byte *)mhdr, false); unsigned const ncmds = mhdr->ncmds; msegcmd = new Mach_segment_command[ncmds]; unsigned char *ptr = (unsigned char *)(1+mhdr); for (unsigned j= 0; j < ncmds; ++j) { msegcmd[j] = *(Mach_segment_command *)ptr; ptr += (unsigned) ((Mach_segment_command *)ptr)->cmdsize; } // Put LC_SEGMENT together at the beginning, ascending by .vmaddr. qsort(msegcmd, ncmds, sizeof(*msegcmd), compare_segment_command); n_segment = 0; for (unsigned j= 0; j < ncmds; ++j) { n_segment += (Mach_segment_command::LC_SEGMENT==msegcmd[j].cmd); } unsigned total_in = 0; unsigned total_out = 0; unsigned c_adler = upx_adler32(NULL, 0); unsigned u_adler = upx_adler32(NULL, 0); Mach_segment_command const *sc = (Mach_segment_command const *)(1+ mhdr); unsigned k; fi->seek(- (off_t)(sizeof(bhdr) + ph.c_len), SEEK_CUR); for ( k = 0; k < ncmds; (++k), (sc = (Mach_segment_command const *)(sc->cmdsize + (char const *)sc)) ) { if (Mach_segment_command::LC_SEGMENT==sc->cmd && 0!=sc->filesize ) { unsigned filesize = sc->filesize; unpackExtent(filesize, fo, total_in, total_out, c_adler, u_adler, false, sizeof(bhdr)); } } for (unsigned j = 0; j < ncmds; ++j) { unsigned const size = find_SEGMENT_gap(j); if (size) { unsigned const where = msegcmd[k].fileoff +msegcmd[k].filesize; if (fo) fo->seek(where, SEEK_SET); unpackExtent(size, fo, total_in, total_out, c_adler, u_adler, false, sizeof(bhdr)); } }}template <class T>bool PackMachBase<T>::canPack(){ fi->seek(0, SEEK_SET); fi->readx(&mhdri, sizeof(mhdri)); if (Mach_header::MH_MAGIC !=mhdri.magic || my_cputype !=mhdri.cputype || Mach_header::MH_EXECUTE !=mhdri.filetype ) return false; rawmseg = (Mach_segment_command *)new char[mhdri.sizeofcmds]; fi->readx(rawmseg, mhdri.sizeofcmds); msegcmd = new Mach_segment_command[mhdri.ncmds]; unsigned char *ptr = (unsigned char *)rawmseg; for (unsigned j= 0; j < mhdri.ncmds; ++j) { msegcmd[j] = *(Mach_segment_command *)ptr; ptr += (unsigned) ((Mach_segment_command *)ptr)->cmdsize; } // Put LC_SEGMENT together at the beginning, ascending by .vmaddr. qsort(msegcmd, mhdri.ncmds, sizeof(*msegcmd), compare_segment_command); // Check that LC_SEGMENTs form one contiguous chunk of the file. for (unsigned j= 0; j < mhdri.ncmds; ++j) { if (Mach_segment_command::LC_SEGMENT==msegcmd[j].cmd) { if (0xfff & (msegcmd[j].fileoff | msegcmd[j].vmaddr)) { return false; } if (0 < j) { unsigned const sz = ~0xfff & (0xfff + msegcmd[j-1].filesize); if ((sz + msegcmd[j-1].fileoff)!=msegcmd[j].fileoff) { return false; } } ++n_segment; sz_segment = msegcmd[j].filesize + msegcmd[j].fileoff - msegcmd[0].fileoff; } } // info: currently the header is 36 (32+4) bytes before EOF unsigned char buf[256]; fi->seek(-(off_t)sizeof(buf), SEEK_END); fi->readx(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf)); // set options opt->o_unix.blocksize = file_size; return 0 < n_segment;}template class PackMachBase<MachClass_BE32>;template class PackMachBase<MachClass_LE32>;PackMachFat::PackMachFat(InputFile *f) : super(f){ bele = &N_BELE_RTP::le_policy; // sham}PackMachFat::~PackMachFat(){}const int *PackMachFat::getCompressionMethods(int /*method*/, int /*level*/) const{ static const int m_nrv2e[] = { M_NRV2E_LE32, M_END }; return m_nrv2e; // sham}const int *PackMachFat::getFilters() const{ static const int filters[] = { 0x49, FT_END }; return filters; // sham}void PackMachFat::pack(OutputFile *fo){ unsigned const in_size = this->file_size; fo->write(&fat_head, sizeof(fat_head.fat) + fat_head.fat.nfat_arch * sizeof(fat_head.arch[0])); unsigned length = 0; for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) { unsigned base = fo->unset_extent(); // actual length base += ~(~0u<<fat_head.arch[j].align) & (0-base); // align up fo->seek(base, SEEK_SET); fo->set_extent(base, ~0u); ph.u_file_size = fat_head.arch[j].size; fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size); switch (fat_head.arch[j].cputype) { case PackMachFat::CPU_TYPE_I386: { PackMachI386 packer(fi); packer.initPackHeader(); packer.canPack(); packer.updatePackHeader(); packer.pack(fo); } break; case PackMachFat::CPU_TYPE_POWERPC: { PackMachPPC32 packer(fi); packer.initPackHeader(); packer.canPack(); packer.updatePackHeader(); packer.pack(fo); } break; } // switch cputype fat_head.arch[j].offset = base; length = fo->unset_extent(); fat_head.arch[j].size = length - base; } ph.u_file_size = in_size; fi->set_extent(0, in_size); fo->seek(0, SEEK_SET); fo->rewrite(&fat_head, sizeof(fat_head.fat) + fat_head.fat.nfat_arch * sizeof(fat_head.arch[0])); fo->set_extent(0, length);}void PackMachFat::unpack(OutputFile *fo){ fo->seek(0, SEEK_SET); fo->write(&fat_head, sizeof(fat_head.fat) + fat_head.fat.nfat_arch * sizeof(fat_head.arch[0])); unsigned length; for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) { unsigned base = fo->unset_extent(); // actual length base += ~(~0u<<fat_head.arch[j].align) & (0-base); // align up fo->seek(base, SEEK_SET); fo->set_extent(base, ~0u); ph.u_file_size = fat_head.arch[j].size; fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size); switch (fat_head.arch[j].cputype) { case PackMachFat::CPU_TYPE_I386: { PackMachI386 packer(fi); packer.initPackHeader(); packer.canUnpack(); packer.unpack(fo); } break; case PackMachFat::CPU_TYPE_POWERPC: { PackMachPPC32 packer(fi); packer.initPackHeader(); packer.canUnpack(); packer.unpack(fo); } break; } // switch cputype fat_head.arch[j].offset = base; length = fo->unset_extent(); fat_head.arch[j].size = length - base; } fo->unset_extent(); fo->seek(0, SEEK_SET); fo->rewrite(&fat_head, sizeof(fat_head.fat) + fat_head.fat.nfat_arch * sizeof(fat_head.arch[0]));}bool PackMachFat::canPack(){ struct Mach_fat_arch *arch = &fat_head.arch[0]; fi->readx(&fat_head, sizeof(fat_head)); if (Mach_fat_header::FAT_MAGIC!=fat_head.fat.magic || N_FAT_ARCH < fat_head.fat.nfat_arch) { return false; } for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) { fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size); switch (arch[j].cputype) { default: return false; case PackMachFat::CPU_TYPE_I386: { PackMachI386 packer(fi); if (!packer.canPack()) return false; } break; case PackMachFat::CPU_TYPE_POWERPC: { PackMachPPC32 packer(fi); if (!packer.canPack()) return false; } break; } // switch cputype } // info: currently the header is 36 (32+4) bytes before EOF unsigned char buf[256]; fi->seek(-(off_t)sizeof(buf), SEEK_END); fi->readx(buf, sizeof(buf)); checkAlreadyPacked(buf, sizeof(buf)); return true;}int PackMachFat::canUnpack(){ struct Mach_fat_arch *arch = &fat_head.arch[0]; fi->readx(&fat_head, sizeof(fat_head)); if (Mach_fat_header::FAT_MAGIC!=fat_head.fat.magic || N_FAT_ARCH < fat_head.fat.nfat_arch) { return false; } for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) { fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size); switch (arch[j].cputype) { default: return false; case PackMachFat::CPU_TYPE_I386: { PackMachI386 packer(fi); if (!packer.canUnpack()) return 0; ph.format = packer.getFormat(); // FIXME: copy entire PackHeader } break; case PackMachFat::CPU_TYPE_POWERPC: { PackMachPPC32 packer(fi); if (!packer.canUnpack()) return 0; ph.format = packer.getFormat(); // FIXME: copy entire PackHeader } break; } // switch cputype } return 1;}void PackMachFat::buildLoader(const Filter */*ft*/){ assert(false);}Linker* PackMachFat::newLinker() const{ return new ElfLinkerX86; // sham}void PackMachFat::list(){ assert(false);}/*vi:ts=4:et*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -