📄 pefile.cpp
字号:
} } info("Relocations: original size: %u bytes, preprocessed size: %u bytes",(unsigned) IDSIZE(PEDIR_RELOC),sorelocs);}/*************************************************************************// import handling**************************************************************************/struct import_desc{ LE32 oft; // orig first thunk char _[8]; LE32 dllname; LE32 iat; // import address table}__attribute_packed;void PeFile::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 PeFile::processImports() // pass 1{ 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; 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; 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].isk32 = strcasecmp(kernel32dll,dlls[ic].name) == 0; soimport += strlen(dlls[ic].name) + 1 + 4; for (LE32 *tarr = dlls[ic].lookupt; *tarr; tarr++) { if (*tarr & 0x80000000) { importbyordinal = true; soimport += 2; // ordinal num: 2 bytes dlls[ic].ordinal = *tarr & 0xffff; //if (dlls[ic].isk32) // kernel32ordinal = true,k32o++; } else { unsigned len = strlen(ibuf + *tarr + 2); soimport += len + 1; if (dlls[ic].shname == NULL || len < strlen (dlls[ic].shname)) dlls[ic].shname = ibuf + *tarr + 2; } 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 (!*tarr) // no imports from this dll continue; 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(idlls[ic]->name,ibuf); // I only need this info } } 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;}/*************************************************************************// export handling**************************************************************************/PeFile::Export::Export(char *_base) : base(_base), iv(_base){ COMPILE_TIME_ASSERT(sizeof(export_dir_t) == 40); ename = functionptrs = ordinals = NULL; names = NULL; memset(&edir,0,sizeof(edir)); size = 0;}PeFile::Export::~Export(){ free(ename); delete [] functionptrs; delete [] ordinals; for (unsigned ic = 0; ic < edir.names + edir.functions; ic++) free(names[ic]); delete [] names;}void PeFile::Export::convert(unsigned eoffs,unsigned esize){ memcpy(&edir,base + eoffs,sizeof(export_dir_t)); size = sizeof(export_dir_t); iv.add(eoffs,size); unsigned len = strlen(base + edir.name) + 1; ename = strdup(base + edir.name); size += len; iv.add(edir.name,len); len = 4 * edir.functions; functionptrs = new char[len + 1]; memcpy(functionptrs,base + edir.addrtable,len); size += len; iv.add(edir.addrtable,len); unsigned ic; names = new char* [edir.names + edir.functions + 1]; for (ic = 0; ic < edir.names; ic++) { char *n = base + get_le32(base + edir.nameptrtable + ic * 4); len = strlen(n) + 1; names[ic] = strdup(n); size += len; iv.add(get_le32(base + edir.nameptrtable + ic * 4),len); } iv.add(edir.nameptrtable,4 * edir.names); size += 4 * edir.names; LE32 *fp = (LE32*) functionptrs; // export forwarders for (ic = 0; ic < edir.functions; ic++) if (fp[ic] >= eoffs && fp[ic] < eoffs + esize) { char *forw = base + fp[ic]; len = strlen(forw) + 1; iv.add(forw,len); size += len; names[ic + edir.names] = strdup(forw); } else names[ic + edir.names] = NULL; len = 2 * edir.names; ordinals = new char[len + 1]; memcpy(ordinals,base + edir.ordinaltable,len); size += len; iv.add(edir.ordinaltable,len); iv.flatten(); if (iv.ivnum == 1) iv.clear();#if defined(DEBUG) else iv.dump();#endif}void PeFile::Export::build(char *newbase, unsigned newoffs){ char * const functionp = newbase + sizeof(edir); char * const namep = functionp + 4 * edir.functions; char * const ordinalp = namep + 4 * edir.names; char * const enamep = ordinalp + 2 * edir.names; char * exports = enamep + strlen(ename) + 1; edir.addrtable = newoffs + ptr_diff(functionp, newbase); edir.ordinaltable = newoffs + ptr_diff(ordinalp, newbase); memcpy(ordinalp,ordinals,2 * edir.names); edir.name = newoffs + ptr_diff(enamep, newbase); strcpy(enamep,ename); edir.nameptrtable = newoffs + ptr_diff(namep, newbase); unsigned ic; for (ic = 0; ic < edir.names; ic++) { strcpy(exports,names[ic]); set_le32(namep + 4 * ic,newoffs + ptr_diff(exports, newbase)); exports += strlen(exports) + 1; } memcpy(functionp,functionptrs,4 * edir.functions); for (ic = 0; ic < edir.functions; ic++) if (names[edir.names + ic]) { strcpy(exports,names[edir.names + ic]); set_le32(functionp + 4 * ic,newoffs + ptr_diff(exports, newbase)); exports += strlen(exports) + 1; } memcpy(newbase,&edir,sizeof(edir)); assert(exports - newbase == (int) size);}void PeFile::processExports(Export *xport) // pass1{ soexport = ALIGN_UP(IDSIZE(PEDIR_EXPORT),4); if (soexport == 0) return; if (!isdll && opt->win32_pe.compress_exports) { infoWarning("exports compressed, --compress-exports=0 might be needed"); soexport = 0; return; } xport->convert(IDADDR(PEDIR_EXPORT),IDSIZE(PEDIR_EXPORT)); soexport = ALIGN_UP(xport->getsize(), 4u); oexport = new upx_byte[soexport]; memset(oexport, 0, soexport);}void PeFile::processExports(Export *xport,unsigned newoffs) // pass2{ if (soexport) xport->build((char*) oexport,newoffs);}/*************************************************************************// TLS handling**************************************************************************/// thanks for theowl for providing me some docs, so that now I understand// what I'm doing here :)// 1999-10-17: this was tricky to find:// when the fixup records and the tls area are on the same page, then// the tls area is not relocated, because the relocation is done by// the virtual memory manager only for pages which are not yet loaded.// of course it was impossible to debug this ;-)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -