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:
John Reiser
2001-01-18 05:45:25 +00:00
parent 4d45677160
commit df9db96bd1
30 changed files with 2014 additions and 1105 deletions
+86 -86
View File
@@ -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
*/