Merge pull request #27035 from DaanDeMeyer/ukify-align

ukify: Add workarounds for older stubs
This commit is contained in:
Daan De Meyer
2023-03-28 19:45:04 +02:00
committed by GitHub
+24 -10
View File
@@ -449,7 +449,26 @@ class PeError(Exception):
def pe_add_sections(uki: UKI, output: str):
pe = pefile.PE(uki.executable, fast_load=True)
assert pe.FILE_HEADER.PointerToSymbolTable != 0 or len(pe.__data__) % pe.OPTIONAL_HEADER.FileAlignment == 0
# Old stubs might have been stripped, leading to unaligned raw data values, so let's fix them up here.
for i, section in enumerate(pe.sections):
oldp = section.PointerToRawData
oldsz = section.SizeOfRawData
section.PointerToRawData = round_up(oldp, pe.OPTIONAL_HEADER.FileAlignment)
section.SizeOfRawData = round_up(oldsz, pe.OPTIONAL_HEADER.FileAlignment)
padp = section.PointerToRawData - oldp
padsz = section.SizeOfRawData - oldsz
for later_section in pe.sections[i+1:]:
later_section.PointerToRawData += padp + padsz
pe.__data__ = pe.__data__[:oldp] + bytes(padp) + pe.__data__[oldp:oldp+oldsz] + bytes(padsz) + pe.__data__[oldp+oldsz:]
# We might not have any space to add new sections. Let's try our best to make some space by padding the
# SizeOfHeaders to a multiple of the file alignment. This is safe because the first section's data starts
# at a multiple of the file alignment, so all space before that is unused.
pe.OPTIONAL_HEADER.SizeOfHeaders = round_up(pe.OPTIONAL_HEADER.SizeOfHeaders, pe.OPTIONAL_HEADER.FileAlignment)
pe = pefile.PE(data=pe.write(), fast_load=True)
warnings = pe.get_warnings()
if warnings:
@@ -460,12 +479,6 @@ def pe_add_sections(uki: UKI, output: str):
# We could strip the signatures, but why would anyone sign the stub?
raise PeError(f'Stub image is signed, refusing.')
# If the executable has not been stripped, it might not be aligned to a multiple of the file alignment so
# let's make sure it is by padding it.
if pe.FILE_HEADER.PointerToSymbolTable != 0:
padlen = round_up(len(pe.__data__), pe.OPTIONAL_HEADER.FileAlignment) - len(pe.__data__)
pe.__data__ = pe.__data__[:] + padlen * b'\0'
for section in uki.sections:
new_section = pefile.SectionStructure(pe.__IMAGE_SECTION_HEADER_format__, pe=pe)
new_section.__unpack__(b'\0' * new_section.sizeof())
@@ -479,7 +492,9 @@ def pe_add_sections(uki: UKI, output: str):
new_section.set_file_offset(offset)
new_section.Name = section.name.encode()
new_section.Misc_VirtualSize = len(data)
new_section.PointerToRawData = len(pe.__data__)
# Non-stripped stubs might still have an unaligned symbol table at the end, making their size
# unaligned, so we make sure to explicitly pad the pointer to new sections to an aligned offset.
new_section.PointerToRawData = round_up(len(pe.__data__), pe.OPTIONAL_HEADER.FileAlignment)
new_section.SizeOfRawData = round_up(len(data), pe.OPTIONAL_HEADER.FileAlignment)
new_section.VirtualAddress = round_up(
pe.sections[-1].VirtualAddress + pe.sections[-1].Misc_VirtualSize,
@@ -493,8 +508,7 @@ def pe_add_sections(uki: UKI, output: str):
else:
new_section.IMAGE_SCN_CNT_INITIALIZED_DATA = True
assert len(pe.__data__) % pe.OPTIONAL_HEADER.FileAlignment == 0
pe.__data__ = pe.__data__[:] + data + b'\0' * (new_section.SizeOfRawData - len(data))
pe.__data__ = pe.__data__[:] + bytes(new_section.PointerToRawData - len(pe.__data__)) + data + bytes(new_section.SizeOfRawData - len(data))
pe.FILE_HEADER.NumberOfSections += 1
pe.OPTIONAL_HEADER.SizeOfInitializedData += new_section.Misc_VirtualSize