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:
John Reiser
2000-05-20 18:27:41 +00:00
parent 1c24a96864
commit 25ade0970b
2 changed files with 100 additions and 117 deletions
+71 -86
View File
@@ -30,6 +30,7 @@
#endif #endif
#include "linux.hh" #include "linux.hh"
#include <elf.h>
/************************************************************************* /*************************************************************************
@@ -47,26 +48,37 @@
#undef xread #undef xread
#undef xwrite #undef xwrite
#if 1 struct Extent {
//static int xread(int fd, void *buf, int count) __attribute__((__stdcall__)); size_t size; // must be first to match size[0] uncompressed size
static int xread(int fd, void *buf, int count) char *buf;
{ };
// 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
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 #if 1
static __inline__ int xwrite(int fd, const void *buf, int count) 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 UPX4 0x34585055 // "UPX4"
#define UPX5 0x35585055 // "UPX5" #define UPX5 0x35585055 // "UPX5"
typedef int f_expand(
#if defined(__i386__) const nrv_byte *src, nrv_uint src_len,
extern int
nrv2b_decompress_asm_fast ( const nrv_byte *src, nrv_uint src_len,
nrv_byte *dst, nrv_uint *dst_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__ */
/************************************************************************* /*************************************************************************
// upx_main - called by our entry code // 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. // This function is optimized for size.
**************************************************************************/ **************************************************************************/
void upx_main(char *argv[], char *envp[]) __asm__("upx_main"); void upx_main(
void upx_main(char *argv[], char *envp[]) 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 // file descriptors
int fdi, fdo; 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; struct p_info header;
// for getpid() // for getpid()
@@ -182,7 +197,7 @@ void upx_main(char *argv[], char *envp[])
// temporary file name (max 14 chars) // temporary file name (max 14 chars)
static char tmpname_buf[] = "/tmp/upxAAAAAAAAAAA"; static char tmpname_buf[] = "/tmp/upxAAAAAAAAAAA";
char *tmpname = tmpname_buf; char *tmpname = tmpname_buf;
char procself_buf[64]; char procself_buf[24]; // /proc/PPPPP/fd/XX
char *procself; char *procself;
// decompression buffer // decompression buffer
@@ -211,30 +226,9 @@ void upx_main(char *argv[], char *envp[])
// ----- Step 1: prepare input file ----- // ----- 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. // Read header.
if (xread(fdi, (void *)&header, sizeof(header)) != 0) xread(&xi, (void *)&header, sizeof(header));
goto error1;
// Paranoia. Make sure this is actually our expected executable // Paranoia. Make sure this is actually our expected executable
// by checking the random program id. (The id is both stored // by checking the random program id. (The id is both stored
// in the header and patched into this stub.) // in the header and patched into this stub.)
@@ -335,57 +329,50 @@ void upx_main(char *argv[], char *envp[])
for (;;) for (;;)
{ {
int32_t size[2]; struct {
// size[0]: uncompressed block size int32_t sz_unc; // uncompressed
// size[1]: compressed block size int32_t sz_cpr; // compressed
// Note: if size[0] == size[1] then the block was not } h;
// Note: if h.sz_unc == h.sz_cpr then the block was not
// compressible and is stored in its uncompressed form. // compressible and is stored in its uncompressed form.
int i; int i;
// Read and check block sizes. // Read and check block sizes.
if (xread(fdi, (void *)size, 8) != 0) xread(&xi, (void *)&h, sizeof(h));
goto error; if (h.sz_unc == 0) // uncompressed size 0 -> EOF
if (size[0] == 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; goto error;
if (header.p_filesize != 0) // all bytes must be written if (header.p_filesize != 0) // all bytes must be written
goto error; goto error;
break; break;
} }
if (size[1] <= 0) if (h.sz_cpr <= 0)
goto error; 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; goto error;
// Now we have: // Now we have:
// assert(size[1] <= size[0]); // assert(h.sz_cpr <= h.sz_unc);
// assert(size[0] > 0 && size[0] <= blocksize); // assert(h.sz_unc > 0 && h.sz_unc <= blocksize);
// assert(size[1] > 0 && size[1] <= blocksize); // assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize);
// Read compressed block. // Read compressed block.
i = header.p_blocksize + OVERHEAD - size[1]; i = header.p_blocksize + OVERHEAD - h.sz_cpr;
if (xread(fdi, buf+i, size[1]) != 0) xread(&xi, buf+i, h.sz_cpr);
goto error;
// Decompress block. // Decompress block.
if (size[1] < size[0]) if (h.sz_cpr < h.sz_unc)
{ {
// in-place decompression // in-place decompression
nrv_uint out_len; nrv_uint out_len;
#if defined(NRV2B) i = (*f_decompress)(buf+i, h.sz_cpr, buf, &out_len);
i = nrv2b_decompress(buf+i, size[1], buf, &out_len); if (i != 0 || out_len != (nrv_uint)h.sz_unc)
#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])
goto error; goto error;
// i == 0 now // i == 0 now
} }
// Write uncompressed block. // 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 exit is here in the middle to keep the jumps short.
error: error:
@@ -396,7 +383,7 @@ void upx_main(char *argv[], char *envp[])
for (;;) for (;;)
(void) exit(127); (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) if (close(fdo) != 0)
goto error; goto error;
if (close(fdi) != 0)
goto error;
// //
+28 -30
View File
@@ -48,6 +48,9 @@
%endif %endif
%include "ident.ash"
; /************************************************************************* ; /*************************************************************************
; // program entry point ; // program entry point
; // see glibc/sysdeps/i386/elf/start.S ; // see glibc/sysdeps/i386/elf/start.S
@@ -57,41 +60,12 @@ GLOBAL _start
EXTERN upx_main EXTERN upx_main
_start: _start:
xor ebp, ebp ; Clear the frame pointer call main ; push &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
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"
; /************************************************************************* ; /*************************************************************************
; // C callable decompressor ; // 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 INP dword [esp+24+4]
%define INS dword [esp+24+8] %define INS dword [esp+24+8]
%define OUTP dword [esp+24+12] %define OUTP dword [esp+24+12]
@@ -144,5 +118,29 @@ decompress:
pop ebp pop ebp
ret 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 ; vi:ts=8:et:nowrap