pe32: refactoring of import handling and unpacking continues

This commit is contained in:
László Molnár 2014-02-16 23:04:39 +01:00
parent 96708d7592
commit 9cb639b505
6 changed files with 264 additions and 953 deletions

View File

@ -67,6 +67,7 @@ static const
#define OPTR_C(type, var, v) type* const var = (v)
#endif
#if 0
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
{
const char *pp = (const char *) p;
@ -74,7 +75,7 @@ static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
throwCantUnpack("pointer out of range; take care!");
}
#if 0
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
{
ACC_UNUSED(b);
@ -141,6 +142,10 @@ Linker* PackArmPe::newLinker() const
// import handling
**************************************************************************/
void PackArmPe::processImports(unsigned myimport, unsigned iat_off) // pass 2
{
PeFile::processImports(myimport, iat_off);
__packed_struct(import_desc)
LE32 oft; // orig first thunk
char _[8];
@ -148,293 +153,23 @@ __packed_struct(import_desc)
LE32 iat; // import address table
__packed_struct_end()
void PackArmPe::processImports(unsigned myimport, unsigned iat_off) // pass 2
{
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
// adjust import data
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
{
if (im->dllname < myimport)
im->dllname += myimport;
LE32 *p = (LE32*) (oimpdlls + im->iat);
im->iat += myimport;
im->oft = im->iat;
while (*p)
if ((*p++ & 0x80000000) == 0) // import by name?
p[-1] += myimport;
im->iat = im == (import_desc*) oimpdlls ? iat_off : iat_off + 12;
}
}
unsigned PackArmPe::processImports() // pass 1
void PackArmPe::addKernelImports()
{
static const unsigned char kernel32dll[] = "COREDLL.dll";
static const char llgpa[] = "\x0\x0""LoadLibraryW\x0\x0"
"GetProcAddressA\x0\x0\x0"
"CacheSync";
//static const char exitp[] = "ExitProcess\x0\x0\x0";
unsigned dllnum = 0;
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
import_desc * const im_save = im;
if (IDADDR(PEDIR_IMPORT))
{
while (im->dllname)
dllnum++, im++;
im = im_save;
}
struct udll
{
const upx_byte *name;
const upx_byte *shname;
unsigned ordinal;
unsigned iat;
LE32 *lookupt;
unsigned npos;
unsigned original_position;
bool isk32;
static int __acc_cdecl_qsort compare(const void *p1, const void *p2)
{
const udll *u1 = * (const udll * const *) p1;
const udll *u2 = * (const udll * const *) p2;
if (u1->isk32) return -1;
if (u2->isk32) return 1;
if (!*u1->lookupt) return 1;
if (!*u2->lookupt) return -1;
int rc = strcasecmp(u1->name,u2->name);
if (rc) return rc;
if (u1->ordinal) return -1;
if (u2->ordinal) return 1;
if (!u1->shname) return 1;
if (!u2->shname) return -1;
return strlen(u1->shname) - strlen(u2->shname);
}
};
// +1 for dllnum=0
Array(struct udll, dlls, dllnum+1);
Array(struct udll *, idlls, dllnum+1);
soimport = 1024; // safety
unsigned ic,k32o;
for (ic = k32o = 0; dllnum && im->dllname; ic++, im++)
{
idlls[ic] = dlls + ic;
dlls[ic].name = ibuf + im->dllname;
dlls[ic].shname = NULL;
dlls[ic].ordinal = 0;
dlls[ic].iat = im->iat;
dlls[ic].lookupt = (LE32*) (ibuf + (im->oft ? im->oft : im->iat));
dlls[ic].npos = 0;
dlls[ic].original_position = ic;
dlls[ic].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0;
soimport += strlen(dlls[ic].name) + 1 + 4;
for (IPTR_I(LE32, tarr, dlls[ic].lookupt); *tarr; tarr += 1)
{
if (*tarr & 0x80000000)
{
importbyordinal = true;
soimport += 2; // ordinal num: 2 bytes
dlls[ic].ordinal = *tarr & 0xffff;
//if (dlls[ic].isk32)
// kernel32ordinal = true,k32o++;
}
else
{
IPTR_I(const upx_byte, n, ibuf + *tarr + 2);
unsigned len = strlen(n);
soimport += len + 1;
if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname))
dlls[ic].shname = n;
}
soimport++; // separator
}
}
oimport = new upx_byte[soimport];
memset(oimport,0,soimport);
oimpdlls = new upx_byte[soimport];
memset(oimpdlls,0,soimport);
qsort(idlls,dllnum,sizeof (udll*),udll::compare);
unsigned dllnamelen = sizeof (kernel32dll);
unsigned dllnum2 = 1;
for (ic = 0; ic < dllnum; ic++)
if (!idlls[ic]->isk32 && (ic == 0 || strcasecmp(idlls[ic - 1]->name,idlls[ic]->name)))
{
dllnum2++;
dllnamelen += strlen(idlls[ic]->name) + 1;
}
//fprintf(stderr,"dllnum=%d dllnum2=%d soimport=%d\n",dllnum,dllnum2,soimport); //
info("Processing imports: %d DLLs", dllnum);
// create the new import table
im = (import_desc*) oimpdlls;
LE32 *ordinals = (LE32*) (oimpdlls + (dllnum2 + 1) * sizeof(import_desc));
LE32 *lookuptable = ordinals + 4;// + k32o + (isdll ? 0 : 1);
upx_byte *dllnames = ((upx_byte*) lookuptable) + (dllnum2 - 1) * 8;
upx_byte *importednames = dllnames + (dllnamelen &~ 1);
unsigned k32namepos = ptr_diff(dllnames,oimpdlls);
memcpy(importednames, llgpa, ALIGN_UP((unsigned) sizeof(llgpa), 2u));
strcpy(dllnames,kernel32dll);
im->dllname = k32namepos;
im->iat = ptr_diff(ordinals,oimpdlls);
*ordinals++ = ptr_diff(importednames,oimpdlls); // LoadLibraryW
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14; // GetProcAddressA
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 18; // CacheSync
dllnames += sizeof(kernel32dll);
importednames += sizeof(llgpa);
im++;
for (ic = 0; ic < dllnum; ic++)
if (idlls[ic]->isk32)
{
idlls[ic]->npos = k32namepos;
/*
if (idlls[ic]->ordinal)
for (LE32 *tarr = idlls[ic]->lookupt; *tarr; tarr++)
if (*tarr & 0x80000000)
*ordinals++ = *tarr;
*/
}
else if (ic && strcasecmp(idlls[ic-1]->name,idlls[ic]->name) == 0)
idlls[ic]->npos = idlls[ic-1]->npos;
else
{
im->dllname = idlls[ic]->npos = ptr_diff(dllnames,oimpdlls);
im->iat = ptr_diff(lookuptable,oimpdlls);
strcpy(dllnames,idlls[ic]->name);
dllnames += strlen(idlls[ic]->name)+1;
if (idlls[ic]->ordinal)
*lookuptable = idlls[ic]->ordinal + 0x80000000;
else if (idlls[ic]->shname)
{
if (ptr_diff(importednames,oimpdlls) & 1)
importednames--;
*lookuptable = ptr_diff(importednames,oimpdlls);
importednames += 2;
strcpy(importednames,idlls[ic]->shname);
importednames += strlen(idlls[ic]->shname) + 1;
}
lookuptable += 2;
im++;
}
soimpdlls = ALIGN_UP(ptr_diff(importednames,oimpdlls),4);
Interval names(ibuf),iats(ibuf),lookups(ibuf);
// create the preprocessed data
//ordinals -= k32o;
upx_byte *ppi = oimport; // preprocessed imports
for (ic = 0; ic < dllnum; ic++)
{
LE32 *tarr = idlls[ic]->lookupt;
#if 0 && ENABLE_THIS_AND_UNCOMPRESSION_WILL_BREAK
if (!*tarr) // no imports from this dll
continue;
#endif
set_le32(ppi,idlls[ic]->npos);
set_le32(ppi+4,idlls[ic]->iat - rvamin);
ppi += 8;
for (; *tarr; tarr++)
if (*tarr & 0x80000000)
{
/*if (idlls[ic]->isk32)
{
*ppi++ = 0xfe; // signed + odd parity
set_le32(ppi,ptr_diff(ordinals,oimpdlls));
ordinals++;
ppi += 4;
}
else*/
{
*ppi++ = 0xff;
set_le16(ppi,*tarr & 0xffff);
ppi += 2;
}
}
else
{
*ppi++ = 1;
unsigned len = strlen(ibuf + *tarr + 2) + 1;
memcpy(ppi,ibuf + *tarr + 2,len);
ppi += len;
names.add(*tarr,len + 2 + 1);
}
ppi++;
unsigned esize = ptr_diff((char *)tarr, (char *)idlls[ic]->lookupt);
lookups.add(idlls[ic]->lookupt,esize);
if (ptr_diff(ibuf + idlls[ic]->iat, (char *)idlls[ic]->lookupt))
{
memcpy(ibuf + idlls[ic]->iat, idlls[ic]->lookupt, esize);
iats.add(idlls[ic]->iat,esize);
}
names.add(idlls[ic]->name,strlen(idlls[ic]->name) + 1 + 1);
}
ppi += 4;
assert(ppi < oimport+soimport);
soimport = ptr_diff(ppi,oimport);
if (soimport == 4)
soimport = 0;
//OutputFile::dump("x0.imp", oimport, soimport);
//OutputFile::dump("x1.imp", oimpdlls, soimpdlls);
unsigned ilen = 0;
names.flatten();
if (names.ivnum > 1)
{
// The area occupied by the dll and imported names is not continuous
// so to still support uncompression, I can't zero the iat area.
// This decreases compression ratio, so FIXME somehow.
infoWarning("can't remove unneeded imports");
ilen += sizeof(import_desc) * dllnum;
#if defined(DEBUG)
if (opt->verbose > 3)
names.dump();
#endif
// do some work for the unpacker
im = im_save;
for (ic = 0; ic < dllnum; ic++, im++)
{
memset(im,FILLVAL,sizeof(*im));
im->dllname = ptr_diff(dlls[idlls[ic]->original_position].name,ibuf);
}
}
else
{
iats.add(im_save,sizeof(import_desc) * dllnum);
// zero unneeded data
iats.clear();
lookups.clear();
}
names.clear();
iats.add(&names);
iats.add(&lookups);
iats.flatten();
for (ic = 0; ic < iats.ivnum; ic++)
ilen += iats.ivarr[ic].len;
info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport);
return names.ivnum == 1 ? names.ivarr[0].start : 0;
addKernelImport("COREDLL.DLL", "LoadLibraryW");
addKernelImport("COREDLL.DLL", "GetProcAddressA");
addKernelImport("COREDLL.DLL", "CacheSync");
}
void PackArmPe::processTls(Interval *) // pass 1
{
if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4u)) == 0)
@ -628,7 +363,7 @@ void PackArmPe::pack(OutputFile *fo)
Interval tlsiv(ibuf);
Export xport((char*)(unsigned char*)ibuf);
const unsigned dllstrings = processImports();
const unsigned dllstrings = PeFile32::processImports();
processTls(&tlsiv); // call before processRelocs!!
processResources(&res);
processExports(&xport);
@ -1029,117 +764,6 @@ int PackArmPe::canUnpack()
return false;
}
void PackArmPe::rebuildImports(upx_byte *& extrainfo)
{
if (ODADDR(PEDIR_IMPORT) == 0
|| ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc))
return;
// const upx_byte * const idata = obuf + get_le32(extrainfo);
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo));
const unsigned inamespos = get_le32(extrainfo + 4);
extrainfo += 8;
unsigned sdllnames = 0;
// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr;
// const upx_byte *p;
IPTR_I(const upx_byte, import, ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
OPTR(const upx_byte, p);
for (p = idata; get_le32(p) != 0; ++p)
{
const upx_byte *dname = get_le32(p) + import;
ICHECK(dname, 1);
const unsigned dlen = strlen(dname);
ICHECK(dname, dlen + 1);
sdllnames += dlen + 1;
for (p += 8; *p;)
if (*p == 1)
p += strlen(++p) + 1;
else if (*p == 0xff)
p += 3; // ordinal
else
p += 5;
}
sdllnames = ALIGN_UP(sdllnames,2u);
upx_byte * const Obuf = obuf - rvamin;
import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT));
import_desc *im = im0;
upx_byte *dllnames = Obuf + inamespos;
upx_byte *importednames = dllnames + sdllnames;
upx_byte * const importednames_start = importednames;
for (p = idata; get_le32(p) != 0; ++p)
{
// restore the name of the dll
const upx_byte *dname = get_le32(p) + import;
ICHECK(dname, 1);
const unsigned dlen = strlen(dname);
ICHECK(dname, dlen + 1);
const unsigned iatoffs = get_le32(p + 4) + rvamin;
if (inamespos)
{
// now I rebuild the dll names
OCHECK(dllnames, dlen + 1);
strcpy(dllnames, dname);
im->dllname = ptr_diff(dllnames,Obuf);
//;;;printf("\ndll: %s:",dllnames);
dllnames += dlen + 1;
}
else
{
OCHECK(Obuf + im->dllname, dlen + 1);
strcpy(Obuf + im->dllname, dname);
}
im->oft = im->iat = iatoffs;
// LE32 *newiat = (LE32 *) (Obuf + iatoffs);
OPTR_I(LE32, newiat, (LE32 *) (Obuf + iatoffs));
// restore the imported names+ordinals
for (p += 8; *p; ++newiat)
if (*p == 1)
{
const unsigned ilen = strlen(++p) + 1;
if (inamespos)
{
if (ptr_diff(importednames, importednames_start) & 1)
importednames -= 1;
omemcpy(importednames + 2, p, ilen);
//;;;printf(" %s",importednames+2);
*newiat = ptr_diff(importednames, Obuf);
importednames += 2 + ilen;
}
else
{
OCHECK(Obuf + *newiat + 2, ilen + 1);
strcpy(Obuf + *newiat + 2, p);
}
p += ilen;
}
else if (*p == 0xff)
{
*newiat = get_le16(p + 1) + 0x80000000;
//;;;printf(" %x",(unsigned)*newiat);
p += 3;
}
else
{
*newiat = get_le32(get_le32(p + 1) + import);
assert(*newiat & 0x80000000);
p += 5;
}
*newiat = 0;
im++;
}
//memset(idata,0,p - idata);
}
/*
vi:ts=4:et
*/

