Skip to content

Commit 4adfa4f

Browse files
committed
[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 622e606 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 965759f). - 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 #2701 (comment) 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.
1 parent 13c6bec commit 4adfa4f

File tree

18 files changed

+179
-98
lines changed

18 files changed

+179
-98
lines changed

.github/workflows/vs2022.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ jobs:
5050
with:
5151
msbuild-architecture: x64
5252

53+
- name: Install UPX
54+
uses: crazy-max/ghaction-upx@v3
55+
with:
56+
install-only: true
57+
5358
- name: Set ALPHA
5459
id: set_alpha
5560
shell: bash
@@ -76,6 +81,10 @@ jobs:
7681
move .\${{ matrix.TARGET_PLATFORM }}\Release\rufus.exe .\rufus_${{ matrix.TARGET_PLATFORM }}.exe
7782
move .\${{ matrix.TARGET_PLATFORM }}\Release\rufus.pdb .\rufus_${{ matrix.TARGET_PLATFORM }}.pdb
7883
84+
- name: Compress executables
85+
if: ${{ matrix.TARGET_PLATFORM != 'arm64' }}
86+
run: upx --lzma --best .\rufus_${{ matrix.TARGET_PLATFORM }}.exe
87+
7988
- name: Display SHA-256
8089
run: sha256sum ./rufus_${{ matrix.TARGET_PLATFORM }}.exe
8190

.mingw/Makefile.am

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ TARGET := $(word 1,$(subst -, ,$(TUPLE)))
2020
DEF_SUFFIX := $(if $(TARGET:x86_64=),.def,.def64)
2121

2222
.PHONY: all
23-
# Ideally, we would also have cfgmgr32-delaylib here, but it doesn't actually delay load... :(
24-
all: dwmapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
23+
all: crypt32-delaylib.lib dwmapi-delaylib.lib setupapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
2524

2625
%.def64: %.def
2726
$(AM_V_SED) "s/@.*//" $< >$@

.mingw/Makefile.in

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,7 @@ uninstall-am:
368368

369369

370370
.PHONY: all
371-
# Ideally, we would also have cfgmgr32-delaylib here, but it doesn't actually delay load... :(
372-
all: dwmapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
371+
all: crypt32-delaylib.lib dwmapi-delaylib.lib setupapi-delaylib.lib version-delaylib.lib virtdisk-delaylib.lib wininet-delaylib.lib wintrust-delaylib.lib
373372

374373
%.def64: %.def
375374
$(AM_V_SED) "s/@.*//" $< >$@

.mingw/crypt32.def

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
EXPORTS
2+
CertFindCertificateInStore@24
3+
CertGetCertificateChain@32
4+
CertGetNameStringA@24
5+
CertCloseStore@8
6+
CertFreeCertificateContext@4
7+
CryptQueryObject@44
8+
CryptDecodeObjectEx@32
9+
CryptHashCertificate@28
10+
CryptMsgGetParam@20
11+
CryptMsgClose@4
12+
CryptMsgGetParam@20
13+
CryptMsgOpenToDecode@24
14+
CryptMsgUpdate@16

.mingw/setupapi.def

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
EXPORTS
2+
CM_Locate_DevNodeA@12
3+
CM_Get_DevNode_Registry_PropertyA@24
4+
CM_Get_DevNode_Status@16
5+
CM_Get_Child@12
6+
CM_Get_Parent@12
7+
CM_Get_Sibling@12
8+
CM_Get_Device_IDA@16
9+
CM_Get_Device_ID_ListA@16
10+
CM_Get_Device_ID_List_SizeA@12
11+
SetupDiGetDeviceInstanceIdA@20
12+
SetupDiGetDeviceRegistryPropertyA@28
13+
SetupDiGetDeviceRegistryPropertyW@28
14+
SetupDiChangeState@8
15+
SetupDiGetClassDevsA@16
16+
SetupDiSetClassInstallParamsW@16
17+
SetupDiEnumDeviceInfo@12
18+
SetupDiEnumDeviceInterfaces@20
19+
SetupDiDestroyDeviceInfoList@4
20+
SetupDiGetDeviceInterfaceDetailA@24

.vs/rufus.vcxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@
168168
<GenerateDebugInformation>true</GenerateDebugInformation>
169169
<SubSystem>Windows</SubSystem>
170170
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories>
171-
<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>
171+
<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>
172172
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
173173
</Link>
174174
<ResourceCompile>
@@ -200,7 +200,7 @@
200200
<GenerateDebugInformation>true</GenerateDebugInformation>
201201
<SubSystem>Windows</SubSystem>
202202
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories>
203-
<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>
203+
<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>
204204
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
205205
</Link>
206206
<ResourceCompile>
@@ -302,7 +302,7 @@
302302
<SubSystem>Windows</SubSystem>
303303
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories>
304304
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
305-
<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>
305+
<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>
306306
</Link>
307307
<ResourceCompile>
308308
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -336,7 +336,7 @@
336336
<SubSystem>Windows</SubSystem>
337337
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories>
338338
<AdditionalOptions>/BREPRO /DEPENDENTLOADFLAG:0x800 %(AdditionalOptions)</AdditionalOptions>
339-
<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>
339+
<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>
340340
</Link>
341341
<ResourceCompile>
342342
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

