mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[msvc] add provision to prevent DLL search order hijacking through delay loading
* Hypothetically if the user's current directory contains a malicious DLL that DLL could be loaded instead of the one in System32. * Whereas the previous patch should have taken care of the one DLL referenced by Rufus that may be vulnerable to this attack (version.dll), we nonetheless add delay loading for all the libraries we reference as a precautionary measure. * One can confirm that this works by using dumpbin.exe /IMPORTS to make sure a specific DLL is delay loaded. Then putting a breakpoint in the delay load hook should also confirm that the hook is used. * Closes #1838
This commit is contained in:
parent
f6ac559f4d
commit
ef2ff7179d
3 changed files with 37 additions and 20 deletions
|
@ -133,11 +133,12 @@
|
||||||
<AdditionalOptions>/utf-8 $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/utf-8 $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<DelayLoadDLLs>advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.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>advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.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>advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||||
</Link>
|
</Link>
|
||||||
<ResourceCompile>
|
<ResourceCompile>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
@ -214,11 +217,12 @@
|
||||||
<AdditionalOptions>/utf-8 $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/utf-8 $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<TargetMachine>MachineX64</TargetMachine>
|
<TargetMachine>MachineX64</TargetMachine>
|
||||||
|
<DelayLoadDLLs>advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||||
</Link>
|
</Link>
|
||||||
<ResourceCompile>
|
<ResourceCompile>
|
||||||
<PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
|
39
src/rufus.c
39
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"
|
||||||
|
@ -3191,6 +3192,23 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// By default the Windows SDK headers have a `const` while MinGW does not.
|
||||||
|
const
|
||||||
|
#endif
|
||||||
|
PfnDliHook __pfnDliNotifyHook2 = dllDelayLoadHook;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Application Entrypoint
|
* Application Entrypoint
|
||||||
|
@ -3202,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;
|
||||||
|
@ -3238,22 +3255,18 @@ 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, we can delay load the DLL and use a delay load
|
||||||
// perform their DLL invocations before you've had a chance to execute anything.
|
// hook to load them from System32. Note that, for this to work, something like:
|
||||||
// Of course, this is not something that security "researchers" will bother looking into
|
// 'somelib.dll;%(DelayLoadDLLs)' must be added to the 'Delay Loaded Dlls' option of
|
||||||
// to try to help fellow developers, when they can get an ego fix by simply throwing
|
// the linker properties in Visual Studio (which means this won't work with MinGW).
|
||||||
// generic URLs around and deliberately refusing to practice *responsible disclosure*...
|
// For all other DLLs, use SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32).
|
||||||
// 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);
|
||||||
|
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_ACCEPTFILES
|
EXSTYLE WS_EX_ACCEPTFILES
|
||||||
CAPTION "Rufus 3.18.1857"
|
CAPTION "Rufus 3.18.1858"
|
||||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||||
|
@ -395,8 +395,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 3,18,1857,0
|
FILEVERSION 3,18,1858,0
|
||||||
PRODUCTVERSION 3,18,1857,0
|
PRODUCTVERSION 3,18,1858,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -414,13 +414,13 @@ BEGIN
|
||||||
VALUE "Comments", "https://rufus.ie"
|
VALUE "Comments", "https://rufus.ie"
|
||||||
VALUE "CompanyName", "Akeo Consulting"
|
VALUE "CompanyName", "Akeo Consulting"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "3.18.1857"
|
VALUE "FileVersion", "3.18.1858"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
VALUE "OriginalFilename", "rufus-3.18.exe"
|
VALUE "OriginalFilename", "rufus-3.18.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "3.18.1857"
|
VALUE "ProductVersion", "3.18.1858"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Reference in a new issue