pe: ImportLinker introduced
This commit is contained in:
+293
-122
@@ -27,7 +27,6 @@
|
|||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
PE+ format extension changes (C) 2010 Stefan Widmann
|
PE+ format extension changes (C) 2010 Stefan Widmann
|
||||||
changes in:
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -135,6 +134,7 @@ PackW64Pep::PackW64Pep(InputFile *f) : super(f)
|
|||||||
|
|
||||||
PackW64Pep::~PackW64Pep()
|
PackW64Pep::~PackW64Pep()
|
||||||
{
|
{
|
||||||
|
oimpdlls = NULL; // this is now a pointer to ImportLinker output
|
||||||
delete [] oloadconf;
|
delete [] oloadconf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,33 +183,262 @@ __packed_struct(import_desc)
|
|||||||
LE32 iat; // import address table
|
LE32 iat; // import address table
|
||||||
__packed_struct_end()
|
__packed_struct_end()
|
||||||
|
|
||||||
|
/*
|
||||||
|
ImportLinker: 32 and 64 bit import table building.
|
||||||
|
Import entries (dll name + proc name/ordinal pairs) can be
|
||||||
|
added in arbitrary order.
|
||||||
|
|
||||||
|
Internally it works by creating sections with special names,
|
||||||
|
and adding relocation entries between those sections. The special
|
||||||
|
names ensure that when the import table is built in the memory
|
||||||
|
from those sections, a correct table can be generated simply by
|
||||||
|
sorting the sections by name, and adding all of them to the output
|
||||||
|
in the sorted order.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ImportLinker : public ElfLinkerAMD64
|
||||||
|
{
|
||||||
|
struct tstr : private ::noncopyable
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
explicit tstr(char *str) : s(str) {}
|
||||||
|
~tstr() { delete [] s; }
|
||||||
|
operator char *() const { return s; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// encoding of dll and proc names are required, so that our special
|
||||||
|
// control characters in the name of sections can work as intended
|
||||||
|
static char *encode_name(const char *name, char *buf)
|
||||||
|
{
|
||||||
|
char *b = buf;
|
||||||
|
while (*name)
|
||||||
|
{
|
||||||
|
*b++ = 'a' + ((*name >> 4) & 0xf);
|
||||||
|
*b++ = 'a' + (*name & 0xf);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
*b = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *name_for_dll(const char *dll, char first_char)
|
||||||
|
{
|
||||||
|
assert(dll);
|
||||||
|
unsigned l = strlen(dll);
|
||||||
|
assert(l > 0);
|
||||||
|
|
||||||
|
char *name = new char[3 * l + 2];
|
||||||
|
assert(name);
|
||||||
|
name[0] = first_char;
|
||||||
|
char *n = name + 1 + 2 * l;
|
||||||
|
do {
|
||||||
|
*n++ = tolower(*dll);
|
||||||
|
} while(*dll++);
|
||||||
|
return encode_name(name + 1 + 2 * l, name + 1) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *name_for_proc(const char *dll, const char *proc,
|
||||||
|
char first_char, char separator)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
encode_name(proc, procn + strlen(procn));
|
||||||
|
return procn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char zeros[sizeof(import_desc)];
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// the order of identifiers is very important below!!
|
||||||
|
descriptor_id = 'D',
|
||||||
|
thunk_id,
|
||||||
|
dll_name_id,
|
||||||
|
proc_name_id,
|
||||||
|
ordinal_id,
|
||||||
|
|
||||||
|
thunk_separator_first,
|
||||||
|
thunk_separator,
|
||||||
|
thunk_separator_last,
|
||||||
|
procname_separator,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned thunk_size; // 4 or 8 bytes
|
||||||
|
|
||||||
|
void add(const char *dll, const char *proc, unsigned ordinal)
|
||||||
|
{
|
||||||
|
tstr sdll(name_for_dll(dll, dll_name_id));
|
||||||
|
tstr desc_name(name_for_dll(dll, descriptor_id));
|
||||||
|
|
||||||
|
char tsep = thunk_separator;
|
||||||
|
if (findSection(sdll, false) == NULL)
|
||||||
|
{
|
||||||
|
tsep = thunk_separator_first;
|
||||||
|
addSection(sdll, dll, strlen(dll) + 1, 0); // name of the dll
|
||||||
|
addSymbol(sdll, sdll, 0);
|
||||||
|
|
||||||
|
addSection(desc_name, zeros, sizeof(zeros), 0); // descriptor
|
||||||
|
addRelocation(desc_name, offsetof(import_desc, dllname),
|
||||||
|
"R_X86_64_32", sdll, 0);
|
||||||
|
}
|
||||||
|
tstr thunk(name_for_proc(dll, proc, thunk_id, tsep));
|
||||||
|
addSection(thunk, zeros, thunk_size, 0);
|
||||||
|
addSymbol(thunk, thunk, 0);
|
||||||
|
if (tsep == thunk_separator_first)
|
||||||
|
{
|
||||||
|
addRelocation(desc_name, offsetof(import_desc, iat),
|
||||||
|
"R_X86_64_32", thunk, 0);
|
||||||
|
|
||||||
|
tstr last_thunk(name_for_proc(dll, "X", thunk_id, thunk_separator_last));
|
||||||
|
addSection(last_thunk, zeros, thunk_size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *reltype = thunk_size == 4 ? "R_X86_64_32" : "R_X86_64_64";
|
||||||
|
if (ordinal != 0u)
|
||||||
|
{
|
||||||
|
addRelocation(thunk, 0, reltype, "*UND*",
|
||||||
|
ordinal | (1ull << (thunk_size * 8 - 1)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tstr proc_name(name_for_proc(dll, proc, proc_name_id, procname_separator));
|
||||||
|
addSection(proc_name, zeros, 2, 1); // 2 bytes of word aligned "hint"
|
||||||
|
addSymbol(proc_name, proc_name, 0);
|
||||||
|
addRelocation(thunk, 0, reltype, proc_name, 0);
|
||||||
|
|
||||||
|
strcat(proc_name, "X");
|
||||||
|
addSection(proc_name, proc, strlen(proc), 0); // the name of the symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __acc_cdecl_qsort compare(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
const Section *s1 = * (const Section * const *) p1;
|
||||||
|
const Section *s2 = * (const Section * const *) p2;
|
||||||
|
return strcmp(s1->name, s2->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
|
||||||
|
|
||||||
|
const Section *getThunk(const char *dll, const char *proc, char tsep) const
|
||||||
|
{
|
||||||
|
assert(dll);
|
||||||
|
assert(proc);
|
||||||
|
tstr thunk(name_for_proc(dll, proc, thunk_id, tsep));
|
||||||
|
return findSection(thunk, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ImportLinker(unsigned thunk_size_) : thunk_size(thunk_size_)
|
||||||
|
{
|
||||||
|
assert(thunk_size == 4 || thunk_size == 8);
|
||||||
|
addSection("*UND*", NULL, 0, 0);
|
||||||
|
addSymbol("*UND*", "*UND*", 0);
|
||||||
|
addSection("*ZSTART", NULL, 0, 0);
|
||||||
|
addSymbol("*ZSTART", "*ZSTART", 0);
|
||||||
|
Section *s = addSection("Dzero", zeros, sizeof(import_desc), 0);
|
||||||
|
assert(s->name[0] == descriptor_id);
|
||||||
|
|
||||||
|
// one trailing 00 byte after the last proc name
|
||||||
|
addSection("Zzero", zeros, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
void add(const C *dll, unsigned ordinal)
|
||||||
|
{
|
||||||
|
assert(ordinal > 0 && ordinal < 0x10000);
|
||||||
|
char ord[20];
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
assert(proc);
|
||||||
|
add((const char*) dll, (const char*) proc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned build()
|
||||||
|
{
|
||||||
|
assert(output == NULL);
|
||||||
|
int osize = 4 + 2 * nsections; // upper limit for alignments
|
||||||
|
for (unsigned ic = 0; ic < nsections; ic++)
|
||||||
|
osize += sections[ic]->size;
|
||||||
|
output = new upx_byte[osize];
|
||||||
|
|
||||||
|
// sort the sections by name before adding them all
|
||||||
|
qsort(sections, nsections, sizeof (Section*), ImportLinker::compare);
|
||||||
|
|
||||||
|
for (unsigned ic = 0; ic < nsections; ic++)
|
||||||
|
addLoader(sections[ic]->name);
|
||||||
|
addLoader("+40D");
|
||||||
|
assert(outputlen <= osize);
|
||||||
|
|
||||||
|
//OutputFile::dump("il0.imp", output, outputlen);
|
||||||
|
return outputlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void relocate(unsigned myimport)
|
||||||
|
{
|
||||||
|
assert(nsections > 0);
|
||||||
|
assert(output);
|
||||||
|
defineSymbol("*ZSTART", /*0xffffffffff1000ull + 0 * */ myimport);
|
||||||
|
ElfLinkerAMD64::relocate();
|
||||||
|
//OutputFile::dump("il1.imp", output, outputlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C1, typename C2>
|
||||||
|
upx_uint64_t getAddress(const C1 *dll, const C2 *proc) const
|
||||||
|
{
|
||||||
|
const Section *s = getThunk((const char*) dll, (const char*) proc,
|
||||||
|
thunk_separator_first);
|
||||||
|
if (s == NULL && (s = getThunk((const char*) dll,(const char*) proc,
|
||||||
|
thunk_separator)) == NULL)
|
||||||
|
throwInternalError("entry not found");
|
||||||
|
return s->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C1>
|
||||||
|
upx_uint64_t getAddress(const C1 *dll, unsigned ordinal) const
|
||||||
|
{
|
||||||
|
assert(ordinal > 0 && ordinal < 0x10000);
|
||||||
|
char ord[20];
|
||||||
|
snprintf(ord, sizeof(ord), "%c%05u", ordinal_id, ordinal);
|
||||||
|
|
||||||
|
const Section *s = getThunk((const char*) dll, ord, thunk_separator_first);
|
||||||
|
if (s == NULL
|
||||||
|
&& (s = getThunk((const char*) dll, ord, thunk_separator)) == NULL)
|
||||||
|
throwInternalError("entry not found");
|
||||||
|
return s->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C1>
|
||||||
|
upx_uint64_t getAddress(const C1 *dll) const
|
||||||
|
{
|
||||||
|
tstr sdll(name_for_dll((const char*) dll, dll_name_id));
|
||||||
|
return findSection(sdll, true)->offset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
char ImportLinker::zeros[sizeof(import_desc)];
|
||||||
|
|
||||||
|
ImportLinker ilinker(8);
|
||||||
|
|
||||||
void PackW64Pep::processImports(unsigned myimport, unsigned) // pass 2
|
void PackW64Pep::processImports(unsigned myimport, unsigned) // pass 2
|
||||||
{
|
{
|
||||||
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
|
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
|
||||||
|
|
||||||
// adjust import data
|
ilinker.relocate(myimport);
|
||||||
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
|
int len;
|
||||||
{
|
oimpdlls = ilinker.getLoader(&len);
|
||||||
if (im->dllname < myimport)
|
assert(len == (int) soimpdlls);
|
||||||
im->dllname += myimport;
|
//OutputFile::dump("x1.imp", oimpdlls, soimpdlls);
|
||||||
LE64 *p = (LE64*) (oimpdlls + im->iat); //changed to LE64 - Stefan Widmann
|
|
||||||
im->iat += myimport;
|
|
||||||
|
|
||||||
while (*p)
|
|
||||||
if ((*p++ & 0x8000000000000000ULL) == 0) // changed to 64 bit - Stefan Widmann
|
|
||||||
p[-1] += myimport;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PackW64Pep::processImports() // pass 1
|
unsigned PackW64Pep::processImports() // pass 1
|
||||||
{
|
{
|
||||||
static const unsigned char kernel32dll[] = "KERNEL32.DLL";
|
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;
|
unsigned dllnum = 0;
|
||||||
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
|
import_desc *im = (import_desc*) (ibuf + IDADDR(PEDIR_IMPORT));
|
||||||
@@ -227,8 +456,7 @@ unsigned PackW64Pep::processImports() // pass 1
|
|||||||
const upx_byte *shname;
|
const upx_byte *shname;
|
||||||
unsigned ordinal;
|
unsigned ordinal;
|
||||||
unsigned iat;
|
unsigned iat;
|
||||||
LE64 *lookupt; //changed to LE64* - Stefan Widmann
|
LE64 *lookupt;
|
||||||
unsigned npos;
|
|
||||||
unsigned original_position;
|
unsigned original_position;
|
||||||
bool isk32;
|
bool isk32;
|
||||||
|
|
||||||
@@ -256,31 +484,28 @@ unsigned PackW64Pep::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 = (LE64*) (ibuf + (im->oft ? im->oft : im->iat)); //changed to LE64* - Stefan Widmann
|
dlls[ic].lookupt = (LE64*) (ibuf + (im->oft ? im->oft : im->iat));
|
||||||
dlls[ic].npos = 0;
|
|
||||||
dlls[ic].original_position = ic;
|
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;
|
||||||
|
|
||||||
// FIXME use IPTR_I as in p32pe.cpp
|
// FIXME use IPTR_I as in p32pe.cpp
|
||||||
for (LE64 *tarr = dlls[ic].lookupt; *tarr; tarr++) //changed to LE64* - Stefan Widmann
|
for (LE64 *tarr = dlls[ic].lookupt; *tarr; tarr++)
|
||||||
{
|
{
|
||||||
if (*tarr & 0x8000000000000000ULL) //in PE32+, bit 63 indicates an ordinal
|
if (*tarr & (1ULL << 63))
|
||||||
{
|
{
|
||||||
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 //it's an import by name
|
else //it's an import by name
|
||||||
{
|
{
|
||||||
@@ -294,113 +519,74 @@ unsigned PackW64Pep::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;
|
ilinker.add(kernel32dll, "LoadLibraryA");
|
||||||
|
ilinker.add(kernel32dll, "GetProcAddress");
|
||||||
LE64 *ordinals = (LE64*) (oimpdlls + (dllnum2 + 1) * sizeof(import_desc)); //changed to LE64* - Stefan Widmann
|
|
||||||
LE64 *lookuptable = ordinals + 6 + k32o + (isdll ? 0 : 1); //changed to LE64* - Stefan Widmann
|
|
||||||
upx_byte *dllnames = ((upx_byte*) lookuptable) + (dllnum2 - 1) * 16; //double the size per hint - is that correct? - Stefan Widmann
|
|
||||||
upx_byte *importednames = dllnames + (dllnamelen &~ 1);
|
|
||||||
|
|
||||||
unsigned k32namepos = ptr_diff(dllnames,oimpdlls);
|
|
||||||
|
|
||||||
memcpy(importednames, llgpa, sizeof(llgpa));
|
|
||||||
if (!isdll)
|
if (!isdll)
|
||||||
memcpy(importednames + sizeof(llgpa) - 1, exitp, sizeof(exitp));
|
ilinker.add(kernel32dll, "ExitProcess");
|
||||||
strcpy(dllnames,kernel32dll);
|
ilinker.add(kernel32dll, "VirtualProtect");
|
||||||
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++)
|
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 (LE64 *tarr = idlls[ic]->lookupt; *tarr; tarr++) //changed to LE64* - Stefan Widmann
|
for (LE64 *tarr = idlls[ic]->lookupt; *tarr; tarr++)
|
||||||
if (*tarr & 0x8000000000000000ULL) //in PE32+, bit 63 indicates an ordinal - Stefan Widmann
|
if (*tarr & (1ULL << 63))
|
||||||
*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 + 0x8000000000000000ULL; //bit 63 indicates an ordinal - Stefan Widmann
|
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;
|
LE64 *tarr = idlls[ic]->lookupt;
|
||||||
LE64 *tarr = idlls[ic]->lookupt; //changed to LE64* - Stefan Widmann
|
|
||||||
#if 0 && ENABLE_THIS_AND_UNCOMPRESSION_WILL_BREAK // FIXME
|
#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;
|
||||||
#endif
|
#endif
|
||||||
set_le32(ppi,idlls[ic]->npos);
|
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 & 0x8000000000000000ULL) //bit 63 indicates ordinal - Stefan Widmann
|
if (*tarr & (1ULL << 63))
|
||||||
{
|
{
|
||||||
|
unsigned ord = *tarr & 0xffff;
|
||||||
if (idlls[ic]->isk32)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,8 +616,7 @@ unsigned PackW64Pep::processImports() // pass 1
|
|||||||
if (soimport == 4)
|
if (soimport == 4)
|
||||||
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();
|
||||||
@@ -688,7 +873,8 @@ void PackW64Pep::buildLoader(const Filter *ft)
|
|||||||
//ph.first_offset_found == 1 ? "PEMAIN03" : "",
|
//ph.first_offset_found == 1 ? "PEMAIN03" : "",
|
||||||
M_IS_LZMA(ph.method) ? "LZMA_HEAD,LZMA_ELF00,LZMA_DEC20,LZMA_TAIL" :
|
M_IS_LZMA(ph.method) ? "LZMA_HEAD,LZMA_ELF00,LZMA_DEC20,LZMA_TAIL" :
|
||||||
M_IS_NRV2B(ph.method) ? "NRV_HEAD,NRV2B" :
|
M_IS_NRV2B(ph.method) ? "NRV_HEAD,NRV2B" :
|
||||||
M_IS_NRV2D(ph.method) ? "NRV_HEAD,NRV2D" : "NRV_HEAD,NRV2E",
|
M_IS_NRV2D(ph.method) ? "NRV_HEAD,NRV2D" :
|
||||||
|
M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E" : "UNKNOWN_COMPRESSION_METHOD",
|
||||||
//getDecompressorSections(),
|
//getDecompressorSections(),
|
||||||
/*multipass ? "PEMULTIP" : */ "",
|
/*multipass ? "PEMULTIP" : */ "",
|
||||||
"PEMAIN10",
|
"PEMAIN10",
|
||||||
@@ -934,12 +1120,6 @@ void PackW64Pep::pack(OutputFile *fo)
|
|||||||
jc += isection[ic].rawdataptr;
|
jc += isection[ic].rawdataptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 //Stefan Widmann: still necessary?
|
|
||||||
// check for NeoLite
|
|
||||||
if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0)
|
|
||||||
throwCantPack("file is already compressed with another packer");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned overlay = file_size - stripDebug(overlaystart);
|
unsigned overlay = file_size - stripDebug(overlaystart);
|
||||||
if (overlay >= (unsigned) file_size)
|
if (overlay >= (unsigned) file_size)
|
||||||
{
|
{
|
||||||
@@ -1112,26 +1292,20 @@ void PackW64Pep::pack(OutputFile *fo)
|
|||||||
linker->defineSymbol("vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ?
|
linker->defineSymbol("vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ?
|
||||||
0x2000 : 0x1000); // 2 pages or 1 page
|
0x2000 : 0x1000); // 2 pages or 1 page
|
||||||
linker->defineSymbol("vp_base", addr &~ 0xfff); // page mask
|
linker->defineSymbol("vp_base", addr &~ 0xfff); // page mask
|
||||||
//NEW: offset of import adjusted - Stefan Widmann
|
linker->defineSymbol("VirtualProtect", myimport +
|
||||||
linker->defineSymbol("VirtualProtect", myimport + get_le32(oimpdlls + 16) + 16);
|
ilinker.getAddress("kernel32.dll", "VirtualProtect"));
|
||||||
}
|
}
|
||||||
// FIXME linker->defineSymbol("reloc_delt", 0u - (unsigned) (ih.imagebase - rvamin));
|
|
||||||
linker->defineSymbol("start_of_relocs", crelocs);
|
linker->defineSymbol("start_of_relocs", crelocs);
|
||||||
//NEW: offset of import adjusted - Stefan Widmann
|
if (!isdll)
|
||||||
linker->defineSymbol("ExitProcess", myimport + get_le32(oimpdlls + 16) + 40);
|
linker->defineSymbol("ExitProcess", myimport +
|
||||||
//NEW: offset of import adjusted - Stefan Widmann
|
ilinker.getAddress("kernel32.dll", "ExitProcess"));
|
||||||
linker->defineSymbol("GetProcAddress", myimport + get_le32(oimpdlls + 16) + 8);
|
linker->defineSymbol("GetProcAddress", myimport +
|
||||||
|
ilinker.getAddress("kernel32.dll", "GetProcAddress"));
|
||||||
linker->defineSymbol("kernel32_ordinals", myimport);
|
linker->defineSymbol("kernel32_ordinals", myimport);
|
||||||
//NEW: offset of import adjusted - Stefan Widmann
|
linker->defineSymbol("LoadLibraryA", myimport +
|
||||||
linker->defineSymbol("LoadLibraryA", myimport + get_le32(oimpdlls + 16));
|
ilinker.getAddress("kernel32.dll", "LoadLibraryA"));
|
||||||
linker->defineSymbol("start_of_imports", myimport);
|
linker->defineSymbol("start_of_imports", myimport);
|
||||||
linker->defineSymbol("compressed_imports", cimports);
|
linker->defineSymbol("compressed_imports", cimports);
|
||||||
#if 0
|
|
||||||
//NEW: offset of import adjusted - Stefan Widmann
|
|
||||||
linker->defineSymbol("VirtualAlloc", myimport + get_le32(oimpdlls + 16) + 24);
|
|
||||||
//NEW: offset of import adjusted - Stefan Widmann
|
|
||||||
linker->defineSymbol("VirtualFree", myimport + get_le32(oimpdlls + 16) + 32);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (M_IS_LZMA(ph.method))
|
if (M_IS_LZMA(ph.method))
|
||||||
{
|
{
|
||||||
@@ -1351,11 +1525,8 @@ void PackW64Pep::pack(OutputFile *fo)
|
|||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, &obuf);
|
||||||
|
|
||||||
#if 0 //REMOVED FOR TESTING! Stefan Widmann
|
|
||||||
// finally check the compression ratio
|
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
throwNotCompressible();
|
throwNotCompressible();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ section PEDOJUMP
|
|||||||
// =============
|
// =============
|
||||||
|
|
||||||
// this is the new TLS callback handler
|
// this is the new TLS callback handler
|
||||||
// it calls the original callbacks ONLY after the compression is done
|
// it calls the original callbacks ONLY after the decompression is done
|
||||||
|
|
||||||
section PETLSC2 // TLS_CALLBACK(hModule, reason, reserved)
|
section PETLSC2 // TLS_CALLBACK(hModule, reason, reserved)
|
||||||
ret // this ret gets overwritten with cld by PETLSC
|
ret // this ret gets overwritten with cld by PETLSC
|
||||||
|
|||||||
Reference in New Issue
Block a user