[misc] more MinGW DLL side loading "improvements"

- Side load SetupAPI.dll, as this is the DLL that was causing the CfgMgr32.dll local load.
  This reverts part of 622e60659c 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 (See 965759f58a).
- 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.
This commit is contained in:
Pete Batard 2025-05-13 20:26:46 +01:00
parent 13c6becf42
commit 4adfa4f37e
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
18 changed files with 179 additions and 98 deletions

View file

@ -50,6 +50,11 @@ jobs:
with:
msbuild-architecture: x64
- name: Install UPX
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
- name: Set ALPHA
id: set_alpha
shell: bash
@ -76,6 +81,10 @@ jobs:
move .\${{ matrix.TARGET_PLATFORM }}\Release\rufus.exe .\rufus_${{ matrix.TARGET_PLATFORM }}.exe
move .\${{ matrix.TARGET_PLATFORM }}\Release\rufus.pdb .\rufus_${{ matrix.TARGET_PLATFORM }}.pdb
- name: Compress executables
if: ${{ matrix.TARGET_PLATFORM != 'arm64' }}
run: upx --lzma --best .\rufus_${{ matrix.TARGET_PLATFORM }}.exe
- name: Display SHA-256
run: sha256sum ./rufus_${{ matrix.TARGET_PLATFORM }}.exe

View file

@ -20,8 +20,7 @@ TARGET := $(word 1,$(subst -, ,$(TUPLE)))
DEF_SUFFIX := $(if $(TARGET:x86_64=),.def,.def64)
.PHONY: all
# Ideally, we would also have cfgmgr32-delaylib here, but it doesn't actually delay load... :(
all: dwmapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
all: crypt32-delaylib.lib dwmapi-delaylib.lib setupapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
%.def64: %.def
$(AM_V_SED) "s/@.*//" $< >$@

View file

@ -368,8 +368,7 @@ uninstall-am:
.PHONY: all
# Ideally, we would also have cfgmgr32-delaylib here, but it doesn't actually delay load... :(
all: dwmapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
all: crypt32-delaylib.lib dwmapi-delaylib.lib setupapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
%.def64: %.def
$(AM_V_SED) "s/@.*//" $< >$@

14
.mingw/crypt32.def Normal file
View file

@ -0,0 +1,14 @@
EXPORTS
CertFindCertificateInStore@24
CertGetCertificateChain@32
CertGetNameStringA@24
CertCloseStore@8
CertFreeCertificateContext@4
CryptQueryObject@44
CryptDecodeObjectEx@32
CryptHashCertificate@28
CryptMsgGetParam@20
CryptMsgClose@4
CryptMsgGetParam@20
CryptMsgOpenToDecode@24
CryptMsgUpdate@16

20
.mingw/setupapi.def Normal file
View file

@ -0,0 +1,20 @@
EXPORTS
CM_Locate_DevNodeA@12
CM_Get_DevNode_Registry_PropertyA@24
CM_Get_DevNode_Status@16
CM_Get_Child@12
CM_Get_Parent@12
CM_Get_Sibling@12
CM_Get_Device_IDA@16
CM_Get_Device_ID_ListA@16
CM_Get_Device_ID_List_SizeA@12
SetupDiGetDeviceInstanceIdA@20
SetupDiGetDeviceRegistryPropertyA@28
SetupDiGetDeviceRegistryPropertyW@28
SetupDiChangeState@8
SetupDiGetClassDevsA@16
SetupDiSetClassInstallParamsW@16
SetupDiEnumDeviceInfo@12
SetupDiEnumDeviceInterfaces@20
SetupDiDestroyDeviceInfoList@4
SetupDiGetDeviceInterfaceDetailA@24

View file

@ -168,7 +168,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
</Link>
<ResourceCompile>
@ -200,7 +200,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
</Link>
<ResourceCompile>
@ -302,7 +302,7 @@
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories>
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -336,7 +336,7 @@
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories>
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<DelayLoadDLLs>advapi32.dll;comctl32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;version.dll;virtdisk.dll;wininet.dll;wintrust.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

