From 982e732b74da936bae32995b01314723fd4aa8b2 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Wed, 4 Dec 2024 17:00:37 -0800 Subject: [PATCH] Allow re-ordering of functions in upxfd_android.c and upxfd_linux.c Compiler has a mind of its own. modified: p_lx_elf.cpp modified: stub/Makefile new file: stub/src/amd64-linux.elf-help_umf.S modified: stub/src/arm.v4a-expand.S new file: stub/src/arm.v4a-linux.elf-help_umf.S modified: stub/src/arm.v4a-linux.elf-so_entry.S modified: stub/src/arm.v4a-linux.elf-so_fold.S new file: stub/src/arm.v5a-linux.elf-help_umf.S new file: stub/src/arm64-linux.elf-help_umf.S modified: stub/src/arm64-linux.elf-so_entry.S new file: stub/src/armeb.v4a-linux.elf-help_umf.S new file: stub/src/i386-linux.elf-help_umf.S modified: stub/src/i386-linux.elf-so_main.c new file: stub/src/mips.r3000-linux.elf-help_umf.S new file: stub/src/mipsel.r3000-linux.elf-help_umf.S modified: stub/src/upxfd_android.c --- src/p_lx_elf.cpp | 20 ++++---- src/stub/Makefile | 33 ++++++++++++ src/stub/src/amd64-linux.elf-help_umf.S | 11 ++++ src/stub/src/arm.v4a-expand.S | 3 +- src/stub/src/arm.v4a-linux.elf-help_umf.S | 5 ++ src/stub/src/arm.v4a-linux.elf-so_entry.S | 8 +++ src/stub/src/arm.v4a-linux.elf-so_fold.S | 50 ++++++++++--------- src/stub/src/arm.v5a-linux.elf-help_umf.S | 1 + src/stub/src/arm64-linux.elf-help_umf.S | 5 ++ src/stub/src/arm64-linux.elf-so_entry.S | 2 +- src/stub/src/armeb.v4a-linux.elf-help_umf.S | 1 + src/stub/src/i386-linux.elf-help_umf.S | 5 ++ src/stub/src/i386-linux.elf-so_main.c | 20 +++++--- src/stub/src/mips.r3000-linux.elf-help_umf.S | 1 + .../src/mipsel.r3000-linux.elf-help_umf.S | 5 ++ src/stub/src/upxfd_android.c | 34 ++++++------- 16 files changed, 144 insertions(+), 60 deletions(-) create mode 100644 src/stub/src/amd64-linux.elf-help_umf.S create mode 100644 src/stub/src/arm.v4a-linux.elf-help_umf.S create mode 100644 src/stub/src/arm.v5a-linux.elf-help_umf.S create mode 100644 src/stub/src/arm64-linux.elf-help_umf.S create mode 100644 src/stub/src/armeb.v4a-linux.elf-help_umf.S create mode 100644 src/stub/src/i386-linux.elf-help_umf.S create mode 100644 src/stub/src/mips.r3000-linux.elf-help_umf.S create mode 100644 src/stub/src/mipsel.r3000-linux.elf-help_umf.S diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 33f69940..e3bb3347 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -1489,8 +1489,8 @@ PackLinuxElf32::buildLinuxLoader( len += snprintf(&sec[len], sizeof(sec) - len, ",%s", (sec_arm_attr || is_asl || opt->o_unix.android_shlib) - ? "UMF_ANDROID" - : "UMF_LINUX"); + ? "HUMF_A,UMF_ANDROID" + : "HUMF_L,UMF_LINUX"); if (hasLoaderSection("STRCON")) { len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "STRCON"); } @@ -1536,8 +1536,8 @@ PackLinuxElf32::buildLinuxLoader( // $ARCH-linux.elf-main2.c calls upx_mmap_and_fd, not direct memfd_create len += snprintf(&sec[len], sizeof(sec) - len, ",%s", (sec_arm_attr || is_asl || opt->o_unix.android_shlib) - ? "UMF_ANDROID" - : "UMF_LINUX"); + ? "HUMF_A,UMF_ANDROID" + : "HUMF_L,UMF_LINUX"); if (hasLoaderSection("SYSCALLS")) { len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "SYSCALLS"); } @@ -1600,8 +1600,8 @@ PackLinuxElf32::buildLinuxLoader( ) { // shlib with ELF2 de-compressor addLoader("ELFMAINX"); addLoader((sec_arm_attr || is_asl || opt->o_unix.android_shlib) - ? "UMF_ANDROID" - : "UMF_LINUX"); + ? "HUMF_A,UMF_ANDROID" + : "HUMF_L,UMF_LINUX"); addLoader("ELFMAINZ,FOLDEXEC,IDENTSTR"); } else if (this->e_machine==Elf32_Ehdr::EM_NONE @@ -1615,8 +1615,8 @@ PackLinuxElf32::buildLinuxLoader( // Only if $ARCH-linux.elf-entry.S calls upx_mmap_and_fd instead of memfd_create if (this->e_machine != Elf32_Ehdr::EM_PPC) // FIXME: also MIPS? addLoader((sec_arm_attr || is_asl || opt->o_unix.android_shlib) - ? "UMF_ANDROID" - : "UMF_LINUX"); + ? "HUMF_A,UMF_ANDROID" + : "HUMF_L,UMF_LINUX"); addLoader("ELFMAINZ,FOLDEXEC,IDENTSTR"); defineSymbols(ft); } @@ -1680,7 +1680,7 @@ PackLinuxElf64::buildLinuxLoader( len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "EXP_TAIL"); // End of daisy-chain fall-through. - len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "UMF_LINUX"); + len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "HUMF_L,UMF_LINUX"); if (hasLoaderSection("STRCON")) { len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "STRCON"); } @@ -5288,7 +5288,7 @@ unsigned PackLinuxElf::pack2_shlib_overlay_write(OutputFile *fo, MemBuffer &mb, memset(&tmp, 0, sizeof(tmp)); set_te32(&tmp.sz_unc, u_len); set_te32(&tmp.sz_cpr, c_len); - tmp.b_method = M_NRV2B_LE32; + tmp.b_method = (EM_ARM == e_machine) ? M_NRV2B_8 : M_NRV2B_LE32; tmp.b_extra = 0; fo->write(&tmp, sizeof(tmp)); total_out += sizeof(tmp); b_len += sizeof(b_info); diff --git a/src/stub/Makefile b/src/stub/Makefile index 553d346c..4dbe728d 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -578,12 +578,14 @@ tc.arm.v4a-linux.elf.gcc += -Wall -W -Wcast-align -Wcast-qual -Wstrict-prototype arm.v4a-linux.elf-entry.h : $(srcdir)/src/arm.v4a-linux.elf-entry.lds \ $(srcdir)/src/$$T.S \ + tmp/arm.v4a-linux.elf-help_umf.o \ tmp/arm.v4a-linux.elf-upxfd_android.o \ tmp/arm.v4a-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r --format=elf32-littlearm -Map tmp/$T.map -o tmp/$T.bin \ -T src/arm.v4a-linux.elf-entry.lds \ tmp/$T.o \ + tmp/arm.v4a-linux.elf-help_umf.o \ tmp/arm.v4a-linux.elf-upxfd_android.o \ tmp/arm.v4a-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -591,12 +593,14 @@ arm.v4a-linux.elf-entry.h : $(srcdir)/src/arm.v4a-linux.elf-entry.lds \ arm.v4a-linux.elf-so_entry.h : src/arm.v4a-linux.elf-so_entry.lds \ $(srcdir)/src/$$T.S \ + tmp/arm.v4a-linux.elf-help_umf.o \ tmp/arm.v4a-linux.elf-upxfd_android.o \ tmp/arm.v4a-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r --format=elf32-littlearm -Map tmp/$T.map -o tmp/$T.bin \ -T src/arm.v4a-linux.elf-so_entry.lds \ tmp/$T.o \ + tmp/arm.v4a-linux.elf-help_umf.o \ tmp/arm.v4a-linux.elf-upxfd_android.o \ tmp/arm.v4a-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -614,6 +618,7 @@ tmp/arm.v4a-linux.elf-upxfd_linux.o : $(srcdir)/src/upxfd_linux.c arm.v4a-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/arm.v4a-linux.elf-help_umf.o \ tmp/arm.v4a-linux.elf-upxfd_android.o \ tmp/arm.v4a-linux.elf-upxfd_linux.o \ tmp/arm.v4a-expand.o \ @@ -624,6 +629,7 @@ arm.v4a-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ arm.v4a-linux.elf-so_fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/arm.v4a-linux.elf-help_umf.o \ tmp/arm.v4a-linux.elf-upxfd_android.o \ tmp/arm.v4a-linux.elf-upxfd_linux.o \ tmp/arm.v4a-expand.o \ @@ -635,6 +641,9 @@ arm.v4a-linux.elf-so_fold.h : $(srcdir)/src/$$T.lds \ tmp/arm.v4a-expand.o: $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ +tmp/arm.v4a-linux.elf-help_umf.o: $(srcdir)/src/$$T.S + $(call tc,gcc) -c $< -o $@ + tmp/arm.v4a-linux.elf-fold.o : $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ $(call tc,f-objstrip,$@) @@ -694,12 +703,14 @@ tc.arm.v5a-linux.elf.gcc += -Wall -W -Wcast-align -Wcast-qual -Wstrict-prototype arm.v5a-linux.elf-entry.h : $(srcdir)/src/arm.v5a-linux.elf-entry.lds \ $(srcdir)/src/$$T.S \ + tmp/arm.v5a-linux.elf-help_umf.o \ tmp/arm.v5a-linux.elf-upxfd_android.o \ tmp/arm.v5a-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r --format=elf32-littlearm -Map tmp/$T.map -o tmp/$T.bin \ -T src/arm.v5a-linux.elf-entry.lds \ tmp/$T.o \ + tmp/arm.v5a-linux.elf-help_umf.o \ tmp/arm.v5a-linux.elf-upxfd_android.o \ tmp/arm.v5a-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -707,12 +718,14 @@ arm.v5a-linux.elf-entry.h : $(srcdir)/src/arm.v5a-linux.elf-entry.lds \ arm.v5a-linux.elf-so_entry.h : src/arm.v5a-linux.elf-so_entry.lds \ $(srcdir)/src/$$T.S \ + tmp/arm.v5a-linux.elf-help_umf.o \ tmp/arm.v5a-linux.elf-upxfd_android.o \ tmp/arm.v5a-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r --format=elf32-littlearm -Map tmp/$T.map -o tmp/$T.bin \ -T src/arm.v5a-linux.elf-so_entry.lds \ tmp/$T.o \ + tmp/arm.v5a-linux.elf-help_umf.o \ tmp/arm.v5a-linux.elf-upxfd_android.o \ tmp/arm.v5a-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -730,6 +743,7 @@ tmp/arm.v5a-linux.elf-upxfd_linux.o : $(srcdir)/src/upxfd_linux.c arm.v5a-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/arm.v5a-linux.elf-help_umf.o \ tmp/arm.v5a-linux.elf-upxfd_android.o \ tmp/arm.v5a-linux.elf-upxfd_linux.o \ tmp/arm.v5a-expand.o \ @@ -740,6 +754,7 @@ arm.v5a-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ arm.v5a-linux.elf-so_fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/arm.v5a-linux.elf-help_umf.o \ tmp/arm.v5a-linux.elf-upxfd_android.o \ tmp/arm.v5a-linux.elf-upxfd_linux.o \ tmp/arm.v5a-expand.o \ @@ -751,6 +766,9 @@ arm.v5a-linux.elf-so_fold.h : $(srcdir)/src/$$T.lds \ tmp/arm.v5a-expand.o: $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ +tmp/arm.v5a-linux.elf-help_umf.o: $(srcdir)/src/$$T.S + $(call tc,gcc) -c $< -o $@ + tmp/arm.v5a-linux.elf-fold.o : $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ $(call tc,f-objstrip,$@) @@ -935,12 +953,14 @@ tc.armeb.v4a-linux.elf.gcc = $(tc.arm.v4a-linux.elf.gcc) -mbig-endian -DBIG_ENDI armeb.v4a-linux.elf-entry.h : $(srcdir)/src/armeb.v4a-linux.elf-entry.lds \ $(srcdir)/src/$$T.S \ + tmp/armeb.v4a-linux.elf-help_umf.o \ tmp/armeb.v4a-linux.elf-upxfd_android.o \ tmp/armeb.v4a-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r --format=elf32-bigarm -Map tmp/$T.map -o tmp/$T.bin \ -T src/armeb.v4a-linux.elf-entry.lds \ tmp/$T.o \ + tmp/armeb.v4a-linux.elf-help_umf.o \ tmp/armeb.v4a-linux.elf-upxfd_android.o \ tmp/armeb.v4a-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -948,6 +968,7 @@ armeb.v4a-linux.elf-entry.h : $(srcdir)/src/armeb.v4a-linux.elf-entry.lds \ armeb.v4a-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/armeb.v4a-linux.elf-help_umf.o \ tmp/armeb.v4a-linux.elf-upxfd_android.o \ tmp/armeb.v4a-linux.elf-upxfd_linux.o \ tmp/armeb.v4a-expand.o \ @@ -969,6 +990,9 @@ tmp/armeb.v4a-linux.elf-upxfd_linux.o : $(srcdir)/src/upxfd_linux.c tmp/armeb.v4a-expand.o: $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ +tmp/armeb.v4a-linux.elf-help_umf.o: $(srcdir)/src/$$T.S + $(call tc,gcc) -c $< -o $@ + tmp/armeb.v4a-linux.elf-fold.o : $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ $(call tc,f-objstrip,$@) @@ -1315,12 +1339,14 @@ tc.i386-linux.elf.gcc += -fweb i386-linux.elf-entry.h : $(srcdir)/src/i386-linux.elf-entry.lds \ $(srcdir)/src/$$T.S \ + tmp/i386-linux.elf-help_umf.o \ tmp/i386-linux.elf-upxfd_android.o \ tmp/i386-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r -Map tmp/$T.map -o tmp/$T.bin \ -T src/i386-linux.elf-entry.lds \ tmp/$T.o \ + tmp/i386-linux.elf-help_umf.o \ tmp/i386-linux.elf-upxfd_android.o \ tmp/i386-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -1328,12 +1354,14 @@ i386-linux.elf-entry.h : $(srcdir)/src/i386-linux.elf-entry.lds \ i386-linux.elf-so_entry.h : $(srcdir)/src/i386-linux.elf-so_entry.lds \ $(srcdir)/src/$$T.S \ + tmp/i386-linux.elf-help_umf.o \ tmp/i386-linux.elf-upxfd_android.o \ tmp/i386-linux.elf-upxfd_linux.o $(call tc,gcc) -c $(srcdir)/src/$T.S -o tmp/$T.o multiarch-ld-2.17 -r -Map tmp/$T.map -o tmp/$T.bin \ -T src/i386-linux.elf-so_entry.lds \ tmp/$T.o \ + tmp/i386-linux.elf-help_umf.o \ tmp/i386-linux.elf-upxfd_android.o \ tmp/i386-linux.elf-upxfd_linux.o $(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin) @@ -1351,6 +1379,7 @@ tmp/i386-linux.elf-upxfd_linux.o : $(srcdir)/src/upxfd_linux.c i386-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/i386-linux.elf-help_umf.o \ tmp/i386-linux.elf-upxfd_android.o \ tmp/i386-linux.elf-upxfd_linux.o \ tmp/i386-expand.o \ @@ -1362,6 +1391,7 @@ i386-linux.elf-fold.h : $(srcdir)/src/$$T.lds \ i386-linux.elf-so_fold.h : $(srcdir)/src/$$T.lds \ tmp/$$T.o \ + tmp/i386-linux.elf-help_umf.o \ tmp/i386-linux.elf-upxfd_android.o \ tmp/i386-linux.elf-upxfd_linux.o \ tmp/i386-expand.o \ @@ -1383,6 +1413,9 @@ tmp/i386-linux.elf-so_fold.o : $(srcdir)/src/$$T.S tmp/i386-expand.o: $(srcdir)/src/$$T.S $(call tc,gcc) -c $< -o $@ +tmp/i386-linux.elf-help_umf.o: $(srcdir)/src/$$T.S + $(call tc,gcc) -c $< -o $@ + tmp/i386-linux.elf-main2.o : $(srcdir)/src/$$T.c $(call tc,gcc) -c $< -o $@ $(call tc,f-objstrip,$@) diff --git a/src/stub/src/amd64-linux.elf-help_umf.S b/src/stub/src/amd64-linux.elf-help_umf.S new file mode 100644 index 00000000..ba94fd9e --- /dev/null +++ b/src/stub/src/amd64-linux.elf-help_umf.S @@ -0,0 +1,11 @@ +// "jmp undef" gets R_X86_64_PLT32; we want R_X86_64_PC32 + + .section HUMF_A, "ax" + .byte 0xe9 // 5-byte jmp opcode + .int upx_mmap_and_fd_android - 0f // force R_X86_64_PC32 relocation +0: + + .section HUMF_L, "ax" + .byte 0xe9 + .int upx_mmap_and_fd_linux - 0f +0: diff --git a/src/stub/src/arm.v4a-expand.S b/src/stub/src/arm.v4a-expand.S index 800eac8a..47d906f1 100644 --- a/src/stub/src/arm.v4a-expand.S +++ b/src/stub/src/arm.v4a-expand.S @@ -169,7 +169,8 @@ decompress: // (src *, cpr_len, dst *, &dstlen); .globl eof eof: // end of a compressed extent POP {tmp} // &input_eof - mov r0,src; SUB2 r0,tmp // src -= eof; // return 0: good; else: bad + mov r0,src; SUB2S r0,tmp // src -= eof + beq 0f; bkpt; 0: // return 0: good; else: bad POP {tmp} // original dst POP {r1}; SUB2 dst,tmp // dst -= original dst POP {tmp}; str dst,[tmp] // actual length used at dst XXX: 4GB diff --git a/src/stub/src/arm.v4a-linux.elf-help_umf.S b/src/stub/src/arm.v4a-linux.elf-help_umf.S new file mode 100644 index 00000000..c32c87c1 --- /dev/null +++ b/src/stub/src/arm.v4a-linux.elf-help_umf.S @@ -0,0 +1,5 @@ + .section HUMF_A, "ax" + b upx_mmap_and_fd_android + + .section HUMF_L, "ax" + b upx_mmap_and_fd_linux diff --git a/src/stub/src/arm.v4a-linux.elf-so_entry.S b/src/stub/src/arm.v4a-linux.elf-so_entry.S index bc443dc6..479ee787 100644 --- a/src/stub/src/arm.v4a-linux.elf-so_entry.S +++ b/src/stub/src/arm.v4a-linux.elf-so_entry.S @@ -245,6 +245,14 @@ f_decompress: // MATCH_01 argv // MATCH_07 envp +// get_page_mask should never be called by so_entry, because the 1st arg +// (the pointer) to upx_mmap_and_fd is 0. But in the general case +// there must be a get_page_mask subroutine. Return something plausible. +get_page_mask: .globl get_page_mask + mvn r0,#0 + mov r0,r0,lsl #12 + ret + upx_mmap_and_fd: .globl upx_mmap_and_fd // UMF_LINX or UMF_ANDROID goes here diff --git a/src/stub/src/arm.v4a-linux.elf-so_fold.S b/src/stub/src/arm.v4a-linux.elf-so_fold.S index 7c518e95..03076876 100644 --- a/src/stub/src/arm.v4a-linux.elf-so_fold.S +++ b/src/stub/src/arm.v4a-linux.elf-so_fold.S @@ -303,48 +303,50 @@ mmap_privanon: .globl mmap_privanon mvn r4,#0 @ fd= -1 b mmap_do -tmp .req r3 -size .req r4 -ptr .req r5 -ulen .req r6 -pflg .req r7 - -underlay: .globl underlay // (unsigned size, char *ptr, unsigned ulen, unsigned p_flags) // ulen <= PAGE_SIZE +underlay: .globl underlay // (unsigned size, char *ptr, unsigned page_mask); stmdb sp!,{r0,r1,r2,r3,r4,r5,r6,r7, lr} ldmia sp!, {r4,r5,r6,r7} // r4= r0; r5= r1; r6= r2; r7= r3; - mov r0,sp - - sub tmp,sp,ulen +size .req r4 +ptr .req r5 +pmsk .req r6 +frag .req r7 +tmp .req r3 + mov r0,sp // old sp + bics frag,ptr,pmsk; beq 3f // page fragment + sub tmp,sp,frag and sp,tmp,#-2*NBPW - str r0,[sp,#-NBPW]! // save sp for pop at return + str r0,[sp,#-NBPW]! // save old sp for pop at return - add r0,sp,#NBPW - // mov r1,ptr // not yet overwritten - // mov r2,ulen // not yet overwritten + mov r2,frag + and r1,ptr,pmsk // beginning of page + add r0,sp,#NBPW // &saved_area bl memcpy +3: - mov r0,ptr - mov r1,size + and r0,ptr,pmsk // beginning of page + add r1,size,frag // include fragment mov r2,#PROT_WRITE|PROT_READ - tst pflg,#PF_X // if eventually PROT_EXEC, - orrne r2,r2,#PROT_EXEC // ... then Linux ARM wants it now, too mov r3,#MAP_FIXED bl mmap_privanon // r0= ptr because MAP_FIXED + mov ptr,r0 - add r1,sp,#NBPW - mov r2,ulen + cmp frag,#0; beq 3f + mov r0,ptr // mapped address + add r1,sp,#NBPW // &saved_area + mov r2,frag bl memcpy - - ldr sp,[sp] + ldr sp,[sp] // original sp +3: + mov r0,ptr // start of mapped region ldmia sp!,{r4,r5,r6,r7, pc} .unreq tmp .unreq size .unreq ptr - .unreq ulen - .unreq pflg + .unreq pmsk + .unreq frag my_alloca: .globl my_alloca sub r0,sp,r0 diff --git a/src/stub/src/arm.v5a-linux.elf-help_umf.S b/src/stub/src/arm.v5a-linux.elf-help_umf.S new file mode 100644 index 00000000..553fc55f --- /dev/null +++ b/src/stub/src/arm.v5a-linux.elf-help_umf.S @@ -0,0 +1 @@ +#include "arm.v4a-linux.elf-help_umf.S" diff --git a/src/stub/src/arm64-linux.elf-help_umf.S b/src/stub/src/arm64-linux.elf-help_umf.S new file mode 100644 index 00000000..c32c87c1 --- /dev/null +++ b/src/stub/src/arm64-linux.elf-help_umf.S @@ -0,0 +1,5 @@ + .section HUMF_A, "ax" + b upx_mmap_and_fd_android + + .section HUMF_L, "ax" + b upx_mmap_and_fd_linux diff --git a/src/stub/src/arm64-linux.elf-so_entry.S b/src/stub/src/arm64-linux.elf-so_entry.S index 808e8321..0389e8d9 100644 --- a/src/stub/src/arm64-linux.elf-so_entry.S +++ b/src/stub/src/arm64-linux.elf-so_entry.S @@ -93,7 +93,7 @@ arg6w .req w5 .balign 4 _start: .globl _start - nop // bkpt // DEBUG + bkpt // DEBUG PUSH4 (x0,x1,x2,lr) // MATCH_00 sub sp,sp,#2*NBPW // space for ADRU, LENU diff --git a/src/stub/src/armeb.v4a-linux.elf-help_umf.S b/src/stub/src/armeb.v4a-linux.elf-help_umf.S new file mode 100644 index 00000000..553fc55f --- /dev/null +++ b/src/stub/src/armeb.v4a-linux.elf-help_umf.S @@ -0,0 +1 @@ +#include "arm.v4a-linux.elf-help_umf.S" diff --git a/src/stub/src/i386-linux.elf-help_umf.S b/src/stub/src/i386-linux.elf-help_umf.S new file mode 100644 index 00000000..ad320aa6 --- /dev/null +++ b/src/stub/src/i386-linux.elf-help_umf.S @@ -0,0 +1,5 @@ + .section HUMF_A, "ax" + jmp upx_mmap_and_fd_android + + .section HUMF_L, "ax" + jmp upx_mmap_and_fd_linux diff --git a/src/stub/src/i386-linux.elf-so_main.c b/src/stub/src/i386-linux.elf-so_main.c index 1ca04303..7fc8d9af 100644 --- a/src/stub/src/i386-linux.elf-so_main.c +++ b/src/stub/src/i386-linux.elf-so_main.c @@ -34,7 +34,7 @@ extern void my_bkpt(void const *arg1, ...); -#define DEBUG 0 +#define DEBUG 1 // Pprotect is mprotect, but page-aligned on the lo end (Linux requirement) unsigned Pprotect(void *, size_t, unsigned); @@ -223,6 +223,7 @@ ERR_LAB if (h.sz_cpr < h.sz_unc) { // Decompress block size_t out_len = h.sz_unc; // EOF for lzma + //my_bkpt((void const *)0x1204, &xi, &xo, out_len); int const j = f_expand((unsigned char *)xi->buf - sizeof(h), (unsigned char *)xo->buf, &out_len); if (j != 0 || out_len != (nrv_uint)h.sz_unc) { @@ -239,6 +240,7 @@ ERR_LAB xo->buf += h.sz_unc; xo->size -= h.sz_unc; } + DPRINTF(" end unpackExtent\\n", 0); } #if defined(__i386__) //}{ @@ -474,6 +476,8 @@ fini_SELinux( ElfW(Addr) base ) { + DPRINTF("fini_SELinux size=%%p ptr=%%p phdr=%%p mfd=%%p base=%%p\\n", + size, ptr, phdr, mfd, base); if (phdr->p_flags & PF_X) { // Map the contents of mfd as per *phdr. Punmap(ptr, size); @@ -492,6 +496,7 @@ prep_SELinux(unsigned size, char *ptr, unsigned len) // returns mfd // Cannot set PROT_EXEC except via mmap() into a region (Linux "vma") // that has never had PROT_WRITE. So use a Linux-only "memory file" // to hold the contents. + DPRINTF("prep_SELinux size=%%p ptr=%%p len=%%p\\n", size, ptr,len); char *val = upx_mmap_and_fd(ptr, size, nullptr); unsigned mfd = 0xfff & (unsigned)val; val -= mfd; --mfd; @@ -581,6 +586,10 @@ upx_so_main( // returns &escape_hatch for (; phdr < phdrN; ++phdr) if (phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_W)) { + if (!base) { + base = (ElfW(Addr))va_load - phdr->p_vaddr; + DPRINTF("base=%%p\\n", base); + } unsigned hi_offset = phdr->p_filesz + phdr->p_offset; struct b_info al_bi; // for aligned data from binfo // Need un-aligned read of b_info to determine compression sizes. @@ -591,10 +600,6 @@ upx_so_main( // returns &escape_hatch x1.buf = (void *)(hi_offset + base - al_bi.sz_unc); x0.size = al_bi.sz_cpr; - if (!base) { - base = (ElfW(Addr))va_load - phdr->p_vaddr; - DPRINTF("base=%%p\\n", base); - } DPRINTF("phdr@%%p p_offset=%%p p_vaddr=%%p p_filesz=%%p p_memsz=%%p\\n", phdr, phdr->p_offset, phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz); DPRINTF("x0=%%p x1=%%p\\n", &x0, &x1); @@ -612,12 +617,13 @@ upx_so_main( // returns &escape_hatch else { underlay(x1.size, x1.buf, page_mask); // also makes PROT_WRITE } + Extent const xt = x1; unpackExtent(&x0, &x1); if (!hatch && phdr->p_flags & PF_X) { hatch = make_hatch(phdr, x1.buf, ~page_mask); } - my_bkpt((void const *)0x1235, &x1); - fini_SELinux(x1.size, x1.buf, phdr, mfd, base); // FIXME: x1 changed! + //my_bkpt((void const *)0x1235, &x1); + fini_SELinux(xt.size, xt.buf, phdr, mfd, base); } } else { // 2nd and later PT_LOADs diff --git a/src/stub/src/mips.r3000-linux.elf-help_umf.S b/src/stub/src/mips.r3000-linux.elf-help_umf.S new file mode 100644 index 00000000..1d047486 --- /dev/null +++ b/src/stub/src/mips.r3000-linux.elf-help_umf.S @@ -0,0 +1 @@ +#include "mipsel.r3000-linux.elf-help_umf.S" diff --git a/src/stub/src/mipsel.r3000-linux.elf-help_umf.S b/src/stub/src/mipsel.r3000-linux.elf-help_umf.S new file mode 100644 index 00000000..866ce6a8 --- /dev/null +++ b/src/stub/src/mipsel.r3000-linux.elf-help_umf.S @@ -0,0 +1,5 @@ + .section HUMF_A, "ax" + j upx_mmap_and_fd_android + + .section HUMF_L, "ax" + j upx_mmap_and_fd_linux diff --git a/src/stub/src/upxfd_android.c b/src/stub/src/upxfd_android.c index 2d43d16d..36752deb 100644 --- a/src/stub/src/upxfd_android.c +++ b/src/stub/src/upxfd_android.c @@ -183,6 +183,7 @@ extern int stat(char const *path, struct stat *statbuf); extern int mkdir(char const *path, unsigned mode); extern int uname(struct utsname *); extern char * get_upxfn_path(void); +extern long get_page_mask(void); unsigned long upx_mmap_and_fd_android( // returns (mapped_addr | (1+ fd)) void *ptr // desired address @@ -190,9 +191,6 @@ unsigned long upx_mmap_and_fd_android( // returns (mapped_addr | (1+ fd)) , char *pathname // 0 ==> get_upxfn_path() ) { - // This used to be a parameter, but was always 0 - unsigned const frag_mask = 0u; - unsigned long addr = 0; // for result // Early 32-bit Android did not implement memfd_create int fd = -ENOSYS; @@ -256,9 +254,13 @@ unsigned long upx_mmap_and_fd_android( // returns (mapped_addr | (1+ fd)) #endif //} // Set the file length - unsigned const frag = frag_mask & (unsigned)(long)ptr; - ptr -= frag; // page-aligned - datlen += frag; + my_bkpt((void const *)0x1302, ptr, datlen); + if (ptr) { + unsigned const page_mask = get_page_mask(); + unsigned const frag = ~page_mask & (unsigned)(long)ptr; + ptr -= frag; // becomes page-aligned + datlen += frag; + } if (datlen) { if (not_android) { // Linux ftruncate() is well-behaved int rv = ftruncate(fd, datlen); @@ -268,21 +270,19 @@ unsigned long upx_mmap_and_fd_android( // returns (mapped_addr | (1+ fd)) } #if ANDROID_FRIEND //{ else { // !not_android: ftruncate has varying system call number on 32-bit - memset(u.buf, 0, BUFLEN); - unsigned wlen = datlen; - while (0 < wlen) { - int x = (wlen < BUFLEN) ? wlen : BUFLEN; - if (x != write(fd, u.buf, x)) { - return -ENOSPC; - } - wlen -= x; - } + lseek(fd, -1+ datlen, SEEK_SET); // last byte + char zero = 0; + write(fd, &zero, 1); // force allocation lseek(fd, 0, SEEK_SET); // go back to the beginning } #endif //} } - if (frag_mask && ptr) { // Preserve entire page that contains *ptr - write(fd, ptr, 1+ frag_mask); + if (ptr) { + unsigned const page_mask = get_page_mask(); + if (~page_mask & (unsigned)(long)ptr) { + // Preserve entire page that contains *ptr + write(fd, ptr, -page_mask); + } } addr = (unsigned long)mmap(ptr, datlen , PROT_WRITE | PROT_READ, MAP_SHARED | (ptr ? MAP_FIXED : 0), fd, 0);