mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	Fix vunerablity to DLL Search Order Hijacking by delay loading version.dll
Hypothetically if the user's current directory contains a malicious DLL named version.dll, this DLL will be loaded instead of the one in System32. I checked the list of DLLs referenced by rufus.exe against the KnownDLLs list visible in Sysinternal's winobj.exe. On both Windows 7 and Windows 11, version.dll was the only DLL not on the KnownDLLs list and thus vunerable to this attack. To confirm that this work, I used dumpbin.exe /IMPORTS to make sure version.dll is delay loaded. I then put a breakpoint in the delay load hook and confirmed that the hook is used. This can be triggered by loading a Windows installation ISO file.
This commit is contained in:
		
							parent
							
								
									eeca1f279c
								
							
						
					
					
						commit
						7712ad6e0f
					
				
					 2 changed files with 30 additions and 13 deletions
				
			
		|  | @ -138,6 +138,7 @@ | ||||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> |       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <TargetMachine>MachineX86</TargetMachine> |       <TargetMachine>MachineX86</TargetMachine> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -162,6 +163,7 @@ | ||||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> |       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories> |       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -188,6 +190,7 @@ | ||||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> |       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories> |       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -219,6 +222,7 @@ | ||||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> |       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <TargetMachine>MachineX64</TargetMachine> |       <TargetMachine>MachineX64</TargetMachine> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -246,6 +250,7 @@ | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <TargetMachine>MachineX86</TargetMachine> |       <TargetMachine>MachineX86</TargetMachine> | ||||||
|       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> |       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -273,6 +278,7 @@ | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories> |       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm</AdditionalLibraryDirectories> | ||||||
|       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> |       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -302,6 +308,7 @@ | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories> |       <AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64</AdditionalLibraryDirectories> | ||||||
|       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> |       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  | @ -334,6 +341,7 @@ | ||||||
|       <SubSystem>Windows</SubSystem> |       <SubSystem>Windows</SubSystem> | ||||||
|       <TargetMachine>MachineX64</TargetMachine> |       <TargetMachine>MachineX64</TargetMachine> | ||||||
|       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> |       <AdditionalOptions>/BREPRO %(AdditionalOptions)</AdditionalOptions> | ||||||
|  |       <DelayLoadDLLs>version.dll;%(DelayLoadDLLs)</DelayLoadDLLs> | ||||||
|     </Link> |     </Link> | ||||||
|     <ResourceCompile> |     <ResourceCompile> | ||||||
|       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -36,6 +36,7 @@ | ||||||
| #include <io.h> | #include <io.h> | ||||||
| #include <getopt.h> | #include <getopt.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  | #include <delayimp.h> | ||||||
| 
 | 
 | ||||||
| #include "rufus.h" | #include "rufus.h" | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
|  | @ -3193,6 +3194,21 @@ static HANDLE SetHogger(void) | ||||||
| 	return hogmutex; | 	return hogmutex; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // For delay-loaded DLLs,
 | ||||||
|  | // use LOAD_LIBRARY_SEARCH_SYSTEM32 to avoid DLL search order hijacking.
 | ||||||
|  | FARPROC WINAPI dllDelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli) | ||||||
|  | { | ||||||
|  | 	if (dliNotify == dliNotePreLoadLibrary) | ||||||
|  | 	{ | ||||||
|  | 		// Windows 7 without KB2533623 does not support the LOAD_LIBRARY_SEARCH_SYSTEM32 flag.
 | ||||||
|  | 		// That is is OK, because the delay load handler will interrupt the NULL return value
 | ||||||
|  | 		// to mean that it should perform a normal LoadLibrary.
 | ||||||
|  | 		return (FARPROC)LoadLibraryExA(pdli->szDll, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | const PfnDliHook __pfnDliNotifyHook2 = dllDelayLoadHook; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Application Entrypoint |  * Application Entrypoint | ||||||
|  | @ -3204,7 +3220,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| #endif | #endif | ||||||
| { | { | ||||||
| 	const char* rufus_loc = "rufus.loc"; | 	const char* rufus_loc = "rufus.loc"; | ||||||
| 	wchar_t kernel32_path[MAX_PATH]; |  | ||||||
| 	int i, opt, option_index = 0, argc = 0, si = 0, lcid = GetUserDefaultUILanguage(); | 	int i, opt, option_index = 0, argc = 0, si = 0, lcid = GetUserDefaultUILanguage(); | ||||||
| 	int wait_for_mutex = 0; | 	int wait_for_mutex = 0; | ||||||
| 	FILE* fd; | 	FILE* fd; | ||||||
|  | @ -3240,22 +3255,16 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 	// Still, we invoke it, for platforms where the following call might actually work...
 | 	// Still, we invoke it, for platforms where the following call might actually work...
 | ||||||
| 	SetDllDirectoryA(""); | 	SetDllDirectoryA(""); | ||||||
| 
 | 
 | ||||||
| 	// Also, even if you use SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32), you're
 | 	// For libraries on the KnownDLLs list, the system will always load them from System32.
 | ||||||
| 	// still going to be brought down if you link to wininet.lib or dwmapi.lib, as these two
 | 	// For other DLLs we link directly to, like version.dll, we delay load the DLL and use
 | ||||||
| 	// perform their DLL invocations before you've had a chance to execute anything.
 | 	// a delay load hook to load them from System32.
 | ||||||
| 	// Of course, this is not something that security "researchers" will bother looking into
 | 	// For all other DLLs, use SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32).
 | ||||||
| 	// to try to help fellow developers, when they can get an ego fix by simply throwing
 |  | ||||||
| 	// generic URLs around and deliberately refusing to practice *responsible disclosure*...
 |  | ||||||
| 	// Finally, we need to perform the whole gymkhana below, where we can't call on
 | 	// Finally, we need to perform the whole gymkhana below, where we can't call on
 | ||||||
| 	// SetDefaultDllDirectories() directly, because Windows 7 doesn't have the API exposed.
 | 	// SetDefaultDllDirectories() directly, because Windows 7 doesn't have the API exposed.
 | ||||||
| 	GetSystemDirectoryW(kernel32_path, ARRAYSIZE(kernel32_path)); | 	// Also, no, Coverity, we never need to care about freeing kernel32 as a library.
 | ||||||
| 	wcsncat(kernel32_path, L"\\kernel32.dll", ARRAYSIZE(kernel32_path) - wcslen(kernel32_path) - 1); |  | ||||||
| 	// NB: Because kernel32 should already be loaded, what we do above to ensure that we
 |  | ||||||
| 	// (re)pick the system one is mostly unnecessary. But since for a hammer everything is a
 |  | ||||||
| 	// nail... Also, no, Coverity, we never need to care about freeing kernel32 as a library.
 |  | ||||||
| 	// coverity[leaked_storage]
 | 	// coverity[leaked_storage]
 | ||||||
| 	pfSetDefaultDllDirectories = (SetDefaultDllDirectories_t) | 	pfSetDefaultDllDirectories = (SetDefaultDllDirectories_t) | ||||||
| 		GetProcAddress(LoadLibraryW(kernel32_path), "SetDefaultDllDirectories"); | 		GetProcAddress(LoadLibraryW(L"kernel32.dll"), "SetDefaultDllDirectories"); | ||||||
| 	if (pfSetDefaultDllDirectories != NULL) | 	if (pfSetDefaultDllDirectories != NULL) | ||||||
| 		pfSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); | 		pfSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue