pe32: refactoring of import handling and unpacking continues
This commit is contained in:
+11
-387
@@ -67,6 +67,7 @@ static const
|
|||||||
#define OPTR_C(type, var, v) type* const var = (v)
|
#define OPTR_C(type, var, v) type* const var = (v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
||||||
{
|
{
|
||||||
const char *pp = (const char *) p;
|
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)
|
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
||||||
throwCantUnpack("pointer out of range; take care!");
|
throwCantUnpack("pointer out of range; take care!");
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
||||||
{
|
{
|
||||||
ACC_UNUSED(b);
|
ACC_UNUSED(b);
|
||||||
@@ -141,6 +142,10 @@ Linker* PackArmPe::newLinker() const
|
|||||||
// import handling
|
// import handling
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackArmPe::processImports(unsigned myimport, unsigned iat_off) // pass 2
|
||||||
|
{
|
||||||
|
PeFile::processImports(myimport, iat_off);
|
||||||
|
|
||||||
__packed_struct(import_desc)
|
__packed_struct(import_desc)
|
||||||
LE32 oft; // orig first thunk
|
LE32 oft; // orig first thunk
|
||||||
char _[8];
|
char _[8];
|
||||||
@@ -148,293 +153,23 @@ __packed_struct(import_desc)
|
|||||||
LE32 iat; // import address table
|
LE32 iat; // import address table
|
||||||
__packed_struct_end()
|
__packed_struct_end()
|
||||||
|
|
||||||
void PackArmPe::processImports(unsigned myimport, unsigned iat_off) // pass 2
|
|
||||||
{
|
|
||||||
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
|
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
|
||||||
|
|
||||||
// adjust import data
|
// adjust import data
|
||||||
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
|
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;
|
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;
|
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";
|
addKernelImport("COREDLL.DLL", "LoadLibraryW");
|
||||||
static const char llgpa[] = "\x0\x0""LoadLibraryW\x0\x0"
|
addKernelImport("COREDLL.DLL", "GetProcAddressA");
|
||||||
"GetProcAddressA\x0\x0\x0"
|
addKernelImport("COREDLL.DLL", "CacheSync");
|
||||||
"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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackArmPe::processTls(Interval *) // pass 1
|
void PackArmPe::processTls(Interval *) // pass 1
|
||||||
{
|
{
|
||||||
if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4u)) == 0)
|
if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4u)) == 0)
|
||||||
@@ -628,7 +363,7 @@ void PackArmPe::pack(OutputFile *fo)
|
|||||||
Interval tlsiv(ibuf);
|
Interval tlsiv(ibuf);
|
||||||
Export xport((char*)(unsigned char*)ibuf);
|
Export xport((char*)(unsigned char*)ibuf);
|
||||||
|
|
||||||
const unsigned dllstrings = processImports();
|
const unsigned dllstrings = PeFile32::processImports();
|
||||||
processTls(&tlsiv); // call before processRelocs!!
|
processTls(&tlsiv); // call before processRelocs!!
|
||||||
processResources(&res);
|
processResources(&res);
|
||||||
processExports(&xport);
|
processExports(&xport);
|
||||||
@@ -1029,117 +764,6 @@ int PackArmPe::canUnpack()
|
|||||||
return false;
|
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
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-2
@@ -56,9 +56,8 @@ protected:
|
|||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft);
|
||||||
virtual Linker* newLinker() const;
|
virtual Linker* newLinker() const;
|
||||||
|
|
||||||
virtual unsigned processImports();
|
|
||||||
virtual void processImports(unsigned, unsigned);
|
virtual void processImports(unsigned, unsigned);
|
||||||
virtual void rebuildImports(upx_byte *&);
|
virtual void addKernelImports();
|
||||||
|
|
||||||
virtual void processTls(Interval *);
|
virtual void processTls(Interval *);
|
||||||
|
|
||||||
|
|||||||
+3
-415
@@ -49,7 +49,7 @@ static const
|
|||||||
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
|
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
//static
|
//static
|
||||||
unsigned my_strlen(const char *s)
|
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)
|
#define OPTR_C(type, var, v) type* const var = (v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
static void xcheck(const void *p, size_t plen, const void *b, size_t blen)
|
||||||
{
|
{
|
||||||
const char *pp = (const char *) p;
|
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)
|
if (pp < bb || pp > bb + blen || pp + plen > bb + blen)
|
||||||
throwCantUnpack("pointer out of range; take care!");
|
throwCantUnpack("pointer out of range; take care!");
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
static void xcheck(size_t poff, size_t plen, const void *b, size_t blen)
|
||||||
{
|
{
|
||||||
ACC_UNUSED(b);
|
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
|
// Load Configuration handling
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -1204,7 +903,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
ODSIZE(PEDIR_RESOURCE) = soresources;
|
ODSIZE(PEDIR_RESOURCE) = soresources;
|
||||||
ic += soresources;
|
ic += soresources;
|
||||||
|
|
||||||
processImports(ic, 0);
|
PeFile::processImports(ic, 0);
|
||||||
ODADDR(PEDIR_IMPORT) = ic;
|
ODADDR(PEDIR_IMPORT) = ic;
|
||||||
ODSIZE(PEDIR_IMPORT) = soimpdlls;
|
ODSIZE(PEDIR_IMPORT) = soimpdlls;
|
||||||
ic += soimpdlls;
|
ic += soimpdlls;
|
||||||
@@ -1411,117 +1110,6 @@ int PackW32Pe::canUnpack()
|
|||||||
return false;
|
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:
|
extra info added to help uncompression:
|
||||||
|
|
||||||
|
|||||||
@@ -58,10 +58,6 @@ protected:
|
|||||||
virtual void buildLoader(const Filter *ft);
|
virtual void buildLoader(const Filter *ft);
|
||||||
virtual Linker* newLinker() const;
|
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
|
virtual void processTls(Interval *); //NEW: TLS callback handling - Stefan Widmann
|
||||||
void processTls(Reloc *, const Interval *, unsigned); //NEW: TLS callback handling - Stefan Widmann
|
void processTls(Reloc *, const Interval *, unsigned); //NEW: TLS callback handling - Stefan Widmann
|
||||||
|
|
||||||
|
|||||||
+233
-137
@@ -44,6 +44,20 @@
|
|||||||
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
|
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
|
||||||
#endif
|
#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__)
|
#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)
|
||||||
#include "bptr.h"
|
#include "bptr.h"
|
||||||
#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
|
#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;
|
unsigned len = 1 + 2 * strlen(dll) + 1 + 2 * strlen(proc) + 1 + 1;
|
||||||
tstr dlln(name_for_dll(dll, first_char));
|
tstr dlln(name_for_dll(dll, first_char));
|
||||||
char *procn = new char[len];
|
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));
|
encode_name(proc, procn + strlen(procn));
|
||||||
return procn;
|
return procn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char zeros[sizeof(import_desc)];
|
static const char zeros[sizeof(import_desc)];
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// the order of identifiers is very important below!!
|
// the order of identifiers is very important below!!
|
||||||
@@ -635,15 +649,18 @@ public:
|
|||||||
template <typename C>
|
template <typename C>
|
||||||
void add(const C *dll, unsigned ordinal)
|
void add(const C *dll, unsigned ordinal)
|
||||||
{
|
{
|
||||||
|
ACC_COMPILE_TIME_ASSERT(sizeof(C) == 1) // "char" or "unsigned char"
|
||||||
assert(ordinal > 0 && ordinal < 0x10000);
|
assert(ordinal > 0 && ordinal < 0x10000);
|
||||||
char ord[20];
|
char ord[1+5+1];
|
||||||
snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
upx_snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
||||||
add((const char*) dll, ord, ordinal);
|
add((const char*) dll, ord, ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C1, typename C2>
|
template <typename C1, typename C2>
|
||||||
void add(const C1 *dll, const C2 *proc)
|
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);
|
assert(proc);
|
||||||
add((const char*) dll, (const char*) proc, 0);
|
add((const char*) dll, (const char*) proc, 0);
|
||||||
}
|
}
|
||||||
@@ -680,6 +697,8 @@ public:
|
|||||||
template <typename C1, typename C2>
|
template <typename C1, typename C2>
|
||||||
upx_uint64_t getAddress(const C1 *dll, const C2 *proc) const
|
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,
|
const Section *s = getThunk((const char*) dll, (const char*) proc,
|
||||||
thunk_separator_first);
|
thunk_separator_first);
|
||||||
if (s == NULL && (s = getThunk((const char*) dll,(const char*) proc,
|
if (s == NULL && (s = getThunk((const char*) dll,(const char*) proc,
|
||||||
@@ -688,12 +707,13 @@ public:
|
|||||||
return s->offset;
|
return s->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C1>
|
template <typename C>
|
||||||
upx_uint64_t getAddress(const C1 *dll, unsigned ordinal) const
|
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);
|
assert(ordinal > 0 && ordinal < 0x10000);
|
||||||
char ord[20];
|
char ord[1+5+1];
|
||||||
snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
upx_snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
||||||
|
|
||||||
const Section *s = getThunk((const char*) dll, ord, thunk_separator_first);
|
const Section *s = getThunk((const char*) dll, ord, thunk_separator_first);
|
||||||
if (s == NULL
|
if (s == NULL
|
||||||
@@ -702,56 +722,45 @@ public:
|
|||||||
return s->offset;
|
return s->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C1>
|
template <typename C>
|
||||||
upx_uint64_t getAddress(const C1 *dll) const
|
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));
|
tstr sdll(name_for_dll((const char*) dll, dll_name_id));
|
||||||
return findSection(sdll, true)->offset;
|
return findSection(sdll, true)->offset;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
char PeFile::ImportLinker::zeros[sizeof(import_desc)];
|
const char PeFile::ImportLinker::zeros[sizeof(import_desc)] = { 0 };
|
||||||
|
|
||||||
#if 0
|
void PeFile::addKernelImport(const char *dll, const char *name)
|
||||||
/*************************************************************************
|
|
||||||
// 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
|
|
||||||
{
|
{
|
||||||
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20)
|
ilinker->add(dll, name);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PeFile::processImports() // pass 1
|
void PeFile::addKernelImports()
|
||||||
{
|
{
|
||||||
static const unsigned char kernel32dll[] = "COREDLL.dll";
|
addKernelImport("KERNEL32.DLL", "LoadLibraryA");
|
||||||
static const char llgpa[] = "\x0\x0""LoadLibraryW\x0\x0"
|
addKernelImport("KERNEL32.DLL", "GetProcAddress");
|
||||||
"GetProcAddressA\x0\x0\x0"
|
if (!isdll)
|
||||||
"CacheSync";
|
addKernelImport("KERNEL32.DLL", "ExitProcess");
|
||||||
//static const char exitp[] = "ExitProcess\x0\x0\x0";
|
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;
|
unsigned dllnum = 0;
|
||||||
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
|
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
|
||||||
@@ -769,8 +778,8 @@ unsigned PeFile::processImports() // pass 1
|
|||||||
const upx_byte *shname;
|
const upx_byte *shname;
|
||||||
unsigned ordinal;
|
unsigned ordinal;
|
||||||
unsigned iat;
|
unsigned iat;
|
||||||
LE32 *lookupt;
|
LEXX *lookupt;
|
||||||
unsigned npos;
|
unsigned original_position;
|
||||||
bool isk32;
|
bool isk32;
|
||||||
|
|
||||||
static int __acc_cdecl_qsort compare(const void *p1, const void *p2)
|
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;
|
const udll *u2 = * (const udll * const *) p2;
|
||||||
if (u1->isk32) return -1;
|
if (u1->isk32) return -1;
|
||||||
if (u2->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);
|
int rc = strcasecmp(u1->name,u2->name);
|
||||||
if (rc) return rc;
|
if (rc) return rc;
|
||||||
if (u1->ordinal) return -1;
|
if (u1->ordinal) return -1;
|
||||||
@@ -795,33 +806,32 @@ unsigned PeFile::processImports() // pass 1
|
|||||||
|
|
||||||
soimport = 1024; // safety
|
soimport = 1024; // safety
|
||||||
|
|
||||||
unsigned ic,k32o;
|
unsigned ic;
|
||||||
for (ic = k32o = 0; dllnum && im->dllname; ic++, im++)
|
for (ic = 0; dllnum && im->dllname; ic++, im++)
|
||||||
{
|
{
|
||||||
idlls[ic] = dlls + ic;
|
idlls[ic] = dlls + ic;
|
||||||
dlls[ic].name = ibuf + im->dllname;
|
dlls[ic].name = ibuf + im->dllname;
|
||||||
dlls[ic].shname = NULL;
|
dlls[ic].shname = NULL;
|
||||||
dlls[ic].ordinal = 0;
|
dlls[ic].ordinal = 0;
|
||||||
dlls[ic].iat = im->iat;
|
dlls[ic].iat = im->iat;
|
||||||
dlls[ic].lookupt = (LE32*) (ibuf + (im->oft ? im->oft : im->iat));
|
dlls[ic].lookupt = (LEXX*) (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;
|
dlls[ic].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0;
|
||||||
|
|
||||||
soimport += strlen(dlls[ic].name) + 1 + 4;
|
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;
|
importbyordinal = true;
|
||||||
soimport += 2; // ordinal num: 2 bytes
|
soimport += 2; // ordinal num: 2 bytes
|
||||||
dlls[ic].ordinal = *tarr & 0xffff;
|
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;
|
soimport += len + 1;
|
||||||
if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname))
|
if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname))
|
||||||
dlls[ic].shname = ibuf + *tarr + 2;
|
dlls[ic].shname = ibuf + *tarr + 2;
|
||||||
@@ -831,106 +841,70 @@ unsigned PeFile::processImports() // pass 1
|
|||||||
}
|
}
|
||||||
oimport = new upx_byte[soimport];
|
oimport = new upx_byte[soimport];
|
||||||
memset(oimport,0,soimport);
|
memset(oimport,0,soimport);
|
||||||
oimpdlls = new upx_byte[soimport];
|
|
||||||
memset(oimpdlls,0,soimport);
|
|
||||||
|
|
||||||
qsort(idlls,dllnum,sizeof (udll*),udll::compare);
|
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);
|
info("Processing imports: %d DLLs", dllnum);
|
||||||
|
|
||||||
// create the new import table
|
// 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++)
|
for (ic = 0; ic < dllnum; ic++)
|
||||||
|
{
|
||||||
if (idlls[ic]->isk32)
|
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)
|
if (idlls[ic]->ordinal)
|
||||||
for (LE32 *tarr = idlls[ic]->lookupt; *tarr; tarr++)
|
for (LEXX *tarr = idlls[ic]->lookupt; *tarr; tarr++)
|
||||||
if (*tarr & 0x80000000)
|
if (*tarr & ord_mask)
|
||||||
*ordinals++ = *tarr;
|
{
|
||||||
*/
|
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
|
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)
|
if (idlls[ic]->ordinal)
|
||||||
*lookuptable = idlls[ic]->ordinal + 0x80000000;
|
ilinker->add(idlls[ic]->name, idlls[ic]->ordinal);
|
||||||
else if (idlls[ic]->shname)
|
else if (idlls[ic]->shname)
|
||||||
{
|
ilinker->add(idlls[ic]->name, idlls[ic]->shname);
|
||||||
if (ptr_diff(importednames,oimpdlls) & 1)
|
else
|
||||||
importednames--;
|
throwInternalError("should not happen");
|
||||||
*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);
|
|
||||||
|
soimpdlls = ilinker->build();
|
||||||
|
|
||||||
Interval names(ibuf),iats(ibuf),lookups(ibuf);
|
Interval names(ibuf),iats(ibuf),lookups(ibuf);
|
||||||
|
|
||||||
// create the preprocessed data
|
// create the preprocessed data
|
||||||
//ordinals -= k32o;
|
|
||||||
upx_byte *ppi = oimport; // preprocessed imports
|
upx_byte *ppi = oimport; // preprocessed imports
|
||||||
for (ic = 0; ic < dllnum; ic++)
|
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
|
if (!*tarr) // no imports from this dll
|
||||||
continue;
|
continue;
|
||||||
set_le32(ppi,idlls[ic]->npos);
|
#endif
|
||||||
|
set_le32(ppi, ilinker->getAddress(idlls[ic]->name));
|
||||||
set_le32(ppi+4,idlls[ic]->iat - rvamin);
|
set_le32(ppi+4,idlls[ic]->iat - rvamin);
|
||||||
ppi += 8;
|
ppi += 8;
|
||||||
for (; *tarr; tarr++)
|
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
|
*ppi++ = 0xfe; // signed + odd parity
|
||||||
set_le32(ppi,ptr_diff(ordinals,oimpdlls));
|
set_le32(ppi, ilinker->getAddress(idlls[ic]->name, ord));
|
||||||
ordinals++;
|
|
||||||
ppi += 4;
|
ppi += 4;
|
||||||
}
|
}
|
||||||
else*/
|
else
|
||||||
{
|
{
|
||||||
*ppi++ = 0xff;
|
*ppi++ = 0xff;
|
||||||
set_le16(ppi,*tarr & 0xffff);
|
set_le16(ppi, ord);
|
||||||
ppi += 2;
|
ppi += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -961,7 +935,6 @@ unsigned PeFile::processImports() // pass 1
|
|||||||
soimport = 0;
|
soimport = 0;
|
||||||
|
|
||||||
//OutputFile::dump("x0.imp", oimport, soimport);
|
//OutputFile::dump("x0.imp", oimport, soimport);
|
||||||
//OutputFile::dump("x1.imp", oimpdlls, soimpdlls);
|
|
||||||
|
|
||||||
unsigned ilen = 0;
|
unsigned ilen = 0;
|
||||||
names.flatten();
|
names.flatten();
|
||||||
@@ -981,7 +954,7 @@ unsigned PeFile::processImports() // pass 1
|
|||||||
for (ic = 0; ic < dllnum; ic++, im++)
|
for (ic = 0; ic < dllnum; ic++, im++)
|
||||||
{
|
{
|
||||||
memset(im,FILLVAL,sizeof(*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
|
else
|
||||||
@@ -1002,7 +975,6 @@ unsigned PeFile::processImports() // pass 1
|
|||||||
info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport);
|
info("Imports: original size: %u bytes, preprocessed size: %u bytes",ilen,soimport);
|
||||||
return names.ivnum == 1 ? names.ivarr[0].start : 0;
|
return names.ivnum == 1 ? names.ivarr[0].start : 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// export handling
|
// export handling
|
||||||
@@ -1816,9 +1788,10 @@ unsigned PeFile::stripDebug(unsigned overlaystart)
|
|||||||
// unpack
|
// 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;
|
return;
|
||||||
|
|
||||||
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
|
if (ODSIZE(PEDIR_RELOC) == 8) // some tricky dlls use this
|
||||||
@@ -1834,7 +1807,7 @@ void PeFile32::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
// upx_byte *p = rdata;
|
// upx_byte *p = rdata;
|
||||||
OPTR_I(upx_byte, p, rdata);
|
OPTR_I(upx_byte, p, rdata);
|
||||||
MemBuffer wrkmem;
|
MemBuffer wrkmem;
|
||||||
unsigned relocn = unoptimizeReloc32(&rdata,obuf,&wrkmem,1);
|
unsigned relocn = unoptimizeReloc(&rdata,obuf,&wrkmem,1,bits);
|
||||||
unsigned r16 = 0;
|
unsigned r16 = 0;
|
||||||
if (big & 6) // 16 bit relocations
|
if (big & 6) // 16 bit relocations
|
||||||
{
|
{
|
||||||
@@ -1863,8 +1836,11 @@ void PeFile32::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
for (unsigned ic = 0; ic < relocn; ic++)
|
for (unsigned ic = 0; ic < relocn; ic++)
|
||||||
{
|
{
|
||||||
p = obuf + get_le32(wrkmem + 4 * ic);
|
p = obuf + get_le32(wrkmem + 4 * ic);
|
||||||
set_le32(p, get_le32((unsigned char *)p) + oh.imagebase + rvamin);
|
if (bits == 32)
|
||||||
rel.add(rvamin + get_le32(wrkmem + 4 * ic),3);
|
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);
|
rel.finish (oxrelocs,soxrelocs);
|
||||||
|
|
||||||
@@ -1931,8 +1907,122 @@ void PeFile::rebuildResources(upx_byte *& extrainfo, unsigned lastvaddr)
|
|||||||
delete [] p;
|
delete [] p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ht>
|
template <typename LEXX, typename ord_mask_t>
|
||||||
void PeFile::unpack(OutputFile *fo, const ht &ih, ht &oh)
|
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);
|
//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);
|
ft.unfilter(obuf + oh.codebase - rvamin, oh.codesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuildImports(extrainfo);
|
rebuildImports<LEXX>(extrainfo, ord_mask, set_oft);
|
||||||
rebuildRelocs(extrainfo);
|
rebuildRelocs(extrainfo, sizeof(ih.imagebase) * 8, oh.flags, oh.imagebase);
|
||||||
rebuildTls();
|
rebuildTls();
|
||||||
rebuildExports();
|
rebuildExports();
|
||||||
|
|
||||||
@@ -2074,7 +2164,13 @@ void PeFile32::readPeHeader()
|
|||||||
|
|
||||||
void PeFile32::unpack(OutputFile *fo)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+15
-7
@@ -48,8 +48,9 @@ protected:
|
|||||||
virtual ~PeFile();
|
virtual ~PeFile();
|
||||||
virtual int getVersion() const { return 13; }
|
virtual int getVersion() const { return 13; }
|
||||||
|
|
||||||
template <typename ht>
|
template <typename ht, typename LEXX, typename ord_mask_t>
|
||||||
void unpack(OutputFile *fo, const ht &ih, ht &oh);
|
void unpack(OutputFile *fo, const ht &ih, ht &oh,
|
||||||
|
ord_mask_t ord_mask, bool set_oft);
|
||||||
|
|
||||||
// unpacker capabilities
|
// unpacker capabilities
|
||||||
virtual bool canUnpackVersion(int version) const
|
virtual bool canUnpackVersion(int version) const
|
||||||
@@ -62,18 +63,25 @@ protected:
|
|||||||
|
|
||||||
unsigned pe_offset;
|
unsigned pe_offset;
|
||||||
|
|
||||||
virtual unsigned processImports() = 0;
|
template <typename LEXX, typename ord_mask_t>
|
||||||
virtual void processImports(unsigned, unsigned) = 0;
|
unsigned processImports(ord_mask_t ord_mask);
|
||||||
virtual void rebuildImports(upx_byte *&) = 0;
|
|
||||||
|
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;
|
upx_byte *oimport;
|
||||||
unsigned soimport;
|
unsigned soimport;
|
||||||
upx_byte *oimpdlls;
|
upx_byte *oimpdlls;
|
||||||
unsigned soimpdlls;
|
unsigned soimpdlls;
|
||||||
ImportLinker *ilinker;
|
ImportLinker *ilinker;
|
||||||
|
void addKernelImport(const char *, const char *);
|
||||||
|
virtual void addKernelImports();
|
||||||
|
|
||||||
virtual void processRelocs() = 0;
|
virtual void processRelocs() = 0;
|
||||||
void processRelocs(Reloc *);
|
void processRelocs(Reloc *);
|
||||||
virtual void rebuildRelocs(upx_byte *&) = 0;
|
void rebuildRelocs(upx_byte *&, unsigned bits,
|
||||||
|
unsigned flags, upx_uint64_t imagebase);
|
||||||
upx_byte *orelocs;
|
upx_byte *orelocs;
|
||||||
unsigned sorelocs;
|
unsigned sorelocs;
|
||||||
upx_byte *oxrelocs;
|
upx_byte *oxrelocs;
|
||||||
@@ -354,8 +362,8 @@ protected:
|
|||||||
|
|
||||||
virtual void readPeHeader();
|
virtual void readPeHeader();
|
||||||
|
|
||||||
|
virtual unsigned processImports();
|
||||||
virtual void processRelocs();
|
virtual void processRelocs();
|
||||||
virtual void rebuildRelocs(upx_byte *&);
|
|
||||||
|
|
||||||
__packed_struct(pe_header_t)
|
__packed_struct(pe_header_t)
|
||||||
// 0x0
|
// 0x0
|
||||||
|
|||||||
Reference in New Issue
Block a user