mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
234 lines
6.4 KiB
NASM
234 lines
6.4 KiB
NASM
; l_lxsep86.asm -- Linux program entry point & decompressor (separate script)
|
|
;
|
|
; This file is part of the UPX executable compressor.
|
|
;
|
|
; Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
|
; Copyright (C) 1996-2000 Laszlo Molnar
|
|
;
|
|
; Integration of virtual exec() with decompression is
|
|
; Copyright (C) 2000 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
|
|
; markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
|
;
|
|
; John F. Reiser
|
|
; jreiser@BitWagon.com
|
|
|
|
|
|
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
|
|
|
|
_start:
|
|
;;;; int3
|
|
;; How to debug this code: Uncomment the 'int3' breakpoint instruction above.
|
|
;; Build the stubs and upx. Compress a testcase, such as a copy of /bin/date.
|
|
;; Invoke gdb on the separate stub (such as "gdb upxb"), and give the command
|
|
;; "run date". Define a single-step macro such as
|
|
;; define g
|
|
;; stepi
|
|
;; x/i $pc
|
|
;; end
|
|
;; and a step-over macro such as
|
|
;; define h
|
|
;; x/2i $pc
|
|
;; tbreak *$_
|
|
;; continue
|
|
;; x/i $pc
|
|
;; end
|
|
;; Step through the code; remember that <Enter> repeats the previous command.
|
|
;;
|
|
call main ; push address of decompress subroutine
|
|
|
|
; /*************************************************************************
|
|
; // 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]
|
|
|
|
decompress:
|
|
pusha
|
|
; cld
|
|
|
|
mov esi, INP
|
|
mov edi, OUTP
|
|
|
|
or ebp, byte -1
|
|
;;; align 8
|
|
%ifdef NRV2B
|
|
%include "n2b_d32.ash"
|
|
%elifdef NRV2D
|
|
%include "n2d_d32.ash"
|
|
%else
|
|
%error
|
|
%endif
|
|
|
|
|
|
; eax is 0 from decompressor code
|
|
;xor eax, eax ; return code
|
|
|
|
; check compressed size
|
|
mov edx, INP
|
|
add edx, INS
|
|
cmp esi, edx
|
|
jz .ok
|
|
dec eax
|
|
.ok:
|
|
|
|
; write back the uncompressed size
|
|
sub edi, OUTP
|
|
mov edx, OUTS
|
|
mov [edx], edi
|
|
|
|
mov [7*4 + esp], eax
|
|
popa
|
|
ret
|
|
|
|
|
|
%define PAGE_MASK (~0<<12)
|
|
%define PAGE_SIZE ( 1<<12)
|
|
|
|
%define szElf32_Phdr 8*4
|
|
%define a_val 4
|
|
%define __NR_munmap 91
|
|
|
|
main:
|
|
pop ebp ; &decompress
|
|
cld
|
|
|
|
; 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 ; edi= &AT_next
|
|
|
|
lea ecx, [4+esp] ; argv
|
|
sub esp, dword MAX_ELF_HDR + OVERHEAD
|
|
|
|
push esp ; argument: temp space
|
|
push edi ; argument: AT_next
|
|
push ebp ; argument: &decompress
|
|
push ecx ; argument: argv
|
|
EXTERN upx_main
|
|
call upx_main ; entry = upx_main(argv, &decompress, AT_next, tmp_ehdr)
|
|
add esp, dword 4*4 + MAX_ELF_HDR + OVERHEAD ; remove temp space, args
|
|
|
|
pop ecx ; argc
|
|
pop edx ; ++argv discard argv[0] == pathname of stub
|
|
dec ecx ; --argc
|
|
push ecx
|
|
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, dword -PAGE_SIZE
|
|
mov ebx, ebp
|
|
and ebx, ecx ; round down to page boundary
|
|
neg ecx ; PAGE_SIZE (this stub fits in it)
|
|
push byte __NR_munmap
|
|
pop eax
|
|
jmp edx ; unmap ourselves, 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
|
|
|