📄 p_lx_elf.cpp
字号:
static const int f_none[] = { FT_END }; return f_none;}const int *PackLinuxElf32mipsel::getFilters() const{ static const int f_none[] = { FT_END }; return f_none;}void PackLinuxElf32::ARM_defineSymbols(Filter const * /*ft*/){ unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info); lsize = /*getLoaderSize()*/ 4 * 1024; // upper bound; avoid circularity unsigned const lo_va_user = 0x8000; // XXX unsigned lo_va_stub = get_native32(&elfout.phdr[0].p_vaddr); unsigned adrc; unsigned adrm; unsigned adrx; bool const is_big = true; if (is_big) { set_native32( &elfout.ehdr.e_entry, linker->getSymbolOffset("_start") + get_native32(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub); set_native32(&elfout.phdr[0].p_vaddr, lo_va_user); set_native32(&elfout.phdr[0].p_paddr, lo_va_user); lo_va_stub = lo_va_user; adrc = lo_va_stub; adrm = getbrk(phdri, get_native16(&ehdri.e_phnum)); adrx = hlen + (page_mask & (~page_mask + adrm)); // round up to page boundary } adrm = page_mask & (~page_mask + adrm); // round up to page boundary adrc = page_mask & (~page_mask + adrc); // round up to page boundary linker->defineSymbol("CPR0", 4+ linker->getSymbolOffset("cpr0")); linker->defineSymbol("LENF", 4+ linker->getSymbolOffset("end_decompress")); linker->defineSymbol("ADRM", adrm); // addr for map}void PackLinuxElf32armLe::defineSymbols(Filter const *ft){ ARM_defineSymbols(ft);}void PackLinuxElf32armBe::defineSymbols(Filter const *ft){ ARM_defineSymbols(ft);}void PackLinuxElf32mipseb::defineSymbols(Filter const * /*ft*/){ unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info); // We want to know if compressed data, plus stub, plus a couple pages, // will fit below the uncompressed program in memory. But we don't // know the final total compressed size yet, so use the uncompressed // size (total over all PT_LOAD32) as an upper bound. unsigned len = 0; unsigned lo_va_user = ~0u; // infinity for (int j= get_native16(&ehdri.e_phnum); --j>=0; ) { if (PT_LOAD32 == get_native32(&phdri[j].p_type)) { len += (unsigned)get_native32(&phdri[j].p_filesz); unsigned const va = get_native32(&phdri[j].p_vaddr); if (va < lo_va_user) { lo_va_user = va; } } } lsize = /*getLoaderSize()*/ 64 * 1024; // XXX: upper bound; avoid circularity unsigned lo_va_stub = get_native32(&elfout.phdr[0].p_vaddr); unsigned adrc; unsigned adrm; unsigned adru; unsigned adrx; unsigned cntc; unsigned lenm; unsigned lenu; len += (7&-lsize) + lsize; bool const is_big = (lo_va_user < (lo_va_stub + len + 2*page_size)); if (is_big) { set_native32( &elfout.ehdr.e_entry, get_native32(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub); set_native32(&elfout.phdr[0].p_vaddr, lo_va_user); set_native32(&elfout.phdr[0].p_paddr, lo_va_user); lo_va_stub = lo_va_user; adrc = lo_va_stub; adrm = getbrk(phdri, get_native16(&ehdri.e_phnum)); adru = page_mask & (~page_mask + adrm); // round up to page boundary adrx = adru + hlen; lenm = page_size + len; lenu = page_size + len; cntc = len >> 3; // over-estimate; corrected at runtime } else { adrm = lo_va_stub + len; adrc = adrm; adru = lo_va_stub; adrx = lo_va_stub + hlen; lenm = page_size; lenu = page_size + len; cntc = 0; } adrm = page_mask & (~page_mask + adrm); // round up to page boundary adrc = page_mask & (~page_mask + adrc); // round up to page boundary linker->defineSymbol("ADRX", adrx); // compressed input for eXpansion // For actual moving, we need the true count, which depends on sz_pack2 // and is not yet known. So the runtime stub detects "no move" // if adrm==adrc, and otherwise uses actual sz_pack2 to compute cntc. //linker->defineSymbol("CNTC", cntc); // count for copy linker->defineSymbol("ADRC", adrc); // addr for copy linker->defineSymbol("LENU", lenu); // len for unmap linker->defineSymbol("ADRU", adru); // addr for unmap linker->defineSymbol("LENM", lenm); // len for map linker->defineSymbol("ADRM", adrm); // addr for map //linker->dumpSymbols(); // debug}void PackLinuxElf32mipsel::defineSymbols(Filter const * /*ft*/){ unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info); // We want to know if compressed data, plus stub, plus a couple pages, // will fit below the uncompressed program in memory. But we don't // know the final total compressed size yet, so use the uncompressed // size (total over all PT_LOAD32) as an upper bound. unsigned len = 0; unsigned lo_va_user = ~0u; // infinity for (int j= get_native16(&ehdri.e_phnum); --j>=0; ) { if (PT_LOAD32 == get_native32(&phdri[j].p_type)) { len += (unsigned)get_native32(&phdri[j].p_filesz); unsigned const va = get_native32(&phdri[j].p_vaddr); if (va < lo_va_user) { lo_va_user = va; } } } lsize = /*getLoaderSize()*/ 64 * 1024; // XXX: upper bound; avoid circularity unsigned lo_va_stub = get_native32(&elfout.phdr[0].p_vaddr); unsigned adrc; unsigned adrm; unsigned adru; unsigned adrx; unsigned cntc; unsigned lenm; unsigned lenu; len += (7&-lsize) + lsize; bool const is_big = (lo_va_user < (lo_va_stub + len + 2*page_size)); if (is_big) { set_native32( &elfout.ehdr.e_entry, get_native32(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub); set_native32(&elfout.phdr[0].p_vaddr, lo_va_user); set_native32(&elfout.phdr[0].p_paddr, lo_va_user); lo_va_stub = lo_va_user; adrc = lo_va_stub; adrm = getbrk(phdri, get_native16(&ehdri.e_phnum)); adru = page_mask & (~page_mask + adrm); // round up to page boundary adrx = adru + hlen; lenm = page_size + len; lenu = page_size + len; cntc = len >> 3; // over-estimate; corrected at runtime } else { adrm = lo_va_stub + len; adrc = adrm; adru = lo_va_stub; adrx = lo_va_stub + hlen; lenm = page_size; lenu = page_size + len; cntc = 0; } adrm = page_mask & (~page_mask + adrm); // round up to page boundary adrc = page_mask & (~page_mask + adrc); // round up to page boundary linker->defineSymbol("ADRX", adrx); // compressed input for eXpansion // For actual moving, we need the true count, which depends on sz_pack2 // and is not yet known. So the runtime stub detects "no move" // if adrm==adrc, and otherwise uses actual sz_pack2 to compute cntc. //linker->defineSymbol("CNTC", cntc); // count for copy linker->defineSymbol("ADRC", adrc); // addr for copy linker->defineSymbol("LENU", lenu); // len for unmap linker->defineSymbol("ADRU", adru); // addr for unmap linker->defineSymbol("LENM", lenm); // len for map linker->defineSymbol("ADRM", adrm); // addr for map //linker->dumpSymbols(); // debug}void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft){ overlay_offset = sz_elf_hdrs + sizeof(linfo); unsigned const zero = 0; unsigned len = fo->getBytesWritten(); fo->write(&zero, 3& -len); // align to 0 mod 4 len += 3& -len; set_native32(&elfout.phdr[0].p_filesz, len); super::pack4(fo, ft); // write PackHeader and overlay_offset // Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel // tries to make .bss, which requires PF_W. // But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.#if 0 /*{*/ // pre-calculate for benefit of runtime disappearing act via munmap() set_native32(&elfout.phdr[0].p_memsz, page_mask & (~page_mask + len));#else /*}{*/ set_native32(&elfout.phdr[0].p_memsz, len);#endif /*}*/ // rewrite Elf header if (Elf32_Ehdr::ET_DYN==get_native16(&ehdri.e_type)) { unsigned const base= get_native32(&elfout.phdr[0].p_vaddr); set_native16(&elfout.ehdr.e_type, Elf32_Ehdr::ET_DYN); set_native16(&elfout.ehdr.e_phnum, 1); set_native32( &elfout.ehdr.e_entry, get_native32(&elfout.ehdr.e_entry) - base); set_native32(&elfout.phdr[0].p_vaddr, get_native32(&elfout.phdr[0].p_vaddr) - base); set_native32(&elfout.phdr[0].p_paddr, get_native32(&elfout.phdr[0].p_paddr) - base); // Strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X //elfout.phdr[0].p_flags |= Elf32_Phdr::PF_W; } fo->seek(0, SEEK_SET); if (Elf32_Phdr::PT_NOTE==get_native32(&elfout.phdr[2].p_type)) { unsigned const reloc = get_native32(&elfout.phdr[0].p_vaddr); set_native32( &elfout.phdr[2].p_vaddr, reloc + get_native32(&elfout.phdr[2].p_vaddr)); set_native32( &elfout.phdr[2].p_paddr, reloc + get_native32(&elfout.phdr[2].p_paddr)); fo->rewrite(&elfout, sz_elf_hdrs); fo->rewrite(&elfnote, sizeof(elfnote)); } else { fo->rewrite(&elfout, sz_elf_hdrs); } fo->rewrite(&linfo, sizeof(linfo));}void PackLinuxElf64::pack4(OutputFile *fo, Filter &ft){ overlay_offset = sz_elf_hdrs + sizeof(linfo); unsigned const zero = 0; unsigned len = fo->getBytesWritten(); fo->write(&zero, 3& -len); // align to 0 mod 4 len += 3& -len; set_native64(&elfout.phdr[0].p_filesz, len); super::pack4(fo, ft); // write PackHeader and overlay_offset // Cannot pre-round .p_memsz. If .p_filesz < .p_memsz, then kernel // tries to make .bss, which requires PF_W. // But strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X.#if 0 /*{*/ // pre-calculate for benefit of runtime disappearing act via munmap() set_native64(&elfout.phdr[0].p_memsz, page_mask & (~page_mask + len));#else /*}{*/ set_native64(&elfout.phdr[0].p_memsz, len);#endif /*}*/ // rewrite Elf header fo->seek(0, SEEK_SET); fo->rewrite(&elfout, sz_elf_hdrs); fo->rewrite(&linfo, sizeof(linfo));}void PackLinuxElf32::unpack(OutputFile *fo){#define MAX_ELF_HDR 512 char bufehdr[MAX_ELF_HDR]; Elf32_Ehdr *const ehdr = (Elf32_Ehdr *)bufehdr; Elf32_Phdr const *phdr = (Elf32_Phdr *)(1+ehdr); unsigned szb_info = sizeof(b_info); { fi->seek(0, SEEK_SET); fi->readx(bufehdr, MAX_ELF_HDR); unsigned const e_entry = get_native32(&ehdr->e_entry); if (e_entry < 0x401180 && ehdr->e_machine==Elf32_Ehdr::EM_386) { /* old style, 8-byte b_info */ szb_info = 2*sizeof(unsigned); } } 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, szb_info); ph.u_len = get_native32(&bhdr.sz_unc); ph.c_len = get_native32(&bhdr.sz_cpr); ph.filter_cto = bhdr.b_cto8; // Uncompress Ehdr and Phdrs. fi->readx(ibuf, ph.c_len); decompress(ibuf, (upx_byte *)ehdr, false); unsigned total_in = 0; unsigned total_out = 0; unsigned c_adler = upx_adler32(NULL, 0); unsigned u_adler = upx_adler32(NULL, 0); // decompress PT_LOAD32 bool first_PF_X = true; unsigned const phnum = get_native16(&ehdr->e_phnum); fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR); for (unsigned j=0; j < phnum; ++phdr, ++j) { if (PT_LOAD32==get_native32(&phdr->p_type)) { unsigned const filesz = get_native32(&phdr->p_filesz); unsigned const offset = get_native32(&phdr->p_offset); if (fo) fo->seek(offset, SEEK_SET); if (Elf32_Phdr::PF_X & get_native32(&phdr->p_flags)) { unpackExtent(filesz, fo, total_in, total_out, c_adler, u_adler, first_PF_X, szb_info); first_PF_X = false; } else { unpackExtent(filesz, fo, total_in, total_out, c_adler, u_adler, false, szb_info); } } } phdr = (Elf32_Phdr *)(1+ehdr); for (unsigned j = 0; j < phnum; ++j) { unsigned const size = find_LOAD_gap(phdr, j, phnum); if (size) { unsigned const where = get_native32(&phdr[j].p_offset) + get_native32(&phdr[j].p_filesz); if (fo) fo->seek(where, SEEK_SET); unpackExtent(size, fo, total_in, total_out, c_adler, u_adler, false, szb_info); } } // check for end-of-file fi->readx(&bhdr, szb_info); unsigned const sz_unc = ph.u_len = get_native32(&bhdr.sz_unc); if (sz_unc == 0) { // uncompressed size 0 -> EOF // note: magic is always stored le32 unsigned const sz_cpr = get_le32(&bhdr.sz_cpr); if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic throwCompressedDataViolation(); } else { // extra bytes after end? throwCompressedDataViolation(); } // update header with totals ph.c_len = total_in; ph.u_len = total_out; // all bytes must be written if (total_out != orig_file_size) throwEOFException(); // finally test the checksums if (ph.c_adler != c_adler || ph.u_adler != u_adler) throwChecksumError();#undef MAX_ELF_HDR}void PackLinuxElf64::unpack(OutputFile *fo){#define MAX_ELF_HDR 1024 char bufehdr[MAX_ELF_HDR]; Elf64_Ehdr *const ehdr = (Elf64_Ehdr *)bufehdr; Elf64_Phdr const *phdr = (Elf64_Phdr *)(1+ehdr); unsigned szb_info = sizeof(b_info); { fi->seek(0, SEEK_SET); fi->readx(bufehdr, MAX_ELF_HDR); acc_uint64l_t const e_entry = get_native64(&ehdr->e_entry); if (e_entry < 0x401180 && ehdr->e_machine==Elf64_Ehdr::EM_386) { /* old style, 8-byte b_info */ szb_info = 2*sizeof(unsigned); } } fi->seek(overlay_offset, SEEK_SET); p_info hbuf; fi->readx(&hbuf, sizeof
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -