arm/pe: the assembly thumb mode decompressor is used in the stub
arm/pe: the C part of the stub is compiled as thumb committer: ml1050 <ml1050> 1143449862 +0000
This commit is contained in:
+31
-267
@@ -29,127 +29,20 @@
|
||||
<jreiser@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#define WRITEFILE(name0, buf, len) \
|
||||
do { short b[3]; b[0] = '\\'; b[1] = name0; b[2] = 0; \
|
||||
typedef int (*CF)(short *, int, int, int, int, int, int); CF cf = (CF) 0x1f99c58; \
|
||||
typedef void (*WF)(int, const void *, int, int *, int); WF wf = (WF) 0x1f99d60; \
|
||||
typedef void (*CH)(int); CH ch = (CH) 0x1f9a2f0; \
|
||||
int h = cf(b, 0x40000000L, 3, 0, 2, 0x80, 0);\
|
||||
int l; wf(h, buf, len, &l, 0); \
|
||||
ch(h); } while (0)
|
||||
int thumb_nrv2e_d8(const unsigned char * src, unsigned src_len,
|
||||
unsigned char * dst, unsigned * dst_len);
|
||||
#define ucl_nrv2e_decompress_8 thumb_nrv2e_d8
|
||||
|
||||
void *LoadLibraryW(const unsigned short *);
|
||||
void *GetProcAddressA(const void *, const void *);
|
||||
|
||||
typedef unsigned int ucl_uint32;
|
||||
typedef int ucl_int32;
|
||||
typedef unsigned int ucl_uint;
|
||||
typedef int ucl_int;
|
||||
|
||||
static int
|
||||
ucl_nrv2e_decompress_8 ( const unsigned char * src, ucl_uint src_len,
|
||||
unsigned char * dst, ucl_uint * dst_len)
|
||||
static void *get_le32(const unsigned char *p)
|
||||
{
|
||||
|
||||
{
|
||||
ucl_uint32 bb = 0;
|
||||
|
||||
|
||||
|
||||
ucl_uint ilen = 0, olen = 0, last_m_off = 1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ucl_uint m_off, m_len;
|
||||
|
||||
while ((((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1))
|
||||
{
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
dst[olen++] = src[ilen++];
|
||||
|
||||
}
|
||||
m_off = 1;
|
||||
for (;;)
|
||||
{
|
||||
m_off = m_off*2 + (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1);
|
||||
;
|
||||
;
|
||||
if ((((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)) break;
|
||||
m_off = (m_off-1)*2 + (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1);
|
||||
}
|
||||
if (m_off == 2)
|
||||
{
|
||||
m_off = last_m_off;
|
||||
m_len = (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
;
|
||||
m_off = (m_off-3)*256 + src[ilen++];
|
||||
if (m_off == ((0xffffffff) + 0U))
|
||||
break;
|
||||
m_len = (m_off ^ ((0xffffffff) + 0U)) & 1;
|
||||
m_off >>= 1;
|
||||
last_m_off = ++m_off;
|
||||
}
|
||||
if (m_len)
|
||||
m_len = 1 + (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1);
|
||||
else if ((((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1))
|
||||
m_len = 3 + (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1);
|
||||
else
|
||||
{
|
||||
m_len++;
|
||||
do {
|
||||
m_len = m_len*2 + (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1);
|
||||
;
|
||||
;
|
||||
} while (!(((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1));
|
||||
m_len += 3;
|
||||
}
|
||||
m_len += (m_off > 0x500);
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
const unsigned char * m_pos;
|
||||
m_pos = dst + olen - m_off;
|
||||
dst[olen++] = *m_pos++;
|
||||
do dst[olen++] = *m_pos++; while (--m_len > 0);
|
||||
}
|
||||
|
||||
}
|
||||
*dst_len = olen;
|
||||
return ilen == src_len ? 0 : (ilen < src_len ? (-205) : (-201));
|
||||
}
|
||||
return (void *) (p[0] + p[1] * 0x100 + p[2] * 0x10000 + p[3] * 0x1000000);
|
||||
}
|
||||
|
||||
typedef void *(*loadlibraryw)(unsigned short *);
|
||||
typedef void *(*getprocaddra)(void *, void *);
|
||||
|
||||
#define T(a,b,c,d) ((a) + ((b) * 0x100) + ((c) * 0x10000) + ((d) * 0x1000000))
|
||||
|
||||
static inline void *get_le32(unsigned char *p)
|
||||
{
|
||||
return (void*) T(p[0], p[1], p[2], p[3]);
|
||||
}
|
||||
|
||||
static void handle_imports(unsigned char *imp,
|
||||
unsigned name_offset,
|
||||
unsigned iat_offset,
|
||||
loadlibraryw ll,
|
||||
getprocaddra gpa)
|
||||
static void handle_imports(const unsigned char *imp, unsigned name_offset,
|
||||
unsigned iat_offset)
|
||||
{
|
||||
unsigned short buf[64];
|
||||
while (1)
|
||||
@@ -166,7 +59,7 @@ static void handle_imports(unsigned char *imp,
|
||||
*b = *name;
|
||||
*b = 0;
|
||||
|
||||
void *dll = ll(buf);
|
||||
void *dll = LoadLibraryW(buf);
|
||||
imp += 8;
|
||||
unsigned ord;
|
||||
|
||||
@@ -176,7 +69,7 @@ static void handle_imports(unsigned char *imp,
|
||||
{
|
||||
case 1:
|
||||
// by name
|
||||
*iat++ = (unsigned) gpa(dll, imp);
|
||||
*iat++ = (unsigned) GetProcAddressA(dll, imp);
|
||||
while (*imp++)
|
||||
;
|
||||
break;
|
||||
@@ -184,7 +77,7 @@ static void handle_imports(unsigned char *imp,
|
||||
// by ordinal
|
||||
ord = ((unsigned) imp[0]) + imp[1] * 0x100;
|
||||
imp += 2;
|
||||
*iat++ = (unsigned) gpa(dll, (void *) ord);
|
||||
*iat++ = (unsigned) GetProcAddressA(dll, (void *) ord);
|
||||
break;
|
||||
default:
|
||||
*(int*) 1 = 0;
|
||||
@@ -195,163 +88,34 @@ static void handle_imports(unsigned char *imp,
|
||||
}
|
||||
}
|
||||
|
||||
void upx_main(unsigned *info)
|
||||
// debugging stuff
|
||||
int CFWrap(short *, int, int, int, int, int, int);
|
||||
void WFwrap(int, const void *, int, int *, int);
|
||||
void CHWrap(int);
|
||||
#define WRITEFILE2(name0, buf, len) \
|
||||
do { short b[3]; b[0] = '\\'; b[1] = name0; b[2] = 0; \
|
||||
int h = CFwrap(b, 0x40000000L, 3, 0, 2, 0x80, 0);\
|
||||
int l; WFwrap(h, buf, len, &l, 0); \
|
||||
CHwrap(h); \
|
||||
} while (0)
|
||||
|
||||
|
||||
void upx_main(const unsigned *info)
|
||||
{
|
||||
int dlen = 0;
|
||||
unsigned src0 = *info++;
|
||||
unsigned srcl = *info++;
|
||||
unsigned dst0 = *info++;
|
||||
unsigned dstl = *info++;
|
||||
unsigned bimp = *info++;
|
||||
unsigned onam = *info++;
|
||||
unsigned getp = *info++;
|
||||
unsigned load = *info++;
|
||||
unsigned entr = *info++;
|
||||
unsigned srcl = *info++;
|
||||
unsigned dstl = *info++;
|
||||
|
||||
//WRITEFILE('1', (void*) 0x11000, load + 256 - 0x11000);
|
||||
//WRITEFILE2('0', (void*) 0x11000, load + 256 - 0x11000);
|
||||
ucl_nrv2e_decompress_8((void *) src0, srcl, (void *) dst0, &dlen);
|
||||
handle_imports((void *) bimp, onam, dst0, *(void**) load, *(void**) getp);
|
||||
//WRITEFILE('2', (void*) 0x11000, load + 256 - 0x11000);
|
||||
//WRITEFILE2('1', (void*) 0x11000, load + 256 - 0x11000);
|
||||
handle_imports((void *) bimp, onam, dst0);
|
||||
//WRITEFILE2('2', (void*) 0x11000, load + 256 - 0x11000);
|
||||
}
|
||||
|
||||
#ifndef __pe__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void *test_loadlibraryw(unsigned short *x)
|
||||
{
|
||||
printf("loadlibraryw called: ");
|
||||
while (*x)
|
||||
printf("%c", *x++);
|
||||
printf("\n");
|
||||
|
||||
static unsigned ret = 0x2a2a2a00;
|
||||
return (void*) ret++;
|
||||
}
|
||||
|
||||
static void *test_getprocaddra(void *a, void *x)
|
||||
{
|
||||
if ((unsigned) x < 0x10000)
|
||||
printf("getprocaddra called: %p %x\n", a, (unsigned) x);
|
||||
else
|
||||
printf("getprocaddra called: %p %s\n", a, (char*) x);
|
||||
|
||||
static unsigned ret = 1;
|
||||
return a + ret++;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
return printf("usage: %s <compressed.exe>\n", argv[0]);
|
||||
|
||||
void *mem = malloc(32*1024*1024);
|
||||
void *mem16m = (void*) ((((unsigned) mem) + 0xffffff) & 0xff000000);
|
||||
printf("mem: %p %p\n", mem, mem16m);
|
||||
|
||||
char command[100 + strlen(argv[1])];
|
||||
snprintf(command, sizeof(command),
|
||||
"arm-wince-pe-objdump -h '%s'|grep '2[*][*]2'", argv[1]);
|
||||
FILE *fp = popen(command, "r");
|
||||
if (fgets(command, 100, fp) == NULL)
|
||||
return printf("error while calling objdump\n");
|
||||
|
||||
unsigned start_uncompressed;
|
||||
if (sscanf(command, "%*d %*s %*x %x", &start_uncompressed) != 1)
|
||||
return printf("scanf failed on '%s'", command);
|
||||
printf("start_uncompressed=%x ", start_uncompressed);
|
||||
|
||||
if (fgets(command, 100, fp) == NULL)
|
||||
return printf("error while calling objdump\n");
|
||||
unsigned size;
|
||||
unsigned offset;
|
||||
unsigned vma;
|
||||
if (sscanf(command, "%*d %*s %x %x %*x %x", &size, &vma, &offset) != 3)
|
||||
return printf("scanf failed on '%s'" , command);
|
||||
printf("size=%x vma=%x offset=%x\n", size, vma, offset);
|
||||
|
||||
if (fgets(command, 100, fp) == NULL)
|
||||
return printf("error while calling objdump\n");
|
||||
|
||||
unsigned size2;
|
||||
unsigned offset2;
|
||||
unsigned vma2;
|
||||
if (sscanf(command, "%*d %*s %x %x %*x %x", &size2, &vma2, &offset2) != 3)
|
||||
return printf("scanf failed on '%s'" , command);
|
||||
printf("size2=%x vma2=%x offset2=%x\n", size2, vma2, offset2);
|
||||
|
||||
pclose(fp);
|
||||
|
||||
FILE *f1 = fopen(argv[1], "rb");
|
||||
if (f1 == NULL)
|
||||
return printf("can not open %s\n", argv[1]);
|
||||
if (fseek(f1, offset, SEEK_SET))
|
||||
return printf("fseek failed\n");
|
||||
if (fread(mem16m + vma, size, 1, f1) != 1)
|
||||
return printf("fread failed\n");
|
||||
if (fseek(f1, offset2, SEEK_SET))
|
||||
return printf("fseek failed\n");
|
||||
if (fread(mem16m + vma2, size2, 1, f1) != 1)
|
||||
return printf("fread failed\n");
|
||||
fclose(f1);
|
||||
|
||||
unsigned *info = (unsigned *) memmem(mem16m + vma, size, "XxxX", 4);
|
||||
if (info == NULL)
|
||||
return printf("decompression info not found\n");
|
||||
|
||||
info++;
|
||||
unsigned src0 = *info++;
|
||||
unsigned dst0 = *info++;
|
||||
unsigned bimp = *info++;
|
||||
unsigned onam = *info++;
|
||||
unsigned getp = *info++;
|
||||
unsigned load = *info++;
|
||||
unsigned entr = *info++;
|
||||
unsigned srcl = *info++;
|
||||
unsigned dstl = *info++;
|
||||
|
||||
printf("%x %x %x %x %x %x %x %x %x\n", src0, srcl, dst0, dstl, bimp, onam, load, getp, entr);
|
||||
|
||||
int dlen = 0;
|
||||
int ret = ucl_nrv2e_decompress_8(mem16m + src0, srcl, mem16m + dst0, &dlen);
|
||||
|
||||
printf("dlen=%x, ret=%d\n", dlen, ret);
|
||||
if (dlen != (int) dstl)
|
||||
return printf("corrupt compressed data\n");
|
||||
|
||||
f1 = fopen("/tmp/image.out", "w");
|
||||
fwrite(mem16m, vma + size + 0x10000, 1, f1);
|
||||
fclose(f1);
|
||||
|
||||
handle_imports(bimp + mem16m, onam + mem16m, dst0 + mem16m,
|
||||
test_loadlibraryw, test_getprocaddra);
|
||||
|
||||
f1 = fopen("/tmp/image.out", "w");
|
||||
fwrite(mem16m, vma2 + size2, 1, f1);
|
||||
fclose(f1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
int main(void)
|
||||
{
|
||||
FILE *f1 = fopen("/r", "w");
|
||||
int h = LoadLibraryW(L"coredll.dll");
|
||||
fprintf(f1, "%p\n", GetProcAddressA(h, "DeleteFileW"));
|
||||
fclose(f1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
typedef void (*df)(ushort *);
|
||||
df dfw = 0x1f99bc8;
|
||||
dfw(L"\\r");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user