PE: Add support for EFI images

This commit is contained in:
Kornel Pal 2021-12-22 03:05:24 +01:00 committed by Markus F.X.J. Oberhumer
parent 1d9c211eed
commit 937bfa4e49
5 changed files with 71 additions and 21 deletions

View File

@ -295,7 +295,10 @@ void PackW32Pe::pack(OutputFile *fo)
super::pack0(fo
, (1u<<IMAGE_SUBSYSTEM_WINDOWS_GUI)
| (1u<<IMAGE_SUBSYSTEM_WINDOWS_CUI)
| (1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION) // no decompressor yet
| (1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION)
| (1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_ROM)
, 0x400000
, false);
}

View File

@ -103,6 +103,8 @@ void PackW64Pep::buildLoader(const Filter *ft)
addLoader("START");
if (ih.entry && isdll)
addLoader("PEISDLL0");
if (isefi)
addLoader("PEISEFI0");
addLoader(isdll ? "PEISDLL1" : "",
"PEMAIN01",
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
@ -167,6 +169,8 @@ void PackW64Pep::buildLoader(const Filter *ft)
if (ih.entry && isdll)
addLoader("PEISDLL9");
if (isefi)
addLoader("PEISEFI9");
addLoader(ih.entry || !ilinker ? "PEDOJUMP" : "PERETURN", nullptr);
//NEW: TLS callback support PART 2, the callback handler - Stefan Widmann
@ -281,7 +285,10 @@ void PackW64Pep::pack(OutputFile *fo)
super::pack0(fo
, (1u<<IMAGE_SUBSYSTEM_WINDOWS_GUI)
| (1u<<IMAGE_SUBSYSTEM_WINDOWS_CUI)
| (1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION) // no decompressor yet
| (1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION)
| (1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_ROM)
, 0x0000000140000000ULL);
}

View File