configure

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4702,7 +4702,7 @@ fi
47024702
printf "%s\n" "enabling Large File Support (ISO support)" >&6; }
47034703
AM_CFLAGS="$AM_CFLAGS -D_FILE_OFFSET_BITS=64 -D_OFF_T_ -D_off_t=off64_t -Doff_t=off64_t -Doff32_t=long"
47044704
4705-
# check for -Wno-pointer-sign compiler support (GCC >= 4)
4705+
# Check for -Wno-pointer-sign compiler support (GCC >= 4)
47064706
saved_CFLAGS="${CFLAGS}"
47074707
CFLAGS="$CFLAGS -Wno-pointer-sign"
47084708
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4725,7 +4725,9 @@ fi
47254725
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
47264726
CFLAGS="${saved_CFLAGS}"
47274727
4728-
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"
4728+
# NB: The DECLSPEC_IMPORT redefinition below is a temporary(?) workaround for MinGW32 delay-loading
4729+
# See https://github.com/pbatard/rufus/pull/2513 as well as https://sourceware.org/bugzilla/show_bug.cgi?id=14339
4730+
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"
47294731
47304732
47314733

configure.ac

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,16 @@ fi
5757
AC_MSG_RESULT([enabling Large File Support (ISO support)])
5858
AM_CFLAGS="$AM_CFLAGS -D_FILE_OFFSET_BITS=64 -D_OFF_T_ -D_off_t=off64_t -Doff_t=off64_t -Doff32_t=long"
5959

60-
# check for -Wno-pointer-sign compiler support (GCC >= 4)
60+
# Check for -Wno-pointer-sign compiler support (GCC >= 4)
6161
saved_CFLAGS="${CFLAGS}"
6262
CFLAGS="$CFLAGS -Wno-pointer-sign"
6363
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
6464
[nopointersign_cflags="-Wno-pointer-sign"], [nopointersign_cflags=""])
6565
CFLAGS="${saved_CFLAGS}"
6666

67-
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"
67+
# NB: The DECLSPEC_IMPORT redefinition below is a temporary(?) workaround for MinGW32 delay-loading
68+
# See https://github.com/pbatard/rufus/pull/2513 as well as https://sourceware.org/bugzilla/show_bug.cgi?id=14339
69+
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"
6870

6971
AC_SUBST([VISIBILITY_CFLAGS])
7072
AC_SUBST([AM_CFLAGS])

loadcfg.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/env python3
2+
3+
# PE Load Configuration section enabler for MinGW/gcc executables.
4+
# The PE executable should have a IMAGE_LOAD_CONFIG_DIRECTORY## section
5+
# in .rdata with a 16-byte IMAGE_DIRECTORY_ENTRY_MARKER marker.
6+
7+
import os
8+
import sys
9+
import pefile
10+
11+
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10
12+
IMAGE_DIRECTORY_ENTRY_MARKER = b"_RUFUS_LOAD_CFG"
13+
14+
if len(sys.argv) < 2:
15+
raise RuntimeError("No executable path supplied")
16+
17+
# Create a temp file as our source
18+
pe_dst = sys.argv[1]
19+
pe_src = sys.argv[1] + ".tmp"
20+
os.replace(pe_dst, pe_src)
21+
22+
# Open and parse PE
23+
pe = pefile.PE(pe_src)
24+
25+
# Find .rdata section
26+
rdata_section = next(
27+
(s for s in pe.sections if s.Name.rstrip(b'\x00') == b'.rdata'),
28+
None
29+
)
30+
if not rdata_section:
31+
raise RuntimeError(".rdata section not found")
32+
33+
# Read the section's raw data to search for the target string
34+
raw_data = rdata_section.get_data()
35+
36+
# Look for the target data in the raw section data
37+
offset = raw_data.find(IMAGE_DIRECTORY_ENTRY_MARKER)
38+
if offset == -1:
39+
raise RuntimeError("Load Config marker not found")
40+
41+
# Move past our 16 bytes marker
42+
offset += 0x10
43+
# Calculate the RVA and size of the Load Config section
44+
load_config_rva = rdata_section.VirtualAddress + offset
45+
print(f"RVA of Load Config: 0x{load_config_rva:X}")
46+
load_config_size = pe.get_dword_at_rva(load_config_rva)
47+
if (load_config_size < 0x20):
48+
raise RuntimeError("Size of Load Config section is too small")
49+
print(f"Size of Load Config: 0x{load_config_size:X}")
50+
51+
# Update Load Config directory entry
52+
pe.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = load_config_rva
53+
pe.OPTIONAL_HEADER.DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = load_config_size
54+
55+
# Update the checksum
56+
pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
57+
58+
# Write the updated PE file and remove temp
59+
pe.write(pe_dst)
60+
os.remove(pe_src)
61+
62+
# Can be validated with `DUMPBIN /LOADCONFIG <.exe>` or `objdump -x <.exe> | grep "Load Configuration"`
63+
print(f"Successfully enabled Load Config section in '{pe_dst}'")

src/Makefile.am

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

108
noinst_PROGRAMS = rufus
119

0 commit comments

Comments
 (0)