mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Decompression part for Mach dylib i386.
This commit is contained in:
parent
3a9e0b5be6
commit
84ac771893
|
@ -49,6 +49,20 @@ static const
|
||||||
static const
|
static const
|
||||||
#include "stub/arm-darwin.macho-fold.h"
|
#include "stub/arm-darwin.macho-fold.h"
|
||||||
|
|
||||||
|
// Packing a Darwin (Mach-o) Mac OS X dylib (dynamic shared library)
|
||||||
|
// is restricted. UPX gets control as the -init function, at the very
|
||||||
|
// end of processing by dyld. Relocation, loading of dependent libraries,
|
||||||
|
// etc., already have taken place before decompression. So the Mach-o
|
||||||
|
// headers, the __IMPORT segment, the __LINKEDIT segment, anything
|
||||||
|
// that is modifed by relocation, etc., cannot be compressed.
|
||||||
|
// We simplify arbitrarily by compressing only the __TEXT segment,
|
||||||
|
// which must be the first segment.
|
||||||
|
|
||||||
|
static const
|
||||||
|
#include "stub/i386-darwin.dylib-entry.h"
|
||||||
|
// The runtime stub for the dyld -init routine does not use "fold"ed code.
|
||||||
|
//#include "stub/i386-darwin.dylib-fold.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
PackMachBase<T>::PackMachBase(InputFile *f, unsigned cputype, unsigned filetype,
|
PackMachBase<T>::PackMachBase(InputFile *f, unsigned cputype, unsigned filetype,
|
||||||
unsigned flavor, unsigned count, unsigned size) :
|
unsigned flavor, unsigned count, unsigned size) :
|
||||||
|
@ -293,7 +307,9 @@ PackMachARMEL::buildLoader(const Filter *ft)
|
||||||
void
|
void
|
||||||
PackDylibI386::buildLoader(const Filter *ft)
|
PackDylibI386::buildLoader(const Filter *ft)
|
||||||
{
|
{
|
||||||
super::buildLoader(ft);
|
buildMachLoader(
|
||||||
|
stub_i386_darwin_dylib_entry, sizeof(stub_i386_darwin_dylib_entry),
|
||||||
|
0, 0, ft );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -383,7 +399,7 @@ void PackDylibI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
||||||
{
|
{
|
||||||
unsigned opos = fo->getBytesWritten();
|
unsigned opos = fo->getBytesWritten();
|
||||||
segcmdo.filesize = opos;
|
segcmdo.filesize = opos;
|
||||||
segcmdo.vmsize += opos;
|
segcmdo.vmsize = msegcmd->vmsize;
|
||||||
rcmd.init_address = threado.state.eip;
|
rcmd.init_address = threado.state.eip;
|
||||||
fo->seek(sizeof(mhdro), SEEK_SET);
|
fo->seek(sizeof(mhdro), SEEK_SET);
|
||||||
fo->rewrite(&segcmdo, sizeof(segcmdo));
|
fo->rewrite(&segcmdo, sizeof(segcmdo));
|
||||||
|
@ -391,7 +407,7 @@ void PackDylibI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
||||||
fo->rewrite(&rcmd, sizeof(rcmd));
|
fo->rewrite(&rcmd, sizeof(rcmd));
|
||||||
fo->rewrite(&linfo, sizeof(linfo));
|
fo->rewrite(&linfo, sizeof(linfo));
|
||||||
|
|
||||||
// Append __IMPORT and __LINKEDIT segments, page aligned.
|
// Append each non-__TEXT segment, page aligned.
|
||||||
int slide = 0;
|
int slide = 0;
|
||||||
unsigned hdrpos = sizeof(mhdro) + sizeof(segcmdo);
|
unsigned hdrpos = sizeof(mhdro) + sizeof(segcmdo);
|
||||||
Mach_segment_command const *seg = rawmseg;
|
Mach_segment_command const *seg = rawmseg;
|
||||||
|
@ -418,10 +434,8 @@ void PackDylibI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader
|
||||||
hdrpos += seg->cmdsize;
|
hdrpos += seg->cmdsize;
|
||||||
break; // contain no file offset fields
|
break; // contain no file offset fields
|
||||||
case Mach_segment_command::LC_SEGMENT: {
|
case Mach_segment_command::LC_SEGMENT: {
|
||||||
// __IMPORT and __LINKEDIT must be seen by dylinker before decompression.
|
// non-__TEXT might be observed and relocated by dyld before us.
|
||||||
// All other segments have been combined into new compressed __TEXT.
|
if (0!=strncmp(&seg->segname[0], "__TEXT", 1+ 6)) {
|
||||||
if (0==strncmp(&seg->segname[0], "__IMPORT", 1+ 8)
|
|
||||||
|| 0==strncmp(&seg->segname[0], "__LINKEDIT", 1+ 10)) {
|
|
||||||
Mach_segment_command segcmdtmp = *seg;
|
Mach_segment_command segcmdtmp = *seg;
|
||||||
opos += ~PAGE_MASK & (0u - opos); // advance to PAGE_SIZE boundary
|
opos += ~PAGE_MASK & (0u - opos); // advance to PAGE_SIZE boundary
|
||||||
slide = opos - segcmdtmp.fileoff;
|
slide = opos - segcmdtmp.fileoff;
|
||||||
|
@ -531,6 +545,26 @@ void PackMachARMEL::pack3(OutputFile *fo, Filter &ft) // append loader
|
||||||
super::pack3(fo, ft);
|
super::pack3(fo, ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PackDylibI386::pack3(OutputFile *fo, Filter &ft) // append loader
|
||||||
|
{
|
||||||
|
LE32 disp;
|
||||||
|
unsigned const zero = 0;
|
||||||
|
unsigned len = fo->getBytesWritten();
|
||||||
|
fo->write(&zero, 3& (0u-len));
|
||||||
|
len += (3& (0u-len)) + 3*sizeof(disp);
|
||||||
|
|
||||||
|
disp = sizeof(mhdro) + mhdro.sizeofcmds + sizeof(l_info) + sizeof(p_info);
|
||||||
|
fo->write(&disp, sizeof(disp)); // src offset(compressed __TEXT)
|
||||||
|
|
||||||
|
disp = len - disp - 3*sizeof(disp);
|
||||||
|
fo->write(&disp, sizeof(disp)); // length(compressed __TEXT)
|
||||||
|
|
||||||
|
unsigned const save_sz_mach_headers(sz_mach_headers);
|
||||||
|
sz_mach_headers = 0;
|
||||||
|
super::pack3(fo, ft);
|
||||||
|
sz_mach_headers = save_sz_mach_headers;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine length of gap between PT_LOAD phdri[k] and closest PT_LOAD
|
// Determine length of gap between PT_LOAD phdri[k] and closest PT_LOAD
|
||||||
// which follows in the file (or end-of-file). Optimize for common case
|
// which follows in the file (or end-of-file). Optimize for common case
|
||||||
// where the PT_LOAD are adjacent ascending by .p_offset. Assume no overlap.
|
// where the PT_LOAD are adjacent ascending by .p_offset. Assume no overlap.
|
||||||
|
@ -593,6 +627,9 @@ void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed bo
|
||||||
if (Mach_segment_command::LC_SEGMENT==msegcmd[k].cmd
|
if (Mach_segment_command::LC_SEGMENT==msegcmd[k].cmd
|
||||||
&& 0!=msegcmd[k].filesize ) {
|
&& 0!=msegcmd[k].filesize ) {
|
||||||
uip->ui_total_passes++;
|
uip->ui_total_passes++;
|
||||||
|
if (my_filetype==Mach_header::MH_DYLIB) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (find_SEGMENT_gap(k)) {
|
if (find_SEGMENT_gap(k)) {
|
||||||
uip->ui_total_passes++;
|
uip->ui_total_passes++;
|
||||||
}
|
}
|
||||||
|
@ -639,7 +676,11 @@ void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed bo
|
||||||
}
|
}
|
||||||
hdr_u_len = 0;
|
hdr_u_len = 0;
|
||||||
++nx;
|
++nx;
|
||||||
|
if (my_filetype==Mach_header::MH_DYLIB) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (my_filetype!=Mach_header::MH_DYLIB)
|
||||||
for (k = 0; k < n_segment; ++k) {
|
for (k = 0; k < n_segment; ++k) {
|
||||||
x.size = find_SEGMENT_gap(k);
|
x.size = find_SEGMENT_gap(k);
|
||||||
if (x.size) {
|
if (x.size) {
|
||||||
|
@ -648,6 +689,7 @@ void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft) // append compressed bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (my_filetype!=Mach_header::MH_DYLIB)
|
||||||
if ((off_t)total_in != file_size)
|
if ((off_t)total_in != file_size)
|
||||||
throwEOFException();
|
throwEOFException();
|
||||||
segcmdo.filesize = fo->getBytesWritten();
|
segcmdo.filesize = fo->getBytesWritten();
|
||||||
|
@ -699,14 +741,16 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
||||||
Mach_segment_command const *const endseg =
|
Mach_segment_command const *const endseg =
|
||||||
(Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg);
|
(Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg);
|
||||||
for (; seg < endseg; seg = (Mach_segment_command const *)(
|
for (; seg < endseg; seg = (Mach_segment_command const *)(
|
||||||
seg->cmdsize + (char const *)seg)) {
|
seg->cmdsize + (char const *)seg))
|
||||||
// All except __IMPORT and __LINKEDIT will be coalesced into __TEXT.
|
switch (~Mach_segment_command::LC_REQ_DYLD & seg->cmd) {
|
||||||
if (0!=strncmp(&seg->segname[0], "__IMPORT", 1+ 8)
|
case Mach_segment_command::LC_SEGMENT: {
|
||||||
&& 0!=strncmp(&seg->segname[0], "__LINKEDIT", 1+ 10)){
|
// Old __TEXT will be replaced by new __TEXT.
|
||||||
|
if (0==strncmp(&seg->segname[0], "__TEXT", 1+ 6)) {
|
||||||
mhdro.ncmds -= 1;
|
mhdro.ncmds -= 1;
|
||||||
mhdro.sizeofcmds -= seg->cmdsize;
|
mhdro.sizeofcmds -= seg->cmdsize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // end 'switch'
|
||||||
}
|
}
|
||||||
fo->write(&mhdro, sizeof(mhdro));
|
fo->write(&mhdro, sizeof(mhdro));
|
||||||
|
|
||||||
|
@ -739,12 +783,17 @@ void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e
|
||||||
Mach_segment_command const *const endseg =
|
Mach_segment_command const *const endseg =
|
||||||
(Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg);
|
(Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg);
|
||||||
for (; seg < endseg; seg = (Mach_segment_command const *)(
|
for (; seg < endseg; seg = (Mach_segment_command const *)(
|
||||||
seg->cmdsize + (char const *)seg)) {
|
seg->cmdsize + (char const *)seg))
|
||||||
if (0==strncmp(&seg->segname[0], "__IMPORT", 1+ 8)
|
switch (~Mach_segment_command::LC_REQ_DYLD & seg->cmd) {
|
||||||
|| 0==strncmp(&seg->segname[0], "__LINKEDIT", 1+ 10)){
|
default: {
|
||||||
|
fo->write(seg, seg->cmdsize);
|
||||||
|
} break;
|
||||||
|
case Mach_segment_command::LC_SEGMENT: {
|
||||||
|
if (0!=strncmp(&seg->segname[0], "__TEXT", 1+ 6)) {
|
||||||
fo->write(seg, seg->cmdsize);
|
fo->write(seg, seg->cmdsize);
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
|
} // end 'switch'
|
||||||
memset(&rcmd, 0, sizeof(rcmd));
|
memset(&rcmd, 0, sizeof(rcmd));
|
||||||
rcmd.cmd= Mach_segment_command::LC_ROUTINES;
|
rcmd.cmd= Mach_segment_command::LC_ROUTINES;
|
||||||
rcmd.cmdsize = sizeof(rcmd);
|
rcmd.cmdsize = sizeof(rcmd);
|
||||||
|
|
|
@ -627,7 +627,7 @@ protected:
|
||||||
//virtual void pack1_setup_threado(OutputFile *const fo);
|
//virtual void pack1_setup_threado(OutputFile *const fo);
|
||||||
//virtual void pack1(OutputFile *, Filter &); // generate executable header
|
//virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||||
//virtual void pack2(OutputFile *, Filter &); // append compressed data
|
//virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||||
//virtual void pack3(OutputFile *, Filter &); // append loader
|
virtual void pack3(OutputFile *, Filter &); // append loader
|
||||||
virtual void pack4(OutputFile *, Filter &); // append PackHeader
|
virtual void pack4(OutputFile *, Filter &); // append PackHeader
|
||||||
//virtual Linker* newLinker() const;
|
//virtual Linker* newLinker() const;
|
||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft);
|
||||||
|
|
|
@ -75,6 +75,8 @@ STUBS += i386-bsd.elf-entry.h
|
||||||
STUBS += i386-bsd.elf-fold.h
|
STUBS += i386-bsd.elf-fold.h
|
||||||
STUBS += i386-bsd.elf.execve-entry.h
|
STUBS += i386-bsd.elf.execve-entry.h
|
||||||
STUBS += i386-bsd.elf.execve-fold.h
|
STUBS += i386-bsd.elf.execve-fold.h
|
||||||
|
STUBS += i386-darwin.dylib-entry.h
|
||||||
|
# STUBS += i386-darwin.dylib-fold.h
|
||||||
STUBS += i386-darwin.macho-entry.h
|
STUBS += i386-darwin.macho-entry.h
|
||||||
STUBS += i386-darwin.macho-fold.h
|
STUBS += i386-darwin.macho-fold.h
|
||||||
STUBS += i386-openbsd.elf-fold.h
|
STUBS += i386-openbsd.elf-fold.h
|
||||||
|
@ -622,6 +624,21 @@ tmp/i386-bsd.elf.execve-upx_itoa.o : $(srcdir)/src/$$T.S
|
||||||
$(call tc,f-objstrip,$@)
|
$(call tc,f-objstrip,$@)
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // i386-darwin.dylib
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
# info: we use the tc settings from i386-linux.elf
|
||||||
|
i386-darwin.dylib%.h : tc_list = i386-linux.elf default
|
||||||
|
i386-darwin.dylib%.h : tc_bfdname = elf32-i386
|
||||||
|
|
||||||
|
## All code is in dylib-entry. There is no dylib-fold, no dylib-main.
|
||||||
|
i386-darwin.dylib-entry.h : $(srcdir)/src/$$T.S
|
||||||
|
$(call tc,gcc) -c $< -o tmp/$T.bin
|
||||||
|
$(call tc,f-embed_objinfo,tmp/$T.bin)
|
||||||
|
$(call tc,bin2h) tmp/$T.bin $@
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // i386-darwin.macho
|
# // i386-darwin.macho
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
2402
src/stub/i386-darwin.dylib-entry.h
Normal file
2402
src/stub/i386-darwin.dylib-entry.h
Normal file
File diff suppressed because it is too large
Load Diff
232
src/stub/src/i386-darwin.dylib-entry.S
Normal file
232
src/stub/src/i386-darwin.dylib-entry.S
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
/*
|
||||||
|
; i386-darwin.dylib-entry.S -- program entry point & decompressor (i386 Mach-o)
|
||||||
|
;
|
||||||
|
; This file is part of the UPX executable compressor.
|
||||||
|
;
|
||||||
|
; Copyright (C) 1996-2009 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
; Copyright (C) 1996-2009 Laszlo Molnar
|
||||||
|
; Copyright (C) 2000-2009 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.com> <ml1050@users.sourceforge.net>
|
||||||
|
;
|
||||||
|
; John F. Reiser
|
||||||
|
; <jreiser@users.sourceforge.net>
|
||||||
|
;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/i386/macros.S"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// We have been CALLed as a subroutine from dyld; C-language rules apply.
|
||||||
|
// -3*4+_start: .long offset(&b_info of compressed Mach_headers)
|
||||||
|
// -2*4+_start: .long length(compressed __TEXT)
|
||||||
|
// -1*4+_start: .long total_length # of preceding bytes in file
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
section LEXEC000
|
||||||
|
_start: .globl _start
|
||||||
|
//// int3 # for debug only
|
||||||
|
pusha
|
||||||
|
call main // push address of decompress subroutine
|
||||||
|
decompress:
|
||||||
|
|
||||||
|
// /*************************************************************************
|
||||||
|
// // C callable decompressor
|
||||||
|
// **************************************************************************/
|
||||||
|
|
||||||
|
// /* Offsets to parameters, allowing for {pusha + call} */
|
||||||
|
#define O_INP (8*4 +1*4)
|
||||||
|
#define O_INS (8*4 +2*4)
|
||||||
|
#define O_OUTP (8*4 +3*4)
|
||||||
|
#define O_OUTS (8*4 +4*4)
|
||||||
|
#define O_PARAM (8*4 +5*4)
|
||||||
|
|
||||||
|
#define INP dword ptr [esp+O_INP]
|
||||||
|
#define INS dword ptr [esp+O_INS]
|
||||||
|
#define OUTP dword ptr [esp+O_OUTP]
|
||||||
|
#define OUTS dword ptr [esp+O_OUTS]
|
||||||
|
#define PARM dword ptr [esp+O_PARAM]
|
||||||
|
|
||||||
|
section LEXEC009
|
||||||
|
//; empty section for commonality with l_lx_exec86.asm
|
||||||
|
section LEXEC010
|
||||||
|
pusha
|
||||||
|
// cld
|
||||||
|
|
||||||
|
mov esi, INP
|
||||||
|
mov edi, OUTP
|
||||||
|
|
||||||
|
or ebp, -1
|
||||||
|
//;; align 8
|
||||||
|
|
||||||
|
#include "arch/i386/nrv2b_d32.S"
|
||||||
|
#include "arch/i386/nrv2d_d32.S"
|
||||||
|
#include "arch/i386/nrv2e_d32.S"
|
||||||
|
#include "arch/i386/lzma_d.S"
|
||||||
|
|
||||||
|
section LEXEC015
|
||||||
|
// 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
|
||||||
|
|
||||||
|
ctojr32
|
||||||
|
ctok32 edi, dl
|
||||||
|
cit32 edi
|
||||||
|
section LEXEC017
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
section LEXEC020
|
||||||
|
|
||||||
|
#define PAGE_SIZE ( 1<<12)
|
||||||
|
|
||||||
|
sz_Mach_header= 7*4
|
||||||
|
mh_sizeofcmds=5*4
|
||||||
|
|
||||||
|
seg_vmaddr=2*4+16
|
||||||
|
seg_vmsize=4+seg_vmaddr
|
||||||
|
seg_filesize=2*4+seg_vmsize
|
||||||
|
|
||||||
|
sz_l_info=3*4
|
||||||
|
sz_p_info=3*4
|
||||||
|
sz_b_info=3*4
|
||||||
|
sz_unc= 0
|
||||||
|
sz_cpr= 4
|
||||||
|
b_method= 8
|
||||||
|
|
||||||
|
#define MAP_FIXED 0x10
|
||||||
|
#define MAP_PRIVATE 0x02
|
||||||
|
#define MAP_ANON 0x1000
|
||||||
|
#define PROT_READ 1
|
||||||
|
#define PROT_WRITE 2
|
||||||
|
#define PROT_EXEC 4
|
||||||
|
|
||||||
|
|
||||||
|
main:
|
||||||
|
pop ebp # &decompress
|
||||||
|
lea ebx,[-4+ _start - decompress + ebp] # &total_length
|
||||||
|
mov eax,[-1*4 + ebx] # length(compressed __TEXT)
|
||||||
|
add eax,offset(dy_top)
|
||||||
|
sub eax,offset(decompress)
|
||||||
|
|
||||||
|
push eax # length for eventual munmap
|
||||||
|
|
||||||
|
push 0 # offset
|
||||||
|
push -1 # fd
|
||||||
|
push MAP_ANON|MAP_PRIVATE
|
||||||
|
push PROT_READ|PROT_WRITE
|
||||||
|
push eax # length
|
||||||
|
push 0 # addr
|
||||||
|
call mmap
|
||||||
|
add esp,6*4
|
||||||
|
|
||||||
|
push eax # addr for eventual munmap
|
||||||
|
|
||||||
|
// Copy interval [decompress, dy_top).
|
||||||
|
mov esi,ebp # decompressor
|
||||||
|
mov ebp,eax # new location
|
||||||
|
mov edi,eax # dst for decompressor
|
||||||
|
mov ecx,offset(dy_top)
|
||||||
|
sub ecx,offset(decompress)
|
||||||
|
cld; rep movsb
|
||||||
|
|
||||||
|
// Goto copied dy_reloc.
|
||||||
|
lea eax,[-offset(dy_top - dy_reloc) + edi]
|
||||||
|
jmp %eax
|
||||||
|
dy_reloc:
|
||||||
|
|
||||||
|
// Copy compressed __TEXT.
|
||||||
|
push edi # remember start of compressed __TEXT
|
||||||
|
mov edx,ebx # &total_length
|
||||||
|
sub edx,[ebx] # runtime base address
|
||||||
|
mov esi,[-2*4 + ebx]; add esi,edx
|
||||||
|
mov ecx,[-1*4 + ebx]
|
||||||
|
rep movsb
|
||||||
|
pop esi # &b_info for Mach_header
|
||||||
|
mov edi,edx # runtime base address
|
||||||
|
|
||||||
|
// Decompress __TEXT.
|
||||||
|
dy_uncpr:
|
||||||
|
push esi; push edi # save in case unfilter
|
||||||
|
|
||||||
|
lodsd; test eax,eax; jz dy_done
|
||||||
|
push eax // sz_uncompressed (maximum dstlen for lzma)
|
||||||
|
mov ecx,esp // save &dstlen
|
||||||
|
push eax // space for 5th param b_info.misc
|
||||||
|
push ecx // &dstlen
|
||||||
|
push edi // dst
|
||||||
|
add edi,eax // next dst
|
||||||
|
lodsd; push eax // sz_compressed (srclen)
|
||||||
|
mov ecx,eax
|
||||||
|
lodsd; mov [3*4 + esp],eax // last 4 bytes of b_info
|
||||||
|
push esi // &compressed __TEXT
|
||||||
|
add esi,ecx // next src
|
||||||
|
call ebp // decompress(src, srclen, dst, &dstlen, b_info.misc)
|
||||||
|
add esp, (5+1)*4 // (5+1) args to decompress
|
||||||
|
|
||||||
|
pop edx; pop eax # edx= old dst; eax= old &b_info
|
||||||
|
movzbl ecx,[1+ b_method + eax]; jecxz dy_uncpr; push ecx # ftid
|
||||||
|
movzbl ecx,[2+ b_method + eax]; push ecx # cto8
|
||||||
|
push [sz_unc + eax]
|
||||||
|
push edx # dst
|
||||||
|
lea eax,[2+ ebp]; call eax # f_unfilter(dst, dstlen, cto8, ftid)
|
||||||
|
add esp,4*4
|
||||||
|
jmp dy_uncpr
|
||||||
|
|
||||||
|
SYS_mmap =197
|
||||||
|
mmap:
|
||||||
|
mov eax,SYS_mmap
|
||||||
|
call sysgo; jncs 0f; or eax,~0
|
||||||
|
0:
|
||||||
|
ret
|
||||||
|
|
||||||
|
SYS_munmap=73
|
||||||
|
dy_done:
|
||||||
|
pop eax # discard, leaving 1 junk word below the regs for POPA
|
||||||
|
lea edx,[-5+ edi] # steal some space at high end of __TEXT
|
||||||
|
mov byte ptr [ edx], 0x58 # pop eax
|
||||||
|
mov dword ptr [1+ edx],0xc3615858 # pop eax; pop eax; popa; ret
|
||||||
|
mov eax,SYS_munmap
|
||||||
|
push edx # retaddr
|
||||||
|
sysgo:
|
||||||
|
pop edx # return address for sysenter
|
||||||
|
mov ecx,esp # &{user_ret, arg1, arg2, ...}
|
||||||
|
.byte 0x0f, 0x34 # sysenter
|
||||||
|
|
||||||
|
dy_top:
|
||||||
|
|
||||||
|
// vi:ts=8:et:nowrap
|
Loading…
Reference in New Issue
Block a user