PackLinuxElf32::generateElfHdr, PackLinuxElf64::buildLinuxLoader

modified:   p_elf_enum.h
	modified:   p_lx_elf.cpp
This commit is contained in:
John Reiser 2024-10-26 10:53:28 -07:00
parent 0cc0e51d5d
commit a9dc43f7fb
2 changed files with 55 additions and 17 deletions

View File

@ -73,6 +73,7 @@ class Dummy {
ET_CORE = 4, /* Core file */ ET_CORE = 4, /* Core file */
}; };
enum { // e_machine enum { // e_machine
EM_NONE = 0, // No machine
EM_386 = 3, // i386 EM_386 = 3, // i386
EM_MIPS = 8, EM_MIPS = 8,
EM_MIPS_RS3_LE = 10, // MIPS R3000 little-endian EM_MIPS_RS3_LE = 10, // MIPS R3000 little-endian

View File

@ -1521,7 +1521,10 @@ PackLinuxElf32::buildLinuxLoader(
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", len += snprintf(&sec[len], sizeof(sec) - len, ",%s",
"LZMA_DAISY,LZMA_ELF00,LZMA_DEC20,LZMA_DEC30"); "LZMA_DAISY,LZMA_ELF00,LZMA_DEC20,LZMA_DEC30");
} }
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "EXP_TAIL,SYSCALLS"); len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "EXP_TAIL");
if (hasLoaderSection("SYSCALLS")) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "SYSCALLS");
}
(void)len; (void)len;
NO_printf("%s\n", sec); NO_printf("%s\n", sec);
addLoader(sec, nullptr); addLoader(sec, nullptr);
@ -1572,7 +1575,7 @@ PackLinuxElf32::buildLinuxLoader(
NO_printf("FOLDEXEC unc=%#x cpr=%#x\n", sz_unc, sz_cpr); NO_printf("FOLDEXEC unc=%#x cpr=%#x\n", sz_unc, sz_cpr);
linker->addSection("FOLDEXEC", mb_cprLoader, sizeof(b_info) + sz_cpr, 0); linker->addSection("FOLDEXEC", mb_cprLoader, sizeof(b_info) + sz_cpr, 0);
if (xct_off // shlib if (xct_off // shlib
&& (0 && (this->e_machine==Elf32_Ehdr::EM_NONE
|| this->e_machine==Elf32_Ehdr::EM_386 || this->e_machine==Elf32_Ehdr::EM_386
|| this->e_machine==Elf32_Ehdr::EM_ARM || this->e_machine==Elf32_Ehdr::EM_ARM
|| this->e_machine==Elf32_Ehdr::EM_PPC || this->e_machine==Elf32_Ehdr::EM_PPC
@ -1581,7 +1584,7 @@ PackLinuxElf32::buildLinuxLoader(
) { // shlib with ELF2 de-compressor ) { // shlib with ELF2 de-compressor
addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR"); addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR");
} }
else if (0 else if (this->e_machine==Elf32_Ehdr::EM_NONE
|| this->e_machine==Elf32_Ehdr::EM_386 || this->e_machine==Elf32_Ehdr::EM_386
|| this->e_machine==Elf32_Ehdr::EM_ARM || this->e_machine==Elf32_Ehdr::EM_ARM
|| this->e_machine==Elf32_Ehdr::EM_PPC || this->e_machine==Elf32_Ehdr::EM_PPC
@ -1661,7 +1664,7 @@ PackLinuxElf64::buildLinuxLoader(
} }
method = M_NRV2B_LE32; // requires unaligned fetch method = M_NRV2B_LE32; // requires unaligned fetch
} }
else if (0 else if (this->e_machine==Elf32_Ehdr::EM_NONE
|| this->e_machine==Elf64_Ehdr::EM_X86_64 || this->e_machine==Elf64_Ehdr::EM_X86_64
|| this->e_machine==Elf64_Ehdr::EM_AARCH64 || this->e_machine==Elf64_Ehdr::EM_AARCH64
|| this->e_machine==Elf64_Ehdr::EM_PPC64 || this->e_machine==Elf64_Ehdr::EM_PPC64
@ -1684,7 +1687,10 @@ PackLinuxElf64::buildLinuxLoader(
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", len += snprintf(&sec[len], sizeof(sec) - len, ",%s",
"LZMA_DAISY,LZMA_ELF00,LZMA_DEC20,LZMA_DEC30"); "LZMA_DAISY,LZMA_ELF00,LZMA_DEC20,LZMA_DEC30");
} }
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "EXP_TAIL,SYSCALLS"); len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "EXP_TAIL");
if (hasLoaderSection("SYSCALLS")) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "SYSCALLS");
}
if (hasLoaderSection("STRCON")) { if (hasLoaderSection("STRCON")) {
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "STRCON"); len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "STRCON");
} }
@ -1700,11 +1706,26 @@ PackLinuxElf64::buildLinuxLoader(
method = M_NRV2B_LE32; // requires unaligned fetch method = M_NRV2B_LE32; // requires unaligned fetch
} }
else { // not shlib: main program with ELF1 de-compressor else { // not shlib: main program with ELF1 de-compressor
cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold; cprElfHdr1 const *hf = (cprElfHdr1 const *)fold;
unsigned fold_hdrlen = usizeof(hf->ehdr) + e_type = get_te16(&hf->ehdr.e_type);
get_te16(&hf->ehdr.e_phentsize) * get_te16(&hf->ehdr.e_phnum)); if (ET_REL == e_type) {
uncLoader = fold_hdrlen + fold; initLoader(fold, szfold);
sz_unc = ((szfold < fold_hdrlen) ? 0 : (szfold - fold_hdrlen)); addLoader(".text", nullptr);
relocateLoader();
int sz_unc_int(0);
uncLoader = linker->getLoader(&sz_unc_int);
sz_unc = sz_unc_int;
}
else if (ET_EXEC == e_type) {
hf = (cprElfHdr1 const *)fold;
unsigned fold_hdrlen = usizeof(hf->ehdr) +
get_te16(&hf->ehdr.e_phentsize) * get_te16(&hf->ehdr.e_phnum);
if (this->e_machine==Elf64_Ehdr::EM_X86_64) {
fold_hdrlen = get_te64(&hf->ehdr.e_entry);
}
uncLoader = &fold[fold_hdrlen];
sz_unc = ((szfold < fold_hdrlen) ? 0 : (szfold - fold_hdrlen));
}
method = ph.method; method = ph.method;
} }
@ -1741,7 +1762,7 @@ PackLinuxElf64::buildLinuxLoader(
) { ) {
addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR"); addLoader("ELFMAINX,ELFMAINZ,FOLDEXEC,IDENTSTR");
} // shlib } // shlib
else if (0 else if (this->e_machine==Elf32_Ehdr::EM_NONE
|| this->e_machine==Elf64_Ehdr::EM_X86_64 || this->e_machine==Elf64_Ehdr::EM_X86_64
|| this->e_machine==Elf64_Ehdr::EM_AARCH64 || this->e_machine==Elf64_Ehdr::EM_AARCH64
|| this->e_machine==Elf64_Ehdr::EM_PPC64 || this->e_machine==Elf64_Ehdr::EM_PPC64
@ -2828,6 +2849,7 @@ upx_uint64_t PackLinuxElf64::canPack_Shdr(Elf64_Phdr const *pload_x0)
for (int j= e_shnum; --j>=0; ++shdr) { for (int j= e_shnum; --j>=0; ++shdr) {
unsigned const sh_type = get_te32(&shdr->sh_type); unsigned const sh_type = get_te32(&shdr->sh_type);
if (Elf64_Shdr::SHF_EXECINSTR & get_te64(&shdr->sh_flags)) { if (Elf64_Shdr::SHF_EXECINSTR & get_te64(&shdr->sh_flags)) {
shdr_xva = shdr;
xct_va = umin(xct_va, get_te64(&shdr->sh_addr)); xct_va = umin(xct_va, get_te64(&shdr->sh_addr));
} }
// Hook the first slot of DT_PREINIT_ARRAY or DT_INIT_ARRAY. // Hook the first slot of DT_PREINIT_ARRAY or DT_INIT_ARRAY.
@ -3490,7 +3512,7 @@ tribool PackLinuxElf64::canPack()
if (Elf64_Ehdr::EM_PPC64 == get_te16(&ehdr->e_machine)) { if (Elf64_Ehdr::EM_PPC64 == get_te16(&ehdr->e_machine)) {
throwCantPack("This test UPX cannot pack .so for PowerPC64; coming soon."); throwCantPack("This test UPX cannot pack .so for PowerPC64; coming soon.");
} }
xct_va = ~0ull; xct_va = ~(upx_uint64_t)0;
if (e_shnum) { if (e_shnum) {
xct_va = canPack_Shdr(pload_x0); xct_va = canPack_Shdr(pload_x0);
} }
@ -3627,20 +3649,35 @@ PackLinuxElf32::generateElfHdr(
cprElfHdr2 *const h2 = (cprElfHdr2 *)(void *)&elfout; cprElfHdr2 *const h2 = (cprElfHdr2 *)(void *)&elfout;
cprElfHdr3 *const h3 = (cprElfHdr3 *)(void *)&elfout; cprElfHdr3 *const h3 = (cprElfHdr3 *)(void *)&elfout;
h3->ehdr = ((cprElfHdr3 const *)proto)->ehdr; h3->ehdr = ((cprElfHdr3 const *)proto)->ehdr;
if (Elf32_Ehdr::ET_REL == get_te16(&h3->ehdr.e_type)) { e_type = get_te16(&h3->ehdr.e_type);
if (!memcmp("\x7f\x45\x4c\x46", proto, 4) && Elf32_Ehdr::ET_EXEC == e_type
&& 2 <= get_te16(&h3->ehdr.e_phnum)) {
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text
}
else {
memcpy(&h3->ehdr.e_ident[0], "\x7f\x45\x4c\x46", 4);
h3->ehdr.e_ident[EI_CLASS] = ei_class;
h3->ehdr.e_ident[EI_DATA] = ei_data;
h3->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
h3->ehdr.e_ident[EI_OSABI] = ei_osabi;
h3->ehdr.e_ident[EI_ABIVERSION] = 1; // ei_abiversion;
set_te32(&h3->ehdr.e_phoff, sizeof(Elf32_Ehdr)); set_te32(&h3->ehdr.e_phoff, sizeof(Elf32_Ehdr));
set_te16(&h3->ehdr.e_ehsize,sizeof(Elf32_Ehdr)); set_te16(&h3->ehdr.e_ehsize,sizeof(Elf32_Ehdr));
set_te16(&h3->ehdr.e_phentsize, sizeof(Elf32_Phdr)); set_te16(&h3->ehdr.e_phentsize, sizeof(Elf32_Phdr));
set_te16(&h3->ehdr.e_phnum, 2); set_te16(&h3->ehdr.e_phnum, 2);
set_te16(&h3->ehdr.e_machine, e_machine);
set_te16(&h3->ehdr.e_shstrndx, 0);
memset(&h3->phdr[C_BASE], 0, sizeof(h3->phdr[C_BASE])); memset(&h3->phdr[C_BASE], 0, sizeof(h3->phdr[C_BASE]));
memset(&h3->phdr[C_TEXT], 0, sizeof(h3->phdr[C_TEXT])); memset(&h3->phdr[C_TEXT], 0, sizeof(h3->phdr[C_TEXT]));
memset(&h3->phdr[2 ], 0, sizeof(h3->phdr[2 ])); memset(&h3->phdr[2 ], 0, sizeof(h3->phdr[2 ]));
set_te32(&h3->phdr[C_BASE].p_flags, 0); set_te32(&h3->phdr[C_BASE].p_flags, 0);
set_te32(&h3->phdr[C_TEXT].p_flags, Elf32_Phdr::PF_X| Elf32_Phdr::PF_R); set_te32(&h3->phdr[C_TEXT].p_flags, Elf32_Phdr::PF_X| Elf32_Phdr::PF_R);
} if (!memcmp("\x7f\x45\x4c\x46", proto, 4) && Elf32_Ehdr::ET_REL == e_type) {
else { }
h3->phdr[C_BASE] = ((cprElfHdr3 const *)proto)->phdr[1]; // .data; .p_align else {
h3->phdr[C_TEXT] = ((cprElfHdr3 const *)proto)->phdr[0]; // .text throwCantPack("unknown e_type %#x", e_type);
}
} }
h3->ehdr.e_type = ehdri.e_type; // ET_EXEC vs ET_DYN (gcc -pie -fPIC) h3->ehdr.e_type = ehdri.e_type; // ET_EXEC vs ET_DYN (gcc -pie -fPIC)
memset(&h3->linfo, 0, sizeof(h3->linfo)); memset(&h3->linfo, 0, sizeof(h3->linfo));