Bug 1435816: Prevent thread start in LoadLibrary; r?aklotz draft
authorCarl Corcoran <ccorcoran@mozilla.com>
Thu, 22 Feb 2018 13:41:15 +0100
changeset 768642 9e5ff564e921948809dcdb2b00a230699a92d35b
parent 768366 c43177719f368d4316d244cac5382f8cfce3832f
push id102943
push userbmo:ccorcoran@mozilla.com
push dateFri, 16 Mar 2018 16:42:57 +0000
reviewersaklotz
bugs1435816
milestone61.0a1
Bug 1435816: Prevent thread start in LoadLibrary; r?aklotz MozReview-Commit-ID: 2TNPfrqebZ8
mozglue/build/WindowsDllBlocklist.cpp
--- 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);