filters for unix(linux)
Modified Files: filteri.cpp filter/ctojr.h linker.cpp linker.h mem.cpp mem.h p_lx_elf.cpp p_lx_elf.h p_lx_exc.cpp p_lx_exc.h p_lx_sh.cpp p_lx_sh.h p_unix.cpp packer.cpp packer.h packhead.cpp stub/Makefile stub/macros.ash stub/l_lx_elf.c stub/l_lx_elf86.asm stub/l_lx_elf86.lds stub/l_lx_exec.c stub/l_lx_exec86.asm stub/l_lx_exec86.lds stub/l_lx_sh86.asm stub/l_lx_sh86.lds Added Files: filter/ctok.h stub/fold_elf86.asm stub/fold_exec86.asm stub/fold_sh86.asm committer: jreiser <jreiser> 979796725 +0000
This commit is contained in:
+58
-72
@@ -31,9 +31,10 @@ STUBS = \
|
||||
l_tmt.h \
|
||||
l_wcle.h \
|
||||
l_w32pe.h \
|
||||
l_lx_n2b.h l_lx_n2d.h \
|
||||
l_le_n2b.h l_le_n2d.h \
|
||||
l_sh_n2b.h l_sh_n2d.h \
|
||||
l_lx_exec86.h fold_exec86.h \
|
||||
l_lx_elf86.h fold_elf86.h \
|
||||
l_lx_sh86.h fold_sh86.h \
|
||||
l_ext2.h \
|
||||
l_vmlinz.h
|
||||
|
||||
# experimental:
|
||||
@@ -80,7 +81,7 @@ STRIPELF = ./util/sstrip/sstrip
|
||||
|
||||
# Use gcc 2.95.2 for smallest code.
|
||||
CC_LINUX_CFLAGS = -Wall -W -Wcast-align -Wcast-qual -Wwrite-strings
|
||||
CC_LINUX_CFLAGS += -Werror
|
||||
###CC_LINUX_CFLAGS += -Werror
|
||||
CC_LINUX_CFLAGS += -funsigned-char
|
||||
###CC_LINUX_CFLAGS += -fwritable-strings -save-temps
|
||||
CC_LINUX = gcc272 -O2 -m386 -malign-functions=0 -malign-jumps=0 -malign-loops=0 $(CC_LINUX_CFLAGS)
|
||||
@@ -170,6 +171,10 @@ l_tmt.h: l_tmt.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin nrv_loader $@
|
||||
|
||||
l_ext2.h: l_ext2.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin nrv_loader $@
|
||||
|
||||
l_vmlinz.h: l_vmlinz.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin nrv_loader $@
|
||||
@@ -249,66 +254,56 @@ l_t_x2ds.h: l_tos2.s
|
||||
# // linux rules (exec, elf, sh, sep)
|
||||
# ************************************************************************/
|
||||
|
||||
l_lx_n2b.h: l_lx_exec.c l_xe_n2b.o l_lx_exec86.lds Makefile
|
||||
$(CC_LINUX) -DNRV2B -o $T.o -c $<
|
||||
ld -T $(srcdir)/l_lx_exec86.lds -Map $T.map -o $T.bin l_xe_n2b.o $T.o
|
||||
$(SETFOLD) $T.bin
|
||||
l_lx_elf86.h: l_lx_elf86.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin linux_i386elf_loader $@
|
||||
|
||||
l_lx_exec86.h: l_lx_exec86.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin linux_i386exec_loader $@
|
||||
|
||||
l_lx_sh86.h: l_lx_sh86.asx
|
||||
$(NASM) -f bin -o $T.bin $<
|
||||
$(BIN2H) $T.bin linux_i386sh_loader $@
|
||||
|
||||
l_lx_elf.o: l_lx_elf.c
|
||||
$(CC_LINUX) -c $<
|
||||
|
||||
fold_elf86.o: fold_elf86.asm
|
||||
$(NASM) -f elf -o $@ $<
|
||||
|
||||
fold_elf86.h: l_lx_elf.o fold_elf86.o l_lx_elf86.lds
|
||||
ld -T l_lx_elf86.lds -Map $T.map -o $T.bin $T.o l_lx_elf.o
|
||||
objcopy -S -R .comment -R .note $T.bin
|
||||
./util/sstrip/sstrip $T.bin
|
||||
$(BRANDELF) $T.bin
|
||||
$(BIN2H) $T.bin linux_i386exec_nrv2b_loader $@
|
||||
$(BIN2H) $T.bin linux_i386elf_fold $@
|
||||
|
||||
l_le_n2b.h: l_lx_elf.c l_6e_n2b.o l_lx_elf86.lds
|
||||
$(CC_LINUX) -DNRV2B -o $T.o -c $<
|
||||
ld -T $(srcdir)/l_lx_elf86.lds -Map $T.map -o $T.bin l_6e_n2b.o $T.o
|
||||
$(SETFOLD) $T.bin
|
||||
l_lx_exec.o: l_lx_exec.c
|
||||
$(CC_LINUX) -c $<
|
||||
|
||||
fold_exec86.o: fold_exec86.asm
|
||||
$(NASM) -f elf -o $@ $<
|
||||
|
||||
fold_exec86.h: l_lx_exec.o fold_exec86.o l_lx_exec86.lds
|
||||
ld -T l_lx_exec86.lds -Map $T.map -o $T.bin $T.o l_lx_exec.o
|
||||
objcopy -S -R .comment -R .note $T.bin
|
||||
./util/sstrip/sstrip $T.bin
|
||||
$(BRANDELF) $T.bin
|
||||
$(BIN2H) $T.bin linux_i386elf_nrv2b_loader $@
|
||||
$(BIN2H) $T.bin linux_i386exec_fold $@
|
||||
|
||||
l_sh_n2b.h: l_lx_sh.c l_6h_n2b.o l_lx_sh86.lds
|
||||
$(CC_LINUX) -DNRV2B -o $T.o -c $<
|
||||
ld -T $(srcdir)/l_lx_sh86.lds -Map $T.map -o $T.bin l_6h_n2b.o $T.o
|
||||
$(SETFOLD) $T.bin
|
||||
l_lx_sh.o: l_lx_sh.c
|
||||
$(CC_LINUX) -c $<
|
||||
|
||||
fold_sh86.o: fold_sh86.asm
|
||||
$(NASM) -f elf -o $@ $<
|
||||
|
||||
fold_sh86.h: l_lx_sh.o fold_sh86.o l_lx_sh86.lds
|
||||
ld -T l_lx_sh86.lds -Map $T.map -o $T.bin $T.o l_lx_sh.o
|
||||
objcopy -S -R .comment -R .note $T.bin
|
||||
./util/sstrip/sstrip $T.bin
|
||||
$(BRANDELF) $T.bin
|
||||
$(BIN2H) $T.bin linux_i386sh_nrv2b_loader $@
|
||||
|
||||
l_xe_n2b.o: l_lx_exec86.asm
|
||||
$(NASM) -i$(UCL_I386)/ -f elf -dNRV2B -o $@ $<
|
||||
|
||||
l_6e_n2b.o: l_lx_elf86.asm
|
||||
$(NASM) -i$(UCL_I386)/ -f elf -dNRV2B -o $@ $<
|
||||
|
||||
l_6h_n2b.o: l_lx_sh86.asm
|
||||
$(NASM) -i$(UCL_I386)/ -f elf -dNRV2B -o $@ $<
|
||||
|
||||
|
||||
l_lx_n2d.h: l_lx_exec.c l_xe_n2d.o l_lx_exec86.lds
|
||||
$(CC_LINUX) -DNRV2D -o $T.o -c $<
|
||||
ld -T $(srcdir)/l_lx_exec86.lds -Map $T.map -o $T.bin l_xe_n2d.o $T.o
|
||||
$(SETFOLD) $T.bin
|
||||
$(BRANDELF) $T.bin
|
||||
$(BIN2H) $T.bin linux_i386exec_nrv2d_loader $@
|
||||
|
||||
l_le_n2d.h: l_lx_elf.c l_6e_n2d.o l_lx_elf86.lds
|
||||
$(CC_LINUX) -DNRV2D -o $T.o -c $<
|
||||
ld -T $(srcdir)/l_lx_elf86.lds -Map $T.map -o $T.bin l_6e_n2d.o $T.o
|
||||
$(SETFOLD) $T.bin
|
||||
$(BRANDELF) $T.bin
|
||||
$(BIN2H) $T.bin linux_i386elf_nrv2d_loader $@
|
||||
|
||||
l_sh_n2d.h: l_lx_sh.c l_6h_n2d.o l_lx_sh86.lds
|
||||
$(CC_LINUX) -DNRV2D -o $T.o -c $<
|
||||
ld -T $(srcdir)/l_lx_sh86.lds -Map $T.map -o $T.bin l_6h_n2d.o $T.o
|
||||
$(SETFOLD) $T.bin
|
||||
$(BRANDELF) $T.bin
|
||||
$(BIN2H) $T.bin linux_i386sh_nrv2d_loader $@
|
||||
|
||||
l_xe_n2d.o: l_lx_exec86.asm
|
||||
$(NASM) -i$(UCL_I386)/ -f elf -dNRV2D -o $@ $<
|
||||
|
||||
l_6e_n2d.o: l_lx_elf86.asm
|
||||
$(NASM) -i$(UCL_I386)/ -f elf -dNRV2D -o $@ $<
|
||||
|
||||
l_6h_n2d.o: l_lx_sh86.asm
|
||||
$(NASM) -i$(UCL_I386)/ -f elf -dNRV2D -o $@ $<
|
||||
$(BIN2H) $T.bin linux_i386sh_fold $@
|
||||
|
||||
l_lx_sep.o: l_lx_sep.c
|
||||
$(CC_LINUX) -c $<
|
||||
@@ -344,25 +339,16 @@ l_t_n2bs.h: n2b_d.ash bits.ash $(DEPS1)
|
||||
l_t_n2d.h: n2d_d.ash bits.ash $(DEPS1)
|
||||
l_t_n2ds.h: n2d_d.ash bits.ash $(DEPS1)
|
||||
l_tmt.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_ext2.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_vmlinz.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_vxd.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_wcle.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
l_w32pe.h: n2b_d32.asy n2d_d32.asy $(DEPS2)
|
||||
|
||||
l_xe_n2b.o: n2b_d32.ash $(DEPS1)
|
||||
l_6e_n2b.o: n2b_d32.ash $(DEPS1)
|
||||
l_6h_n2b.o: n2b_d32.ash $(DEPS1)
|
||||
l_lx_elf86.asx: l_lx_elf86.asm macros.ash macros.asy
|
||||
l_lx_exec86.asx: l_lx_exec86.asm macros.ash macros.asy
|
||||
l_lx_sh86.asx: l_lx_sh86.asm macros.ash macros.asy
|
||||
|
||||
l_xe_n2d.o: n2d_d32.ash $(DEPS1)
|
||||
l_6e_n2d.o: n2d_d32.ash $(DEPS1)
|
||||
l_6h_n2d.o: n2d_d32.ash $(DEPS1)
|
||||
|
||||
l_lx_n2b.h: linux.hh
|
||||
l_lx_n2d.h: linux.hh
|
||||
l_le_n2b.h: linux.hh
|
||||
l_le_n2d.h: linux.hh
|
||||
l_sh_n2b.h: linux.hh
|
||||
l_sh_n2d.h: linux.hh
|
||||
upxb: linux.hh
|
||||
upxd: linux.hh
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
; fold_elf86.asm -- linkage to C code to process Elf binary
|
||||
;
|
||||
; This file is part of the UPX executable compressor.
|
||||
;
|
||||
; Copyright (C) 2000-2001 John F. Reiser
|
||||
; All Rights Reserved.
|
||||
;
|
||||
; UPX and the UCL library are free software; you can redistribute them
|
||||
; and/or modify them under the terms of the GNU General Public License as
|
||||
; published by the Free Software Foundation; either version 2 of
|
||||
; the License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; see the file COPYING.
|
||||
; If not, write to the Free Software Foundation, Inc.,
|
||||
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
; Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
; markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||
;
|
||||
|
||||
%define szElf32_Ehdr 0x34
|
||||
%define szElf32_Phdr 8*4
|
||||
%define p_memsz 5*4
|
||||
%define a_val 4
|
||||
|
||||
%define __NR_munmap 91
|
||||
|
||||
;; control just falls through, after this part and compiled C code
|
||||
;; are uncompressed.
|
||||
|
||||
fold_begin:
|
||||
; patchLoader will modify to be
|
||||
; dword sz_uncompressed, sz_compressed
|
||||
; byte compressed_data...
|
||||
|
||||
pop eax ; discard &sz_uncompressed
|
||||
pop eax ; discard sz_uncompressed
|
||||
|
||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||
|
||||
%define OVERHEAD 2048
|
||||
%define MAX_ELF_HDR 512
|
||||
|
||||
mov esi, esp
|
||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
||||
mov edi, esp
|
||||
call do_auxv
|
||||
|
||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||
push esp ; argument: temp space
|
||||
push edi ; argument: AT_next
|
||||
push ebp ; argument: &decompress
|
||||
push edx ; argument: my_elfhdr
|
||||
add edx, [p_memsz + szElf32_Ehdr + edx]
|
||||
push edx ; argument: uncbuf
|
||||
EXTERN upx_main
|
||||
call upx_main ; entry = upx_main(uncbuf, my_elfhdr, &decompress, AT_next, tmp_ehdr)
|
||||
pop esi ; decompression buffer == (p_vaddr + p_memsz) of stub
|
||||
pop ebx ; my_elfhdr
|
||||
add esp, dword 3*4 + MAX_ELF_HDR + OVERHEAD ; remove 3 params, temp space
|
||||
push eax ; save entry address
|
||||
|
||||
mov edi, [a_val + edi] ; AT_PHDR
|
||||
find_hatch:
|
||||
push edi
|
||||
EXTERN make_hatch
|
||||
call make_hatch ; find hatch = make_hatch(phdr)
|
||||
pop ecx ; junk the parameter
|
||||
add edi, byte szElf32_Phdr ; prepare to try next Elf32_Phdr
|
||||
test eax,eax
|
||||
jz find_hatch
|
||||
xchg eax,edx ; edx= &hatch
|
||||
|
||||
; _dl_start and company (ld-linux.so.2) assumes that it has virgin stack,
|
||||
; and does not initialize all its stack local variables to zero.
|
||||
; Ulrich Drepper (drepper@cyngus.com) has refused to fix the bugs.
|
||||
; See GNU wwwgnats libc/1165 .
|
||||
|
||||
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
||||
lea edi, [esp - 4*N_STKCLR]
|
||||
pusha ; values will be zeroed
|
||||
mov ecx, N_STKCLR
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
|
||||
mov ecx,esi ; my p_vaddr + p_memsz
|
||||
mov bh,0 ; round down to 64KB boundary
|
||||
sub ecx,ebx ; length to unmap
|
||||
push byte __NR_munmap
|
||||
pop eax
|
||||
jmp edx ; unmap ourselves via escape hatch, then goto entry
|
||||
|
||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||
; cld
|
||||
|
||||
L10: ; move argc+argv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L10
|
||||
|
||||
L20: ; move envp
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L20
|
||||
|
||||
L30: ; move existing Elf32_auxv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax ; AT_NULL ?
|
||||
lodsd
|
||||
stosd
|
||||
jne L30
|
||||
|
||||
sub edi, byte 8 ; point to AT_NULL
|
||||
ret
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
; fold_exec86.asm -- linkage to C code to process Elf binary
|
||||
;
|
||||
; This file is part of the UPX executable compressor.
|
||||
;
|
||||
; Copyright (C) 2000-2001 John F. Reiser
|
||||
; All Rights Reserved.
|
||||
;
|
||||
; UPX and the UCL library are free software; you can redistribute them
|
||||
; and/or modify them under the terms of the GNU General Public License as
|
||||
; published by the Free Software Foundation; either version 2 of
|
||||
; the License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; see the file COPYING.
|
||||
; If not, write to the Free Software Foundation, Inc.,
|
||||
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
; Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
; markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||
;
|
||||
|
||||
;; control just falls through, after this part and compiled C code
|
||||
;; are uncompressed.
|
||||
|
||||
fold_begin: ;; this label is known to the Makefile
|
||||
pop eax ; discard &dstlen
|
||||
pop eax ; discard dstlen
|
||||
|
||||
pop eax ; Pop the argument count
|
||||
mov ecx, esp ; argv starts just at the current stack top
|
||||
lea edx, [ecx+eax*4+4] ; envp = &argv[argc + 1]
|
||||
push eax ; Restore the stack
|
||||
push ebp ; argument: &decompress
|
||||
push ebx ; argument: &my_elfhdr
|
||||
push edx ; argument: envp
|
||||
push ecx ; argument: argv
|
||||
EXTERN upx_main
|
||||
call upx_main ; Call the UPX main function
|
||||
hlt ; Crash if somehow upx_main does return
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
@@ -0,0 +1,134 @@
|
||||
; fold_sh86.asm -- Linux program entry point & decompressor (shell script)
|
||||
;
|
||||
; This file is part of the UPX executable compressor.
|
||||
;
|
||||
; Copyright (C) 1996-2001 Markus Franz Xaver Johannes Oberhumer
|
||||
; Copyright (C) 1996-2001 Laszlo Molnar
|
||||
; Copyright (C) 2000-2001 John F. Reiser
|
||||
; All Rights Reserved.
|
||||
;
|
||||
; UPX and the UCL library are free software; you can redistribute them
|
||||
; and/or modify them under the terms of the GNU General Public License as
|
||||
; published by the Free Software Foundation; either version 2 of
|
||||
; the License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; see the file COPYING.
|
||||
; If not, write to the Free Software Foundation, Inc.,
|
||||
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
; Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
; markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||
;
|
||||
|
||||
|
||||
BITS 32
|
||||
SECTION .text
|
||||
|
||||
fold_begin:
|
||||
; patchLoader will modify to be
|
||||
; dword sz_uncompressed, sz_compressed
|
||||
; byte compressed_data...
|
||||
|
||||
pop eax ; discard &sz_uncompressed
|
||||
pop eax ; discard sz_uncompressed
|
||||
|
||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||
|
||||
%define OVERHEAD 2048
|
||||
%define MAX_ELF_HDR 512
|
||||
%define PAGE_SIZE ( 1<<12)
|
||||
|
||||
mov esi, esp
|
||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
||||
mov edi, esp
|
||||
call do_auxv
|
||||
|
||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||
push esp ; argument: temp space
|
||||
push edi ; argument: AT_next
|
||||
push ebp ; argument: &decompress
|
||||
push edx ; argument: my_elfhdr
|
||||
add ecx, PAGE_SIZE ; uncompressed stub fits in this
|
||||
push ecx ; argument: uncbuf
|
||||
EXTERN upx_main
|
||||
call upx_main ; entry = upx_main(uncbuf, my_elfhdr, &decompress, AT_next, tmp_ehdr)
|
||||
pop esi ; decompression buffer
|
||||
pop ebx ; my_elfhdr
|
||||
add esp, dword 3*4 + MAX_ELF_HDR + OVERHEAD ; remove 3 params, temp space
|
||||
|
||||
pop ecx ; argc
|
||||
pop edx ; $0 filename, to become argv[0]
|
||||
push edx ; restore $0 filename
|
||||
|
||||
add esi, byte 3
|
||||
inc ecx
|
||||
push esi ; &uncompressed shell script
|
||||
sub esi, byte 3
|
||||
|
||||
mov [esi], word 0x632d ; "-c"
|
||||
inc ecx
|
||||
push esi ; "-c"
|
||||
|
||||
inc ecx
|
||||
push edx ; argv[0] is duplicate of $0
|
||||
|
||||
push ecx ; new argc
|
||||
push eax ; save entry address
|
||||
|
||||
; _dl_start and company (ld-linux.so.2) assumes that it has virgin stack,
|
||||
; and does not initialize all its stack local variables to zero.
|
||||
; Ulrich Drepper (drepper@cyngus.com) has refused to fix the bugs.
|
||||
; See GNU wwwgnats libc/1165 .
|
||||
|
||||
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
||||
lea edi, [esp - 4*N_STKCLR]
|
||||
pusha ; values will be zeroed
|
||||
mov ecx, N_STKCLR
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
|
||||
; Because the decompressed shell script occupies low memory anyway,
|
||||
; there isn't much payback to unmapping the compressed script and
|
||||
; ourselves the stub. We would need a place to put the escape hatch
|
||||
; "int $0x80; popa; ret", and some kernels do not allow execution
|
||||
; on the stack. So, we would have to dirty a page of the shell
|
||||
; or of /lib/ld-linux.so. It's simpler just to omit the unapping.
|
||||
popa
|
||||
ret
|
||||
|
||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||
; cld
|
||||
|
||||
L10: ; move argc+argv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L10
|
||||
|
||||
L20: ; move envp
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L20
|
||||
|
||||
L30: ; move existing Elf32_auxv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax ; AT_NULL ?
|
||||
lodsd
|
||||
stosd
|
||||
jne L30
|
||||
|
||||
sub edi, byte 8 ; point to AT_NULL
|
||||
ret
|
||||
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
+17
-5
@@ -102,7 +102,11 @@ do_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
// UPX & NRV stuff
|
||||
**************************************************************************/
|
||||
|
||||
typedef void f_unfilter(nrv_byte *, nrv_uint); // 1st param is also addvalue
|
||||
typedef void f_unfilter(
|
||||
nrv_byte *, // also addvalue
|
||||
nrv_uint,
|
||||
unsigned cto8 // junk in high 24 bits
|
||||
);
|
||||
typedef int f_expand(
|
||||
const nrv_byte *, nrv_uint,
|
||||
nrv_byte *, nrv_uint * );
|
||||
@@ -116,6 +120,7 @@ unpackExtent(
|
||||
)
|
||||
{
|
||||
while (xo->size) {
|
||||
unsigned cto8;
|
||||
struct {
|
||||
int32_t sz_unc; // uncompressed
|
||||
int32_t sz_cpr; // compressed
|
||||
@@ -125,6 +130,8 @@ unpackExtent(
|
||||
|
||||
// Read and check block sizes.
|
||||
xread(xi, (char *)&h, sizeof(h));
|
||||
cto8 = h.sz_cpr;
|
||||
h.sz_cpr >>= 8;
|
||||
if (h.sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||
if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic
|
||||
err_exit(2);
|
||||
@@ -155,7 +162,7 @@ ERR_LAB
|
||||
&& ((512 < out_len) // this block is longer than Ehdr+Phdrs
|
||||
|| (xo->size==(unsigned)h.sz_unc) ) // block is last in Extent
|
||||
) {
|
||||
(*f_unf)(xo->buf, out_len);
|
||||
(*f_unf)(xo->buf, out_len, cto8);
|
||||
}
|
||||
xi->buf += h.sz_cpr;
|
||||
xi->size -= h.sz_cpr;
|
||||
@@ -330,14 +337,19 @@ void *upx_main(
|
||||
Elf32_Ehdr *const ehdr // temp char[MAX_ELF_HDR+OVERHEAD]
|
||||
)
|
||||
{
|
||||
size_t const lsize = *(unsigned short const *)(0x7c + (char const *)my_ehdr);
|
||||
struct cprElfhdr {
|
||||
Elf32_Ehdr ehdr;
|
||||
Elf32_Phdr phdr[2];
|
||||
struct l_info linfo;
|
||||
};
|
||||
size_t const lsize = ((struct cprElfhdr const *)my_ehdr)->linfo.l_lsize;
|
||||
Elf32_Phdr const *phdr = (Elf32_Phdr const *)(1+ehdr);
|
||||
Elf32_Addr entry;
|
||||
struct Extent xo;
|
||||
struct Extent xi = { 0, sizeof(struct p_info) + lsize + CONST_CAST(char *, my_ehdr) };
|
||||
|
||||
size_t const sz_elfhdrs = ((size_t *)xi.buf)[0]; // sizeof(Ehdr+Phdrs), uncompressed
|
||||
size_t const sz_pckhdrs = ((size_t *)xi.buf)[1]; // sizeof(Ehdr+Phdrs), compressed
|
||||
size_t const sz_elfhdrs = ((size_t *)xi.buf)[0]; // sizeof(Ehdr+Phdrs), uncompressed
|
||||
size_t const sz_pckhdrs = ((size_t *)xi.buf)[1]>>8; // sizeof(Ehdr+Phdrs), compressed
|
||||
|
||||
(void)uncbuf; // used by l_lx_sh.c
|
||||
// Uncompress Ehdr and Phdrs.
|
||||
|
||||
+21
-327
@@ -33,42 +33,13 @@
|
||||
%define jmps jmp short
|
||||
%define jmpn jmp near
|
||||
|
||||
; defines for ident.ash and n2b_d32.ash
|
||||
%ifdef SMALL
|
||||
%define __IDENTSMA__
|
||||
%define __N2BSMA10__
|
||||
%define __N2BSMA20__
|
||||
%define __N2BSMA30__
|
||||
%define __N2BSMA40__
|
||||
%define __N2BSMA50__
|
||||
%define __N2BSMA60__
|
||||
%define __N2DSMA10__
|
||||
%define __N2DSMA20__
|
||||
%define __N2DSMA30__
|
||||
%define __N2DSMA40__
|
||||
%define __N2DSMA50__
|
||||
%define __N2DSMA60__
|
||||
%endif
|
||||
|
||||
|
||||
|
||||
%include "ident.ash"
|
||||
|
||||
;;;; names of pseudo-sections for addLoader:
|
||||
;; LXUNFnnn Linux unfilter
|
||||
;; LXNJMPnn omit filtering of 6-byte Jxx (0x0f 0x80..0x8f)
|
||||
;; LXMRUnnn MostRecentlyUsed recoding of destinations
|
||||
;; MRUARBnn arbitrary number of entries in wheel
|
||||
;; MRUBITSn power of 2 entries in wheel (smaller code)
|
||||
;; MRUBYTEn 256 entries in wheel (smallest code)
|
||||
|
||||
; /*************************************************************************
|
||||
; // program entry point
|
||||
; // see glibc/sysdeps/i386/elf/start.S
|
||||
; **************************************************************************/
|
||||
|
||||
GLOBAL _start
|
||||
|
||||
;__LEXEC000__
|
||||
_start:
|
||||
;;;; int3
|
||||
;; How to debug this code: Uncomment the 'int3' breakpoint instruction above.
|
||||
@@ -89,27 +60,6 @@ _start:
|
||||
;;
|
||||
call main ; push address of decompress subroutine
|
||||
decompress:
|
||||
;__LXUNF000__
|
||||
jmps decompr0
|
||||
;; 2+ address of decompress subroutine
|
||||
;; unfilter(upx_byte *, length)
|
||||
pop edx ; return address
|
||||
pop eax ; upx_byte *, same as addvalue
|
||||
pop ecx ; length
|
||||
pusha ; save C-convention ebx, ebp, esi, edi; also eax, edx
|
||||
xchg eax, edi ; edi= pointer
|
||||
|
||||
push dword ('?'<<8) | 0x0f ; cto8_0f (cto8 byte is modified)
|
||||
%ifdef __MRUBYTE0__
|
||||
xor ebx, ebx ; zero
|
||||
%else ;__MRUARB00__ (also __MRUBITS0__)
|
||||
mov ebx, 'NMRU' ; modified N_MRU or N_MRU -1
|
||||
%endif ;__LXMRU010__
|
||||
|
||||
xor edx, edx ; zero
|
||||
;__LXUNF010__
|
||||
jmpn unf0
|
||||
;__LXELF010__
|
||||
|
||||
; /*************************************************************************
|
||||
; // C callable decompressor
|
||||
@@ -120,7 +70,9 @@ decompress:
|
||||
%define OUTP dword [esp+8*4+12]
|
||||
%define OUTS dword [esp+8*4+16]
|
||||
|
||||
decompr0:
|
||||
;__LEXEC009__
|
||||
;; empty section for commonality with l_lx_exec86.asm
|
||||
;__LEXEC010__
|
||||
pusha
|
||||
; cld
|
||||
|
||||
@@ -129,15 +81,13 @@ decompr0:
|
||||
|
||||
or ebp, byte -1
|
||||
;;; align 8
|
||||
%ifdef NRV2B
|
||||
%include "n2b_d32.ash"
|
||||
%elifdef NRV2D
|
||||
%include "n2d_d32.ash"
|
||||
%else
|
||||
%error
|
||||
%endif
|
||||
|
||||
%include "n2b_d32.ash"
|
||||
%include "n2d_d32.ash"
|
||||
%include "macros.ash"
|
||||
cjt32 0
|
||||
|
||||
;__LEXEC015__
|
||||
; eax is 0 from decompressor code
|
||||
;xor eax, eax ; return code
|
||||
|
||||
@@ -158,191 +108,17 @@ decompr0:
|
||||
popa
|
||||
ret
|
||||
|
||||
;__LXUNF020__
|
||||
;; continuation of entry prolog for unfilter
|
||||
unf0:
|
||||
;__LXMRU020__
|
||||
push edx ; tail
|
||||
push ebx ; n_mru or n_mru1
|
||||
;__LXUNF025__
|
||||
mov esi, esp
|
||||
ctojr32
|
||||
ckt32 dl
|
||||
;__LEXEC017__
|
||||
popa
|
||||
ret
|
||||
|
||||
%define n_mru [esi]
|
||||
%define n_mru1 [esi]
|
||||
%define tail [esi + 4*1]
|
||||
%define cto8_0f [esi + 4*2]
|
||||
%define cto8 [esi + 4*2 +1]
|
||||
%define addvalue [esi + 4*3 + 7*4]
|
||||
|
||||
%ifdef __MRUBITS1__
|
||||
inc ebx ; n_mru1 ==> n_mru
|
||||
%endif ;__LXMRU030__
|
||||
unf1: ; allocate and clear mru[]
|
||||
push edx ; zero
|
||||
%ifdef __MRUBYTE1__
|
||||
dec bl
|
||||
%else ;__MRUARB10__
|
||||
dec ebx
|
||||
%endif ;__LXMRU040__
|
||||
jnz unf1 ; leaves 0=='hand'
|
||||
|
||||
%define tmp ebp
|
||||
|
||||
%define jc eax
|
||||
%define hand ebx
|
||||
%define hand_l al
|
||||
%define kh edx
|
||||
%define kh_l dl
|
||||
|
||||
;__LXUNF030__
|
||||
calltrickloop:
|
||||
mov al, [edi]
|
||||
inc edi
|
||||
%ifndef __LXNJMP00__
|
||||
sub al, 0x80 ; base of Jcc <d32>
|
||||
cmp al, 0x8f - 0x80 ; span of Jcc <d32>
|
||||
ja ct2 ; not Jcc <d32>
|
||||
mov edx, [edi] ; often unaligned
|
||||
cmp dx, cto8_0f
|
||||
jne unfcount
|
||||
mov byte [edi -1], dl ; 0x0f prefix
|
||||
add al, 0x80 ; reconstitute Jcc
|
||||
dec ecx
|
||||
mov byte [edi], al ; Jcc opcode
|
||||
inc edi
|
||||
jmps lxunf
|
||||
ct2:
|
||||
sub al, 0xE8 - 0x80 ; base of JMP/CALL <d32>
|
||||
cmp al, 0xE9 - 0xE8 ; span of JMP/CALL <d32>
|
||||
%else ;__LXNJMP10__
|
||||
sub al, 0xE8 ; base of JMP/CALL <d32>
|
||||
cmp al, 0xE9 - 0xE8 ; span of JMP/CALL <d32>
|
||||
%endif ;__LXMRU050__
|
||||
ja unfcount
|
||||
mov al, [edi]
|
||||
cmp al, cto8
|
||||
je lxunf
|
||||
unfcount:
|
||||
dec ecx
|
||||
jg calltrickloop
|
||||
|
||||
mov edi,esp ; clear mru[] portion of stack
|
||||
%ifdef __MRUBYTE2__
|
||||
mov ecx, 3+ 256 ; unused, tail, ct8_0f
|
||||
%elifdef __MRUBITS2__
|
||||
mov ecx, n_mru1
|
||||
add ecx, byte 1+ 3 ; n_mru1, tail, ct8_0f
|
||||
%else ;__MRUARB20__
|
||||
mov ecx, n_mru
|
||||
add ecx, byte 3 ; n_mru, tail, ct8_0f
|
||||
%endif ;__LXMRU060__
|
||||
xor eax,eax
|
||||
rep
|
||||
stosd
|
||||
mov esp,edi
|
||||
popa
|
||||
push ecx
|
||||
push eax
|
||||
push edx
|
||||
ret
|
||||
|
||||
lxunf:
|
||||
mov eax, [edi]
|
||||
shr ax, 8
|
||||
rol eax, 16
|
||||
xchg al, ah
|
||||
;__LXMRU065__
|
||||
shr jc, 1 ; eax= jc, or mru index
|
||||
jnc mru4 ; not 1st time for this jc
|
||||
%ifdef __MRUBYTE3__
|
||||
dec hand_l
|
||||
%else ;__MRUARB30__
|
||||
dec hand
|
||||
%ifdef __MRUBITS3__
|
||||
and hand, n_mru1
|
||||
%else ;__MRUARB40__
|
||||
jge mru3
|
||||
add hand, n_mru
|
||||
mru3:
|
||||
%endif
|
||||
%endif ;__LXMRU070__
|
||||
|
||||
mov [esp + 4*hand], jc ; 1st time: mru[hand] = jc
|
||||
jmps unf_store
|
||||
|
||||
mru4: ; not 1st time for this jc
|
||||
lea kh, [jc + hand] ; kh = jc + hand
|
||||
%ifdef __MRUBYTE4__
|
||||
movzbl kh, kh_l
|
||||
%elifdef __MRUBITS4__
|
||||
and kh, n_mru1
|
||||
%else ;__MRUARB50__
|
||||
cmp kh, n_mru
|
||||
jb mru5
|
||||
sub kh, n_mru
|
||||
mru5:
|
||||
%endif ;__LXMRU080__
|
||||
mov jc, [esp + 4*kh] ; jc = mru[kh]
|
||||
%ifdef __MRUBYTE5__
|
||||
dec hand_l
|
||||
%else ;__MRUARB60__
|
||||
dec hand
|
||||
%ifdef __MRUBITS5__
|
||||
and hand, n_mru1
|
||||
%else ;__MRUARB70__
|
||||
jge mru6
|
||||
add hand, n_mru
|
||||
mru6:
|
||||
%endif
|
||||
%endif ;__LXMRU090__
|
||||
|
||||
mov tmp, [esp + 4*hand] ; tmp = mru[hand]
|
||||
test tmp,tmp
|
||||
jnz mru8
|
||||
|
||||
push jc ; ran out of registers
|
||||
mov eax, tail
|
||||
|
||||
%ifdef __MRUBYTE6__
|
||||
dec al
|
||||
%else ;__MRUARB80__
|
||||
dec eax
|
||||
%ifdef __MRUBITS6__
|
||||
and eax, n_mru1
|
||||
%else ;__MRUARB90__
|
||||
jge mru7
|
||||
add eax, n_mru
|
||||
mru7:
|
||||
%endif
|
||||
%endif ;__LXMRU100__
|
||||
|
||||
xor tmp,tmp
|
||||
mov tail, eax
|
||||
xchg [4+ esp + 4*eax], tmp ; tmp = mru[tail]; mru[tail] = 0
|
||||
pop jc
|
||||
mru8:
|
||||
mov [esp + 4*kh ], tmp ; mru[kh] = tmp
|
||||
mov [esp + 4*hand], jc ; mru[hand] = jc
|
||||
;__LXUNF040__
|
||||
unf_store:
|
||||
sub eax, edi
|
||||
sub ecx, byte 4
|
||||
add eax, addvalue
|
||||
mov [edi], eax
|
||||
add edi, byte 4
|
||||
jmps unfcount
|
||||
|
||||
;__LXELF020__
|
||||
;__LEXEC020__
|
||||
|
||||
%define PAGE_MASK (~0<<12)
|
||||
%define PAGE_SIZE ( 1<<12)
|
||||
|
||||
%define szElf32_Ehdr 0x34
|
||||
%define szElf32_Phdr 8*4
|
||||
%define p_filesz 4*4
|
||||
%define p_memsz 5*4
|
||||
%define a_val 4
|
||||
|
||||
%define MAP_FIXED 0x10
|
||||
%define MAP_PRIVATE 0x02
|
||||
%define MAP_ANONYMOUS 0x20
|
||||
@@ -366,7 +142,7 @@ unfold:
|
||||
push eax ; &destination
|
||||
|
||||
; mmap a page to hold the decompressed program
|
||||
xor ecx,ecx
|
||||
xor ecx, ecx
|
||||
push ecx
|
||||
push ecx
|
||||
mov ch, PAGE_SIZE >> 8
|
||||
@@ -390,94 +166,12 @@ unfold:
|
||||
main:
|
||||
pop ebp ; &decompress
|
||||
call unfold
|
||||
fold_begin:
|
||||
; patchLoader will modify to be
|
||||
; dword sz_uncompressed, sz_compressed
|
||||
; byte compressed_data...
|
||||
|
||||
pop eax ; discard &sz_uncompressed
|
||||
pop eax ; discard sz_uncompressed
|
||||
|
||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||
|
||||
%define OVERHEAD 2048
|
||||
%define MAX_ELF_HDR 512
|
||||
|
||||
mov esi, esp
|
||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
||||
mov edi, esp
|
||||
call do_auxv
|
||||
|
||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||
push esp ; argument: temp space
|
||||
push edi ; argument: AT_next
|
||||
push ebp ; argument: &decompress
|
||||
push edx ; argument: my_elfhdr
|
||||
add edx, [p_memsz + szElf32_Ehdr + edx]
|
||||
push edx ; argument: uncbuf
|
||||
EXTERN upx_main
|
||||
call upx_main ; entry = upx_main(uncbuf, my_elfhdr, &decompress, AT_next, tmp_ehdr)
|
||||
pop esi ; decompression buffer == (p_vaddr + p_memsz) of stub
|
||||
pop ebx ; my_elfhdr
|
||||
add esp, dword 3*4 + MAX_ELF_HDR + OVERHEAD ; remove 3 params, temp space
|
||||
push eax ; save entry address
|
||||
|
||||
mov edi, [a_val + edi] ; AT_PHDR
|
||||
find_hatch:
|
||||
push edi
|
||||
EXTERN make_hatch
|
||||
call make_hatch ; find hatch = make_hatch(phdr)
|
||||
pop ecx ; junk the parameter
|
||||
add edi, byte szElf32_Phdr ; prepare to try next Elf32_Phdr
|
||||
test eax,eax
|
||||
jz find_hatch
|
||||
xchg eax,edx ; edx= &hatch
|
||||
|
||||
; _dl_start and company (ld-linux.so.2) assumes that it has virgin stack,
|
||||
; and does not initialize all its stack local variables to zero.
|
||||
; Ulrich Drepper (drepper@cyngus.com) has refused to fix the bugs.
|
||||
; See GNU wwwgnats libc/1165 .
|
||||
|
||||
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
||||
lea edi, [esp - 4*N_STKCLR]
|
||||
pusha ; values will be zeroed
|
||||
mov ecx, N_STKCLR
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
|
||||
mov ecx,esi ; my p_vaddr + p_memsz
|
||||
mov bh,0 ; round down to 64KB boundary
|
||||
sub ecx,ebx ; length to unmap
|
||||
push byte __NR_munmap
|
||||
pop eax
|
||||
jmp edx ; unmap ourselves via escape hatch, then goto entry
|
||||
|
||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||
; cld
|
||||
|
||||
L10: ; move argc+argv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L10
|
||||
|
||||
L20: ; move envp
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L20
|
||||
|
||||
L30: ; move existing Elf32_auxv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax ; AT_NULL ?
|
||||
lodsd
|
||||
stosd
|
||||
jne L30
|
||||
|
||||
sub edi, byte 8 ; point to AT_NULL
|
||||
ret
|
||||
eof:
|
||||
; __XTHEENDX__
|
||||
section .data
|
||||
dd -1
|
||||
dw eof
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
/*ENTRY(_start)*/
|
||||
SECTIONS
|
||||
{
|
||||
/* 0x00401000: l_lx_elf86.asm assumes 1 page up from 64KB boundary */
|
||||
|
||||
+86
-86
@@ -101,12 +101,19 @@ static uint32_t ascii5(char *p, uint32_t v, unsigned n)
|
||||
do {
|
||||
unsigned char d = v % 32;
|
||||
if (d >= 26) d -= 43; // 43 == 'Z' - '0' + 1
|
||||
*--p += d;
|
||||
*--p = (d += 'A');
|
||||
v /= 32;
|
||||
} while (--n > 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
static char *
|
||||
do_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
(void)len; (void)prot; (void)flags; (void)fd; (void)offset;
|
||||
return mmap((int *)&addr);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__i386__)
|
||||
# define SET2(p, c0, c1) \
|
||||
@@ -125,6 +132,51 @@ static uint32_t ascii5(char *p, uint32_t v, unsigned n)
|
||||
#endif
|
||||
|
||||
|
||||
// go_self is a separate subroutine to spread the burden of local arrays.
|
||||
// Otherwise the size of the stack frame in upx_main exceeds 128 bytes,
|
||||
// which causes too many offsets to expand from 1 byte to 4.
|
||||
|
||||
static int
|
||||
go_self(char const *tmpname, char *argv[], char *envp[])
|
||||
{
|
||||
// FIXME: why not use "/proc/self/fd/XX"? *BSD doesn't have it?
|
||||
|
||||
// Open the temp file.
|
||||
int const fdi = open(tmpname, O_RDONLY, 0);
|
||||
|
||||
if (0 <= fdi) {
|
||||
// 17 chars for "/proc/PPPPP/fd/XX" should be enough, but we
|
||||
// play safe in case there will be 32-bit pid_t at some time.
|
||||
//char procself_buf[17+1];
|
||||
char procself_buf[31+1];
|
||||
|
||||
// Compute name of temp fdi.
|
||||
SET4(procself_buf + 0, '/', 'p', 'r', 'o');
|
||||
SET4(procself_buf + 4, 'c', '/', 0 , 0 );
|
||||
{
|
||||
char *const procself = upx_itoa(procself_buf + 6, getpid());
|
||||
SET4(procself, '/', 'f', 'd', '/');
|
||||
upx_itoa(procself + 4, fdi);
|
||||
}
|
||||
|
||||
// Check for working /proc/self/fd/X by accessing the
|
||||
// temp file again, now via temp fdi.
|
||||
if (UPX2 == access(procself_buf, R_OK | X_OK)) {
|
||||
// Now it's safe to unlink the temp file (as it is still open).
|
||||
unlink(tmpname);
|
||||
// Set the file close-on-exec.
|
||||
fcntl(fdi, F_SETFD, FD_CLOEXEC);
|
||||
// Execute the original program via /proc/self/fd/X.
|
||||
execve(procself_buf, argv, envp);
|
||||
// NOTE: if we get here we've lost.
|
||||
}
|
||||
|
||||
// The proc filesystem isn't working. No problem.
|
||||
close(fdi);
|
||||
}
|
||||
return fdi;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// UPX & NRV stuff
|
||||
**************************************************************************/
|
||||
@@ -153,59 +205,29 @@ void upx_main(
|
||||
f_expand *const f_decompress
|
||||
)
|
||||
{
|
||||
// file descriptors
|
||||
int fdi, fdo;
|
||||
Elf32_Phdr const *const phdr = (Elf32_Phdr const *)
|
||||
(my_ehdr->e_phoff + (char const *)my_ehdr);
|
||||
struct Extent xi = { phdr[1].p_memsz, (char *)phdr[1].p_vaddr };
|
||||
char *next_unmap = (char *)(PAGE_MASK & (unsigned)xi.buf);
|
||||
struct p_info header;
|
||||
|
||||
// for getpid()
|
||||
pid_t pid;
|
||||
|
||||
// temporary file name (max 14 chars)
|
||||
static char tmpname_buf[] = "/tmp/upxAAAAAAAAAAA";
|
||||
char *tmpname = tmpname_buf;
|
||||
// 17 chars for "/proc/PPPPP/fd/XX" should be enough, but we
|
||||
// play safe in case there will be 32-bit pid_t at some time.
|
||||
//char procself_buf[17+1];
|
||||
char procself_buf[31+1];
|
||||
char *procself;
|
||||
// file descriptor
|
||||
int fdo;
|
||||
|
||||
// decompression buffer
|
||||
unsigned char *buf;
|
||||
static struct MallocArgs {
|
||||
char *ma_addr;
|
||||
size_t ma_length;
|
||||
int ma_prot;
|
||||
int ma_flags;
|
||||
int ma_fd;
|
||||
off_t ma_offset;
|
||||
} malloc_args = {
|
||||
#if defined(USE_MMAP_FO)
|
||||
0, 0, PROT_READ | PROT_WRITE, MAP_SHARED, 0, 0
|
||||
#else
|
||||
0, 0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0
|
||||
#endif
|
||||
};
|
||||
#if defined(USE_MMAP_FO)
|
||||
static struct MallocArgs scratch_page = {
|
||||
0, -PAGE_MASK, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0
|
||||
};
|
||||
#endif
|
||||
|
||||
char *tmpname;
|
||||
|
||||
Elf32_Phdr const *const phdr = (Elf32_Phdr const *)
|
||||
(my_ehdr->e_phoff + (char const *)my_ehdr);
|
||||
struct Extent xi = { phdr[1].p_memsz, (char *)phdr[1].p_vaddr };
|
||||
|
||||
char *next_unmap = (char *)(PAGE_MASK & (unsigned)xi.buf);
|
||||
struct p_info header;
|
||||
|
||||
// temporary file name
|
||||
char tmpname_buf[20];
|
||||
|
||||
//
|
||||
// ----- Step 0: set /proc/self using /proc/<pid> -----
|
||||
//
|
||||
|
||||
//personality(PER_LINUX);
|
||||
pid = getpid();
|
||||
SET4(procself_buf + 0, '/', 'p', 'r', 'o');
|
||||
SET2(procself_buf + 4, 'c', '/');
|
||||
procself = upx_itoa(procself_buf + 6, pid);
|
||||
*procself++ = '/';
|
||||
|
||||
|
||||
//
|
||||
@@ -226,7 +248,7 @@ void upx_main(
|
||||
// Paranoia. Make sure this is actually our expected executable
|
||||
// by checking the random program id. (The id is both stored
|
||||
// in the header and patched into this stub.)
|
||||
if (header.p_progid != UPX2)
|
||||
if (header.p_progid != UPX3)
|
||||
goto error1;
|
||||
|
||||
|
||||
@@ -234,13 +256,17 @@ void upx_main(
|
||||
// ----- Step 2: prepare temporary output file -----
|
||||
//
|
||||
|
||||
tmpname = tmpname_buf;
|
||||
SET4(tmpname + 0, '/', 't', 'm', 'p');
|
||||
SET4(tmpname + 4, '/', 'u', 'p', 'x');
|
||||
|
||||
// Compute name of temporary output file in tmpname[].
|
||||
// Protect against Denial-of-Service attacks.
|
||||
{
|
||||
char *p = tmpname_buf + sizeof(tmpname_buf) - 1;
|
||||
|
||||
// Compute the last 4 characters (20 bits) from getpid().
|
||||
uint32_t r = ascii5(p, (uint32_t)pid, 4); p-=4;
|
||||
uint32_t r = ascii5(p, (uint32_t)getpid(), 4); *p = '\0'; p -= 4;
|
||||
|
||||
// Provide 4 random bytes from our program id.
|
||||
r ^= header.p_progid;
|
||||
@@ -254,7 +280,7 @@ void upx_main(
|
||||
r ^= ((uint32_t) tv.tv_usec) << 12; // shift into high-bits
|
||||
#else
|
||||
// using adjtimex() may cause portability problems
|
||||
static struct timex tx;
|
||||
struct timex tx;
|
||||
adjtimex(&tx);
|
||||
r ^= (uint32_t) tx.time.tv_sec;
|
||||
r ^= ((uint32_t) tx.time.tv_usec) << 12; // shift into high-bits
|
||||
@@ -294,23 +320,23 @@ void upx_main(
|
||||
//
|
||||
|
||||
#if defined(USE_MMAP_FO)
|
||||
// mmap()ed output file.
|
||||
malloc_args.ma_fd = fdo;
|
||||
// FIXME: packer could set ma_length
|
||||
malloc_args.ma_length = header.p_filesize;
|
||||
buf = mmap((int *)&malloc_args);
|
||||
// FIXME: packer could set length
|
||||
buf = do_mmap(0, header.p_filesize,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fdo, 0);
|
||||
if ((unsigned long) buf >= (unsigned long) -4095)
|
||||
goto error;
|
||||
|
||||
// Decompressor can overrun the output by 3 bytes.
|
||||
// Defend against SIGSEGV by using a scratch page.
|
||||
scratch_page.ma_addr = buf + (PAGE_MASK & (header.p_filesize + ~PAGE_MASK));
|
||||
mmap((int *)&scratch_page);
|
||||
// FIXME: packer could set address delta
|
||||
do_mmap(buf + (PAGE_MASK & (header.p_filesize + ~PAGE_MASK)),
|
||||
-PAGE_MASK, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
|
||||
#else
|
||||
// Temporary decompression buffer.
|
||||
// FIXME: packer could set ma_length
|
||||
malloc_args.ma_length = (header.p_blocksize + OVERHEAD + ~PAGE_MASK) & PAGE_MASK;
|
||||
buf = mmap((int *)&malloc_args);
|
||||
// FIXME: packer could set length
|
||||
buf = do_mmap(0, (header.p_blocksize + OVERHEAD + ~PAGE_MASK) & PAGE_MASK,
|
||||
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
|
||||
if ((unsigned long) buf >= (unsigned long) -4095)
|
||||
goto error;
|
||||
#endif
|
||||
@@ -429,34 +455,9 @@ void upx_main(
|
||||
// Many thanks to Andi Kleen <ak@muc.de> and
|
||||
// Jamie Lokier <nospam@cern.ch> for this nice idea.
|
||||
|
||||
// Open the temp file.
|
||||
fdi = open(tmpname, O_RDONLY, 0);
|
||||
if (fdi < 0)
|
||||
if (0 > go_self(tmpname, argv, envp))
|
||||
goto error;
|
||||
|
||||
// Compute name of temp fdi.
|
||||
SET3(procself, 'f', 'd', '/');
|
||||
upx_itoa(procself + 3, fdi);
|
||||
|
||||
// Check for working /proc/self/fd/X by accessing the
|
||||
// temp file again, now via temp fdi.
|
||||
#define err fdo
|
||||
err = access(procself_buf, R_OK | X_OK);
|
||||
if (err == UPX3)
|
||||
{
|
||||
// Now it's safe to unlink the temp file (as it is still open).
|
||||
unlink(tmpname);
|
||||
// Set the file close-on-exec.
|
||||
fcntl(fdi, F_SETFD, FD_CLOEXEC);
|
||||
// Execute the original program via /proc/self/fd/X.
|
||||
execve(procself_buf, argv, envp);
|
||||
// NOTE: if we get here we've lost.
|
||||
}
|
||||
#undef err
|
||||
|
||||
// The proc filesystem isn't working. No problem.
|
||||
close(fdi);
|
||||
|
||||
|
||||
//
|
||||
// ----- Step 7: start program in /tmp -----
|
||||
@@ -474,7 +475,7 @@ void upx_main(
|
||||
if (fork() == 0)
|
||||
{
|
||||
// Sleep 3 seconds, then remove the temp file.
|
||||
static const struct timespec ts = { UPX4, 0 };
|
||||
struct timespec ts; ts.tv_sec = UPX4; ts.tv_nsec = 0;
|
||||
nanosleep(&ts, 0);
|
||||
unlink(tmpname);
|
||||
}
|
||||
@@ -500,4 +501,3 @@ void upx_main(
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
|
||||
+64
-83
@@ -33,34 +33,13 @@
|
||||
%define jmps jmp short
|
||||
%define jmpn jmp near
|
||||
|
||||
; defines for ident.ash and n2b_d32.ash
|
||||
%ifdef SMALL
|
||||
%define __IDENTSMA__
|
||||
%define __N2BSMA10__
|
||||
%define __N2BSMA20__
|
||||
%define __N2BSMA30__
|
||||
%define __N2BSMA40__
|
||||
%define __N2BSMA50__
|
||||
%define __N2BSMA60__
|
||||
%define __N2DSMA10__
|
||||
%define __N2DSMA20__
|
||||
%define __N2DSMA30__
|
||||
%define __N2DSMA40__
|
||||
%define __N2DSMA50__
|
||||
%define __N2DSMA60__
|
||||
%endif
|
||||
|
||||
|
||||
|
||||
%include "ident.ash"
|
||||
|
||||
; /*************************************************************************
|
||||
; // program entry point
|
||||
; // see glibc/sysdeps/i386/elf/start.S
|
||||
; **************************************************************************/
|
||||
|
||||
GLOBAL _start
|
||||
|
||||
;__LEXEC000__
|
||||
_start:
|
||||
;;;; int3
|
||||
;; How to debug this code: Uncomment the 'int3' breakpoint instruction above.
|
||||
@@ -85,19 +64,24 @@ _start:
|
||||
xor ebx, ebx ; PER_LINUX
|
||||
int 0x80
|
||||
%endif
|
||||
|
||||
call main ; push address of decompress subroutine
|
||||
decompress:
|
||||
|
||||
; /*************************************************************************
|
||||
; // C callable decompressor
|
||||
; **************************************************************************/
|
||||
|
||||
%define INP dword [esp+8*4+4]
|
||||
%define INS dword [esp+8*4+8]
|
||||
%define OUTP dword [esp+8*4+12]
|
||||
%define OUTS dword [esp+8*4+16]
|
||||
%define INP dword [esp+8*4+8]
|
||||
%define INS dword [esp+8*4+12]
|
||||
%define OUTP dword [esp+8*4+16]
|
||||
%define OUTS dword [esp+8*4+20]
|
||||
|
||||
decompress:
|
||||
;__LEXEC009__
|
||||
mov eax, 'NMRU' ; free slot in following 'pusha'
|
||||
;__LEXEC010__
|
||||
pusha
|
||||
push byte '?' ; cto8 (sign extension does not matter)
|
||||
; cld
|
||||
|
||||
mov esi, INP
|
||||
@@ -105,75 +89,81 @@ decompress:
|
||||
|
||||
or ebp, byte -1
|
||||
;;; align 8
|
||||
%ifdef NRV2B
|
||||
%include "n2b_d32.ash"
|
||||
%elifdef NRV2D
|
||||
%include "n2d_d32.ash"
|
||||
%else
|
||||
%error
|
||||
%endif
|
||||
|
||||
%include "n2b_d32.ash"
|
||||
%include "n2d_d32.ash"
|
||||
%include "macros.ash"
|
||||
cjt32 0
|
||||
|
||||
;__LEXEC015__
|
||||
; eax is 0 from decompressor code
|
||||
;xor eax, eax ; return code
|
||||
|
||||
; check compressed size
|
||||
mov edx, INP
|
||||
add edx, INS
|
||||
cmp esi, edx
|
||||
cmp edx, esi
|
||||
jz .ok
|
||||
dec eax
|
||||
.ok:
|
||||
xchg [8*4 + esp], eax ; store success/failure, fetch NMRU
|
||||
|
||||
; write back the uncompressed size
|
||||
sub edi, OUTP
|
||||
mov edx, OUTS
|
||||
mov [edx], edi
|
||||
; write back the uncompressed size, and prepare for unfilter
|
||||
mov edx, OUTS
|
||||
mov ecx, edi
|
||||
mov edi, OUTP
|
||||
sub ecx, edi ; ecx= uncompressed size
|
||||
mov [edx], ecx
|
||||
|
||||
mov [7*4 + esp], eax
|
||||
pop edx ; cto8
|
||||
|
||||
;__LEXEC110__ Jcc and/or possible n_mru
|
||||
push edi ; addvalue
|
||||
push byte 0x0f
|
||||
pop ebx
|
||||
mov bh, dl ; ebx= 0,,cto8,0x0F
|
||||
|
||||
;__LEXEC100__ 0!=n_mru
|
||||
xchg eax, ebx ; eax= ct08_0f; ebx= n_mru {or n_mru1}
|
||||
|
||||
;;LEXEC016 bug in APP: jmp and target must be in same .asx
|
||||
;; jmpn lxunf0 ; logically belongs here
|
||||
|
||||
ctojr32
|
||||
ckt32 dl
|
||||
;__LEXEC017__
|
||||
popa
|
||||
ret
|
||||
|
||||
;__LEXEC020__
|
||||
|
||||
%define PAGE_MASK (~0<<12)
|
||||
%define PAGE_SIZE ( 1<<12)
|
||||
|
||||
%define szElf32_Ehdr 0x34
|
||||
%define szElf32_Phdr 8*4
|
||||
%define p_filesz 4*4
|
||||
%define p_memsz 5*4
|
||||
%define a_val 4
|
||||
|
||||
%define MAP_FIXED 0x10
|
||||
%define MAP_PRIVATE 0x02
|
||||
%define MAP_ANONYMOUS 0x20
|
||||
%define PROT_READ 1
|
||||
%define PROT_WRITE 2
|
||||
%define PROT_EXEC 4
|
||||
%define __NR_mmap 90
|
||||
%define __NR_munmap 91
|
||||
|
||||
; Decompress the rest of this loader, and jump to it
|
||||
unfold:
|
||||
pop esi ; &fold_begin = src
|
||||
pop esi ; &{ sz_uncompressed, sz_compressed, compressed_data...}
|
||||
mov ecx, PAGE_MASK
|
||||
push esi ; &dst
|
||||
mov ecx, ebp ; &decompress
|
||||
and ecx, dword PAGE_MASK ; &my_elfhdr
|
||||
mov ebx, ecx ; save &my_elfhdr for later
|
||||
mov ebx, ebp ; &decompress
|
||||
and ebx, ecx ; &my_elfhdr
|
||||
neg ecx ; ecx= PAGE_SIZE
|
||||
|
||||
cld
|
||||
lodsd ; sz_uncompressed
|
||||
lodsd ; sz_compressed
|
||||
|
||||
;; Compressed code now begins at fold_begin.
|
||||
;; We want decompressed code to begin at fold_begin, too.
|
||||
;; Move the compressed code to the high end of the page.
|
||||
;; Assume non-overlapping so that forward movsb is OK.
|
||||
lea edi, [-PAGE_MASK + ecx] ; high end of page
|
||||
add ecx, [p_filesz + szElf32_Ehdr + ecx] ; beyond src
|
||||
sub ecx, esi ; srclen
|
||||
push ecx ; srclen
|
||||
sub edi, ecx
|
||||
push edi ; &src
|
||||
cld
|
||||
rep movsb
|
||||
|
||||
lea edi, [ecx + ebx] ; high end of page
|
||||
push eax ; srclen (of both movsb and decompress)
|
||||
sub edi, eax ; dst of movsb
|
||||
push edi ; &src for decompression (after movsb)
|
||||
xchg ecx, eax ; ecx= len of movsb
|
||||
rep movsb
|
||||
call ebp ; decompress(&src, srclen, &dst, &dstlen)
|
||||
pop eax ; discard &src
|
||||
pop eax ; discard srclen
|
||||
@@ -188,23 +178,14 @@ unfold:
|
||||
|
||||
main:
|
||||
pop ebp ; &decompress
|
||||
push eax ; place to store dstlen
|
||||
push esp ; &dstlen
|
||||
push eax ; sz_uncompressed (junk, actually)
|
||||
push esp ; &sz_uncompressed
|
||||
call unfold
|
||||
fold_begin: ;; this label is known to the Makefile
|
||||
pop eax ; discard &dstlen
|
||||
pop eax ; discard dstlen
|
||||
|
||||
pop eax ; Pop the argument count
|
||||
mov ecx, esp ; argv starts just at the current stack top
|
||||
lea edx, [ecx+eax*4+4] ; envp = &argv[argc + 1]
|
||||
push eax ; Restore the stack
|
||||
push ebp ; argument: &decompress
|
||||
push ebx ; argument: &my_elfhdr
|
||||
push edx ; argument: envp
|
||||
push ecx ; argument: argv
|
||||
EXTERN upx_main
|
||||
call upx_main ; Call the UPX main function
|
||||
hlt ; Crash if somehow upx_main does return
|
||||
eof:
|
||||
; __XTHEENDX__
|
||||
section .data
|
||||
dd -1
|
||||
dw eof
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
/*ENTRY(_start)*/
|
||||
SECTIONS
|
||||
{
|
||||
/* 0x08048000: customary Linux/x86 Elf .text start */
|
||||
|
||||
+15
-134
@@ -30,37 +30,13 @@
|
||||
BITS 32
|
||||
SECTION .text
|
||||
|
||||
%define jmps jmp short
|
||||
%define jmpn jmp near
|
||||
|
||||
; defines for ident.ash and n2b_d32.ash
|
||||
%ifdef SMALL
|
||||
%define __IDENTSMA__
|
||||
%define __N2BSMA10__
|
||||
%define __N2BSMA20__
|
||||
%define __N2BSMA30__
|
||||
%define __N2BSMA40__
|
||||
%define __N2BSMA50__
|
||||
%define __N2BSMA60__
|
||||
%define __N2DSMA10__
|
||||
%define __N2DSMA20__
|
||||
%define __N2DSMA30__
|
||||
%define __N2DSMA40__
|
||||
%define __N2DSMA50__
|
||||
%define __N2DSMA60__
|
||||
%endif
|
||||
|
||||
|
||||
|
||||
%include "ident.ash"
|
||||
|
||||
; /*************************************************************************
|
||||
; // program entry point
|
||||
; // see glibc/sysdeps/i386/elf/start.S
|
||||
; **************************************************************************/
|
||||
|
||||
GLOBAL _start
|
||||
|
||||
;__LEXEC000__
|
||||
_start:
|
||||
;;;; int3
|
||||
;; How to debug this code: Uncomment the 'int3' breakpoint instruction above.
|
||||
@@ -79,7 +55,9 @@ _start:
|
||||
;; end
|
||||
;; Step through the code; remember that <Enter> repeats the previous command.
|
||||
;;
|
||||
|
||||
call main ; push address of decompress subroutine
|
||||
decompress:
|
||||
|
||||
; /*************************************************************************
|
||||
; // C callable decompressor
|
||||
@@ -90,7 +68,7 @@ _start:
|
||||
%define OUTP dword [esp+8*4+12]
|
||||
%define OUTS dword [esp+8*4+16]
|
||||
|
||||
decompress:
|
||||
;__LEXEC010__
|
||||
pusha
|
||||
; cld
|
||||
|
||||
@@ -99,15 +77,13 @@ decompress:
|
||||
|
||||
or ebp, byte -1
|
||||
;;; align 8
|
||||
%ifdef NRV2B
|
||||
%include "n2b_d32.ash"
|
||||
%elifdef NRV2D
|
||||
%include "n2d_d32.ash"
|
||||
%else
|
||||
%error
|
||||
%endif
|
||||
|
||||
%include "n2b_d32.ash"
|
||||
%include "n2d_d32.ash"
|
||||
%include "macros.ash"
|
||||
cjt32 0
|
||||
|
||||
;__LEXEC015__
|
||||
; eax is 0 from decompressor code
|
||||
;xor eax, eax ; return code
|
||||
|
||||
@@ -128,15 +104,13 @@ decompress:
|
||||
popa
|
||||
ret
|
||||
|
||||
;__LEXEC020__
|
||||
|
||||
%define PAGE_MASK (~0<<12)
|
||||
%define PAGE_SIZE ( 1<<12)
|
||||
|
||||
%define szElf32_Ehdr 0x34
|
||||
%define szElf32_Phdr 8*4
|
||||
%define p_filesz 4*4
|
||||
%define p_memsz 5*4
|
||||
%define a_val 4
|
||||
|
||||
%define MAP_FIXED 0x10
|
||||
%define MAP_PRIVATE 0x02
|
||||
@@ -145,7 +119,6 @@ decompress:
|
||||
%define PROT_WRITE 2
|
||||
%define PROT_EXEC 4
|
||||
%define __NR_mmap 90
|
||||
%define __NR_munmap 91
|
||||
|
||||
; Decompress the rest of this loader, and jump to it
|
||||
unfold:
|
||||
@@ -186,104 +159,12 @@ unfold:
|
||||
main:
|
||||
pop ebp ; &decompress
|
||||
call unfold
|
||||
fold_begin:
|
||||
; patchLoader will modify to be
|
||||
; dword sz_uncompressed, sz_compressed
|
||||
; byte compressed_data...
|
||||
|
||||
pop eax ; discard &sz_uncompressed
|
||||
pop eax ; discard sz_uncompressed
|
||||
|
||||
; Move argc,argv,envp down so that we can insert more Elf_auxv entries.
|
||||
; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance
|
||||
|
||||
%define OVERHEAD 2048
|
||||
%define MAX_ELF_HDR 512
|
||||
|
||||
mov esi, esp
|
||||
sub esp, byte 6*8 ; AT_PHENT, AT_PHNUM, AT_PAGESZ, AT_ENTRY, AT_PHDR, AT_NULL
|
||||
mov edi, esp
|
||||
call do_auxv
|
||||
|
||||
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
||||
push esp ; argument: temp space
|
||||
push edi ; argument: AT_next
|
||||
push ebp ; argument: &decompress
|
||||
push edx ; argument: my_elfhdr
|
||||
add ecx, PAGE_SIZE ; uncompressed stub fits in this
|
||||
push ecx ; argument: uncbuf
|
||||
EXTERN upx_main
|
||||
call upx_main ; entry = upx_main(uncbuf, my_elfhdr, &decompress, AT_next, tmp_ehdr)
|
||||
pop esi ; decompression buffer
|
||||
pop ebx ; my_elfhdr
|
||||
add esp, dword 3*4 + MAX_ELF_HDR + OVERHEAD ; remove 3 params, temp space
|
||||
|
||||
pop ecx ; argc
|
||||
pop edx ; $0 filename, to become argv[0]
|
||||
push edx ; restore $0 filename
|
||||
|
||||
add esi, byte 3
|
||||
inc ecx
|
||||
push esi ; &uncompressed shell script
|
||||
sub esi, byte 3
|
||||
|
||||
mov [esi], word 0x632d ; "-c"
|
||||
inc ecx
|
||||
push esi ; "-c"
|
||||
|
||||
inc ecx
|
||||
push edx ; argv[0] is duplicate of $0
|
||||
|
||||
push ecx ; new argc
|
||||
push eax ; save entry address
|
||||
|
||||
; _dl_start and company (ld-linux.so.2) assumes that it has virgin stack,
|
||||
; and does not initialize all its stack local variables to zero.
|
||||
; Ulrich Drepper (drepper@cyngus.com) has refused to fix the bugs.
|
||||
; See GNU wwwgnats libc/1165 .
|
||||
|
||||
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
||||
lea edi, [esp - 4*N_STKCLR]
|
||||
pusha ; values will be zeroed
|
||||
mov ecx, N_STKCLR
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
|
||||
; Because the decompressed shell script occupies low memory anyway,
|
||||
; there isn't much payback to unmapping the compressed script and
|
||||
; ourselves the stub. We would need a place to put the escape hatch
|
||||
; "int $0x80; popa; ret", and some kernels do not allow execution
|
||||
; on the stack. So, we would have to dirty a page of the shell
|
||||
; or of /lib/ld-linux.so. It's simpler just to omit the unapping.
|
||||
popa
|
||||
ret
|
||||
|
||||
do_auxv: ; entry: %esi=src = &argc; %edi=dst. exit: %edi= &AT_NULL
|
||||
; cld
|
||||
|
||||
L10: ; move argc+argv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L10
|
||||
|
||||
L20: ; move envp
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax
|
||||
jne L20
|
||||
|
||||
L30: ; move existing Elf32_auxv
|
||||
lodsd
|
||||
stosd
|
||||
test eax,eax ; AT_NULL ?
|
||||
lodsd
|
||||
stosd
|
||||
jne L30
|
||||
|
||||
sub edi, byte 8 ; point to AT_NULL
|
||||
ret
|
||||
|
||||
eof:
|
||||
; __XTHEENDX__
|
||||
section .data
|
||||
dd -1
|
||||
dw eof
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
|
||||
+12
-1
@@ -27,18 +27,29 @@
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
/*ENTRY(_start)*/
|
||||
SECTIONS
|
||||
{
|
||||
/* 0x00800000: avoid 0x00400000 for shell itself being compressed */
|
||||
. = 0x00800000 + SIZEOF_HEADERS;
|
||||
. = ALIGN(0x80);
|
||||
/*
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.data)
|
||||
}
|
||||
*/
|
||||
.data : { /* put everything together in one Phdr */
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
*(.data)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
/* 0x08048000: customary Linux/x86 Elf .text start */
|
||||
/*
|
||||
. = 0x08048000 + (0xfff & .);
|
||||
.data : {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -168,6 +168,53 @@ ctend:
|
||||
%endmacro
|
||||
|
||||
|
||||
;; call/jump/jcc trick; also used more than once (and/or optionally), so
|
||||
;; ecx has byte count (not count of applied instances), and
|
||||
;; edi points to buffer.
|
||||
%macro ckt32 1 ; param: where is cto8 (dl, bl, or literal)
|
||||
;__CKLLTR00__
|
||||
mov esi, edi ; base of block
|
||||
jmps ckstart
|
||||
ckloop3:
|
||||
mov al, [edi]
|
||||
inc edi
|
||||
;__CKLLTR10__ Jcc only
|
||||
cmp al, 0x80 ; lo of 6-byte Jcc
|
||||
jb ckloop2
|
||||
cmp al, 0x8f ; hi of 6-byte Jcc
|
||||
ja ckloop2
|
||||
cmp byte [edi -2], 0x0F ; prefix of 6-byte Jcc
|
||||
je ckmark
|
||||
ckloop2:
|
||||
;__CKLLTR20__
|
||||
sub al, 0xE8
|
||||
cmp al, 0xE9 - 0xE8
|
||||
ja ckcount
|
||||
ckmark:
|
||||
cmp byte [edi], %1 ; cto8
|
||||
jnz ckcount
|
||||
mov eax, [edi]
|
||||
|
||||
shr ax, 8
|
||||
rol eax, 16
|
||||
xchg al, ah
|
||||
|
||||
sub eax, edi
|
||||
add eax, esi
|
||||
mov [edi], eax
|
||||
add edi, byte 4
|
||||
ckstart:
|
||||
sub ecx, byte 4
|
||||
;__CKLLTR30__ Jcc only
|
||||
mov al, [edi]
|
||||
inc edi
|
||||
loop ckloop2 ; prefix cannot overlap previous displacement
|
||||
;__CKLLTR40__
|
||||
ckcount:
|
||||
dec ecx
|
||||
jg ckloop3
|
||||
ckend:
|
||||
%endmacro
|
||||
|
||||
;; =============
|
||||
;; ============= 32-BIT RELOCATIONS
|
||||
@@ -213,4 +260,312 @@ reloc_endx:
|
||||
%endmacro
|
||||
|
||||
|
||||
;; =============
|
||||
;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER
|
||||
;; =============
|
||||
|
||||
;;;; names of pseudo-sections for addLoader:
|
||||
;; LXUNFnnn Linux unfilter
|
||||
;; LXMRUnnn MostRecentlyUsed recoding of destinations
|
||||
;; MRUARBnn arbitrary number of entries in wheel
|
||||
;; MRUBITSn power of 2 entries in wheel (smaller code)
|
||||
;; MRUBYTEn 256 entries in wheel (smallest code)
|
||||
|
||||
%macro ctojr32 0
|
||||
;; I got confused by the syntactic sugar of the fake %ifdefs.
|
||||
;; I can read the section name more easily when it is at the left margin.
|
||||
;; Also, some of the logic to select the sections is not that simple,
|
||||
;; and any mismatch between the logic and the %ifdefs is very confusing.
|
||||
;; Instead, I use comments after the section name, and blank lines for grouping.
|
||||
|
||||
;__LXUNF000__ enter at +0 for decompression; +2 for unfiltering
|
||||
jmps decompr0
|
||||
;__LXUNF002__
|
||||
;; 2+ address of decompress subroutine
|
||||
;; unfilter(upx_byte *, length, cto8)
|
||||
lxunfilter:
|
||||
pop edx ; return address
|
||||
pop eax ; upx_byte *, same as addvalue
|
||||
pop ecx ; length
|
||||
xchg eax, edi ; edi= pointer; eax= saved_edi
|
||||
pusha ; save C-convention ebx, ebp, esi, edi; also eax, edx
|
||||
|
||||
; at most one of the next 2
|
||||
;__MRUBYTE0__ 256==n_mru
|
||||
xor ebx, ebx ; zero
|
||||
;__LXMRU005__ 0!=n_mru
|
||||
mov ebx, 'NMRU' ; modified N_MRU or N_MRU -1
|
||||
|
||||
;__LXMRU006__ 0!=n_mru
|
||||
push byte 0x0f ; prefix of 6-byte Jcc <d32>
|
||||
pop eax
|
||||
mov ah, [esp + 8*4] ; cto8
|
||||
;__LXMRU007__ 0==n_mru
|
||||
push byte 0x0f ; prefix of 6-byte Jcc <d32>
|
||||
pop ebx
|
||||
mov bh, [esp + 8*4] ; cto8
|
||||
|
||||
;__LXUNF008__
|
||||
mov dl, [esp + 8*4] ; cto8
|
||||
|
||||
;__LXUNF010__
|
||||
jmpn lxunf0
|
||||
decompr0:
|
||||
|
||||
;; These %define are only if 0!=n_mru;
|
||||
;; else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
|
||||
%define n_mru [esi]
|
||||
%define n_mru1 [esi]
|
||||
%define tail [esi + 4*1]
|
||||
%define cto8_e8e9 [esi + 4*2]
|
||||
%define cto8_0f [esi + 4*3]
|
||||
%define addvalue [esi + 4*4]
|
||||
%define tmp ebp
|
||||
%define hand ebx
|
||||
%define hand_l bl
|
||||
%define kh edx
|
||||
%define kh_l dl
|
||||
|
||||
;__LXJCC010__
|
||||
lxunf2: ; have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
|
||||
movzx ebp, word [edi] ; 2 bytes, zero-extended
|
||||
|
||||
;__LXMRU045__ 0!=n_mru
|
||||
sub ebp, cto8_0f
|
||||
;__LXMRU046__ 0==n_mru
|
||||
sub ebp, ebx
|
||||
|
||||
;__LXJCC020__ 0==n_mru, or Jcc excluded ('sub' of equals clears Carry)
|
||||
jne unfcount
|
||||
;__LXJCC021__ 0!=n_mru and Jcc participates; must set Carry
|
||||
sub ebp, byte 1 ; set Carry iff in range
|
||||
jnb unfcount
|
||||
|
||||
;__LXJCC023__ found Jcc; re-swap 0x8Y opcode and 0x0f prefix
|
||||
mov byte [edi -1], bl ; 0x0f prefix
|
||||
dec ecx ; preserve Carry
|
||||
mov byte [edi], al ; Jcc opcode
|
||||
inc edi ; preserve Carry
|
||||
|
||||
;__LXUNF037__
|
||||
%define jc eax
|
||||
|
||||
lxunf: ; in: Carry set iff we should apply mru and 0!=n_mru
|
||||
mov eax, [edi] ; BE32 displacement with cto8 in low 8 bits
|
||||
|
||||
;__LXUNF386__ 0!=n_mru && 386
|
||||
pushf
|
||||
;__LXUNF387__ ==386
|
||||
shr ax, 8
|
||||
rol eax, 16
|
||||
xchg al, ah
|
||||
;__LXUNF388__ 0!=n_mru && 386
|
||||
popf
|
||||
jnc unf_store ; do not apply mru
|
||||
|
||||
;__LXUNF486__ >=486
|
||||
mov al, byte 0
|
||||
bswap eax ; preserve Carry (2-byte instruction)
|
||||
;__LXUNF487__ 0!=n_mru && >=486
|
||||
jnc unf_store ; do not apply mru
|
||||
|
||||
;__LXMRU065__ 0!=n_mru
|
||||
shr jc, 1 ; eax= jc, or mru index
|
||||
jnc mru4 ; not 1st time for this jc
|
||||
;__MRUBYTE3__
|
||||
dec hand_l
|
||||
;__MRUARB30__
|
||||
dec hand
|
||||
;__MRUBITS3__
|
||||
and hand, n_mru1
|
||||
;__MRUARB40__
|
||||
jge mru3
|
||||
add hand, n_mru
|
||||
mru3:
|
||||
;__LXMRU070__
|
||||
|
||||
mov [esp + 4*hand], jc ; 1st time: mru[hand] = jc
|
||||
jmps unf_store
|
||||
|
||||
mru4: ; not 1st time for this jc
|
||||
lea kh, [jc + hand] ; kh = jc + hand
|
||||
;__MRUBYTE4__
|
||||
movzx kh, kh_l
|
||||
;__MRUBITS4__
|
||||
and kh, n_mru1
|
||||
;__MRUARB50__
|
||||
cmp kh, n_mru
|
||||
jb mru5
|
||||
sub kh, n_mru
|
||||
mru5:
|
||||
;__LXMRU080__
|
||||
mov jc, [esp + 4*kh] ; jc = mru[kh]
|
||||
;__MRUBYTE5__
|
||||
dec hand_l
|
||||
;__MRUARB60__
|
||||
dec hand
|
||||
;__MRUBITS5__
|
||||
and hand, n_mru1
|
||||
;__MRUARB70__
|
||||
jge mru6
|
||||
add hand, n_mru
|
||||
mru6:
|
||||
;__LXMRU090__
|
||||
|
||||
mov tmp, [esp + 4*hand] ; tmp = mru[hand]
|
||||
test tmp,tmp
|
||||
jnz mru8
|
||||
|
||||
push jc ; ran out of registers
|
||||
mov eax, tail
|
||||
|
||||
;__MRUBYTE6__
|
||||
dec al
|
||||
;__MRUARB80__
|
||||
dec eax
|
||||
;__MRUBITS6__
|
||||
and eax, n_mru1
|
||||
;__MRUARB90__
|
||||
jge mru7
|
||||
add eax, n_mru
|
||||
mru7:
|
||||
;__LXMRU100__
|
||||
|
||||
xor tmp,tmp
|
||||
mov tail, eax
|
||||
xchg [4+ esp + 4*eax], tmp ; tmp = mru[tail]; mru[tail] = 0
|
||||
pop jc
|
||||
mru8:
|
||||
mov [esp + 4*kh ], tmp ; mru[kh] = tmp
|
||||
mov [esp + 4*hand], jc ; mru[hand] = jc
|
||||
;__LXUNF040__
|
||||
unf_store:
|
||||
sub eax, edi
|
||||
sub ecx, byte 4
|
||||
|
||||
; one of the next2
|
||||
;__LXMRU110__ 0!=n_mru
|
||||
add eax, addvalue
|
||||
;__LXMRU111__ 0==n_mru
|
||||
add eax, esi ; addvalue (same as initial pointer)
|
||||
|
||||
;__LXUNF041__
|
||||
mov [edi], eax
|
||||
add edi, byte 4
|
||||
jmps unfcount
|
||||
;__LXUNF042__
|
||||
lxunf0: ;; continuation of entry prolog for unfilter
|
||||
;__LEXEC016__ bug in APP: jmp and label must be in same .asx/.asy
|
||||
jmp lxunf0 ; this instr does not really go here!
|
||||
|
||||
;__LXMRU010__ 0!=n_mru
|
||||
push eax ; cto8_0f
|
||||
;__LXJMPA00__ only JMP, and not CALL, is filtered
|
||||
mov al, 0xE9
|
||||
;__LXCALLB0__ only CALL, or both CALL and JMP are filtered
|
||||
mov al, 0xE8
|
||||
;__LXUNF021__ common tail
|
||||
push eax ; cto8_e8e9
|
||||
push byte 0 ; tail
|
||||
push ebx ; n_mru or n_mru1
|
||||
mov esi, esp ; flat model "[esi]" saves a byte over "[ebp]"
|
||||
|
||||
;__LXMRU022__ 0==n_mru
|
||||
pop esi ; addvalue
|
||||
mov edx, ebx ; dh= cto8
|
||||
;__LXJMPA01__ only JMP, and not CALL, is filtered
|
||||
mov dl, 0xE9
|
||||
;__LXCALLB1__ only CALL, or both CALL and JMP are filtered
|
||||
mov dl, 0xE8
|
||||
|
||||
|
||||
;__MRUBITS1__
|
||||
inc hand ; n_mru1 ==> n_mru
|
||||
;__LXMRU030__
|
||||
lxunf1: ; allocate and clear mru[]
|
||||
push byte 0
|
||||
|
||||
; one of the next 2, if n_mru
|
||||
;__MRUBYTE1__
|
||||
dec hand_l
|
||||
;__MRUARB10__
|
||||
dec hand
|
||||
|
||||
;__LXMRU040__ 0!=n_mru
|
||||
jnz lxunf1 ; leaves 0=='hand'
|
||||
|
||||
;__LXUNF030__
|
||||
lxctloop:
|
||||
movzx eax, word [edi] ; 2 bytes, zero extended
|
||||
inc edi
|
||||
;__LXJCC000__
|
||||
cmp al, 0x80 ; lo of Jcc <d32>
|
||||
jb lxct1
|
||||
cmp al, 0x8f ; hi of Jcc <d32>
|
||||
jbe lxunf2
|
||||
lxct1:
|
||||
|
||||
;__LXCJ0MRU__ 0==n_mru
|
||||
sub eax, edx
|
||||
;__LXCJ1MRU__ 0!=n_mru
|
||||
sub eax, cto8_e8e9
|
||||
|
||||
; both CALL and JMP are filtered
|
||||
;__LXCALJMP__
|
||||
sub eax, byte 1+ (0xE9 - 0xE8) ; set Carry iff in range (result: -2, -1)
|
||||
|
||||
; only CALL, or only JMP, is filtered
|
||||
;__LXCALL00__ 0==n_mru
|
||||
je lxunf
|
||||
;__LXCALL01__ 0!=n_rmu
|
||||
sub eax, byte 1 ; set Carry iff in range
|
||||
|
||||
;__LXCJ2MRU__ 0==n_mru, or apply mru to all that are filtered here
|
||||
jb lxunf ; only Carry (Borrow) matters
|
||||
;__LXCJ4MRU__ 0!=n_mru, but apply mru only to subset of filtered here
|
||||
jnb unfcount ; was not filtered anyway: do not unfilter
|
||||
|
||||
;we will unfilter, and 0!=n_mru, but should we apply mru?
|
||||
;__LXCJ6MRU__ apply mru to JMP only (0xFF==al)
|
||||
jpe lxct3 ; jump if even number of 1 bits in al
|
||||
;__LXCJ7MRU__ apply mru to CALL only (0xFE==al)
|
||||
jpo lxct3 ; jump if odd number of 1 bits in al
|
||||
;__LXCJ8MRU__ do not apply mru to one or both
|
||||
clc
|
||||
lxct3:
|
||||
jmps lxunf
|
||||
|
||||
;__LXUNF034__
|
||||
unfcount:
|
||||
dec ecx
|
||||
jg lxctloop
|
||||
|
||||
;__LXMRU055__
|
||||
mov edi, esp ; clear mru[] portion of stack
|
||||
;__MRUBYTE2__
|
||||
mov ecx, 4+ 256 ; unused, tail, cto8_e8e9, cto8_0f
|
||||
;__MRUBITS2__
|
||||
mov ecx, n_mru1
|
||||
add ecx, byte 1+ 4 ; n_mru1, tail, cto8_e8e9, cto8_0f
|
||||
;__MRUARB20__
|
||||
mov ecx, n_mru
|
||||
add ecx, byte 4 ; n_mru, tail, cto8_e8e9, cto8_0f
|
||||
;__LXMRU057__
|
||||
xor eax, eax
|
||||
rep
|
||||
stosd
|
||||
mov esp, edi
|
||||
|
||||
;__LXMRU058__ 0==n_mru
|
||||
push esi
|
||||
;__LXUNF035__
|
||||
popa
|
||||
xchg eax, edi
|
||||
push ecx
|
||||
push eax
|
||||
push edx
|
||||
ret
|
||||
|
||||
%endmacro
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
Reference in New Issue
Block a user