Bug 1435816: Prevent thread start in LoadLibrary; r?aklotz
MozReview-Commit-ID: 2TNPfrqebZ8
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -24,16 +24,17 @@
#pragma warning( pop )
#include "Authenticode.h"
#include "nsAutoPtr.h"
#include "nsWindowsDllInterceptor.h"
#include "mozilla/Sprintf.h"
#include "mozilla/StackWalk_windows.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/Vector.h"
#include "mozilla/WindowsVersion.h"
#include "nsWindowsHelpers.h"
#include "WindowsDllBlocklist.h"
#include "mozilla/AutoProfilerLabel.h"
#include "mozilla/glue/WindowsDllServices.h"
using namespace mozilla;
@@ -798,23 +799,37 @@ continue_loading:
// Prevent the stack walker from suspending this thread when LdrLoadDll
// holds the RtlLookupFunctionEntry lock.
AutoSuppressStackWalking suppress;
#endif
return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
}
+#if defined(NIGHTLY_BUILD)
+// Map of specific thread proc addresses we should block. In particular,
+// LoadLibrary* APIs which indicate DLL injection
+static mozilla::Vector<void*, 4>* gStartAddressesToBlock;
+#endif
+
static bool
ShouldBlockThread(void* aStartAddress)
{
// Allows crashfirefox.exe to continue to work. Also if your threadproc is null, this crash is intentional.
if (aStartAddress == 0)
return false;
+#if defined(NIGHTLY_BUILD)
+ for (auto p : *gStartAddressesToBlock) {
+ if (p == aStartAddress) {
+ return true;
+ }
+ }
+#endif
+
bool shouldBlock = false;
MEMORY_BASIC_INFORMATION startAddressInfo = {0};
if (VirtualQuery(aStartAddress, &startAddressInfo, sizeof(startAddressInfo))) {
shouldBlock |= startAddressInfo.State != MEM_COMMIT;
shouldBlock |= startAddressInfo.Protect != PAGE_EXECUTE_READ;
}
return shouldBlock;
@@ -845,16 +860,17 @@ static WindowsDllInterceptor Kernel32Int
MFBT_API void
DllBlocklist_Initialize(uint32_t aInitFlags)
{
if (sBlocklistInitAttempted) {
return;
}
sInitFlags = aInitFlags;
sBlocklistInitAttempted = true;
+ gStartAddressesToBlock = new mozilla::Vector<void*, 4>;
// In order to be effective against AppInit DLLs, the blocklist must be
// initialized before user32.dll is loaded into the process (bug 932100).
if (GetModuleHandleA("user32.dll")) {
sUser32BeforeBlocklist = true;
#ifdef DEBUG
printf_stderr("DLL blocklist was unable to intercept AppInit DLLs.\n");
#endif
@@ -900,16 +916,44 @@ DllBlocklist_Initialize(uint32_t aInitFl
if(!Kernel32Intercept.AddDetour("BaseThreadInitThunk",
reinterpret_cast<intptr_t>(patched_BaseThreadInitThunk),
(void**) &stub_BaseThreadInitThunk)) {
#ifdef DEBUG
printf_stderr("BaseThreadInitThunk hook failed\n");
#endif
}
}
+
+#if defined(NIGHTLY_BUILD)
+ // Populate a list of thread start addresses to block.
+ HMODULE hKernel = GetModuleHandleW(L"kernel32.dll");
+ if (hKernel) {
+ void* pProc;
+
+ pProc = (void*)GetProcAddress(hKernel, "LoadLibraryA");
+ if (pProc) {
+ gStartAddressesToBlock->append(pProc);
+ }
+
+ pProc = (void*)GetProcAddress(hKernel, "LoadLibraryW");
+ if (pProc) {
+ gStartAddressesToBlock->append(pProc);
+ }
+
+ pProc = (void*)GetProcAddress(hKernel, "LoadLibraryExA");
+ if (pProc) {
+ gStartAddressesToBlock->append(pProc);
+ }
+
+ pProc = (void*)GetProcAddress(hKernel, "LoadLibraryExW");
+ if (pProc) {
+ gStartAddressesToBlock->append(pProc);
+ }
+ }
+#endif
}
MFBT_API void
DllBlocklist_WriteNotes(HANDLE file)
{
DWORD nBytes;
WriteFile(file, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);