src: clang-format pefile

This commit is contained in:
Markus F.X.J. Oberhumer 2023-01-29 12:34:05 +01:00
parent 19147963b9
commit 3fa18c1799
5 changed files with 1166 additions and 1565 deletions

View File

@ -81,7 +81,7 @@ ifeq ($(shell uname),Linux)
# Markus loves clang-format, but John hates it; find a compromise # Markus loves clang-format, but John hates it; find a compromise
CLANG_FORMAT_EXCLUDE_FILES += conf.h miniacc.h version.h help.cpp CLANG_FORMAT_EXCLUDE_FILES += conf.h miniacc.h version.h help.cpp
CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli% CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli%
CLANG_FORMAT_EXCLUDE_FILES += p_w32pe.cpp p_w64pep.cpp packer_c.cpp packer_f.cpp pefile% CLANG_FORMAT_EXCLUDE_FILES += packer_c.cpp packer_f.cpp
CLANG_FORMAT_EXCLUDE_FILES += compress/compress.h filter/filter_impl.cpp CLANG_FORMAT_EXCLUDE_FILES += compress/compress.h filter/filter_impl.cpp
CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* [cu]*/*.[ch]*)) CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* [cu]*/*.[ch]*))
CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES)) CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES))

View File

@ -25,7 +25,6 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@ -34,55 +33,40 @@
#include "p_w32pe.h" #include "p_w32pe.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/i386-win32.pe.h" #include "stub/i386-win32.pe.h"
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
PackW32Pe::PackW32Pe(InputFile *f) : super(f) PackW32Pe::PackW32Pe(InputFile *f) : super(f) {}
{}
PackW32Pe::~PackW32Pe() {}
PackW32Pe::~PackW32Pe() const int *PackW32Pe::getCompressionMethods(int method, int level) const {
{} bool small = ih.codesize + ih.datasize <= 256 * 1024;
const int *PackW32Pe::getCompressionMethods(int method, int level) const
{
bool small = ih.codesize + ih.datasize <= 256*1024;
return Packer::getDefaultCompressionMethods_le32(method, level, small); return Packer::getDefaultCompressionMethods_le32(method, level, small);
} }
const int *PackW32Pe::getFilters() const {
const int *PackW32Pe::getFilters() const static const int filters[] = {0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14,
{ 0x11, FT_ULTRA_BRUTE, 0x25, 0x15, 0x12, FT_END};
static const int filters[] = {
0x26, 0x24, 0x49, 0x46, 0x16, 0x13, 0x14, 0x11,
FT_ULTRA_BRUTE, 0x25, 0x15, 0x12,
FT_END };
return filters; return filters;
} }
Linker *PackW32Pe::newLinker() const { return new ElfLinkerX86; }
Linker* PackW32Pe::newLinker() const
{
return new ElfLinkerX86;
}
/************************************************************************* /*************************************************************************
// util // util
**************************************************************************/ **************************************************************************/
int PackW32Pe::readFileHeader() int PackW32Pe::readFileHeader() {
{
if (fi->st_size() >= 0x206) { if (fi->st_size() >= 0x206) {
char buf[6]; char buf[6];
fi->seek(0x200, SEEK_SET); fi->seek(0x200, SEEK_SET);
fi->readx(buf, 6); fi->readx(buf, 6);
isrtm = memcmp(buf, "32STUB" ,6) == 0; isrtm = memcmp(buf, "32STUB", 6) == 0;
} }
return super::readFileHeader(); return super::readFileHeader();
} }
@ -91,118 +75,89 @@ int PackW32Pe::readFileHeader()
// pack // pack
**************************************************************************/ **************************************************************************/
bool PackW32Pe::canPack() bool PackW32Pe::canPack() {
{
if (!readFileHeader() || ih.cpu < 0x14c || ih.cpu > 0x150) if (!readFileHeader() || ih.cpu < 0x14c || ih.cpu > 0x150)
return false; return false;
return true; return true;
} }
void PackW32Pe::buildLoader(const Filter *ft) {
void PackW32Pe::buildLoader(const Filter *ft)
{
// recompute tlsindex (see pack() below) // recompute tlsindex (see pack() below)
unsigned tmp_tlsindex = tlsindex; unsigned tmp_tlsindex = tlsindex;
const unsigned oam1 = ih.objectalign - 1; const unsigned oam1 = ih.objectalign - 1;
const unsigned newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; const unsigned newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) & ~oam1;
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) & ~oam1) > tlsindex + 4)
tmp_tlsindex = 0; tmp_tlsindex = 0;
// prepare loader // prepare loader
initLoader(stub_i386_win32_pe, sizeof(stub_i386_win32_pe), 2); initLoader(stub_i386_win32_pe, sizeof(stub_i386_win32_pe), 2);
if (isdll) if (isdll)
addLoader("PEISDLL1"); addLoader("PEISDLL1");
addLoader("PEMAIN01", addLoader("PEMAIN01", use_stub_relocs ? "PESOCREL" : "PESOCPIC", "PESOUNC0",
use_stub_relocs ? "PESOCREL" : "PESOCPIC",
"PESOUNC0",
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "", icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
tmp_tlsindex ? "PETLSHAK" : "", tmp_tlsindex ? "PETLSHAK" : "", "PEMAIN02",
"PEMAIN02", ph.first_offset_found == 1 ? "PEMAIN03" : "", getDecompressorSections(),
ph.first_offset_found == 1 ? "PEMAIN03" : "", // multipass ? "PEMULTIP" : "",
getDecompressorSections(), "PEMAIN10", nullptr);
//multipass ? "PEMULTIP" : "",
"PEMAIN10",
nullptr
);
addLoader(tmp_tlsindex ? "PETLSHAK2" : ""); addLoader(tmp_tlsindex ? "PETLSHAK2" : "");
if (ft->id) if (ft->id) {
{
const unsigned texv = ih.codebase - rvamin; const unsigned texv = ih.codebase - rvamin;
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader(texv ? "PECTTPOS" : "PECTTNUL",nullptr); addLoader(texv ? "PECTTPOS" : "PECTTNUL", nullptr);
addFilter32(ft->id); addFilter32(ft->id);
} }
if (soimport) if (soimport)
addLoader("PEIMPORT", addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "",
importbyordinal ? "PEIBYORD" : "", importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE",
kernel32ordinal ? "PEK32ORD" : "", "PEIMDONE", nullptr);
importbyordinal ? "PEIMORD1" : "", if (sorelocs) {
"PEIMPOR2",
isdll ? "PEIERDLL" : "PEIEREXE",
"PEIMDONE",
nullptr
);
if (sorelocs)
{
addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2", addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2",
"PERELOC3,RELOC320", "PERELOC3,RELOC320", big_relocs ? "REL32BIG" : "", "RELOC32J", nullptr);
big_relocs ? "REL32BIG" : "", // FIXME: the following should be moved out of the above if
"RELOC32J", addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
nullptr big_relocs & 2 ? "PERELHI0" : "", nullptr);
);
//FIXME: the following should be moved out of the above if
addLoader(big_relocs&6 ? "PERLOHI0" : "",
big_relocs&4 ? "PERELLO0" : "",
big_relocs&2 ? "PERELHI0" : "",
nullptr
);
} }
if (use_dep_hack) if (use_dep_hack)
addLoader("PEDEPHAK", nullptr); addLoader("PEDEPHAK", nullptr);
//NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann // NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann
if(use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC", nullptr); addLoader("PETLSC", nullptr);
addLoader("PEMAIN20", nullptr); addLoader("PEMAIN20", nullptr);
if (use_clear_dirty_stack) if (use_clear_dirty_stack)
addLoader("CLEARSTACK", nullptr); addLoader("CLEARSTACK", nullptr);
addLoader("PEMAIN21", nullptr); addLoader("PEMAIN21", nullptr);
//NEW: last loader sections split up to insert TLS callback handler - Stefan Widmann // NEW: last loader sections split up to insert TLS callback handler - Stefan Widmann
addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr); addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr);
//NEW: TLS callback support PART 2, the callback handler - Stefan Widmann // NEW: TLS callback support PART 2, the callback handler - Stefan Widmann
if(use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC2", nullptr); addLoader("PETLSC2", nullptr);
addLoader("IDENTSTR,UPX1HEAD", nullptr); addLoader("IDENTSTR,UPX1HEAD", nullptr);
} }
bool PackW32Pe::handleForceOption() bool PackW32Pe::handleForceOption() {
{ return (ih.cpu < 0x14c || ih.cpu > 0x150) || (ih.opthdrsize != 0xe0) ||
return (ih.cpu < 0x14c || ih.cpu > 0x150) ((ih.flags & EXECUTABLE) == 0) ||
|| (ih.opthdrsize != 0xe0) ((ih.flags & BITS_32_MACHINE) ==
|| ((ih.flags & EXECUTABLE) == 0) 0) // NEW: 32 bit machine flag must be set - Stefan Widmann
|| ((ih.flags & BITS_32_MACHINE) == 0) //NEW: 32 bit machine flag must be set - Stefan Widmann || (ih.coffmagic !=
|| (ih.coffmagic != 0x10B) //COFF magic is 0x10B in PE files, 0x20B in PE32+ files - Stefan Widmann 0x10B) // COFF magic is 0x10B in PE files, 0x20B in PE32+ files - Stefan Widmann
|| (ih.entry == 0 && !isdll) || (ih.entry == 0 && !isdll) || (ih.ddirsentries != 16) ||
|| (ih.ddirsentries != 16) IDSIZE(PEDIR_EXCEPTION) // is this used on i386?
|| IDSIZE(PEDIR_EXCEPTION) // is this used on i386? // || IDSIZE(PEDIR_COPYRIGHT)
// || IDSIZE(PEDIR_COPYRIGHT)
; ;
} }
void PackW32Pe::defineSymbols(unsigned ncsection, unsigned upxsection, void PackW32Pe::defineSymbols(unsigned ncsection, unsigned upxsection, unsigned sizeof_oh,
unsigned sizeof_oh, unsigned ic, unsigned ic, unsigned s1addr) {
unsigned s1addr)
{
const unsigned myimport = ncsection + soresources - rvamin; const unsigned myimport = ncsection + soresources - rvamin;
// patch loader // patch loader
linker->defineSymbol("original_entry", ih.entry); linker->defineSymbol("original_entry", ih.entry);
if (use_dep_hack) if (use_dep_hack) {
{
// This works around a "protection" introduced in MSVCRT80, which // This works around a "protection" introduced in MSVCRT80, which
// works like this: // works like this:
// When the compiler detects that it would link in some code from its // When the compiler detects that it would link in some code from its
@ -222,27 +177,27 @@ void PackW32Pe::defineSymbols(unsigned ncsection, unsigned upxsection,
const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1; const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1;
// make sure we only touch the minimum number of pages // make sure we only touch the minimum number of pages
const unsigned addr = 0u - rvamin + swri; const unsigned addr = 0u - rvamin + swri;
linker->defineSymbol("swri", addr & 0xfff); // page offset linker->defineSymbol("swri", addr & 0xfff); // page offset
// check whether osection[0].flags and osection[1].flags // check whether osection[0].flags and osection[1].flags
// are on the same page // are on the same page
linker->defineSymbol("vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ? linker->defineSymbol(
0x2000 : 0x1000); // 2 pages or 1 page "vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ? 0x2000 : 0x1000); // 2 pages or 1 page
linker->defineSymbol("vp_base", addr &~ 0xfff); // page mask linker->defineSymbol("vp_base", addr & ~0xfff); // page mask
linker->defineSymbol("VirtualProtect", 0u-rvamin + linker->defineSymbol("VirtualProtect",
ilinkerGetAddress("kernel32.dll", "VirtualProtect")); 0u - rvamin + ilinkerGetAddress("kernel32.dll", "VirtualProtect"));
} }
linker->defineSymbol("reloc_delt", 0u - (unsigned) ih.imagebase - rvamin); linker->defineSymbol("reloc_delt", 0u - (unsigned) ih.imagebase - rvamin);
linker->defineSymbol("start_of_relocs", crelocs); linker->defineSymbol("start_of_relocs", crelocs);
if (ilinker) { if (ilinker) {
if (!isdll) if (!isdll)
linker->defineSymbol("ExitProcess", 0u-rvamin + linker->defineSymbol("ExitProcess",
ilinkerGetAddress("kernel32.dll", "ExitProcess")); 0u - rvamin + ilinkerGetAddress("kernel32.dll", "ExitProcess"));
linker->defineSymbol("GetProcAddress", 0u-rvamin + linker->defineSymbol("GetProcAddress",
ilinkerGetAddress("kernel32.dll", "GetProcAddress")); 0u - rvamin + ilinkerGetAddress("kernel32.dll", "GetProcAddress"));
linker->defineSymbol("kernel32_ordinals", myimport); linker->defineSymbol("kernel32_ordinals", myimport);
linker->defineSymbol("LoadLibraryA", 0u-rvamin + linker->defineSymbol("LoadLibraryA",
ilinkerGetAddress("kernel32.dll", "LoadLibraryA")); 0u - rvamin + ilinkerGetAddress("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);
} }
@ -253,8 +208,8 @@ void PackW32Pe::defineSymbols(unsigned ncsection, unsigned upxsection,
// in case of overlapping decompression, this hack is needed, // in case of overlapping decompression, this hack is needed,
// because windoze zeroes the word pointed by tlsindex before // because windoze zeroes the word pointed by tlsindex before
// it starts programs // it starts programs
linker->defineSymbol("tls_value", (tlsindex + 4 > s1addr) ? linker->defineSymbol("tls_value",
get_le32(obuf + tlsindex - s1addr - ic) : 0); (tlsindex + 4 > s1addr) ? get_le32(obuf + tlsindex - s1addr - ic) : 0);
linker->defineSymbol("tls_address", tlsindex - rvamin); linker->defineSymbol("tls_address", tlsindex - rvamin);
linker->defineSymbol("icon_delta", icondir_count - 1); linker->defineSymbol("icon_delta", icondir_count - 1);
@ -264,44 +219,34 @@ void PackW32Pe::defineSymbols(unsigned ncsection, unsigned upxsection,
linker->defineSymbol("start_of_uncompressed", 0u - esi0 + rvamin); linker->defineSymbol("start_of_uncompressed", 0u - esi0 + rvamin);
linker->defineSymbol("start_of_compressed", use_stub_relocs ? esi0 + ih.imagebase : esi0); linker->defineSymbol("start_of_compressed", use_stub_relocs ? esi0 + ih.imagebase : esi0);
if (use_tls_callbacks) if (use_tls_callbacks) {
{ // esi is ih.imagebase + rvamin
//esi is ih.imagebase + rvamin
linker->defineSymbol("tls_callbacks_ptr", tlscb_ptr); linker->defineSymbol("tls_callbacks_ptr", tlscb_ptr);
linker->defineSymbol("tls_module_base", 0u - rvamin); linker->defineSymbol("tls_module_base", 0u - rvamin);
} }
linker->defineSymbol(isdll ? "PEISDLL1" : "PEMAIN01", upxsection); linker->defineSymbol(isdll ? "PEISDLL1" : "PEMAIN01", upxsection);
//linker->dumpSymbols(); // linker->dumpSymbols();
} }
void PackW32Pe::addNewRelocations(Reloc &rel, unsigned base) void PackW32Pe::addNewRelocations(Reloc &rel, unsigned base) {
{
if (use_stub_relocs) if (use_stub_relocs)
rel.add(base + linker->getSymbolOffset("PESOCREL") + 1, 3); rel.add(base + linker->getSymbolOffset("PESOCREL") + 1, 3);
} }
void PackW32Pe::setOhDataBase(const pe_section_t *osection) void PackW32Pe::setOhDataBase(const pe_section_t *osection) { oh.database = osection[2].vaddr; }
{
oh.database = osection[2].vaddr;
}
void PackW32Pe::setOhHeaderSize(const pe_section_t *osection) void PackW32Pe::setOhHeaderSize(const pe_section_t *osection) {
{
oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(*osection) * oh.objects, oh.filealign); oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(*osection) * oh.objects, oh.filealign);
} }
void PackW32Pe::pack(OutputFile *fo) void PackW32Pe::pack(OutputFile *fo) {
{ super::pack0(fo,
super::pack0(fo (1u << IMAGE_SUBSYSTEM_WINDOWS_GUI) | (1u << IMAGE_SUBSYSTEM_WINDOWS_CUI) |
, (1u<<IMAGE_SUBSYSTEM_WINDOWS_GUI) (1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) |
| (1u<<IMAGE_SUBSYSTEM_WINDOWS_CUI) (1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) |
| (1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION) (1u << IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_ROM),
| (1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 0x400000, false);
| (1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_ROM)
, 0x400000
, false);
} }
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -30,7 +30,6 @@
*/ */
#include "conf.h" #include "conf.h"
#include "file.h" #include "file.h"
#include "filter.h" #include "filter.h"
@ -39,63 +38,46 @@
#include "p_w64pep.h" #include "p_w64pep.h"
#include "linker.h" #include "linker.h"
static const static const CLANG_FORMAT_DUMMY_STATEMENT
#include "stub/amd64-win64.pep.h" #include "stub/amd64-win64.pep.h"
/************************************************************************* /*************************************************************************
// //
**************************************************************************/ **************************************************************************/
PackW64Pep::PackW64Pep(InputFile *f) : super(f) PackW64Pep::PackW64Pep(InputFile *f) : super(f) { use_stub_relocs = false; }
{
use_stub_relocs = false;
}
PackW64Pep::~PackW64Pep() {}
PackW64Pep::~PackW64Pep() const int *PackW64Pep::getCompressionMethods(int method, int level) const {
{} bool small = ih.codesize + ih.datasize <= 256 * 1024;
const int *PackW64Pep::getCompressionMethods(int method, int level) const
{
bool small = ih.codesize + ih.datasize <= 256*1024;
return Packer::getDefaultCompressionMethods_le32(method, level, small); return Packer::getDefaultCompressionMethods_le32(method, level, small);
} }
const int *PackW64Pep::getFilters() const {
const int *PackW64Pep::getFilters() const static const int filters[] = {0x49, FT_END};
{
static const int filters[] = { 0x49, FT_END };
return filters; return filters;
} }
Linker *PackW64Pep::newLinker() const { return new ElfLinkerAMD64; }
Linker* PackW64Pep::newLinker() const
{
return new ElfLinkerAMD64;
}
/************************************************************************* /*************************************************************************
// pack // pack
**************************************************************************/ **************************************************************************/
bool PackW64Pep::canPack() bool PackW64Pep::canPack() {
{ // just check if machine type is 0x8664
//just check if machine type is 0x8664 if (!readFileHeader() || ih.cpu != 0x8664) // CPU magic of AMD64 is 0x8664
if (!readFileHeader() || ih.cpu != 0x8664) // CPU magic of AMD64 is 0x8664
return false; return false;
return true; return true;
} }
void PackW64Pep::buildLoader(const Filter *ft) {
void PackW64Pep::buildLoader(const Filter *ft)
{
// recompute tlsindex (see pack() below) // recompute tlsindex (see pack() below)
unsigned tmp_tlsindex = tlsindex; unsigned tmp_tlsindex = tlsindex;
const unsigned oam1 = ih.objectalign - 1; const unsigned oam1 = ih.objectalign - 1;
const unsigned newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; const unsigned newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) & ~oam1;
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) & ~oam1) > tlsindex + 4)
tmp_tlsindex = 0; tmp_tlsindex = 0;
// prepare loader // prepare loader
@ -105,61 +87,41 @@ void PackW64Pep::buildLoader(const Filter *ft)
addLoader("PEISDLL0"); addLoader("PEISDLL0");
if (isefi) if (isefi)
addLoader("PEISEFI0"); addLoader("PEISEFI0");
addLoader(isdll ? "PEISDLL1" : "", addLoader(isdll ? "PEISDLL1" : "", "PEMAIN01",
"PEMAIN01",
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "", icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
tmp_tlsindex ? "PETLSHAK" : "", tmp_tlsindex ? "PETLSHAK" : "", "PEMAIN02",
"PEMAIN02", // 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"
M_IS_NRV2D(ph.method) ? "NRV_HEAD,NRV2D" : : M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E"
M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E" : "UNKNOWN_COMPRESSION_METHOD", : "UNKNOWN_COMPRESSION_METHOD",
//getDecompressorSections(), // getDecompressorSections(),
/*multipass ? "PEMULTIP" : */ "", /*multipass ? "PEMULTIP" : */ "", "PEMAIN10", nullptr);
"PEMAIN10",
nullptr
);
addLoader(tmp_tlsindex ? "PETLSHAK2" : ""); addLoader(tmp_tlsindex ? "PETLSHAK2" : "");
if (ft->id) if (ft->id) {
{
const unsigned texv = ih.codebase - rvamin; const unsigned texv = ih.codebase - rvamin;
assert(ft->calls > 0); assert(ft->calls > 0);
addLoader(texv ? "PECTTPOS" : "PECTTNUL",nullptr); addLoader(texv ? "PECTTPOS" : "PECTTNUL", nullptr);
addLoader("PEFILTER49"); addLoader("PEFILTER49");
} }
if (soimport) if (soimport)
addLoader("PEIMPORT", addLoader("PEIMPORT", importbyordinal ? "PEIBYORD" : "", kernel32ordinal ? "PEK32ORD" : "",
importbyordinal ? "PEIBYORD" : "", importbyordinal ? "PEIMORD1" : "", "PEIMPOR2", isdll ? "PEIERDLL" : "PEIEREXE",
kernel32ordinal ? "PEK32ORD" : "", "PEIMDONE", nullptr);
importbyordinal ? "PEIMORD1" : "", if (sorelocs) {
"PEIMPOR2",
isdll ? "PEIERDLL" : "PEIEREXE",
"PEIMDONE",
nullptr
);
if (sorelocs)
{
addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2", addLoader(soimport == 0 || soimport + cimports != crelocs ? "PERELOC1" : "PERELOC2",
"PERELOC3", "PERELOC3", big_relocs ? "REL64BIG" : "", "RELOC64J", nullptr);
big_relocs ? "REL64BIG" : "", if __acc_cte (0) {
"RELOC64J", addLoader(big_relocs & 6 ? "PERLOHI0" : "", big_relocs & 4 ? "PERELLO0" : "",
nullptr big_relocs & 2 ? "PERELHI0" : "", nullptr);
);
if __acc_cte(0)
{
addLoader(big_relocs&6 ? "PERLOHI0" : "",
big_relocs&4 ? "PERELLO0" : "",
big_relocs&2 ? "PERELHI0" : "",
nullptr
);
} }
} }
if (use_dep_hack) if (use_dep_hack)
addLoader("PEDEPHAK", nullptr); addLoader("PEDEPHAK", nullptr);
//NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann // NEW: TLS callback support PART 1, the callback handler installation - Stefan Widmann
if(use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC", nullptr); addLoader("PETLSC", nullptr);
addLoader("PEMAIN20", nullptr); addLoader("PEMAIN20", nullptr);
@ -173,35 +135,32 @@ void PackW64Pep::buildLoader(const Filter *ft)
addLoader("PEISEFI9"); addLoader("PEISEFI9");
addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr); addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr);
//NEW: TLS callback support PART 2, the callback handler - Stefan Widmann // NEW: TLS callback support PART 2, the callback handler - Stefan Widmann
if(use_tls_callbacks) if (use_tls_callbacks)
addLoader("PETLSC2", nullptr); addLoader("PETLSC2", nullptr);
addLoader("IDENTSTR,UPX1HEAD", nullptr); addLoader("IDENTSTR,UPX1HEAD", nullptr);
} }
bool PackW64Pep::handleForceOption() bool PackW64Pep::handleForceOption() {
{ return (ih.cpu != 0x8664) // CPU magic of AMD64 is 0x8664
return (ih.cpu != 0x8664) //CPU magic of AMD64 is 0x8664 ||
|| (ih.opthdrsize != 0xF0) //optional header size is 0xF0 in PE32+ files - Stefan Widmann (ih.opthdrsize != 0xF0) // optional header size is 0xF0 in PE32+ files - Stefan Widmann
|| (ih.coffmagic != 0x20B) //COFF magic is 0x20B in PE+ files, 0x10B in "normal" 32 bit PE files - Stefan Widmann || (ih.coffmagic != 0x20B) // COFF magic is 0x20B in PE+ files, 0x10B in "normal" 32 bit
|| ((ih.flags & EXECUTABLE) == 0) // PE files - Stefan Widmann
|| ((ih.flags & BITS_32_MACHINE) != 0) //NEW: 32 bit machine flag may not be set - Stefan Widmann || ((ih.flags & EXECUTABLE) == 0) ||
|| (ih.entry == 0 && !isdll) ((ih.flags & BITS_32_MACHINE) !=
|| (ih.ddirsentries != 16) 0) // NEW: 32 bit machine flag may not be set - Stefan Widmann
; || (ih.entry == 0 && !isdll) || (ih.ddirsentries != 16);
} }
void PackW64Pep::defineSymbols(unsigned ncsection, unsigned upxsection, void PackW64Pep::defineSymbols(unsigned ncsection, unsigned upxsection, unsigned sizeof_oh,
unsigned sizeof_oh, unsigned ic, unsigned ic, unsigned s1addr) {
unsigned s1addr)
{
const unsigned myimport = ncsection + soresources - rvamin; const unsigned myimport = ncsection + soresources - rvamin;
// patch loader // patch loader
linker->defineSymbol("original_entry", ih.entry); linker->defineSymbol("original_entry", ih.entry);
if (use_dep_hack) if (use_dep_hack) {
{
// This works around a "protection" introduced in MSVCRT80, which // This works around a "protection" introduced in MSVCRT80, which
// works like this: // works like this:
// When the compiler detects that it would link in some code from its // When the compiler detects that it would link in some code from its
@ -221,32 +180,27 @@ void PackW64Pep::defineSymbols(unsigned ncsection, unsigned upxsection,
const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1; const unsigned swri = pe_offset + sizeof_oh + sizeof(pe_section_t) - 1;
// make sure we only touch the minimum number of pages // make sure we only touch the minimum number of pages
const unsigned addr = 0u - rvamin + swri; const unsigned addr = 0u - rvamin + swri;
linker->defineSymbol("swri", addr & 0xfff); // page offset linker->defineSymbol("swri", addr & 0xfff); // page offset
// check whether osection[0].flags and osection[1].flags // check whether osection[0].flags and osection[1].flags
// are on the same page // are on the same page
linker->defineSymbol("vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ? linker->defineSymbol(
0x2000 : 0x1000); // 2 pages or 1 page "vp_size", ((addr & 0xfff) + 0x28 >= 0x1000) ? 0x2000 : 0x1000); // 2 pages or 1 page
linker->defineSymbol("vp_base", addr &~ 0xfff); // page mask linker->defineSymbol("vp_base", addr & ~0xfff); // page mask
linker->defineSymbol("VirtualProtect", linker->defineSymbol("VirtualProtect", ilinkerGetAddress("kernel32.dll", "VirtualProtect"));
ilinkerGetAddress("kernel32.dll", "VirtualProtect"));
} }
linker->defineSymbol("start_of_relocs", crelocs); linker->defineSymbol("start_of_relocs", crelocs);
if (ilinker) { if (ilinker) {
if (!isdll) if (!isdll)
linker->defineSymbol("ExitProcess", linker->defineSymbol("ExitProcess", ilinkerGetAddress("kernel32.dll", "ExitProcess"));
ilinkerGetAddress("kernel32.dll", "ExitProcess")); linker->defineSymbol("GetProcAddress", ilinkerGetAddress("kernel32.dll", "GetProcAddress"));
linker->defineSymbol("GetProcAddress",
ilinkerGetAddress("kernel32.dll", "GetProcAddress"));
linker->defineSymbol("kernel32_ordinals", myimport); linker->defineSymbol("kernel32_ordinals", myimport);
linker->defineSymbol("LoadLibraryA", linker->defineSymbol("LoadLibraryA", ilinkerGetAddress("kernel32.dll", "LoadLibraryA"));
ilinkerGetAddress("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 (M_IS_LZMA(ph.method)) if (M_IS_LZMA(ph.method)) {
{
linker->defineSymbol("lzma_c_len", ph.c_len - 2); linker->defineSymbol("lzma_c_len", ph.c_len - 2);
linker->defineSymbol("lzma_u_len", ph.u_len); linker->defineSymbol("lzma_u_len", ph.u_len);
} }
@ -255,8 +209,8 @@ void PackW64Pep::defineSymbols(unsigned ncsection, unsigned upxsection,
// in case of overlapping decompression, this hack is needed, // in case of overlapping decompression, this hack is needed,
// because windoze zeroes the word pointed by tlsindex before // because windoze zeroes the word pointed by tlsindex before
// it starts programs // it starts programs
linker->defineSymbol("tls_value", (tlsindex + 4 > s1addr) ? linker->defineSymbol("tls_value",
get_le32(obuf + tlsindex - s1addr - ic) : 0); (tlsindex + 4 > s1addr) ? get_le32(obuf + tlsindex - s1addr - ic) : 0);
linker->defineSymbol("tls_address", tlsindex - rvamin); linker->defineSymbol("tls_address", tlsindex - rvamin);
linker->defineSymbol("icon_delta", icondir_count - 1); linker->defineSymbol("icon_delta", icondir_count - 1);
@ -266,8 +220,7 @@ void PackW64Pep::defineSymbols(unsigned ncsection, unsigned upxsection,
linker->defineSymbol("start_of_uncompressed", 0u - esi0 + rvamin); linker->defineSymbol("start_of_uncompressed", 0u - esi0 + rvamin);
linker->defineSymbol("start_of_compressed", esi0); linker->defineSymbol("start_of_compressed", esi0);
if (use_tls_callbacks) if (use_tls_callbacks) {
{
linker->defineSymbol("tls_callbacks_ptr", tlscb_ptr - ih.imagebase); linker->defineSymbol("tls_callbacks_ptr", tlscb_ptr - ih.imagebase);
linker->defineSymbol("tls_module_base", 0u - rvamin); linker->defineSymbol("tls_module_base", 0u - rvamin);
} }
@ -275,21 +228,17 @@ void PackW64Pep::defineSymbols(unsigned ncsection, unsigned upxsection,
linker->defineSymbol("START", upxsection); linker->defineSymbol("START", upxsection);
} }
void PackW64Pep::setOhHeaderSize(const pe_section_t *osection) void PackW64Pep::setOhHeaderSize(const pe_section_t *osection) {
{
oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(*osection) * oh.objects, oh.filealign); oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(*osection) * oh.objects, oh.filealign);
} }
void PackW64Pep::pack(OutputFile *fo) void PackW64Pep::pack(OutputFile *fo) {
{ super::pack0(fo,
super::pack0(fo (1u << IMAGE_SUBSYSTEM_WINDOWS_GUI) | (1u << IMAGE_SUBSYSTEM_WINDOWS_CUI) |
, (1u<<IMAGE_SUBSYSTEM_WINDOWS_GUI) (1u << IMAGE_SUBSYSTEM_EFI_APPLICATION) |
| (1u<<IMAGE_SUBSYSTEM_WINDOWS_CUI) (1u << IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) |
| (1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION) (1u << IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) | (1u << IMAGE_SUBSYSTEM_EFI_ROM),
| (1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) 0x0000000140000000ULL);
| (1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_ROM)
, 0x0000000140000000ULL);
} }
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

File diff suppressed because it is too large Load Diff

View File

@ -25,19 +25,17 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com> <markus@oberhumer.com> <ezerotven+github@gmail.com>
*/ */
#pragma once
#ifndef __UPX_PEFILE_H #ifndef UPX_PEFILE_H__
#define __UPX_PEFILE_H 1 #define UPX_PEFILE_H__ 1
#include "util/membuffer.h" #include "util/membuffer.h"
/************************************************************************* /*************************************************************************
// general/pe handling // general/pe handling
**************************************************************************/ **************************************************************************/
class PeFile : public Packer class PeFile : public Packer {
{
typedef Packer super; typedef Packer super;
public: public:
virtual int getVersion() const override { return 13; } virtual int getVersion() const override { return 13; }
@ -53,20 +51,17 @@ protected:
virtual ~PeFile(); virtual ~PeFile();
void readSectionHeaders(unsigned objs, unsigned sizeof_ih); void readSectionHeaders(unsigned objs, unsigned sizeof_ih);
unsigned readSections(unsigned objs, unsigned usize, unsigned readSections(unsigned objs, unsigned usize, unsigned ih_filealign,
unsigned ih_filealign, unsigned ih_datasize); unsigned ih_datasize);
void checkHeaderValues(unsigned subsystem, unsigned mask, void checkHeaderValues(unsigned subsystem, unsigned mask, unsigned ih_entry,
unsigned ih_entry, unsigned ih_filealign); unsigned ih_filealign);
unsigned handleStripRelocs(upx_uint64_t ih_imagebase, unsigned handleStripRelocs(upx_uint64_t ih_imagebase, upx_uint64_t default_imagebase,
upx_uint64_t default_imagebase,
LE16 &dllflags); LE16 &dllflags);
virtual bool handleForceOption() = 0; virtual bool handleForceOption() = 0;
virtual void callCompressWithFilters(Filter &, int filter_strategy, virtual void callCompressWithFilters(Filter &, int filter_strategy, unsigned ih_codebase);
unsigned ih_codebase); virtual void defineSymbols(unsigned ncsection, unsigned upxsection, unsigned sizeof_oh,
virtual void defineSymbols(unsigned ncsection, unsigned upxsection, unsigned isize_isplit, unsigned s1addr) = 0;
unsigned sizeof_oh, unsigned isize_isplit,
unsigned s1addr) = 0;
virtual void addNewRelocations(Reloc &, unsigned) {} virtual void addNewRelocations(Reloc &, unsigned) {}
void callProcessRelocs(Reloc &rel, unsigned &ic); void callProcessRelocs(Reloc &rel, unsigned &ic);
void callProcessResources(Resource &res, unsigned &ic); void callProcessResources(Resource &res, unsigned &ic);
@ -75,20 +70,18 @@ protected:
virtual void setOhHeaderSize(const pe_section_t *osection) = 0; virtual void setOhHeaderSize(const pe_section_t *osection) = 0;
template <typename LEXX, typename ht> template <typename LEXX, typename ht>
void pack0(OutputFile *fo, ht &ih, ht &oh, void pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
unsigned subsystem_mask, upx_uint64_t default_imagebase, upx_uint64_t default_imagebase, bool last_section_rsrc_only);
bool last_section_rsrc_only);
template <typename ht, typename LEXX, typename ord_mask_t> template <typename ht, typename LEXX, typename ord_mask_t>
void unpack0(OutputFile *fo, const ht &ih, ht &oh, void unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask, bool set_oft);
ord_mask_t ord_mask, bool set_oft);
// unpacker capabilities // unpacker capabilities
virtual bool canUnpackVersion(int version) const override virtual bool canUnpackVersion(int version) const override {
{ return (version >= 12 && version <= 13); } return (version >= 12 && version <= 13);
}
int canUnpack0(unsigned max_sections, unsigned objs, int canUnpack0(unsigned max_sections, unsigned objs, unsigned ih_entry, unsigned ih_size);
unsigned ih_entry, unsigned ih_size);
protected: protected:
virtual int readFileHeader(); virtual int readFileHeader();
@ -101,8 +94,7 @@ protected:
unsigned processImports0(ord_mask_t ord_mask); unsigned processImports0(ord_mask_t ord_mask);
template <typename LEXX, typename ord_mask_t> template <typename LEXX, typename ord_mask_t>
void rebuildImports(SPAN_S(upx_byte) & extrainfo, void rebuildImports(SPAN_S(upx_byte) & extrainfo, ord_mask_t ord_mask, bool set_oft);
ord_mask_t ord_mask, bool set_oft);
virtual unsigned processImports() = 0; virtual unsigned processImports() = 0;
virtual void processImports2(unsigned, unsigned); virtual void processImports2(unsigned, unsigned);
MemBuffer mb_oimport; MemBuffer mb_oimport;
@ -118,8 +110,7 @@ protected:
virtual void processRelocs() = 0; virtual void processRelocs() = 0;
void processRelocs(Reloc *); void processRelocs(Reloc *);
void rebuildRelocs(SPAN_S(upx_byte) &, unsigned bits, void rebuildRelocs(SPAN_S(upx_byte) &, unsigned bits, unsigned flags, upx_uint64_t imagebase);
unsigned flags, upx_uint64_t imagebase);
MemBuffer mb_orelocs; MemBuffer mb_orelocs;
SPAN_0(upx_byte) orelocs = nullptr; SPAN_0(upx_byte) orelocs = nullptr;
unsigned sorelocs; unsigned sorelocs;
@ -127,7 +118,7 @@ protected:
unsigned soxrelocs; unsigned soxrelocs;
void processExports(Export *); void processExports(Export *);
void processExports(Export *,unsigned); void processExports(Export *, unsigned);
void rebuildExports(); void rebuildExports();
MemBuffer mb_oexport; MemBuffer mb_oexport;
SPAN_0(upx_byte) oexport = nullptr; SPAN_0(upx_byte) oexport = nullptr;
@ -143,11 +134,10 @@ protected:
template <typename> template <typename>
struct tls_traits; struct tls_traits;
template <typename LEXX> template <typename LEXX>
void processTls1(Interval *iv, void processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t imagebase,
typename tls_traits<LEXX>::cb_value_t imagebase,
unsigned imagesize); // pass 1 unsigned imagesize); // pass 1
template <typename LEXX> template <typename LEXX>
void processTls2(Reloc *rel,const Interval *iv,unsigned newaddr, void processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
typename tls_traits<LEXX>::cb_value_t imagebase); // pass 2 typename tls_traits<LEXX>::cb_value_t imagebase); // pass 2
virtual void processTls(Interval *iv) = 0; virtual void processTls(Interval *iv) = 0;
virtual void processTls(Reloc *r, const Interval *iv, unsigned a) = 0; virtual void processTls(Reloc *r, const Interval *iv, unsigned a) = 0;
@ -175,22 +165,22 @@ protected:
bool importbyordinal; bool importbyordinal;
bool kernel32ordinal; bool kernel32ordinal;
unsigned rvamin; unsigned rvamin;
unsigned cimports; // rva of preprocessed imports unsigned cimports; // rva of preprocessed imports
unsigned crelocs; // rva of preprocessed fixups unsigned crelocs; // rva of preprocessed fixups
int big_relocs; int big_relocs;
struct alignas(1) ddirs_t { struct alignas(1) ddirs_t {
LE32 vaddr; LE32 vaddr;
LE32 size; LE32 size;
}; };
ddirs_t *iddirs; ddirs_t *iddirs;
ddirs_t *oddirs; ddirs_t *oddirs;
struct alignas(1) import_desc { struct alignas(1) import_desc {
LE32 oft; // orig first thunk LE32 oft; // orig first thunk
char _[8]; char _[8];
LE32 dllname; LE32 dllname;
LE32 iat; // import address table LE32 iat; // import address table
}; };
LE32 &IDSIZE(unsigned x); LE32 &IDSIZE(unsigned x);
@ -199,13 +189,13 @@ protected:
LE32 &ODADDR(unsigned x); LE32 &ODADDR(unsigned x);
struct alignas(1) pe_section_t { struct alignas(1) pe_section_t {
char name[8]; char name[8];
LE32 vsize; LE32 vsize;
LE32 vaddr; LE32 vaddr;
LE32 size; LE32 size;
LE32 rawdataptr; LE32 rawdataptr;
char _[12]; char _[12];
LE32 flags; LE32 flags;
}; };
MemBuffer mb_isection; MemBuffer mb_isection;
@ -217,105 +207,119 @@ protected:
bool use_clear_dirty_stack; bool use_clear_dirty_stack;
bool use_stub_relocs; bool use_stub_relocs;
static unsigned virta2objnum(unsigned, SPAN_0(pe_section_t), unsigned);
static unsigned virta2objnum (unsigned, SPAN_0(pe_section_t), unsigned); unsigned tryremove(unsigned, unsigned);
unsigned tryremove (unsigned, unsigned);
enum { enum {
PEDIR_EXPORT = 0, PEDIR_EXPORT = 0,
PEDIR_IMPORT = 1, PEDIR_IMPORT = 1,
PEDIR_RESOURCE = 2, PEDIR_RESOURCE = 2,
PEDIR_EXCEPTION = 3, // Exception table PEDIR_EXCEPTION = 3, // Exception table
PEDIR_SEC = 4, // Certificate table (file pointer) PEDIR_SEC = 4, // Certificate table (file pointer)
PEDIR_RELOC = 5, PEDIR_RELOC = 5,
PEDIR_DEBUG = 6, PEDIR_DEBUG = 6,
PEDIR_COPYRIGHT = 7, // Architecture-specific data PEDIR_COPYRIGHT = 7, // Architecture-specific data
PEDIR_GLOBALPTR = 8, // Global pointer PEDIR_GLOBALPTR = 8, // Global pointer
PEDIR_TLS = 9, PEDIR_TLS = 9,
PEDIR_LOADCONF = 10, // Load Config Table PEDIR_LOADCONF = 10, // Load Config Table
PEDIR_BOUNDIM = 11, PEDIR_BOUNDIM = 11,
PEDIR_IAT = 12, PEDIR_IAT = 12,
PEDIR_DELAYIMP = 13, // Delay Import Descriptor PEDIR_DELAYIMP = 13, // Delay Import Descriptor
PEDIR_COMRT = 14, // Com+ Runtime Header PEDIR_COMRT = 14, // Com+ Runtime Header
}; };
enum { enum {
PEFL_CODE = 0x20, PEFL_CODE = 0x20,
PEFL_DATA = 0x40, PEFL_DATA = 0x40,
PEFL_BSS = 0x80, PEFL_BSS = 0x80,
PEFL_INFO = 0x200, PEFL_INFO = 0x200,
PEFL_EXTRELS = 0x01000000, // extended relocations PEFL_EXTRELS = 0x01000000, // extended relocations
PEFL_DISCARD = 0x02000000, PEFL_DISCARD = 0x02000000,
PEFL_NOCACHE = 0x04000000, PEFL_NOCACHE = 0x04000000,
PEFL_NOPAGE = 0x08000000, PEFL_NOPAGE = 0x08000000,
PEFL_SHARED = 0x10000000, PEFL_SHARED = 0x10000000,
PEFL_EXEC = 0x20000000, PEFL_EXEC = 0x20000000,
PEFL_READ = 0x40000000, PEFL_READ = 0x40000000,
PEFL_WRITE = 0x80000000, PEFL_WRITE = 0x80000000,
}; };
enum { enum {
RELOCS_STRIPPED = 0x0001, RELOCS_STRIPPED = 0x0001,
EXECUTABLE = 0x0002, EXECUTABLE = 0x0002,
LNUM_STRIPPED = 0x0004, LNUM_STRIPPED = 0x0004,
LSYMS_STRIPPED = 0x0008, LSYMS_STRIPPED = 0x0008,
AGGRESSIVE_TRIM = 0x0010, AGGRESSIVE_TRIM = 0x0010,
TWO_GIGS_AWARE = 0x0020, TWO_GIGS_AWARE = 0x0020,
FLITTLE_ENDIAN = 0x0080, FLITTLE_ENDIAN = 0x0080,
BITS_32_MACHINE = 0x0100, BITS_32_MACHINE = 0x0100,
DEBUG_STRIPPED = 0x0200, DEBUG_STRIPPED = 0x0200,
REMOVABLE_SWAP = 0x0400, REMOVABLE_SWAP = 0x0400,
SYSTEM_PROGRAM = 0x1000, SYSTEM_PROGRAM = 0x1000,
DLL_FLAG = 0x2000, DLL_FLAG = 0x2000,
FBIG_ENDIAN = 0x8000, FBIG_ENDIAN = 0x8000,
}; };
//NEW: DLL characteristics definition for ASLR, ... - Stefan Widmann // NEW: DLL characteristics definition for ASLR, ... - Stefan Widmann
enum { enum {
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020,
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040, IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040,
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080, IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100, IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100,
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200, IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400, IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800, IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000, IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
IMAGE_DLLCHARACTERISTICS_CONTROL_FLOW_GUARD = 0x4000, IMAGE_DLLCHARACTERISTICS_CONTROL_FLOW_GUARD = 0x4000,
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000,
}; };
enum { enum {
IMAGE_SUBSYSTEM_UNKNOWN = 0, IMAGE_SUBSYSTEM_UNKNOWN = 0,
IMAGE_SUBSYSTEM_NATIVE = 1, IMAGE_SUBSYSTEM_NATIVE = 1,
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Grapical IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Grapical
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character-mode IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character-mode
IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5, IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5,
IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7, IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7,
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
IMAGE_SUBSYSTEM_EFI_ROM = 13, IMAGE_SUBSYSTEM_EFI_ROM = 13,
IMAGE_SUBSYSTEM_XBOX = 14, IMAGE_SUBSYSTEM_XBOX = 14,
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16, IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16,
}; };
// predefined resource types // predefined resource types
enum { enum {
RT_CURSOR = 1, RT_BITMAP, RT_ICON, RT_MENU, RT_DIALOG, RT_STRING, RT_CURSOR = 1,
RT_FONTDIR, RT_FONT, RT_ACCELERATOR, RT_RCDATA, RT_MESSAGETABLE, RT_BITMAP,
RT_GROUP_CURSOR, RT_GROUP_ICON = 14, RT_VERSION = 16, RT_DLGINCLUDE, RT_ICON,
RT_PLUGPLAY = 19, RT_VXD, RT_ANICURSOR, RT_ANIICON, RT_HTML, RT_MENU,
RT_MANIFEST, RT_LAST RT_DIALOG,
RT_STRING,
RT_FONTDIR,
RT_FONT,
RT_ACCELERATOR,
RT_RCDATA,
RT_MESSAGETABLE,
RT_GROUP_CURSOR,
RT_GROUP_ICON = 14,
RT_VERSION = 16,
RT_DLGINCLUDE,
RT_PLUGPLAY = 19,
RT_VXD,
RT_ANICURSOR,
RT_ANIICON,
RT_HTML,
RT_MANIFEST,
RT_LAST
}; };
class Interval : private noncopyable class Interval : private noncopyable {
{
unsigned capacity; unsigned capacity;
void *base; void *base;
public: public:
struct interval struct interval {
{
unsigned start, len; unsigned start, len;
} *ivarr; } *ivarr;
@ -324,9 +328,9 @@ protected:
Interval(void *b); Interval(void *b);
~Interval(); ~Interval();
void add(unsigned start,unsigned len); void add(unsigned start, unsigned len);
void add(const void *start,unsigned len); void add(const void *start, unsigned len);
void add(const void *start,const void *end); void add(const void *start, const void *end);
void add(const Interval *iv); void add(const Interval *iv);
void flatten(); void flatten();
@ -334,11 +338,10 @@ protected:
void dump() const; void dump() const;
private: private:
static int __acc_cdecl_qsort compare(const void *p1,const void *p2); static int __acc_cdecl_qsort compare(const void *p1, const void *p2);
}; };
class Reloc : private noncopyable class Reloc : private noncopyable {
{
upx_byte *start; upx_byte *start;
unsigned size; unsigned size;
@ -350,18 +353,17 @@ protected:
unsigned counts[16]; unsigned counts[16];
public: public:
Reloc(upx_byte *,unsigned); Reloc(upx_byte *, unsigned);
Reloc(unsigned rnum); Reloc(unsigned rnum);
// //
bool next(unsigned &pos,unsigned &type); bool next(unsigned &pos, unsigned &type);
const unsigned *getcounts() const { return counts; } const unsigned *getcounts() const { return counts; }
// //
void add(unsigned pos,unsigned type); void add(unsigned pos, unsigned type);
void finish(upx_byte* &p,unsigned &size); void finish(upx_byte *&p, unsigned &size);
}; };
class Resource : private noncopyable class Resource : private noncopyable {
{
struct res_dir_entry; struct res_dir_entry;
struct res_dir; struct res_dir;
struct res_data; struct res_data;
@ -371,29 +373,28 @@ protected:
MemBuffer mb_start; MemBuffer mb_start;
const upx_byte *start; const upx_byte *start;
upx_byte *newstart; upx_byte *newstart;
upx_rnode *root; upx_rnode *root;
upx_rleaf *head; upx_rleaf *head;
upx_rleaf *current; upx_rleaf *current;
unsigned dsize; unsigned dsize;
unsigned ssize; unsigned ssize;
const upx_byte *ibufstart; const upx_byte *ibufstart;
const upx_byte *ibufend; const upx_byte *ibufend;
void check(const res_dir*,unsigned); void check(const res_dir *, unsigned);
upx_rnode *convert(const void *,upx_rnode *,unsigned); upx_rnode *convert(const void *, upx_rnode *, unsigned);
void build(const upx_rnode *,unsigned &,unsigned &,unsigned); void build(const upx_rnode *, unsigned &, unsigned &, unsigned);
void clear(upx_byte *,unsigned,Interval *); void clear(upx_byte *, unsigned, Interval *);
void dump(const upx_rnode *,unsigned) const; void dump(const upx_rnode *, unsigned) const;
void destroy(upx_rnode *urd,unsigned level); void destroy(upx_rnode *urd, unsigned level);
void ibufcheck(const void *m, unsigned size); void ibufcheck(const void *m, unsigned size);
public: public:
Resource(const upx_byte *ibufstart, const upx_byte *ibufen); Resource(const upx_byte *ibufstart, const upx_byte *ibufen);
Resource(const upx_byte *p, const upx_byte *ibufstart, Resource(const upx_byte *p, const upx_byte *ibufstart, const upx_byte *ibufend);
const upx_byte *ibufend);
~Resource(); ~Resource();
void init(const upx_byte *); void init(const upx_byte *);
@ -418,26 +419,25 @@ protected:
*/ */
}; };
class Export : private noncopyable class Export : private noncopyable {
{
struct alignas(1) export_dir_t { struct alignas(1) export_dir_t {
char _[12]; // flags, timedate, version char _[12]; // flags, timedate, version
LE32 name; LE32 name;
char __[4]; // ordinal base char __[4]; // ordinal base
LE32 functions; LE32 functions;
LE32 names; LE32 names;
LE32 addrtable; LE32 addrtable;
LE32 nameptrtable; LE32 nameptrtable;
LE32 ordinaltable; LE32 ordinaltable;
}; };
export_dir_t edir; export_dir_t edir;
char *ename; char *ename;
char *functionptrs; char *functionptrs;
char *ordinals; char *ordinals;
char **names; char **names;
char *base; char *base;
unsigned size; unsigned size;
Interval iv; Interval iv;
@ -445,21 +445,19 @@ protected:
Export(char *_base); Export(char *_base);
~Export(); ~Export();
void convert(unsigned eoffs,unsigned esize); void convert(unsigned eoffs, unsigned esize);
void build(char *base,unsigned newoffs); void build(char *base, unsigned newoffs);
unsigned getsize() const { return size; } unsigned getsize() const { return size; }
}; };
}; };
class PeFile32 : public PeFile class PeFile32 : public PeFile {
{
typedef PeFile super; typedef PeFile super;
protected: protected:
PeFile32(InputFile *f); PeFile32(InputFile *f);
virtual ~PeFile32(); virtual ~PeFile32();
void pack0(OutputFile *fo, unsigned subsystem_mask, void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase,
upx_uint64_t default_imagebase, bool last_section_rsrc_only); bool last_section_rsrc_only);
virtual void unpack(OutputFile *fo) override; virtual void unpack(OutputFile *fo) override;
virtual int canUnpack() override; virtual int canUnpack() override;
@ -472,39 +470,39 @@ protected:
struct alignas(1) pe_header_t { struct alignas(1) pe_header_t {
// 0x0 // 0x0
char _[4]; // pemagic char _[4]; // pemagic
LE16 cpu; LE16 cpu;
LE16 objects; LE16 objects;
char __[12]; // timestamp + reserved char __[12]; // timestamp + reserved
LE16 opthdrsize; LE16 opthdrsize;
LE16 flags; LE16 flags;
// optional header // optional header
LE16 coffmagic; // NEW: Stefan Widmann LE16 coffmagic; // NEW: Stefan Widmann
char ___[2]; // linkerversion char ___[2]; // linkerversion
LE32 codesize; LE32 codesize;
// 0x20 // 0x20
LE32 datasize; LE32 datasize;
LE32 bsssize; LE32 bsssize;
LE32 entry; LE32 entry;
LE32 codebase; LE32 codebase;
// 0x30 // 0x30
LE32 database; LE32 database;
// nt specific fields // nt specific fields
LE32 imagebase; LE32 imagebase;
LE32 objectalign; LE32 objectalign;
LE32 filealign; // should set to 0x200 ? LE32 filealign; // should set to 0x200 ?
// 0x40 // 0x40
char ____[16]; // versions char ____[16]; // versions
// 0x50 // 0x50
LE32 imagesize; LE32 imagesize;
LE32 headersize; LE32 headersize;
LE32 chksum; // should set to 0 LE32 chksum; // should set to 0
LE16 subsystem; LE16 subsystem;
LE16 dllflags; LE16 dllflags;
// 0x60 // 0x60
char _____[20]; // stack + heap sizes char _____[20]; // stack + heap sizes
// 0x74 // 0x74
LE32 ddirsentries; // usually 16 LE32 ddirsentries; // usually 16
ddirs_t ddirs[16]; ddirs_t ddirs[16];
}; };
@ -512,15 +510,13 @@ protected:
pe_header_t ih, oh; pe_header_t ih, oh;
}; };
class PeFile64 : public PeFile class PeFile64 : public PeFile {
{
typedef PeFile super; typedef PeFile super;
protected: protected:
PeFile64(InputFile *f); PeFile64(InputFile *f);
virtual ~PeFile64(); virtual ~PeFile64();
void pack0(OutputFile *fo, unsigned subsystem_mask, void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase);
upx_uint64_t default_imagebase);
virtual void unpack(OutputFile *fo) override; virtual void unpack(OutputFile *fo) override;
virtual int canUnpack() override; virtual int canUnpack() override;
@ -534,39 +530,39 @@ protected:
struct alignas(1) pe_header_t { struct alignas(1) pe_header_t {
// 0x0 // 0x0
char _[4]; // pemagic char _[4]; // pemagic
LE16 cpu; LE16 cpu;
LE16 objects; // number of sections LE16 objects; // number of sections
char __[12]; // timestamp + reserved char __[12]; // timestamp + reserved
LE16 opthdrsize; LE16 opthdrsize;
LE16 flags; // characteristics LE16 flags; // characteristics
// optional header // optional header
LE16 coffmagic; // NEW: Stefan Widmann LE16 coffmagic; // NEW: Stefan Widmann
char ___[2]; // linkerversion char ___[2]; // linkerversion
LE32 codesize; LE32 codesize;
// 0x20 // 0x20
LE32 datasize; LE32 datasize;
LE32 bsssize; LE32 bsssize;
LE32 entry; // still a 32 bit RVA LE32 entry; // still a 32 bit RVA
LE32 codebase; LE32 codebase;
// 0x30 // 0x30
//LE32 database; // field does not exist in PE+! // LE32 database; // field does not exist in PE+!
// nt specific fields // nt specific fields
LE64 imagebase; // LE32 -> LE64 - Stefan Widmann standard is 0x0000000140000000 LE64 imagebase; // LE32 -> LE64 - Stefan Widmann standard is 0x0000000140000000
LE32 objectalign; LE32 objectalign;
LE32 filealign; // should set to 0x200 ? LE32 filealign; // should set to 0x200 ?
// 0x40 // 0x40
char ____[16]; // versions char ____[16]; // versions
// 0x50 // 0x50
LE32 imagesize; LE32 imagesize;
LE32 headersize; LE32 headersize;
LE32 chksum; // should set to 0 LE32 chksum; // should set to 0
LE16 subsystem; LE16 subsystem;
LE16 dllflags; LE16 dllflags;
// 0x60 // 0x60
char _____[36]; // stack + heap sizes + loader flag char _____[36]; // stack + heap sizes + loader flag
// 0x84 // 0x84
LE32 ddirsentries; // usually 16 LE32 ddirsentries; // usually 16
ddirs_t ddirs[16]; ddirs_t ddirs[16];
}; };