6
configure vendored
View file

@ -4702,7 +4702,7 @@ fi
printf "%s\n" "enabling Large File Support (ISO support)" >&6; }
AM_CFLAGS="$AM_CFLAGS -D_FILE_OFFSET_BITS=64 -D_OFF_T_ -D_off_t=off64_t -Doff_t=off64_t -Doff32_t=long"
# check for -Wno-pointer-sign compiler support (GCC >= 4)
# Check for -Wno-pointer-sign compiler support (GCC >= 4)
saved_CFLAGS="${CFLAGS}"
CFLAGS="$CFLAGS -Wno-pointer-sign"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@ -4725,7 +4725,9 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS="${saved_CFLAGS}"
AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -std=gnu11 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Wno-array-bounds -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags"
# NB: The DECLSPEC_IMPORT redefinition below is a temporary(?) workaround for MinGW32 delay-loading
# See https://github.com/pbatard/rufus/pull/2513 as well as https://sourceware.org/bugzilla/show_bug.cgi?id=14339
AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -UDECLSPEC_IMPORT -DDECLSPEC_IMPORT=__attribute__\(\(visibility\(\\\"hidden\\\"\)\)\) -std=gnu11 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Wno-array-bounds -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags"

View file

@ -57,14 +57,16 @@ fi
AC_MSG_RESULT([enabling Large File Support (ISO support)])
AM_CFLAGS="$AM_CFLAGS -D_FILE_OFFSET_BITS=64 -D_OFF_T_ -D_off_t=off64_t -Doff_t=off64_t -Doff32_t=long"
# check for -Wno-pointer-sign compiler support (GCC >= 4)
# Check for -Wno-pointer-sign compiler support (GCC >= 4)
saved_CFLAGS="${CFLAGS}"
CFLAGS="$CFLAGS -Wno-pointer-sign"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[nopointersign_cflags="-Wno-pointer-sign"], [nopointersign_cflags=""])
CFLAGS="${saved_CFLAGS}"
AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -std=gnu11 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Wno-array-bounds -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags"
# NB: The DECLSPEC_IMPORT redefinition below is a temporary(?) workaround for MinGW32 delay-loading
# See https://github.com/pbatard/rufus/pull/2513 as well as https://sourceware.org/bugzilla/show_bug.cgi?id=14339
AM_CFLAGS="$AM_CFLAGS -DUNICODE -D_UNICODE -UNDEBUG -DCOBJMACROS -D__USE_MINGW_ANSI_STDIO=0 -UDECLSPEC_IMPORT -DDECLSPEC_IMPORT=__attribute__\(\(visibility\(\\\"hidden\\\"\)\)\) -std=gnu11 -Wshadow -Wall -Wformat-security -Wundef -Wunused -Wstrict-prototypes -Wno-restrict -Wno-array-bounds -Werror-implicit-function-declaration -Wbidi-chars=none $nopointersign_cflags"
AC_SUBST([VISIBILITY_CFLAGS])
AC_SUBST([AM_CFLAGS])

63
loadcfg.py Normal file
View file

@ -0,0 +1,63 @@
#!/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}'")

View file

@ -1,11 +1,9 @@
SUBDIRS = ../.mingw bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller syslinux/win libcdio/iso9660 libcdio/udf libcdio/driver wimlib ../res/loc
# As far as I can tell, the following libraries are *not* vulnerable to side-loading, so we link using their regular version:
NONVULNERABLE_LIBS = -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lcomctl32 -luuid -lntdll
NONVULNERABLE_LIBS = -lole32 -lgdi32 -lshlwapi -lcomctl32 -luuid -lntdll
# The following libraries are vulnerable (or have an unknown vulnerability status), so we link using our delay-loaded replacement:
# See https://github.com/pbatard/rufus/issues/2272
# Oh, and don't bother trying to delay load cfgmgr32.dll, even with the DECLSPEC_IMPORT __attribute__((visibility("hidden")))
# override. It just DOESN'T BLOODY WORK and you will waste HOURS on a wild goose chase!!!
VULNERABLE_LIBS = -ldwmapi-delaylib -lversion-delaylib -lvirtdisk-delaylib -lwininet-delaylib -lwintrust-delaylib
VULNERABLE_LIBS = -lcrypt32-delaylib -ldwmapi-delaylib -lsetupapi-delaylib -lversion-delaylib -lvirtdisk-delaylib -lwininet-delaylib -lwintrust-delaylib
noinst_PROGRAMS = rufus

View file

@ -275,12 +275,10 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = ../.mingw bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller syslinux/win libcdio/iso9660 libcdio/udf libcdio/driver wimlib ../res/loc
# As far as I can tell, the following libraries are *not* vulnerable to side-loading, so we link using their regular version:
NONVULNERABLE_LIBS = -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lcomctl32 -luuid -lntdll
NONVULNERABLE_LIBS = -lole32 -lgdi32 -lshlwapi -lcomctl32 -luuid -lntdll
# The following libraries are vulnerable (or have an unknown vulnerability status), so we link using our delay-loaded replacement:
# See https://github.com/pbatard/rufus/issues/2272
# Oh, and don't bother trying to delay load cfgmgr32.dll, even with the DECLSPEC_IMPORT __attribute__((visibility("hidden")))
# override. It just DOESN'T BLOODY WORK and you will waste HOURS on a wild goose chase!!!
VULNERABLE_LIBS = -ldwmapi-delaylib -lversion-delaylib -lvirtdisk-delaylib -lwininet-delaylib -lwintrust-delaylib
VULNERABLE_LIBS = -lcrypt32-delaylib -ldwmapi-delaylib -lsetupapi-delaylib -lversion-delaylib -lvirtdisk-delaylib -lwininet-delaylib -lwintrust-delaylib
AM_V_WINDRES_0 = @echo " RC $@";$(WINDRES)
AM_V_WINDRES_1 = $(WINDRES)
AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY))