View File

@ -56,9 +56,8 @@ protected:
virtual void buildLoader(const Filter *ft);
virtual Linker* newLinker() const;
virtual unsigned processImports();
virtual void processImports(unsigned, unsigned);
virtual void rebuildImports(upx_byte *&);
virtual void addKernelImports();
virtual void processTls(Interval *);

View File

@ -49,7 +49,7 @@ static const
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
#endif
#if 1
#if 0
//static
unsigned my_strlen(const char *s)
{
@ -81,6 +81,7 @@ static unsigned my_strlen(const unsigned char *s)
#define OPTR_C(type, var, v) type* const var = (v)
#endif
#if 0
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
{
const char *pp = (const char *) p;
@ -88,7 +89,6 @@ static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
throwCantUnpack("pointer out of range; take care!");
}
#if 0
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
{
ACC_UNUSED(b);
@ -299,307 +299,6 @@ void PackW32Pe::processTls(Reloc *rel,const Interval *iv,unsigned newaddr) // pa
}
}
/*************************************************************************
// import handling
**************************************************************************/
__packed_struct(import_desc)
LE32 oft; // orig first thunk
char _[8];
LE32 dllname;
LE32 iat; // import address table
__packed_struct_end()
void PackW32Pe::processImports(unsigned myimport, unsigned) // pass 2
{
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
// adjust import data
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
{
if (im->dllname < myimport)
im->dllname += myimport;
LE32 *p = (LE32*) (oimpdlls + im->iat);
im->iat += myimport;
while (*p)
if ((*p++ & 0x80000000) == 0) // import by name?
p[-1] += myimport;
}
}
unsigned PackW32Pe::processImports() // pass 1
{
static const unsigned char kernel32dll[] = "KERNEL32.DLL";
static const char llgpa[] = "\x0\x0""LoadLibraryA\x0\x0"
"GetProcAddress\x0\x0"
"VirtualProtect\x0\x0"
"VirtualAlloc\x0\x0"
"VirtualFree\x0\x0\x0";
static const char exitp[] = "ExitProcess\x0\x0\x0";
unsigned dllnum = 0;
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
import_desc * const im_save = im;
if (IDADDR(PEDIR_IMPORT))
{
while (im->dllname)
dllnum++, im++;
im = im_save;
}
struct udll
{
const upx_byte *name;
const upx_byte *shname;
unsigned ordinal;
unsigned iat;
LE32 *lookupt;
unsigned npos;
unsigned original_position;
bool isk32;
static int __acc_cdecl_qsort compare(const void *p1, const void *p2)
{
const udll *u1 = * (const udll * const *) p1;
const udll *u2 = * (const udll * const *) p2;
if (u1->isk32) return -1;
if (u2->isk32) return 1;
if (!*u1->lookupt) return 1;
if (!*u2->lookupt) return -1;
int rc = strcasecmp(u1->name,u2->name);
if (rc) return rc;
if (u1->ordinal) return -1;
if (u2->ordinal) return 1;
if (!u1->shname) return 1;
if (!u2->shname) return -1;
return strlen(u1->shname) - strlen(u2->shname);
}
};
// +1 for dllnum=0
Array(struct udll, dlls, dllnum+1);
Array(struct udll *, idlls, dllnum+1);
soimport = 1024; // safety
unsigned ic,k32o;
for (ic = k32o = 0; dllnum && im->dllname; ic++, im++)
{
idlls[ic] = dlls + ic;
dlls[ic].name = ibuf + im->dllname;
dlls[ic].shname = NULL;
dlls[ic].ordinal = 0;
dlls[ic].iat = im->iat;
dlls[ic].lookupt = (LE32*) (ibuf + (im->oft ? im->oft : im->iat));
dlls[ic].npos = 0;
dlls[ic].original_position = ic;
dlls[ic].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0;
soimport += strlen(dlls[ic].name) + 1 + 4;
for (IPTR_I(LE32, tarr, dlls[ic].lookupt); *tarr; tarr += 1)
{
if (*tarr & 0x80000000)
{
importbyordinal = true;
soimport += 2; // ordinal num: 2 bytes
dlls[ic].ordinal = *tarr & 0xffff;
if (dlls[ic].isk32)
kernel32ordinal = true,k32o++;
}
else
{
IPTR_I(const upx_byte, n, ibuf + *tarr + 2);
unsigned len = strlen(n);
soimport += len + 1;
if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname))
dlls[ic].shname = n;
}
soimport++; // separator
}
}
oimport = new upx_byte[soimport];
memset(oimport,0,soimport);
oimpdlls = new upx_byte[soimport];
memset(oimpdlls,0,soimport);
qsort(idlls,dllnum,sizeof (udll*),udll::compare);
unsigned dllnamelen = sizeof (kernel32dll);
unsigned dllnum2 = 1;
for (ic = 0; ic < dllnum; ic++)
if (!idlls[ic]->isk32 && (ic == 0 || strcasecmp(idlls[ic - 1]->name,idlls[ic]->name)))
{
dllnum2++;
dllnamelen += strlen(idlls[ic]->name) + 1;
}
//fprintf(stderr,"dllnum=%d dllnum2=%d soimport=%d\n",dllnum,dllnum2,soimport); //
info("Processing imports: %d DLLs", dllnum);
// create the new import table
im = (import_desc*) oimpdlls;
LE32 *ordinals = (LE32*) (oimpdlls + (dllnum2 + 1) * sizeof(import_desc));
LE32 *lookuptable = ordinals + 6 + k32o + (isdll ? 0 : 1);
upx_byte *dllnames = ((upx_byte*) lookuptable) + (dllnum2 - 1) * 8;
upx_byte *importednames = dllnames + (dllnamelen &~ 1);
unsigned k32namepos = ptr_diff(dllnames,oimpdlls);
memcpy(importednames, llgpa, sizeof(llgpa));
if (!isdll)
memcpy(importednames + sizeof(llgpa) - 1, exitp, sizeof(exitp));
strcpy(dllnames,kernel32dll);
im->dllname = k32namepos;
im->iat = ptr_diff(ordinals,oimpdlls);
*ordinals++ = ptr_diff(importednames,oimpdlls); // LoadLibraryA
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14; // GetProcAddress
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 16; // VirtualProtect
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 16 + 16; // VirtualAlloc
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 16 + 16 + 14; // VirtualFree
if (!isdll)
*ordinals++ = ptr_diff(importednames,oimpdlls) + sizeof(llgpa) - 3; // ExitProcess
dllnames += sizeof(kernel32dll);
importednames += sizeof(llgpa) - 2 + (isdll ? 0 : sizeof(exitp) - 1);
im++;
for (ic = 0; ic < dllnum; ic++)
if (idlls[ic]->isk32)
{
idlls[ic]->npos = k32namepos;
if (idlls[ic]->ordinal)
for (LE32 *tarr = idlls[ic]->lookupt; *tarr; tarr++)
if (*tarr & 0x80000000)
*ordinals++ = *tarr;
}
else if (ic && strcasecmp(idlls[ic-1]->name,idlls[ic]->name) == 0)
idlls[ic]->npos = idlls[ic-1]->npos;
else
{
im->dllname = idlls[ic]->npos = ptr_diff(dllnames,oimpdlls);
im->iat = ptr_diff(lookuptable,oimpdlls);
strcpy(dllnames,idlls[ic]->name);
dllnames += strlen(idlls[ic]->name)+1;
if (idlls[ic]->ordinal)
*lookuptable = idlls[ic]->ordinal + 0x80000000;
else if (idlls[ic]->shname)
{
if (ptr_diff(importednames,oimpdlls) & 1)
importednames--;
*lookuptable = ptr_diff(importednames,oimpdlls);
importednames += 2;
strcpy(importednames,idlls[ic]->shname);
importednames += strlen(idlls[ic]->shname) + 1;
}
lookuptable += 2;
im++;
}
soimpdlls = ALIGN_UP(ptr_diff(importednames,oimpdlls),4);
Interval names(ibuf),iats(ibuf),lookups(ibuf);
// create the preprocessed data
ordinals -= k32o;
upx_byte *ppi = oimport; // preprocessed imports
for (ic = 0; ic < dllnum; ic++)
{
LE32 *tarr = idlls[ic]->lookupt;
#if 0 && ENABLE_THIS_AND_UNCOMPRESSION_WILL_BREAK
if (!*tarr) // no imports from this dll
continue;
#endif
set_le32(ppi,idlls[ic]->npos);
set_le32(ppi+4,idlls[ic]->iat - rvamin);
ppi += 8;
for (; *tarr; tarr++)
if (*tarr & 0x80000000)
{
if (idlls[ic]->isk32)
{
*ppi++ = 0xfe; // signed + odd parity
set_le32(ppi,ptr_diff(ordinals,oimpdlls));
ordinals++;
ppi += 4;
}
else
{
*ppi++ = 0xff;
set_le16(ppi,*tarr & 0xffff);
ppi += 2;
}
}
else
{
*ppi++ = 1;
unsigned len = strlen(ibuf + *tarr + 2) + 1;
memcpy(ppi,ibuf + *tarr + 2,len);
ppi += len;
names.add(*tarr,len + 2 + 1);
}
ppi++;
unsigned esize = ptr_diff((char *)tarr, (char *)idlls[ic]->lookupt);
lookups.add(idlls[ic]->lookupt,esize);
if (ptr_diff(ibuf + idlls[ic]->iat, (char *)idlls[ic]->lookupt))
{
memcpy(ibuf + idlls[ic]->iat, idlls[ic]->lookupt, esize);
iats.add(idlls[ic]->iat,esize);
}
names.add(idlls[ic]->name,strlen(idlls[ic]->name) + 1 + 1);
}
ppi += 4;
assert(ppi < oimport+soimport);
soimport = ptr_diff(ppi,oimport);
if (soimport == 4)
soimport = 0;
//OutputFile::dump("x0.imp", oimport, soimport);
//OutputFile::dump("x1.imp", oimpdlls, soimpdlls);
unsigned ilen = 0;
names.flatten();
if (names.ivnum > 1)
{
// The area occupied by the dll and imported names is not continuous
// so to still support uncompression, I can't zero the iat area.
// This decreases compression ratio, so FIXME somehow.
infoWarning("can't remove unneeded imports");
ilen += sizeof(import_desc) * dllnum;
#if defined(DEBUG)
if (opt->verbose > 3)
names.dump();
#endif
// do some work for the unpacker
im = im_save;
for (ic = 0; ic < dllnum; ic++, im++)
{
memset(im,FILLVAL,sizeof(*im));
im->dllname = ptr_diff(dlls[idlls[ic]->original_position].name,ibuf);
}
}
else
{
iats.add(im_save,sizeof(import_desc) * dllnum);
// zero unneeded data
iats.clear();
lookups.clear();
}
names.clear();
iats.add(&names);
iats.add(&lookups);
iats.flatten();
for (ic = 0; ic < iats.ivnum; ic++)
ilen += iats.ivarr[ic].len;
info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport);
return names.ivnum == 1 ? names.ivarr[0].start : 0;
}
/*************************************************************************
// Load Configuration handling
**************************************************************************/
@ -1204,7 +903,7 @@ void PackW32Pe::pack(OutputFile *fo)
ODSIZE(PEDIR_RESOURCE) = soresources;
ic += soresources;
processImports(ic, 0);
PeFile::processImports(ic, 0);
ODADDR(PEDIR_IMPORT) = ic;
ODSIZE(PEDIR_IMPORT) = soimpdlls;
ic += soimpdlls;
@ -1411,117 +1110,6 @@ int PackW32Pe::canUnpack()
return false;
}
void PackW32Pe::rebuildImports(upx_byte *& extrainfo)
{
if (ODADDR(PEDIR_IMPORT) == 0
|| ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc))
return;
// const upx_byte * const idata = obuf + get_le32(extrainfo);
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo));
const unsigned inamespos = get_le32(extrainfo + 4);
extrainfo += 8;
unsigned sdllnames = 0;
// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr;
// const upx_byte *p;
IPTR_I(const upx_byte, import, ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
OPTR(const upx_byte, p);
for (p = idata; get_le32(p) != 0; ++p)
{
const upx_byte *dname = get_le32(p) + import;
ICHECK(dname, 1);
const unsigned dlen = strlen(dname);
ICHECK(dname, dlen + 1);
sdllnames += dlen + 1;
for (p += 8; *p;)
if (*p == 1)
p += strlen(++p) + 1;
else if (*p == 0xff)
p += 3; // ordinal
else
p += 5;
}
sdllnames = ALIGN_UP(sdllnames, 2u);
upx_byte * const Obuf = obuf - rvamin;
import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT));
import_desc *im = im0;
upx_byte *dllnames = Obuf + inamespos;
upx_byte *importednames = dllnames + sdllnames;
upx_byte * const importednames_start = importednames;
for (p = idata; get_le32(p) != 0; ++p)
{
// restore the name of the dll
const upx_byte *dname = get_le32(p) + import;
ICHECK(dname, 1);
const unsigned dlen = strlen(dname);
ICHECK(dname, dlen + 1);
const unsigned iatoffs = get_le32(p + 4) + rvamin;
if (inamespos)
{
// now I rebuild the dll names
OCHECK(dllnames, dlen + 1);
strcpy(dllnames, dname);
im->dllname = ptr_diff(dllnames,Obuf);
//;;;printf("\ndll: %s:",dllnames);
dllnames += dlen + 1;
}
else
{
OCHECK(Obuf + im->dllname, dlen + 1);
strcpy(Obuf + im->dllname, dname);
}
im->iat = iatoffs;
// LE32 *newiat = (LE32 *) (Obuf + iatoffs);
OPTR_I(LE32, newiat, (LE32 *) (Obuf + iatoffs));
// restore the imported names+ordinals
for (p += 8; *p; ++newiat)
if (*p == 1)
{
const unsigned ilen = strlen(++p) + 1;
if (inamespos)
{
if (ptr_diff(importednames, importednames_start) & 1)
importednames -= 1;
omemcpy(importednames + 2, p, ilen);
//;;;printf(" %s",importednames+2);
*newiat = ptr_diff(importednames, Obuf);
importednames += 2 + ilen;
}
else
{
OCHECK(Obuf + *newiat + 2, ilen + 1);
strcpy(Obuf + *newiat + 2, p);
}
p += ilen;
}
else if (*p == 0xff)
{
*newiat = get_le16(p + 1) + 0x80000000;
//;;;printf(" %x",(unsigned)*newiat);
p += 3;
}
else
{
*newiat = get_le32(get_le32(p + 1) + import);
assert(*newiat & 0x80000000);
p += 5;
}
*newiat = 0;
im++;
}
//memset(idata,0,p - idata);
}
/*
extra info added to help uncompression:

View File

@ -58,10 +58,6 @@ protected:
virtual void buildLoader(const Filter *ft);
virtual Linker* newLinker() const;
virtual unsigned processImports();
virtual void processImports(unsigned, unsigned);
virtual void rebuildImports(upx_byte *&);
virtual void processTls(Interval *); //NEW: TLS callback handling - Stefan Widmann
void processTls(Reloc *, const Interval *, unsigned); //NEW: TLS callback handling - Stefan Widmann

View File

@ -44,6 +44,20 @@
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
#endif
#if 1
//static
unsigned my_strlen(const char *s)
{
size_t l = strlen((const char*)s); assert((unsigned) l == l); return (unsigned) l;
}
static unsigned my_strlen(const unsigned char *s)
{
size_t l = strlen((const char*)s); assert((unsigned) l == l); return (unsigned) l;
}
#undef strlen
#define strlen my_strlen
#endif
#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)
#include "bptr.h"
#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
@ -531,12 +545,12 @@ class PeFile::ImportLinker : public ElfLinkerAMD64
unsigned len = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
tstr dlln(name_for_dll(dll, first_char));
char *procn = new char[len];
snprintf(procn, len - 1, "%s%c", (const char*) dlln, separator);
upx_snprintf(procn, len - 1, "%s%c", (const char*) dlln, separator);
encode_name(proc, procn + strlen(procn));
return procn;
}
static char zeros[sizeof(import_desc)];
static const char zeros[sizeof(import_desc)];
enum {
// the order of identifiers is very important below!!
@ -635,15 +649,18 @@ public:
template <typename C>
void add(const C *dll, unsigned ordinal)
{
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "unsigned char"
assert(ordinal > 0 && ordinal < 0x10000);
char ord[20];
snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
char ord[1+5+1];
upx_snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
add((const char*) dll, ord, ordinal);
}
template <typename C1, typename C2>
void add(const C1 *dll, const C2 *proc)
{
ACC_COMPILE_TIME_ASSERT(sizeof(C1) == 1) // "char" or "unsigned char"
ACC_COMPILE_TIME_ASSERT(sizeof(C2) == 1) // "char" or "unsigned char"
assert(proc);
add((const char*) dll, (const char*) proc, 0);
}
@ -680,6 +697,8 @@ public:
template <typename C1, typename C2>
upx_uint64_t getAddress(const C1 *dll, const C2 *proc) const
{
ACC_COMPILE_TIME_ASSERT(sizeof(C1) == 1) // "char" or "unsigned char"
ACC_COMPILE_TIME_ASSERT(sizeof(C2) == 1) // "char" or "unsigned char"
const Section *s = getThunk((const char*) dll, (const char*) proc,
thunk_separator_first);
if (s == NULL && (s = getThunk((const char*) dll,(const char*) proc,
@ -688,12 +707,13 @@ public:
return s->offset;
}
template <typename C1>
upx_uint64_t getAddress(const C1 *dll, unsigned ordinal) const
template <typename C>
upx_uint64_t getAddress(const C *dll, unsigned ordinal) const
{
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "unsigned char"
assert(ordinal > 0 && ordinal < 0x10000);
char ord[20];
snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
char ord[1+5+1];
upx_snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
const Section *s = getThunk((const char*) dll, ord, thunk_separator_first);
if (s == NULL
@ -702,56 +722,45 @@ public:
return s->offset;
}
template <typename C1>
upx_uint64_t getAddress(const C1 *dll) const
template <typename C>
upx_uint64_t getAddress(const C *dll) const
{
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "unsigned char"
tstr sdll(name_for_dll((const char*) dll, dll_name_id));
return findSection(sdll, true)->offset;
}
};
char PeFile::ImportLinker::zeros[sizeof(import_desc)];
const char PeFile::ImportLinker::zeros[sizeof(import_desc)] = { 0 };
#if 0
/*************************************************************************
// import handling
**************************************************************************/
__packed_struct(import_desc)
LE32 oft; // orig first thunk
char _[8];
LE32 dllname;
LE32 iat; // import address table
__packed_struct_end()
void PeFile::processImports(unsigned myimport, unsigned iat_off) // pass 2
void PeFile::addKernelImport(const char *dll, const char *name)
{
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20)
COMPILE_TIME_ASSERT_ALIGNED1(import_desc)
// adjust import data
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
{
if (im->dllname < myimport)
im->dllname += myimport;
LE32 *p = (LE32*) (oimpdlls + im->iat);
im->iat += myimport;
im->oft = im->iat;
while (*p)
if ((*p++ & 0x80000000) == 0) // import by name?
p[-1] += myimport;
im->iat = im == (import_desc*) oimpdlls ? iat_off : iat_off + 12;
}
ilinker->add(dll, name);
}
unsigned PeFile::processImports() // pass 1
void PeFile::addKernelImports()
{
static const unsigned char kernel32dll[] = "COREDLL.dll";
static const char llgpa[] = "\x0\x0""LoadLibraryW\x0\x0"
"GetProcAddressA\x0\x0\x0"
"CacheSync";
//static const char exitp[] = "ExitProcess\x0\x0\x0";
addKernelImport("KERNEL32.DLL", "LoadLibraryA");
addKernelImport("KERNEL32.DLL", "GetProcAddress");
if (!isdll)
addKernelImport("KERNEL32.DLL", "ExitProcess");
addKernelImport("KERNEL32.DLL", "VirtualProtect");
}
void PeFile::processImports(unsigned myimport, unsigned) // pass 2
{
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
ilinker->relocate(myimport);
int len;
oimpdlls = ilinker->getLoader(&len);
assert(len == (int) soimpdlls);
//OutputFile::dump("x1.imp", oimpdlls, soimpdlls);
}
template <typename LEXX, typename ord_mask_t>
unsigned PeFile::processImports(ord_mask_t ord_mask) // pass 1
{
static const unsigned char kernel32dll[] = "KERNEL32.DLL";
unsigned dllnum = 0;
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
@ -769,8 +778,8 @@ unsigned PeFile::processImports() // pass 1
const upx_byte *shname;
unsigned ordinal;
unsigned iat;
LE32 *lookupt;
unsigned npos;
LEXX *lookupt;
unsigned original_position;
bool isk32;
static int __acc_cdecl_qsort compare(const void *p1, const void *p2)
@ -779,6 +788,8 @@ unsigned PeFile::processImports() // pass 1
const udll *u2 = * (const udll * const *) p2;
if (u1->isk32) return -1;
if (u2->isk32) return 1;
if (!*u1->lookupt) return 1;
if (!*u2->lookupt) return -1;
int rc = strcasecmp(u1->name,u2->name);
if (rc) return rc;
if (u1->ordinal) return -1;
@ -795,33 +806,32 @@ unsigned PeFile::processImports() // pass 1
soimport = 1024; // safety
unsigned ic,k32o;
for (ic = k32o = 0; dllnum && im->dllname; ic++, im++)
unsigned ic;
for (ic = 0; dllnum && im->dllname; ic++, im++)
{
idlls[ic] = dlls + ic;
dlls[ic].name = ibuf + im->dllname;
dlls[ic].shname = NULL;
dlls[ic].ordinal = 0;
dlls[ic].iat = im->iat;
dlls[ic].lookupt = (LE32*) (ibuf + (im->oft ? im->oft : im->iat));
dlls[ic].npos = 0;
dlls[ic].lookupt = (LEXX*) (ibuf + (im->oft ? im->oft : im->iat));
dlls[ic].original_position = ic;
dlls[ic].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0;
soimport += strlen(dlls[ic].name) + 1 + 4;
for (LE32 *tarr = dlls[ic].lookupt; *tarr; tarr++)
for (IPTR_I(LEXX, tarr, dlls[ic].lookupt); *tarr; tarr += 1)
{
if (*tarr & 0x80000000)
if (*tarr & ord_mask)
{
importbyordinal = true;
soimport += 2; // ordinal num: 2 bytes
dlls[ic].ordinal = *tarr & 0xffff;
//if (dlls[ic].isk32)
// kernel32ordinal = true,k32o++;
}
else
else //it's an import by name
{
unsigned len = strlen(ibuf + *tarr + 2);
IPTR_I(const upx_byte, n, ibuf + *tarr + 2);
unsigned len = strlen(n);
soimport += len + 1;
if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname))
dlls[ic].shname = ibuf + *tarr + 2;
@ -831,106 +841,70 @@ unsigned PeFile::processImports() // pass 1
}
oimport = new upx_byte[soimport];
memset(oimport,0,soimport);
oimpdlls = new upx_byte[soimport];
memset(oimpdlls,0,soimport);
qsort(idlls,dllnum,sizeof (udll*),udll::compare);
unsigned dllnamelen = sizeof (kernel32dll);
unsigned dllnum2 = 1;
for (ic = 0; ic < dllnum; ic++)
if (!idlls[ic]->isk32 && (ic == 0 || strcasecmp(idlls[ic - 1]->name,idlls[ic]->name)))
{
dllnum2++;
dllnamelen += strlen(idlls[ic]->name) + 1;
}
//fprintf(stderr,"dllnum=%d dllnum2=%d soimport=%d\n",dllnum,dllnum2,soimport); //
info("Processing imports: %d DLLs", dllnum);
// create the new import table
im = (import_desc*) oimpdlls;
addKernelImports();
LE32 *ordinals = (LE32*) (oimpdlls + (dllnum2 + 1) * sizeof(import_desc));
LE32 *lookuptable = ordinals + 4;// + k32o + (isdll ? 0 : 1);
upx_byte *dllnames = ((upx_byte*) lookuptable) + (dllnum2 - 1) * 8;
upx_byte *importednames = dllnames + (dllnamelen &~ 1);
unsigned k32namepos = ptr_diff(dllnames,oimpdlls);
memcpy(importednames, llgpa, ALIGN_UP((unsigned) sizeof(llgpa), 2u));
strcpy(dllnames,kernel32dll);
im->dllname = k32namepos;
im->iat = ptr_diff(ordinals,oimpdlls);
*ordinals++ = ptr_diff(importednames,oimpdlls); // LoadLibraryW
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14; // GetProcAddressA
*ordinals++ = ptr_diff(importednames,oimpdlls) + 14 + 18; // CacheSync
dllnames += sizeof(kernel32dll);
importednames += sizeof(llgpa);
im++;
for (ic = 0; ic < dllnum; ic++)
{
if (idlls[ic]->isk32)
{
idlls[ic]->npos = k32namepos;
/*
// for kernel32.dll we need to put all the imported
// ordinals into the output import table, as on
// some versions of windows GetProcAddress does not resolve them
if (idlls[ic]->ordinal)
for (LE32 *tarr = idlls[ic]->lookupt; *tarr; tarr++)
if (*tarr & 0x80000000)
*ordinals++ = *tarr;
*/
for (LEXX *tarr = idlls[ic]->lookupt; *tarr; tarr++)
if (*tarr & ord_mask)
{
ilinker->add(kernel32dll, *tarr & 0xffff);
kernel32ordinal = true;
}
}
else if (ic && strcasecmp(idlls[ic-1]->name,idlls[ic]->name) == 0)
idlls[ic]->npos = idlls[ic-1]->npos;
else
{
im->dllname = idlls[ic]->npos = ptr_diff(dllnames,oimpdlls);
im->iat = ptr_diff(lookuptable,oimpdlls);
strcpy(dllnames,idlls[ic]->name);
dllnames += strlen(idlls[ic]->name)+1;
if (idlls[ic]->ordinal)
*lookuptable = idlls[ic]->ordinal + 0x80000000;
ilinker->add(idlls[ic]->name, idlls[ic]->ordinal);
else if (idlls[ic]->shname)
{
if (ptr_diff(importednames,oimpdlls) & 1)
importednames--;
*lookuptable = ptr_diff(importednames,oimpdlls);
importednames += 2;
strcpy(importednames,idlls[ic]->shname);
importednames += strlen(idlls[ic]->shname) + 1;
}
lookuptable += 2;
im++;
ilinker->add(idlls[ic]->name, idlls[ic]->shname);
else
throwInternalError("should not happen");
}
soimpdlls = ALIGN_UP(ptr_diff(importednames,oimpdlls),4);
}
soimpdlls = ilinker->build();
Interval names(ibuf),iats(ibuf),lookups(ibuf);
// create the preprocessed data
//ordinals -= k32o;
upx_byte *ppi = oimport; // preprocessed imports
for (ic = 0; ic < dllnum; ic++)
{
LE32 *tarr = idlls[ic]->lookupt;
LEXX *tarr = idlls[ic]->lookupt;
#if 0 && ENABLE_THIS_AND_UNCOMPRESSION_WILL_BREAK // FIXME
if (!*tarr) // no imports from this dll
continue;
set_le32(ppi,idlls[ic]->npos);
#endif
set_le32(ppi, ilinker->getAddress(idlls[ic]->name));
set_le32(ppi+4,idlls[ic]->iat - rvamin);
ppi += 8;
for (; *tarr; tarr++)
if (*tarr & 0x80000000)
if (*tarr & ord_mask)
{
/*if (idlls[ic]->isk32)
unsigned ord = *tarr & 0xffff;
if (idlls[ic]->isk32)
{
*ppi++ = 0xfe; // signed + odd parity
set_le32(ppi,ptr_diff(ordinals,oimpdlls));
ordinals++;
set_le32(ppi, ilinker->getAddress(idlls[ic]->name, ord));
ppi += 4;
}
else*/
else
{
*ppi++ = 0xff;
set_le16(ppi,*tarr & 0xffff);
set_le16(ppi, ord);
ppi += 2;
}
}
@ -961,7 +935,6 @@ unsigned PeFile::processImports() // pass 1
soimport = 0;
//OutputFile::dump("x0.imp", oimport, soimport);
//OutputFile::dump("x1.imp", oimpdlls, soimpdlls);
unsigned ilen = 0;
names.flatten();
@ -981,7 +954,7 @@ unsigned PeFile::processImports() // pass 1
for (ic = 0; ic < dllnum; ic++, im++)
{
memset(im,FILLVAL,sizeof(*im));
im->dllname = ptr_diff(idlls[ic]->name,ibuf); // I only need this info
im->dllname = ptr_diff(dlls[idlls[ic]->original_position].name,ibuf);
}
}
else
@ -1002,7 +975,6 @@ unsigned PeFile::processImports() // pass 1
info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport);
return names.ivnum == 1 ? names.ivarr[0].start : 0;
}
#endif
/*************************************************************************
// export handling
@ -1816,9 +1788,10 @@ unsigned PeFile::stripDebug(unsigned overlaystart)
// unpack
**************************************************************************/
void PeFile32::rebuildRelocs(upx_byte *& extrainfo)
void PeFile::rebuildRelocs(upx_byte *& extrainfo, unsigned bits,
unsigned flags, upx_uint64_t imagebase)
{
if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (oh.flags & RELOCS_STRIPPED))
if (!ODADDR(PEDIR_RELOC) || !ODSIZE(PEDIR_RELOC) || (flags & RELOCS_STRIPPED))
return;
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
@ -1834,7 +1807,7 @@ void PeFile32::rebuildRelocs(upx_byte *& extrainfo)
// upx_byte *p = rdata;
OPTR_I(upx_byte, p, rdata);
MemBuffer wrkmem;
unsigned relocn = unoptimizeReloc32(&rdata,obuf,&wrkmem,1);
unsigned relocn = unoptimizeReloc(&rdata,obuf,&wrkmem,1,bits);
unsigned r16 = 0;
if (big & 6) // 16 bit relocations
{
@ -1863,8 +1836,11 @@ void PeFile32::rebuildRelocs(upx_byte *& extrainfo)
for (unsigned ic = 0; ic < relocn; ic++)
{
p = obuf + get_le32(wrkmem + 4 * ic);
set_le32(p, get_le32((unsigned char *)p) + oh.imagebase + rvamin);
rel.add(rvamin + get_le32(wrkmem + 4 * ic),3);
if (bits == 32)
set_le32(p, get_le32((unsigned char *)p) + imagebase + rvamin);
else
set_le64(p, get_le64((unsigned char *)p) + imagebase + rvamin);
rel.add(rvamin + get_le32(wrkmem + 4 * ic), bits == 32 ? 3 : 10);
}
rel.finish (oxrelocs,soxrelocs);
@ -1931,8 +1907,122 @@ void PeFile::rebuildResources(upx_byte *& extrainfo, unsigned lastvaddr)
delete [] p;
}
template <typename ht>
void PeFile::unpack(OutputFile *fo, const ht &ih, ht &oh)
template <typename LEXX, typename ord_mask_t>
void PeFile::rebuildImports(upx_byte *& extrainfo,
ord_mask_t ord_mask, bool set_oft)
{
if (ODADDR(PEDIR_IMPORT) == 0
|| ODSIZE(PEDIR_IMPORT) <= sizeof(import_desc))
return;
// const upx_byte * const idata = obuf + get_le32(extrainfo);
OPTR_C(const upx_byte, idata, obuf + get_le32(extrainfo));
const unsigned inamespos = get_le32(extrainfo + 4);
extrainfo += 8;
unsigned sdllnames = 0;
// const upx_byte *import = ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr;
// const upx_byte *p;
IPTR_I(const upx_byte, import, ibuf + IDADDR(PEDIR_IMPORT) - isection[2].vaddr);
OPTR(const upx_byte, p);
for (p = idata; get_le32(p) != 0; ++p)
{
const upx_byte *dname = get_le32(p) + import;
ICHECK(dname, 1);
const unsigned dlen = strlen(dname);
ICHECK(dname, dlen + 1);
sdllnames += dlen + 1;
for (p += 8; *p;)
if (*p == 1)
p += strlen(++p) + 1;
else if (*p == 0xff)
p += 3; // ordinal
else
p += 5;
}
sdllnames = ALIGN_UP(sdllnames, 2u);
upx_byte * const Obuf = obuf - rvamin;
import_desc * const im0 = (import_desc*) (Obuf + ODADDR(PEDIR_IMPORT));
import_desc *im = im0;
upx_byte *dllnames = Obuf + inamespos;
upx_byte *importednames = dllnames + sdllnames;
upx_byte * const importednames_start = importednames;
for (p = idata; get_le32(p) != 0; ++p)
{
// restore the name of the dll
const upx_byte *dname = get_le32(p) + import;
ICHECK(dname, 1);
const unsigned dlen = strlen(dname);
ICHECK(dname, dlen + 1);
const unsigned iatoffs = get_le32(p + 4) + rvamin;
if (inamespos)
{
// now I rebuild the dll names
OCHECK(dllnames, dlen + 1);
strcpy(dllnames, dname);
im->dllname = ptr_diff(dllnames,Obuf);
//;;;printf("\ndll: %s:",dllnames);
dllnames += dlen + 1;
}
else
{
OCHECK(Obuf + im->dllname, dlen + 1);
strcpy(Obuf + im->dllname, dname);
}
im->iat = iatoffs;
if (set_oft)
im->oft = iatoffs;
OPTR_I(LEXX, newiat, (LEXX *) (Obuf + iatoffs));
// restore the imported names+ordinals
for (p += 8; *p; ++newiat)
if (*p == 1)
{
const unsigned ilen = strlen(++p) + 1;
if (inamespos)
{
if (ptr_diff(importednames, importednames_start) & 1)
importednames -= 1;
omemcpy(importednames + 2, p, ilen);
//;;;printf(" %s",importednames+2);
*newiat = ptr_diff(importednames, Obuf);
importednames += 2 + ilen;
}
else
{
OCHECK(Obuf + *newiat + 2, ilen + 1);
strcpy(Obuf + *newiat + 2, p);
}
p += ilen;
}
else if (*p == 0xff)
{
*newiat = get_le16(p + 1) + ord_mask;
//;;;printf(" %x",(unsigned)*newiat);
p += 3;
}
else
{
*newiat = *(const LEXX*)(get_le32(p + 1) + import);
assert(*newiat & ord_mask);
p += 5;
}
*newiat = 0;
im++;
}
//memset(idata,0,p - idata);
}
template <typename ht, typename LEXX, typename ord_mask_t>
void PeFile::unpack(OutputFile *fo, const ht &ih, ht &oh,
ord_mask_t ord_mask, bool set_oft)
{
//infoHeader("[Processing %s, format %s, %d sections]", fn_basename(fi->getName()), getName(), objs);
@ -1981,8 +2071,8 @@ void PeFile::unpack(OutputFile *fo, const ht &ih, ht &oh)
ft.unfilter(obuf + oh.codebase - rvamin, oh.codesize);
}
rebuildImports(extrainfo);
rebuildRelocs(extrainfo);
rebuildImports<LEXX>(extrainfo, ord_mask, set_oft);
rebuildRelocs(extrainfo, sizeof(ih.imagebase) * 8, oh.flags, oh.imagebase);
rebuildTls();
rebuildExports();
@ -2074,7 +2164,13 @@ void PeFile32::readPeHeader()
void PeFile32::unpack(OutputFile *fo)
{
super::unpack(fo, ih, oh);
bool set_oft = getFormat() == UPX_F_WINCE_ARM_PE;
super::unpack<pe_header_t, LE32>(fo, ih, oh, 1U << 31, set_oft);
}
unsigned PeFile32::processImports() // pass 1
{
return super::processImports<LE32>(1u << 31);
}
/*

View File

@ -48,8 +48,9 @@ protected:
virtual ~PeFile();
virtual int getVersion() const { return 13; }
template <typename ht>
void unpack(OutputFile *fo, const ht &ih, ht &oh);
template <typename ht, typename LEXX, typename ord_mask_t>
void unpack(OutputFile *fo, const ht &ih, ht &oh,
ord_mask_t ord_mask, bool set_oft);
// unpacker capabilities
virtual bool canUnpackVersion(int version) const
@ -62,18 +63,25 @@ protected:
unsigned pe_offset;
virtual unsigned processImports() = 0;
virtual void processImports(unsigned, unsigned) = 0;
virtual void rebuildImports(upx_byte *&) = 0;
template <typename LEXX, typename ord_mask_t>
unsigned processImports(ord_mask_t ord_mask);
template <typename LEXX, typename ord_mask_t>
void rebuildImports(upx_byte *& extrainfo,
ord_mask_t ord_mask, bool set_oft);
virtual void processImports(unsigned, unsigned);
upx_byte *oimport;
unsigned soimport;
upx_byte *oimpdlls;
unsigned soimpdlls;
ImportLinker *ilinker;
void addKernelImport(const char *, const char *);
virtual void addKernelImports();
virtual void processRelocs() = 0;
void processRelocs(Reloc *);
virtual void rebuildRelocs(upx_byte *&) = 0;
void rebuildRelocs(upx_byte *&, unsigned bits,
unsigned flags, upx_uint64_t imagebase);
upx_byte *orelocs;
unsigned sorelocs;
upx_byte *oxrelocs;
@ -354,8 +362,8 @@ protected:
virtual void readPeHeader();
virtual unsigned processImports();
virtual void processRelocs();
virtual void rebuildRelocs(upx_byte *&);
__packed_struct(pe_header_t)
// 0x0