mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-15 07:34:28 -04:00

- Side load SetupAPI.dll, as this is the DLL that was causing the CfgMgr32.dll local load. This reverts part of622e60659c
since we no longer have to hook into CfgMgr32.dll directly. - Also set the redefinition of DECLSPEC_IMPORT, which we need for MinGW32 x86, in the global AM_CFLAGS of configure.ac, so that we no longer have to worry about forgetting to do it in a source and experience crashes on 32-bit as a result (See965759f58a
). - Also delay-load crypt32.dll while we're at it. - Also add provision for enabling /DEPENDENTLOADFLAG:0x800 on MinGW, by leaving a properly crafted entry in the .rdata section that can then be used with the loadcfg.py Python script. - Sadly, per https://github.com/pbatard/rufus/issues/2701#issuecomment-2874788564 and subsequent comment, having DependentLoadFlags set to LOAD_LIBRARY_SEARCH_SYSTEM32 is still not enough to take care of side loading issues, as, ever since the introduction of wimlib support, we are seeing CRYPTBASE.DLL being side-loaded in MinGW, and, even with crypt32.dll being delay-loaded there is literally *nothing* we can do about it! - The end result of all the above is that we will have no choice but ditch MinGW for release executables as it's just impossible to properly take care of side-loading vulnerabilities with MinGW (and Microsoft are REALLY not helping with this whole mess either, when they don't even use LOAD_LIBRARY_SEARCH_SYSTEM32 for Windows' system DLLs). - In preparation for this, we add UPX compression to the x86_64 and x86_32 MSVC executables. - Finally, we also fix one last Coverity warning in xml.c and remove duplicates in .vcxproj for ARM64.
63 lines
2 KiB
Python
63 lines
2 KiB
Python
#!/bin/env python3
|
|
|
|
# PE Load Configuration section enabler for MinGW/gcc executables.
|
|
# The PE executable should have a IMAGE_LOAD_CONFIG_DIRECTORY## section
|
|
# in .rdata with a 16-byte IMAGE_DIRECTORY_ENTRY_MARKER marker.
|
|
|
|
import os
|
|
import sys
|
|
import pefile
|
|
|
|
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
|
|
IMAGE_DIRECTORY_ENTRY_MARKER = b"_RUFUS_LOAD_CFG"
|
|
|
|
if len(sys.argv) < 2:
|
|
raise RuntimeError("No executable path supplied")
|
|
|
|
# Create a temp file as our source
|
|
pe_dst = sys.argv[1]
|
|
pe_src = sys.argv[1] + ".tmp"
|
|
os.replace(pe_dst, pe_src)
|
|
|
|
# Open and parse PE
|
|
pe = pefile.PE(pe_src)
|
|
|
|
# Find .rdata section
|
|
rdata_section = next(
|
|
(s for s in pe.sections if s.Name.rstrip(b'\x00') == b'.rdata'),
|
|
None
|
|
)
|
|
if not rdata_section:
|
|
raise RuntimeError(".rdata section not found")
|
|
|
|
# Read the section's raw data to search for the target string
|
|
raw_data = rdata_section.get_data()
|
|
|
|
# Look for the target data in the raw section data
|
|
offset = raw_data.find(IMAGE_DIRECTORY_ENTRY_MARKER)
|
|
if offset == -1:
|
|
raise RuntimeError("Load Config marker not found")
|
|
|
|
# Move past our 16 bytes marker
|
|
offset += 0x10
|
|
# Calculate the RVA and size of the Load Config section
|
|
load_config_rva = rdata_section.VirtualAddress + offset
|
|
print(f"RVA of Load Config: 0x{load_config_rva:X}")
|
|
load_config_size = pe.get_dword_at_rva(load_config_rva)
|
|
if (load_config_size < 0x20):
|
|
raise RuntimeError("Size of Load Config section is too small")
|
|
print(f"Size of Load Config: 0x{load_config_size:X}")
|
|
|
|
# Update Load Config directory entry
|
|
pe.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = load_config_rva
|
|
pe.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = load_config_size
|
|
|
|
# Update the checksum
|
|
pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
|
|
|
|
# Write the updated PE file and remove temp
|
|
pe.write(pe_dst)
|
|
os.remove(pe_src)
|
|
|
|
# Can be validated with `DUMPBIN /LOADCONFIG <.exe>` or `objdump -x <.exe> | grep "Load Configuration"`
|
|
print(f"Successfully enabled Load Config section in '{pe_dst}'")
|