View file

@ -49,21 +49,6 @@ extern RUFUS_DRIVE rufus_drive[MAX_DRIVES];
extern BOOL enable_HDDs, enable_VHDs, use_fake_units, enable_vmdk, usb_debug;
extern BOOL list_non_usb_removable_drives, its_a_me_mario;
/*
* CfgMgr32.dll interface.
* Note that, unlike what is the case with other DLLs, delay-loading of cfgmgr32
* does *not* work with MinGW, so we have to go through direct hooking yet again...
*/
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, CHAR*, ULONG, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Device_ID_List_SizeA, (PULONG, PCSTR, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Device_ID_ListA, (PCSTR, PCHAR, ULONG, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Locate_DevNodeA, (PDEVINST, DEVINSTID_A, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_DevNode_Status, (PULONG, PULONG, DEVINST, ULONG));
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_DevNode_Registry_PropertyA, (DEVINST, ULONG, PULONG, PVOID, PULONG, ULONG));
/*
* Get the VID, PID and current device speed
*/
@ -80,10 +65,7 @@ static BOOL GetUSBProperties(char* parent_path, char* device_id, usb_device_prop
if ((parent_path == NULL) || (device_id == NULL) || (props == NULL))
goto out;
PF_INIT_OR_OUT(CM_Locate_DevNodeA, CfgMgr32);
PF_INIT_OR_OUT(CM_Get_DevNode_Registry_PropertyA, CfgMgr32);
cr = pfCM_Locate_DevNodeA(&device_inst, device_id, 0);
cr = CM_Locate_DevNodeA(&device_inst, device_id, 0);
if (cr != CR_SUCCESS) {
uprintf("Could not get device instance handle for '%s': CR error %d", device_id, cr);
goto out;
@ -91,7 +73,7 @@ static BOOL GetUSBProperties(char* parent_path, char* device_id, usb_device_prop
props->port = 0;
size = sizeof(props->port);
cr = pfCM_Get_DevNode_Registry_PropertyA(device_inst, CM_DRP_ADDRESS, NULL, (PVOID)&props->port, &size, 0);
cr = CM_Get_DevNode_Registry_PropertyA(device_inst, CM_DRP_ADDRESS, NULL, (PVOID)&props->port, &size, 0);
if (cr != CR_SUCCESS) {
uprintf("Could not get port for '%s': CR error %d", device_id, cr);
goto out;
@ -214,8 +196,6 @@ int CycleDevice(int index)
if ((index < 0) || (safe_strlen(rufus_drive[index].id) < 8))
return ERROR_INVALID_PARAMETER;
PF_INIT_OR_OUT(CM_Get_DevNode_Status, CfgMgr32);
// Need DIGCF_ALLCLASSES else disabled devices won't be listed.
dev_info = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (dev_info == INVALID_HANDLE_VALUE) {
@ -238,7 +218,7 @@ int CycleDevice(int index)
found = TRUE;
// Detect if the device is already disabled
if (pfCM_Get_DevNode_Status(&dev_status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS)
if (CM_Get_DevNode_Status(&dev_status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS)
disabled = (dev_status & DN_HAS_PROBLEM) && (problem_code == CM_PROB_DISABLED);
// Disable the device
@ -287,7 +267,7 @@ int CycleDevice(int index)
// successful, but leave the device in an actual disabled state... So we can end up
// with zombie devices, that are effectively disabled, but that Windows still sees
// as enabled... So we need to detect this.
if (pfCM_Get_DevNode_Status(&dev_status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS) {
if (CM_Get_DevNode_Status(&dev_status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS) {
disabled = (dev_status & DN_HAS_PROBLEM) && (problem_code == CM_PROB_DISABLED);
if (disabled)
ret = ERROR_DEVICE_REINITIALIZATION_NEEDED;
@ -298,7 +278,6 @@ int CycleDevice(int index)
SetupDiDestroyDeviceInfoList(dev_info);
if (!found)
uprintf("Could not find a device to cycle!");
out:
return ret;
}
@ -518,14 +497,6 @@ BOOL GetDevices(DWORD devnum)
uint64_t drive_size = 0;
usb_device_props props;
PF_INIT_OR_OUT(CM_Get_Child, CfgMgr32);
PF_INIT_OR_OUT(CM_Get_Parent, CfgMgr32);
PF_INIT_OR_OUT(CM_Get_Sibling, CfgMgr32);
PF_INIT_OR_OUT(CM_Get_Device_IDA, CfgMgr32);
PF_INIT_OR_OUT(CM_Get_Device_ID_ListA, CfgMgr32);
PF_INIT_OR_OUT(CM_Get_Device_ID_List_SizeA, CfgMgr32);
PF_INIT_OR_OUT(CM_Locate_DevNodeA, CfgMgr32);
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
ClearDrives();
StrArrayCreate(&dev_if_path, 128);
@ -555,19 +526,19 @@ BOOL GetDevices(DWORD devnum)
if (SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) {
// Find the Device IDs for all the children of this hub
if (pfCM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) {
if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) {
device_id[0] = 0;
s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath, TRUE);
uuprintf(" Hub[%d] = '%s'", s, devint_detail_data->DevicePath);
if ((s>= 0) && (pfCM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) {
if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) {
ToUpper(device_id);
if ((k = htab_hash(device_id, &htab_devid)) != 0) {
htab_devid.table[k].data = (void*)(uintptr_t)s;
}
uuprintf(" Found ID[%03d]: %s", k, device_id);
while (pfCM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) {
while (CM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) {
device_id[0] = 0;
if (pfCM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS) {
if (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS) {
ToUpper(device_id);
if ((k = htab_hash(device_id, &htab_devid)) != 0) {
htab_devid.table[k].data = (void*)(uintptr_t)s;
@ -595,7 +566,7 @@ BOOL GetDevices(DWORD devnum)
// Also compute the uasp_start index
if (strcmp(usbstor_name[s], "UASPSTOR") == 0)
uasp_start = s;
if (pfCM_Get_Device_ID_List_SizeA(&list_size[s], usbstor_name[s], ulFlags) != CR_SUCCESS)
if (CM_Get_Device_ID_List_SizeA(&list_size[s], usbstor_name[s], ulFlags) != CR_SUCCESS)
list_size[s] = 0;
if (list_size[s] != 0)
full_list_size += list_size[s]-1; // remove extra NUL terminator
@ -630,7 +601,7 @@ BOOL GetDevices(DWORD devnum)
for (s = 0, i = 0; s < ARRAYSIZE(usbstor_name); s++) {
list_start[s] = i;
if (list_size[s] > 1) {
if (pfCM_Get_Device_ID_ListA(usbstor_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS)
if (CM_Get_Device_ID_ListA(usbstor_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS)
continue;
if (usb_debug) {
uprintf("Processing IDs belonging to '%s':", usbstor_name[s]);
@ -737,17 +708,17 @@ BOOL GetDevices(DWORD devnum)
// a lookup table, but there shouldn't be that many USB storage devices connected...
// NB: Each of these Device IDs should have a child, from which we get the Device Instance match.
for (device_id = devid_list; *device_id != 0; device_id += strlen(device_id) + 1) {
if (pfCM_Locate_DevNodeA(&parent_inst, device_id, 0) != CR_SUCCESS) {
if (CM_Locate_DevNodeA(&parent_inst, device_id, 0) != CR_SUCCESS) {
uuprintf("Could not locate device node for '%s'", device_id);
continue;
}
if (pfCM_Get_Child(&device_inst, parent_inst, 0) != CR_SUCCESS) {
if (CM_Get_Child(&device_inst, parent_inst, 0) != CR_SUCCESS) {
uuprintf("Could not get children of '%s'", device_id);
continue;
}
if (device_inst != dev_info_data.DevInst) {
// Try the siblings
while (pfCM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) {
while (CM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) {
if (device_inst == dev_info_data.DevInst) {
uuprintf("NOTE: Matched instance from sibling for '%s'", device_id);
break;
@ -788,8 +759,8 @@ BOOL GetDevices(DWORD devnum)
// for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods)
// so try to see if we can match the grandparent.
if ( ((uintptr_t)htab_devid.table[j].data == 0)
&& (pfCM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS)
&& (pfCM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) {
&& (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS)
&& (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) {
device_id = str;
method_str = "[GP]";
ToUpper(device_id);

View file

@ -24,12 +24,6 @@
#endif
#include <windows.h>
// Temporary workaround for MinGW32 delay-loading
// See https://github.com/pbatard/rufus/pull/2513
#if defined(__MINGW32__)
#undef DECLSPEC_IMPORT
#define DECLSPEC_IMPORT __attribute__((visibility("hidden")))
#endif
#include <wininet.h>
#include <netlistmgr.h>
#include <stdio.h>

View file

@ -22,14 +22,6 @@
#include <crtdbg.h>
#endif
// Temporary workaround for MinGW32 delay-loading
// See https://github.com/pbatard/rufus/pull/2513 as well as
// https://sourceware.org/bugzilla/show_bug.cgi?id=14339
#if defined(__MINGW32__)
#undef DECLSPEC_IMPORT
#define DECLSPEC_IMPORT __attribute__((visibility("hidden")))
#endif
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
@ -4219,3 +4211,30 @@ out:
return 0;
}
/*
* The following adds a Load Configuration section in .rdata for MinGW, that can then be referenced
* by a PE post processing script to emulate the /DEPENDENTLOADFLAG:0x800 behaviour of MSVC.
* See https://github.com/pbatard/rufus/blob/master/loadcfg.py for such a script.
* Note however that, per https://github.com/pbatard/rufus/issues/2701#issuecomment-2874788564
* /DEPENDENTLOADFLAG is far from being the ultimate solution to stop DLL side-loading vulnerabilities...
*/
#if defined(__MINGW32__)
// MinGW produces a warning since we don't use this section in the code => silence it.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-const-variable"
// Add a 16-byte marker for scripts to easily locate this section.
static const char _load_config_marker[16] __attribute__((aligned(16))) __attribute__((section(".rdata"))) = "_RUFUS_LOAD_CFG";
#if defined(_M_AMD64)
static const IMAGE_LOAD_CONFIG_DIRECTORY64 _load_config __attribute__((aligned(16))) __attribute__((section(".rdata"))) = {
.Size = sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64),
.DependentLoadFlags = LOAD_LIBRARY_SEARCH_SYSTEM32
};
#else
static const IMAGE_LOAD_CONFIG_DIRECTORY32 _load_config __attribute__((aligned(16))) __attribute__((section(".rdata"))) = {
.Size = sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32),
.DependentLoadFlags = LOAD_LIBRARY_SEARCH_SYSTEM32
};
#endif
#pragma GCC diagnostic pop
#endif

View file

@ -58,14 +58,13 @@
#endif
#define COMPANY_NAME "Akeo Consulting"
#define STR_NO_LABEL "NO_LABEL"
// Yes, there exist characters between these seemingly empty quotes!
#define LEFT_TO_RIGHT_MARK ""
#define RIGHT_TO_LEFT_MARK ""
#define LEFT_TO_RIGHT_EMBEDDING ""
#define RIGHT_TO_LEFT_EMBEDDING ""
#define POP_DIRECTIONAL_FORMATTING ""
#define LEFT_TO_RIGHT_OVERRIDE ""
#define RIGHT_TO_LEFT_OVERRIDE ""
#define LEFT_TO_RIGHT_MARK "\u200e"
#define RIGHT_TO_LEFT_MARK "\u200f"
#define LEFT_TO_RIGHT_EMBEDDING "\u202a"
#define RIGHT_TO_LEFT_EMBEDDING "\u202b"
#define POP_DIRECTIONAL_FORMATTING "\u202c"
#define LEFT_TO_RIGHT_OVERRIDE "\u202d"
#define RIGHT_TO_LEFT_OVERRIDE "\u202e"
#define DRIVE_ACCESS_TIMEOUT 15000 // How long we should retry drive access (in ms)
#define DRIVE_ACCESS_RETRIES 150 // How many times we should retry
#define DRIVE_INDEX_MIN 0x00000080

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 4.8.2243"
CAPTION "Rufus 4.8.2244"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -407,8 +407,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,8,2243,0
PRODUCTVERSION 4,8,2243,0
FILEVERSION 4,8,2244,0
PRODUCTVERSION 4,8,2244,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -426,13 +426,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.8.2243"
VALUE "FileVersion", "4.8.2244"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2025 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.8.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.8.2243"
VALUE "ProductVersion", "4.8.2244"
END
END
BLOCK "VarFileInfo"

View file

@ -19,12 +19,6 @@
#include <stdint.h>
#include <windows.h>
// Temporary workaround for MinGW32 delay-loading
// See https://github.com/pbatard/rufus/pull/2513
#if defined(__MINGW32__)
#undef DECLSPEC_IMPORT
#define DECLSPEC_IMPORT __attribute__((visibility("hidden")))
#endif
#include <virtdisk.h>
#pragma once

View file

@ -240,8 +240,8 @@ char *ezxml_decode(char *s, char **ent, char t)
l = (d = (long)(s - r)) + c + (long)(e ? strlen(e) : 0); // new length
r = (r == m) ? strcpy(malloc(l), r) : _realloc(r, l);
e = strchr((s = r + d), ';'); // fix up pointers
if (!e) return r;
}
if (!e) return r;
memmove(s + c, e + 1, strlen(e)); // shift rest of string
strncpy_s(s, c, ent[b], _TRUNCATE); // copy in replacement text