Extent for xread(); more args for upx_main()
l_lx_exec.c l_lx_exec86.asm committer: jreiser <jreiser> 958847261 +0000
This commit is contained in:
parent
1c24a96864
commit
25ade0970b
@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
#include "linux.hh"
|
||||
#include <elf.h>
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@ -47,26 +48,37 @@
|
||||
#undef xread
|
||||
#undef xwrite
|
||||
|
||||
#if 1
|
||||
//static int xread(int fd, void *buf, int count) __attribute__((__stdcall__));
|
||||
static int xread(int fd, void *buf, int count)
|
||||
{
|
||||
// note: we can assert(count > 0);
|
||||
do {
|
||||
int n = read(fd, buf, count);
|
||||
if (n == -EINTR)
|
||||
continue;
|
||||
if (n <= 0)
|
||||
break;
|
||||
buf += n; // gcc extension: add to void *
|
||||
count -= n;
|
||||
} while (count > 0);
|
||||
return count;
|
||||
}
|
||||
#else
|
||||
#define xread(fd,buf,count) ((count) - read(fd,buf,count))
|
||||
#endif
|
||||
struct Extent {
|
||||
size_t size; // must be first to match size[0] uncompressed size
|
||||
char *buf;
|
||||
};
|
||||
|
||||
static void
|
||||
xread(struct Extent *const x, char *const buf, size_t const count)
|
||||
{
|
||||
if (x->size < count) {
|
||||
exit(127);
|
||||
}
|
||||
#if 0 //{
|
||||
{
|
||||
char *p=x->buf, *q=buf;
|
||||
size_t j;
|
||||
for (j = count; 0!=j--; ++p, ++q) {
|
||||
*q = *p;
|
||||
}
|
||||
}
|
||||
#else //}{
|
||||
{
|
||||
register unsigned long int __d0, __d1, __d2;
|
||||
__asm__ __volatile__( "cld; rep; movsb"
|
||||
: "=&c" (__d0), "=&D" (__d1), "=&S" (__d2)
|
||||
: "0" (count), "1" (buf), "2" (x->buf)
|
||||
: "memory");
|
||||
}
|
||||
#endif //}
|
||||
x->buf += count;
|
||||
x->size -= count;
|
||||
}
|
||||
|
||||
#if 1
|
||||
static __inline__ int xwrite(int fd, const void *buf, int count)
|
||||
@ -149,18 +161,9 @@ static char *upx_itoa(char *buf, unsigned long v)
|
||||
#define UPX4 0x34585055 // "UPX4"
|
||||
#define UPX5 0x35585055 // "UPX5"
|
||||
|
||||
|
||||
#if defined(__i386__)
|
||||
extern int
|
||||
nrv2b_decompress_asm_fast ( const nrv_byte *src, nrv_uint src_len,
|
||||
nrv_byte *dst, nrv_uint *dst_len );
|
||||
#define nrv2b_decompress nrv2b_decompress_asm_fast
|
||||
extern int
|
||||
nrv2d_decompress_asm_fast ( const nrv_byte *src, nrv_uint src_len,
|
||||
nrv_byte *dst, nrv_uint *dst_len );
|
||||
#define nrv2d_decompress nrv2d_decompress_asm_fast
|
||||
#endif /* __i386__ */
|
||||
|
||||
typedef int f_expand(
|
||||
const nrv_byte *src, nrv_uint src_len,
|
||||
nrv_byte *dst, nrv_uint *dst_len );
|
||||
|
||||
/*************************************************************************
|
||||
// upx_main - called by our entry code
|
||||
@ -168,12 +171,24 @@ nrv2d_decompress_asm_fast ( const nrv_byte *src, nrv_uint src_len,
|
||||
// This function is optimized for size.
|
||||
**************************************************************************/
|
||||
|
||||
void upx_main(char *argv[], char *envp[]) __asm__("upx_main");
|
||||
void upx_main(char *argv[], char *envp[])
|
||||
void upx_main(
|
||||
char *argv[],
|
||||
char *envp[],
|
||||
Elf32_Ehdr const *const my_ehdr,
|
||||
f_expand *const f_decompress
|
||||
) __asm__("upx_main");
|
||||
void upx_main(
|
||||
char *argv[],
|
||||
char *envp[],
|
||||
Elf32_Ehdr const *const my_ehdr,
|
||||
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 };
|
||||
struct p_info header;
|
||||
|
||||
// for getpid()
|
||||
@ -182,7 +197,7 @@ void upx_main(char *argv[], char *envp[])
|
||||
// temporary file name (max 14 chars)
|
||||
static char tmpname_buf[] = "/tmp/upxAAAAAAAAAAA";
|
||||
char *tmpname = tmpname_buf;
|
||||
char procself_buf[64];
|
||||
char procself_buf[24]; // /proc/PPPPP/fd/XX
|
||||
char *procself;
|
||||
|
||||
// decompression buffer
|
||||
@ -211,30 +226,9 @@ void upx_main(char *argv[], char *envp[])
|
||||
// ----- Step 1: prepare input file -----
|
||||
//
|
||||
|
||||
// Open the exe.
|
||||
SET3(procself, 'e', 'x', 'e');
|
||||
fdi = open(procself_buf, O_RDONLY, 0);
|
||||
#if 1
|
||||
// try /proc/<pid>/file for the sake of FreeBSD
|
||||
if (fdi < 0)
|
||||
{
|
||||
SET4(procself, 'f', 'i', 'l', 'e');
|
||||
fdi = open(procself_buf, O_RDONLY, 0);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
// Save some bytes of code - the lseek() below will fail anyway.
|
||||
if (fdi < 0)
|
||||
goto error1;
|
||||
#endif
|
||||
|
||||
// Seek to start of compressed data. The offset is patched
|
||||
// by the compressor.
|
||||
if (lseek(fdi, UPX1, 0) < 0)
|
||||
goto error1;
|
||||
// Read header.
|
||||
if (xread(fdi, (void *)&header, sizeof(header)) != 0)
|
||||
goto error1;
|
||||
xread(&xi, (void *)&header, sizeof(header));
|
||||
|
||||
// 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.)
|
||||
@ -335,57 +329,50 @@ void upx_main(char *argv[], char *envp[])
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int32_t size[2];
|
||||
// size[0]: uncompressed block size
|
||||
// size[1]: compressed block size
|
||||
// Note: if size[0] == size[1] then the block was not
|
||||
struct {
|
||||
int32_t sz_unc; // uncompressed
|
||||
int32_t sz_cpr; // compressed
|
||||
} h;
|
||||
// Note: if h.sz_unc == h.sz_cpr then the block was not
|
||||
// compressible and is stored in its uncompressed form.
|
||||
int i;
|
||||
|
||||
// Read and check block sizes.
|
||||
if (xread(fdi, (void *)size, 8) != 0)
|
||||
goto error;
|
||||
if (size[0] == 0) // uncompressed size 0 -> EOF
|
||||
xread(&xi, (void *)&h, sizeof(h));
|
||||
if (h.sz_unc == 0) // uncompressed size 0 -> EOF
|
||||
{
|
||||
if (size[1] != UPX_MAGIC_LE32) // size[1] must be h->magic
|
||||
if (h.sz_cpr != UPX_MAGIC_LE32) // h.sz_cpr must be h->magic
|
||||
goto error;
|
||||
if (header.p_filesize != 0) // all bytes must be written
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
if (size[1] <= 0)
|
||||
if (h.sz_cpr <= 0)
|
||||
goto error;
|
||||
if (size[1] > size[0] || size[0] > (int32_t)header.p_blocksize)
|
||||
if (h.sz_cpr > h.sz_unc || h.sz_unc > (int32_t)header.p_blocksize)
|
||||
goto error;
|
||||
// Now we have:
|
||||
// assert(size[1] <= size[0]);
|
||||
// assert(size[0] > 0 && size[0] <= blocksize);
|
||||
// assert(size[1] > 0 && size[1] <= blocksize);
|
||||
// assert(h.sz_cpr <= h.sz_unc);
|
||||
// assert(h.sz_unc > 0 && h.sz_unc <= blocksize);
|
||||
// assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize);
|
||||
|
||||
// Read compressed block.
|
||||
i = header.p_blocksize + OVERHEAD - size[1];
|
||||
if (xread(fdi, buf+i, size[1]) != 0)
|
||||
goto error;
|
||||
i = header.p_blocksize + OVERHEAD - h.sz_cpr;
|
||||
xread(&xi, buf+i, h.sz_cpr);
|
||||
|
||||
// Decompress block.
|
||||
if (size[1] < size[0])
|
||||
if (h.sz_cpr < h.sz_unc)
|
||||
{
|
||||
// in-place decompression
|
||||
nrv_uint out_len;
|
||||
#if defined(NRV2B)
|
||||
i = nrv2b_decompress(buf+i, size[1], buf, &out_len);
|
||||
#elif defined(NRV2D)
|
||||
i = nrv2d_decompress(buf+i, size[1], buf, &out_len);
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
if (i != 0 || out_len != (nrv_uint)size[0])
|
||||
i = (*f_decompress)(buf+i, h.sz_cpr, buf, &out_len);
|
||||
if (i != 0 || out_len != (nrv_uint)h.sz_unc)
|
||||
goto error;
|
||||
// i == 0 now
|
||||
}
|
||||
|
||||
// Write uncompressed block.
|
||||
if (xwrite(fdo, buf+i, size[0]) != 0)
|
||||
if (xwrite(fdo, buf+i, h.sz_unc) != 0)
|
||||
{
|
||||
// error exit is here in the middle to keep the jumps short.
|
||||
error:
|
||||
@ -396,7 +383,7 @@ void upx_main(char *argv[], char *envp[])
|
||||
for (;;)
|
||||
(void) exit(127);
|
||||
}
|
||||
header.p_filesize -= size[0];
|
||||
header.p_filesize -= h.sz_unc;
|
||||
}
|
||||
|
||||
|
||||
@ -410,8 +397,6 @@ void upx_main(char *argv[], char *envp[])
|
||||
|
||||
if (close(fdo) != 0)
|
||||
goto error;
|
||||
if (close(fdi) != 0)
|
||||
goto error;
|
||||
|
||||
|
||||
//
|
||||
|
||||
@ -48,6 +48,9 @@
|
||||
%endif
|
||||
|
||||
|
||||
%include "ident.ash"
|
||||
|
||||
|
||||
; /*************************************************************************
|
||||
; // program entry point
|
||||
; // see glibc/sysdeps/i386/elf/start.S
|
||||
@ -57,41 +60,12 @@ GLOBAL _start
|
||||
EXTERN upx_main
|
||||
|
||||
_start:
|
||||
xor ebp, ebp ; Clear the frame pointer
|
||||
%if 0
|
||||
; personality(PER_LINUX)
|
||||
mov eax, 136 ; syscall_personality
|
||||
xor ebx, ebx ; PER_LINUX
|
||||
int 0x80
|
||||
%endif
|
||||
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
|
||||
and esp, byte -8 ; Align the stack
|
||||
push edx ; Push third argument: envp
|
||||
push ecx ; Push second argument: argv
|
||||
;;; push eax ; Push first argument: argc
|
||||
call upx_main ; Call the UPX main function
|
||||
hlt ; Crash if somehow upx_main does return
|
||||
|
||||
%include "ident.ash"
|
||||
|
||||
call main ; push &decompress
|
||||
|
||||
; /*************************************************************************
|
||||
; // C callable decompressor
|
||||
; **************************************************************************/
|
||||
|
||||
%ifdef NRV2B
|
||||
%define decompress nrv2b_decompress_asm_fast
|
||||
%elifdef NRV2D
|
||||
%define decompress nrv2d_decompress_asm_fast
|
||||
%else
|
||||
%error
|
||||
%endif
|
||||
|
||||
GLOBAL decompress
|
||||
|
||||
%define INP dword [esp+24+4]
|
||||
%define INS dword [esp+24+8]
|
||||
%define OUTP dword [esp+24+12]
|
||||
@ -144,5 +118,29 @@ decompress:
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
; /*************************************************************************
|
||||
; // prepare arguments and call upx_main
|
||||
; **************************************************************************/
|
||||
main:
|
||||
pop ebp ; &decompress
|
||||
%if 0
|
||||
; personality(PER_LINUX)
|
||||
mov eax, 136 ; syscall_personality
|
||||
xor ebx, ebx ; PER_LINUX
|
||||
int 0x80
|
||||
%endif
|
||||
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
|
||||
%define PAGE_MASK (~0<<12)
|
||||
and ebp, PAGE_MASK
|
||||
push ebp ; argument: &Elf32_Ehdr
|
||||
push edx ; Push third argument: envp
|
||||
push ecx ; Push second argument: argv
|
||||
;;; push eax ; Push first argument: argc
|
||||
call upx_main ; Call the UPX main function
|
||||
hlt ; Crash if somehow upx_main does return
|
||||
|
||||
; vi:ts=8:et:nowrap
|
||||
|
||||
Loading…
Reference in New Issue
Block a user