@ -119,6 +119,7 @@ PeFile::PeFile(InputFile *f) : super(f)
use_clear_dirty_stack = true;
use_stub_relocs = true;
isrtm = false;
isefi = false;
}
@ -880,6 +881,13 @@ void PeFile::processImports2(unsigned myimport, unsigned) // pass 2
template <typename LEXX, typename ord_mask_t>
unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1
{
if (isefi) {
if (IDSIZE(PEDIR_IMPORT))
throwCantPack("imports not supported on EFI");
return 0;
}
unsigned dllnum = 0;
unsigned const take = IDSIZE(PEDIR_IMPORT);
unsigned const skip = IDADDR(PEDIR_IMPORT);
@ -1314,6 +1322,9 @@ void PeFile::processTls1(Interval *iv,
COMPILE_TIME_ASSERT(sizeof(tls) == tls_traits<LEXX>::sotls)
COMPILE_TIME_ASSERT_ALIGNED1(tls)
if (isefi && IDSIZE(PEDIR_TLS))
throwCantPack("TLS not supported on EFI");
unsigned const take = ALIGN_UP(IDSIZE(PEDIR_TLS),4u);
sotls = take;
if (!sotls)
@ -1916,7 +1927,7 @@ void PeFile::processResources(Resource *res)
// setup default options for resource compression
if (opt->win32_pe.compress_resources < 0)
opt->win32_pe.compress_resources = true;
opt->win32_pe.compress_resources = !isefi;
if (!opt->win32_pe.compress_resources)
{
opt->win32_pe.compress_icons = false;
@ -2151,16 +2162,6 @@ void PeFile::checkHeaderValues(unsigned subsystem, unsigned mask,
subsystem);
throwCantPack(buf);
}
if (mask & (
(1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION)
|(1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
|(1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
|(1u<<IMAGE_SUBSYSTEM_EFI_ROM)
))
{
infoWarning("PE: subsystem %u (EFI) lacks a run-time decompressor",
subsystem);
}
//check CLR Runtime Header directory entry
if (IDSIZE(PEDIR_COMRT))
throwCantPack(".NET files are not yet supported");
@ -2187,15 +2188,15 @@ unsigned PeFile::handleStripRelocs(upx_uint64_t ih_imagebase,
{
if (opt->win32_pe.strip_relocs < 0)
{
if (isdll || dllflags & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
if (isdll || isefi || dllflags & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
opt->win32_pe.strip_relocs = false;
else
opt->win32_pe.strip_relocs = ih_imagebase >= default_imagebase;
}
if (opt->win32_pe.strip_relocs)
{
if (isdll)
throwCantPack("--strip-relocs is not allowed with DLL images");
if (isdll || isefi)
throwCantPack("--strip-relocs is not allowed with DLL and EFI images");
if (dllflags & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
{
if (opt->force) // Disable ASLR
@ -2326,7 +2327,22 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
else
ih.flags |= handleStripRelocs(ih.imagebase, default_imagebase, ih.dllflags);
handleStub(fi,fo,pe_offset);
if (isefi) {
// PIC for EFI only to avoid false positive detections of Win32 images
// without relocations fixed address is smaller
if (!opt->win32_pe.strip_relocs)
use_stub_relocs = false;
// EFI build tools already clear DOS stub
// and small file alignment benefits from extra space
unsigned char stub[0x40];
memset(stub, 0, sizeof(stub));
set_le16(stub, 'M' + 'Z'*256);
set_le32(stub + sizeof(stub) - sizeof(LE32), sizeof(stub));
fo->write(stub, sizeof(stub));
pe_offset = sizeof(stub);
} else
handleStub(fi,fo,pe_offset);
unsigned overlaystart = readSections(objs, ih.imagesize, ih.filealign, ih.datasize);
unsigned overlay = file_size - stripDebug(overlaystart);
if (overlay >= (unsigned) file_size)
@ -3102,9 +3118,10 @@ int PeFile::canUnpack0(unsigned max_sections, LE16 &ih_objects,
isection = (pe_section_t *)mb_isection.getVoidPtr();
fi->seek(pe_offset + ihsize, SEEK_SET);
fi->readx(isection,sizeof(pe_section_t)*objs);
if (ih_objects < 3)
const unsigned min_sections = isefi ? 2 : 3;
if (ih_objects < min_sections)
return -1;
bool is_packed = ((ih_objects == 3 || ih_objects == max_sections) &&
bool is_packed = (ih_objects >= min_sections && ih_objects <= max_sections &&
(IDSIZE(15) || ih_entry > isection[1].vaddr));
bool found_ph = false;
if (memcmp(isection[0].name,"UPX",3) == 0)
@ -3188,7 +3205,15 @@ PeFile32::~PeFile32()
void PeFile32::readPeHeader()
{
fi->readx(&ih,sizeof(ih));
isdll = ((ih.flags & DLL_FLAG) != 0);
isefi = ((1u << ih.subsystem) & (
(1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION)
| (1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_ROM)
)) != 0;
isdll = !isefi && (ih.flags & DLL_FLAG) != 0;
use_dep_hack &= !isefi;
use_clear_dirty_stack &= !isefi;
}
void PeFile32::pack0(OutputFile *fo, unsigned subsystem_mask,
@ -3246,7 +3271,15 @@ PeFile64::~PeFile64()
void PeFile64::readPeHeader()
{
fi->readx(&ih,sizeof(ih));
isdll = ((ih.flags & DLL_FLAG) != 0);
isefi = ((1u << ih.subsystem) & (
(1u<<IMAGE_SUBSYSTEM_EFI_APPLICATION)
| (1u<<IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
| (1u<<IMAGE_SUBSYSTEM_EFI_ROM)
)) != 0;
isdll = !isefi && (ih.flags & DLL_FLAG) != 0;
use_dep_hack &= !isefi;
use_clear_dirty_stack &= !isefi;
}
void PeFile64::pack0(OutputFile *fo, unsigned subsystem_mask,

View File

@ -212,6 +212,7 @@ protected:
pe_section_t *isection;
bool isdll;
bool isrtm;
bool isefi;
bool use_dep_hack;
bool use_clear_dirty_stack;
bool use_stub_relocs;

View File

@ -74,6 +74,9 @@ section PEISDLL0
mov [rsp + 8], rcx
mov [rsp + 0x10], rdx
mov [rsp + 0x18], r8
section PEISEFI0
push rcx
push rdx
section PEISDLL1
cmp dl, 1
@ -457,6 +460,9 @@ section PEISDLL9
mov r8, [rsp + 0x18]
mov rdx, [rsp + 0x10]
mov rcx, [rsp + 8]
section PEISEFI9
pop rdx
pop rcx
section PERETURN
push 1