mirror of https://github.com/upx/upx.git
627 lines
20 KiB
C++
627 lines
20 KiB
C++
/* pefile.h --
|
|
|
|
This file is part of the UPX executable compressor.
|
|
|
|
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
|
Copyright (C) 1996-2023 Laszlo Molnar
|
|
All Rights Reserved.
|
|
|
|
UPX and the UCL library are free software; you can redistribute them
|
|
and/or modify them under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; see the file COPYING.
|
|
If not, write to the Free Software Foundation, Inc.,
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
|
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
/*************************************************************************
|
|
// general/pe handling
|
|
**************************************************************************/
|
|
|
|
class PeFile : public Packer {
|
|
typedef Packer super;
|
|
public:
|
|
virtual int getVersion() const override { return 13; }
|
|
protected:
|
|
class Interval;
|
|
class Reloc;
|
|
class Resource;
|
|
class Export;
|
|
class ImportLinker;
|
|
struct pe_section_t;
|
|
|
|
explicit PeFile(InputFile *f);
|
|
virtual ~PeFile() noexcept;
|
|
|
|
void readSectionHeaders(unsigned objs, unsigned sizeof_ih);
|
|
unsigned readSections(unsigned objs, unsigned usize, unsigned ih_filealign,
|
|
unsigned ih_datasize);
|
|
void checkHeaderValues(unsigned subsystem, unsigned mask, unsigned ih_entry,
|
|
unsigned ih_filealign);
|
|
unsigned handleStripRelocs(upx_uint64_t ih_imagebase, upx_uint64_t default_imagebase,
|
|
LE16 &dllflags);
|
|
|
|
virtual bool needForceOption() const = 0;
|
|
virtual void callCompressWithFilters(Filter &, int filter_strategy, unsigned ih_codebase);
|
|
virtual void defineSymbols(unsigned ncsection, unsigned upxsection, unsigned sizeof_oh,
|
|
unsigned isize_isplit, unsigned s1addr) = 0;
|
|
virtual void addNewRelocations(Reloc &, unsigned) {}
|
|
void callProcessRelocs(Reloc &rel, unsigned &ic);
|
|
void callProcessResources(Resource &res, unsigned &ic);
|
|
virtual unsigned getProcessImportParam(unsigned) { return 0; }
|
|
virtual void setOhDataBase(const pe_section_t *osection) = 0;
|
|
virtual void setOhHeaderSize(const pe_section_t *osection) = 0;
|
|
|
|
template <typename LEXX, typename ht>
|
|
void pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
|
|
upx_uint64_t default_imagebase, bool last_section_rsrc_only);
|
|
|
|
template <typename ht, typename LEXX, typename ord_mask_t>
|
|
void unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask, bool set_oft);
|
|
|
|
// unpacker capabilities
|
|
virtual bool canUnpackVersion(int version) const override {
|
|
return (version >= 12 && version <= 13);
|
|
}
|
|
|
|
int canUnpack0(unsigned max_sections, unsigned objs, unsigned ih_entry, unsigned ih_size);
|
|
|
|
protected:
|
|
static int checkMachine(unsigned cpu);
|
|
virtual int readFileHeader();
|
|
virtual bool testUnpackVersion(int version) const override;
|
|
virtual void readPeHeader() = 0;
|
|
|
|
unsigned pe_offset;
|
|
|
|
template <typename LEXX, typename ord_mask_t>
|
|
unsigned processImports0(ord_mask_t ord_mask);
|
|
|
|
template <typename LEXX, typename ord_mask_t>
|
|
void rebuildImports(SPAN_S(byte) & extra_info, ord_mask_t ord_mask, bool set_oft);
|
|
virtual unsigned processImports() = 0;
|
|
virtual void processImports2(unsigned, unsigned);
|
|
MemBuffer mb_oimport;
|
|
SPAN_0(byte) oimport = nullptr;
|
|
unsigned soimport;
|
|
byte *oimpdlls = nullptr;
|
|
unsigned soimpdlls;
|
|
ImportLinker *ilinker = nullptr;
|
|
virtual const char *kernelDll() const { return "KERNEL32.DLL"; }
|
|
void addKernelImport(const char *);
|
|
virtual void addStubImports();
|
|
upx_uint64_t ilinkerGetAddress(const char *, const char *) const;
|
|
|
|
virtual void processRelocs() = 0;
|
|
void processRelocs(Reloc *);
|
|
void rebuildRelocs(SPAN_S(byte) &, unsigned bits, unsigned flags, upx_uint64_t imagebase);
|
|
MemBuffer mb_orelocs;
|
|
SPAN_0(byte) orelocs = nullptr;
|
|
unsigned sorelocs;
|
|
byte *oxrelocs = nullptr;
|
|
unsigned soxrelocs;
|
|
|
|
void processExports(Export *);
|
|
void processExports(Export *, unsigned);
|
|
void rebuildExports();
|
|
MemBuffer mb_oexport;
|
|
SPAN_0(byte) oexport = nullptr;
|
|
unsigned soexport;
|
|
|
|
void processResources(Resource *);
|
|
void processResources(Resource *, unsigned);
|
|
void rebuildResources(SPAN_S(byte) &, unsigned);
|
|
MemBuffer mb_oresources;
|
|
SPAN_0(byte) oresources = nullptr;
|
|
unsigned soresources;
|
|
|
|
template <typename>
|
|
struct tls_traits;
|
|
template <typename LEXX>
|
|
void processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t imagebase,
|
|
unsigned imagesize); // pass 1
|
|
template <typename LEXX>
|
|
void processTls2(Reloc *rel, const Interval *iv, unsigned newaddr,
|
|
typename tls_traits<LEXX>::cb_value_t imagebase); // pass 2
|
|
virtual void processTls(Interval *iv) = 0;
|
|
virtual void processTls(Reloc *r, const Interval *iv, unsigned a) = 0;
|
|
|
|
void rebuildTls();
|
|
MemBuffer mb_otls;
|
|
SPAN_0(byte) otls = nullptr;
|
|
unsigned sotls;
|
|
unsigned tlsindex;
|
|
unsigned tlscb_ptr;
|
|
unsigned tls_handler_offset = 0;
|
|
bool use_tls_callbacks = false;
|
|
|
|
void processLoadConf(Reloc *, const Interval *, unsigned);
|
|
void processLoadConf(Interval *);
|
|
MemBuffer mb_oloadconf;
|
|
byte *oloadconf = nullptr;
|
|
unsigned soloadconf;
|
|
|
|
unsigned stripDebug(unsigned);
|
|
|
|
unsigned icondir_offset;
|
|
int icondir_count;
|
|
|
|
bool importbyordinal = false;
|
|
bool kernel32ordinal = false;
|
|
unsigned rvamin;
|
|
unsigned cimports; // rva of preprocessed imports
|
|
unsigned crelocs; // rva of preprocessed fixups
|
|
int big_relocs;
|
|
|
|
struct alignas(1) ddirs_t {
|
|
LE32 vaddr;
|
|
LE32 size;
|
|
};
|
|
ddirs_t *iddirs = nullptr;
|
|
ddirs_t *oddirs = nullptr;
|
|
|
|
LE32 &IDSIZE(unsigned x);
|
|
LE32 &IDADDR(unsigned x);
|
|
LE32 &ODSIZE(unsigned x);
|
|
LE32 &ODADDR(unsigned x);
|
|
const LE32 &IDSIZE(unsigned x) const;
|
|
const LE32 &IDADDR(unsigned x) const;
|
|
|
|
struct alignas(1) import_desc {
|
|
LE32 oft; // orig first thunk
|
|
byte _[8];
|
|
LE32 dllname;
|
|
LE32 iat; // import address table
|
|
};
|
|
|
|
struct alignas(1) pe_section_t {
|
|
char name[8];
|
|
LE32 vsize;
|
|
LE32 vaddr;
|
|
LE32 size;
|
|
LE32 rawdataptr;
|
|
byte _[12];
|
|
LE32 flags;
|
|
};
|
|
|
|
MemBuffer mb_isection;
|
|
SPAN_0(pe_section_t) isection = nullptr;
|
|
bool isdll = false;
|
|
bool isrtm = false;
|
|
bool isefi = false;
|
|
bool use_dep_hack = true;
|
|
bool use_clear_dirty_stack = true;
|
|
bool use_stub_relocs = true;
|
|
|
|
static unsigned virta2objnum(unsigned, SPAN_0(pe_section_t), unsigned);
|
|
unsigned tryremove(unsigned, unsigned);
|
|
|
|
enum {
|
|
IMAGE_FILE_MACHINE_UNKNOWN = 0,
|
|
IMAGE_FILE_MACHINE_AMD64 = 0x8664, // win64/pe (amd64)
|
|
IMAGE_FILE_MACHINE_ARM = 0x01c0, // wince/arm (Windows CE)
|
|
IMAGE_FILE_MACHINE_ARMNT = 0x01c4, // win32/arm
|
|
IMAGE_FILE_MACHINE_ARM64 = 0xaa64, // win64/arm64
|
|
IMAGE_FILE_MACHINE_ARM64EC = 0xa641, // win64/arm64ec
|
|
IMAGE_FILE_MACHINE_I386 = 0x014c, // win32/pe (i386)
|
|
IMAGE_FILE_MACHINE_IA64 = 0x200,
|
|
IMAGE_FILE_MACHINE_LOONGARCH32 = 0x6232,
|
|
IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264,
|
|
IMAGE_FILE_MACHINE_RISCV32 = 0x5032,
|
|
IMAGE_FILE_MACHINE_RISCV64 = 0x5064,
|
|
IMAGE_FILE_MACHINE_RISCV128 = 0x5128,
|
|
IMAGE_FILE_MACHINE_THUMB = 0x01c2, // wince/arm (Windows CE)
|
|
};
|
|
|
|
enum {
|
|
PEDIR_EXPORT = 0,
|
|
PEDIR_IMPORT = 1,
|
|
PEDIR_RESOURCE = 2,
|
|
PEDIR_EXCEPTION = 3, // Exception table
|
|
PEDIR_SECURITY = 4, // Certificate table (file pointer)
|
|
PEDIR_BASERELOC = 5,
|
|
PEDIR_DEBUG = 6,
|
|
PEDIR_ARCHITECTURE = 7, // Architecture-specific data
|
|
PEDIR_GLOBALPTR = 8, // Global pointer
|
|
PEDIR_TLS = 9,
|
|
PEDIR_LOAD_CONFIG = 10, // Load Config Table
|
|
PEDIR_BOUND_IMPORT = 11,
|
|
PEDIR_IAT = 12,
|
|
PEDIR_DELAY_IMPORT = 13, // Delay Import Descriptor
|
|
PEDIR_COM_DESCRIPTOR = 14, // Com+ Runtime Header
|
|
};
|
|
|
|
// section flags
|
|
enum : unsigned {
|
|
IMAGE_SCN_CNT_CODE = 0x00000020,
|
|
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
|
|
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
|
|
IMAGE_SCN_LNK_OTHER = 0x00000100,
|
|
IMAGE_SCN_LNK_INFO = 0x00000200,
|
|
IMAGE_SCN_LNK_REMOVE = 0x00000800,
|
|
IMAGE_SCN_LNK_COMDAT = 0x00001000,
|
|
IMAGE_SCN_GPREL = 0x00008000,
|
|
IMAGE_SCN_MEM_PURGEABLE = 0x00020000,
|
|
IMAGE_SCN_MEM_16BIT = 0x00020000,
|
|
IMAGE_SCN_MEM_LOCKED = 0x00040000,
|
|
IMAGE_SCN_MEM_PRELOAD = 0x00080000,
|
|
IMAGE_SCN_ALIGN_1BYTES = 0x00100000,
|
|
IMAGE_SCN_ALIGN_2BYTES = 0x00200000,
|
|
IMAGE_SCN_ALIGN_4BYTES = 0x00300000,
|
|
IMAGE_SCN_ALIGN_8BYTES = 0x00400000,
|
|
IMAGE_SCN_ALIGN_16BYTES = 0x00500000,
|
|
IMAGE_SCN_ALIGN_32BYTES = 0x00600000,
|
|
IMAGE_SCN_ALIGN_64BYTES = 0x00700000,
|
|
IMAGE_SCN_ALIGN_128BYTES = 0x00800000,
|
|
IMAGE_SCN_ALIGN_256BYTES = 0x00900000,
|
|
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000,
|
|
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000,
|
|
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000,
|
|
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000,
|
|
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000,
|
|
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000,
|
|
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000,
|
|
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000,
|
|
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000,
|
|
IMAGE_SCN_MEM_SHARED = 0x10000000,
|
|
IMAGE_SCN_MEM_EXECUTE = 0x20000000,
|
|
IMAGE_SCN_MEM_READ = 0x40000000,
|
|
IMAGE_SCN_MEM_WRITE = 0x80000000,
|
|
};
|
|
|
|
enum {
|
|
IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
|
|
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
|
|
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
|
|
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008,
|
|
IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010,
|
|
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
|
|
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
|
|
IMAGE_FILE_32BIT_MACHINE = 0x0100,
|
|
IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
|
|
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
|
|
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
|
|
IMAGE_FILE_SYSTEM = 0x1000,
|
|
IMAGE_FILE_DLL = 0x2000,
|
|
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
|
|
IMAGE_FILE_BYTES_REVERSE_HI = 0x8000,
|
|
};
|
|
|
|
enum {
|
|
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020,
|
|
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040,
|
|
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
|
|
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100,
|
|
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
|
|
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
|
|
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
|
|
IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000,
|
|
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
|
|
IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000,
|
|
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000,
|
|
};
|
|
|
|
enum {
|
|
IMAGE_SUBSYSTEM_UNKNOWN = 0,
|
|
IMAGE_SUBSYSTEM_NATIVE = 1,
|
|
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Graphical User Interface
|
|
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Character User Interface
|
|
IMAGE_SUBSYSTEM_WINDOWS_OS2_CUI = 5,
|
|
IMAGE_SUBSYSTEM_WINDOWS_POSIX_CUI = 7,
|
|
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8,
|
|
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9,
|
|
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
|
|
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
|
|
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
|
|
IMAGE_SUBSYSTEM_EFI_ROM = 13,
|
|
IMAGE_SUBSYSTEM_XBOX = 14,
|
|
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16,
|
|
};
|
|
|
|
// predefined Resource Types
|
|
enum {
|
|
RT_CURSOR = 1,
|
|
RT_BITMAP,
|
|
RT_ICON,
|
|
RT_MENU,
|
|
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 {
|
|
unsigned capacity = 0;
|
|
void *base = nullptr;
|
|
public:
|
|
struct interval {
|
|
unsigned start, len;
|
|
};
|
|
struct interval *ivarr = nullptr;
|
|
unsigned ivnum = 0;
|
|
|
|
explicit Interval(void *b);
|
|
~Interval() noexcept;
|
|
|
|
void add(unsigned start, unsigned len);
|
|
void add(const void *start, unsigned len);
|
|
void add(const void *start, const void *end);
|
|
void add(const Interval *iv);
|
|
void flatten();
|
|
|
|
void clear();
|
|
void dump() const;
|
|
|
|
private:
|
|
static int __acc_cdecl_qsort compare(const void *p1, const void *p2);
|
|
};
|
|
|
|
class Reloc : private noncopyable {
|
|
// these are set in constructor
|
|
byte *start = nullptr;
|
|
unsigned start_size_in_bytes = 0;
|
|
bool start_did_alloc = false;
|
|
SPAN_0(byte) start_buf = nullptr;
|
|
|
|
struct alignas(1) BaseReloc {
|
|
LE32 pagestart;
|
|
LE32 size_of_block;
|
|
};
|
|
SPAN_0(BaseReloc) rel = nullptr;
|
|
SPAN_0(LE16) rel1 = nullptr;
|
|
void advanceBaseRelocPos(void *p);
|
|
|
|
unsigned counts[16] = {};
|
|
|
|
public:
|
|
explicit Reloc(byte *, unsigned);
|
|
explicit Reloc(unsigned relocnum);
|
|
void initSpans();
|
|
~Reloc() noexcept;
|
|
//
|
|
bool next(unsigned &result_pos, unsigned &result_type);
|
|
const unsigned *getcounts() const { return counts; }
|
|
//
|
|
void add(unsigned pos, unsigned type);
|
|
void finish(byte *(&result_ptr), unsigned &result_size); // => transfer ownership
|
|
};
|
|
|
|
class Resource : private noncopyable {
|
|
struct res_dir_entry;
|
|
struct res_dir;
|
|
struct res_data;
|
|
struct upx_rnode;
|
|
struct upx_rbranch;
|
|
struct upx_rleaf;
|
|
|
|
MemBuffer mb_start;
|
|
const byte *start = nullptr;
|
|
byte *newstart = nullptr;
|
|
upx_rnode *root = nullptr;
|
|
upx_rleaf *head = nullptr;
|
|
upx_rleaf *current = nullptr;
|
|
unsigned dsize = 0;
|
|
unsigned ssize = 0;
|
|
|
|
const byte *ibufstart = nullptr;
|
|
const byte *ibufend = nullptr;
|
|
|
|
void check(const res_dir *, unsigned);
|
|
upx_rnode *convert(const void *, upx_rnode *, unsigned);
|
|
void build(const upx_rnode *, unsigned &, unsigned &, unsigned);
|
|
void clear(byte *, unsigned, Interval *);
|
|
void dump(const upx_rnode *, unsigned) const;
|
|
void destroy(upx_rnode *urd, unsigned level) noexcept;
|
|
|
|
void ibufcheck(const void *m, unsigned size);
|
|
|
|
public:
|
|
explicit Resource(const byte *ibufstart, const byte *ibufen);
|
|
explicit Resource(const byte *p, const byte *ibufstart, const byte *ibufend);
|
|
~Resource() noexcept;
|
|
void init(const byte *);
|
|
|
|
unsigned dirsize() const;
|
|
bool next();
|
|
|
|
unsigned itype() const;
|
|
const byte *ntype() const;
|
|
unsigned size() const;
|
|
unsigned offs() const;
|
|
unsigned &newoffs();
|
|
|
|
byte *build();
|
|
bool clear();
|
|
|
|
void dump() const;
|
|
unsigned iname() const;
|
|
const byte *nname() const;
|
|
/*
|
|
unsigned ilang() const {return current->id;}
|
|
const byte *nlang() const {return current->name;}
|
|
*/
|
|
};
|
|
|
|
class Export : private noncopyable {
|
|
struct alignas(1) export_dir_t {
|
|
byte _[12]; // flags, timedate, version
|
|
LE32 name;
|
|
byte __[4]; // ordinal base
|
|
LE32 functions;
|
|
LE32 names;
|
|
LE32 addrtable;
|
|
LE32 nameptrtable;
|
|
LE32 ordinaltable;
|
|
};
|
|
|
|
export_dir_t edir;
|
|
char *ename;
|
|
char *functionptrs;
|
|
char *ordinals;
|
|
char **names;
|
|
|
|
char *base;
|
|
unsigned size;
|
|
Interval iv;
|
|
|
|
public:
|
|
explicit Export(char *_base);
|
|
~Export() noexcept;
|
|
|
|
void convert(unsigned eoffs, unsigned esize);
|
|
void build(char *base, unsigned newoffs);
|
|
unsigned getsize() const { return size; }
|
|
};
|
|
};
|
|
|
|
class PeFile32 : public PeFile {
|
|
typedef PeFile super;
|
|
protected:
|
|
explicit PeFile32(InputFile *f);
|
|
virtual ~PeFile32() noexcept;
|
|
|
|
void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase,
|
|
bool last_section_rsrc_only);
|
|
virtual void unpack(OutputFile *fo) override;
|
|
virtual tribool canUnpack() override;
|
|
|
|
virtual void readPeHeader() override;
|
|
|
|
virtual unsigned processImports() override;
|
|
virtual void processRelocs() override;
|
|
virtual void processTls(Interval *) override;
|
|
virtual void processTls(Reloc *, const Interval *, unsigned) override;
|
|
|
|
struct alignas(1) pe_header_t {
|
|
// 0x00
|
|
byte _[4]; // pemagic
|
|
// 0x04 IMAGE_FILE_HEADER
|
|
LE16 cpu; // IMAGE_FILE_MACHINE_xxx
|
|
LE16 objects; // NumberOfSections
|
|
byte __[12]; // timestamp + reserved
|
|
LE16 opthdrsize; // SizeOfOptionalHeader
|
|
LE16 flags; // IMAGE_FILE_xxx Characteristics
|
|
// 0x18 IMAGE_OPTIONAL_HEADER32
|
|
LE16 coffmagic; // NEW: Stefan Widmann
|
|
byte ___[2]; // linkerversion
|
|
LE32 codesize;
|
|
// 0x20
|
|
LE32 datasize;
|
|
LE32 bsssize;
|
|
LE32 entry;
|
|
LE32 codebase;
|
|
// 0x30
|
|
LE32 database;
|
|
// nt specific fields
|
|
LE32 imagebase;
|
|
LE32 objectalign;
|
|
LE32 filealign; // should set to 0x200 ?
|
|
// 0x40
|
|
byte ____[16]; // versions
|
|
// 0x50
|
|
LE32 imagesize;
|
|
LE32 headersize;
|
|
LE32 chksum; // should set to 0
|
|
LE16 subsystem; // IMAGE_SUBSYSTEM_xxx
|
|
LE16 dllflags; // IMAGE_DLLCHARACTERISTICS_xxx
|
|
// 0x60
|
|
byte _____[20]; // stack + heap sizes
|
|
// 0x74
|
|
LE32 ddirsentries; // usually 16
|
|
// 0x78
|
|
ddirs_t ddirs[16];
|
|
};
|
|
|
|
pe_header_t ih, oh;
|
|
};
|
|
|
|
class PeFile64 : public PeFile {
|
|
typedef PeFile super;
|
|
protected:
|
|
explicit PeFile64(InputFile *f);
|
|
virtual ~PeFile64() noexcept;
|
|
|
|
void pack0(OutputFile *fo, unsigned subsystem_mask, upx_uint64_t default_imagebase);
|
|
|
|
virtual void unpack(OutputFile *fo) override;
|
|
virtual tribool canUnpack() override;
|
|
|
|
virtual void readPeHeader() override;
|
|
|
|
virtual unsigned processImports() override;
|
|
virtual void processRelocs() override;
|
|
virtual void processTls(Interval *) override;
|
|
virtual void processTls(Reloc *, const Interval *, unsigned) override;
|
|
|
|
struct alignas(1) pe_header_t {
|
|
// 0x00
|
|
byte _[4]; // pemagic
|
|
// 0x04 IMAGE_FILE_HEADER
|
|
LE16 cpu; // IMAGE_FILE_MACHINE_xxx
|
|
LE16 objects; // NumberOfSections
|
|
byte __[12]; // timestamp + reserved
|
|
LE16 opthdrsize; // SizeOfOptionalHeader
|
|
LE16 flags; // IMAGE_FILE_xxx Characteristics
|
|
// 0x18 IMAGE_OPTIONAL_HEADER64
|
|
LE16 coffmagic; // NEW: Stefan Widmann
|
|
byte ___[2]; // linkerversion
|
|
LE32 codesize;
|
|
// 0x20
|
|
LE32 datasize;
|
|
LE32 bsssize;
|
|
LE32 entry; // still a 32 bit RVA
|
|
LE32 codebase;
|
|
// 0x30
|
|
// LE32 database; // field does not exist in PE+!
|
|
// nt specific fields
|
|
LE64 imagebase; // LE32 -> LE64 - Stefan Widmann standard is 0x0000000140000000
|
|
LE32 objectalign;
|
|
LE32 filealign; // should set to 0x200 ?
|
|
// 0x40
|
|
byte ____[16]; // versions
|
|
// 0x50
|
|
LE32 imagesize;
|
|
LE32 headersize;
|
|
LE32 chksum; // should set to 0
|
|
LE16 subsystem; // IMAGE_SUBSYSTEM_xxx
|
|
LE16 dllflags; // IMAGE_DLLCHARACTERISTICS_xxx
|
|
// 0x60
|
|
byte _____[36]; // stack + heap sizes + loader flag
|
|
// 0x84
|
|
LE32 ddirsentries; // usually 16
|
|
// 0x88
|
|
ddirs_t ddirs[16];
|
|
};
|
|
|
|
pe_header_t ih, oh;
|
|
};
|
|
|
|
/* vim:set ts=4 sw=4 et: */
|