forked from mirrors/gecko-dev
Bug 1443411: Add gtests for blocking threads with LoadLibrary start address;r=aklotz
MozReview-Commit-ID: 2wIUNnNoKa8 --HG-- extra : rebase_source : f1990af6cd130d9bca38ef21d64d66584d20b94e
This commit is contained in:
parent
a162eddf84
commit
63153c7e3b
9 changed files with 436 additions and 1 deletions
|
|
@ -374,6 +374,45 @@ static wchar_t* lastslash(wchar_t* s, int len)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
DllLoadHookType gDllLoadHook = nullptr;
|
||||
|
||||
void
|
||||
DllBlocklist_SetDllLoadHook(DllLoadHookType aHook)
|
||||
{
|
||||
gDllLoadHook = aHook;
|
||||
}
|
||||
|
||||
void
|
||||
CallDllLoadHook(bool aDllLoaded, NTSTATUS aStatus, HANDLE aDllBase, PUNICODE_STRING aDllName)
|
||||
{
|
||||
if (gDllLoadHook) {
|
||||
gDllLoadHook(aDllLoaded, aStatus, aDllBase, aDllName);
|
||||
}
|
||||
}
|
||||
|
||||
CreateThreadHookType gCreateThreadHook = nullptr;
|
||||
|
||||
void
|
||||
DllBlocklist_SetCreateThreadHook(CreateThreadHookType aHook)
|
||||
{
|
||||
gCreateThreadHook = aHook;
|
||||
}
|
||||
|
||||
void
|
||||
CallCreateThreadHook(bool aWasAllowed, void* aStartAddress)
|
||||
{
|
||||
if (gCreateThreadHook) {
|
||||
gCreateThreadHook(aWasAllowed, aStartAddress);
|
||||
}
|
||||
}
|
||||
|
||||
#else // ENABLE_TESTS
|
||||
#define CallDllLoadHook(...)
|
||||
#define CallCreateThreadHook(...)
|
||||
#endif // ENABLE_TESTS
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
|
||||
{
|
||||
|
|
@ -453,6 +492,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||
char * end = nullptr;
|
||||
_strtoui64(dot+1, &end, 16);
|
||||
if (end == dot+13) {
|
||||
CallDllLoadHook(false, STATUS_DLL_NOT_FOUND, 0, moduleFileName);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
|
@ -463,6 +503,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||
current++;
|
||||
}
|
||||
if (current == dot) {
|
||||
CallDllLoadHook(false, STATUS_DLL_NOT_FOUND, 0, moduleFileName);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
|
@ -510,6 +551,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||
if (!full_fname) {
|
||||
// uh, we couldn't find the DLL at all, so...
|
||||
printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
|
||||
CallDllLoadHook(false, STATUS_DLL_NOT_FOUND, 0, moduleFileName);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
|
@ -548,6 +590,7 @@ patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileNam
|
|||
if (!load_ok) {
|
||||
printf_stderr("LdrLoadDll: Blocking load of '%s' -- see http://www.mozilla.com/en-US/blocklist/\n", dllName);
|
||||
DllBlockSet::Add(info->name, fVersion);
|
||||
CallDllLoadHook(false, STATUS_DLL_NOT_FOUND, 0, moduleFileName);
|
||||
return STATUS_DLL_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
|
@ -570,7 +613,9 @@ continue_loading:
|
|||
AutoSuppressStackWalking suppress;
|
||||
#endif
|
||||
|
||||
return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
|
||||
NTSTATUS ret = stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
|
||||
CallDllLoadHook(true, ret, handle ? *handle : 0, moduleFileName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
|
|
@ -616,7 +661,10 @@ patched_BaseThreadInitThunk(BOOL aIsInitialThread, void* aStartAddress,
|
|||
void* aThreadParam)
|
||||
{
|
||||
if (ShouldBlockThread(aStartAddress)) {
|
||||
CallCreateThreadHook(false, aStartAddress);
|
||||
aStartAddress = (void*)NopThreadProc;
|
||||
} else {
|
||||
CallCreateThreadHook(true, aStartAddress);
|
||||
}
|
||||
|
||||
stub_BaseThreadInitThunk(aIsInitialThread, aStartAddress, aThreadParam);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
#if (defined(_MSC_VER) || defined(__MINGW32__)) && (defined(_M_IX86) || defined(_M_X64))
|
||||
|
||||
#include <windows.h>
|
||||
#ifdef ENABLE_TESTS
|
||||
#include <winternl.h>
|
||||
#endif // ENABLE_TESTS
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
|
|
@ -25,6 +28,14 @@ MFBT_API void DllBlocklist_Initialize(uint32_t aInitFlags = eDllBlocklistInitFla
|
|||
MFBT_API void DllBlocklist_WriteNotes(HANDLE file);
|
||||
MFBT_API bool DllBlocklist_CheckStatus();
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
typedef void (*DllLoadHookType)(bool aDllLoaded, NTSTATUS aNtStatus,
|
||||
HANDLE aDllBase, PUNICODE_STRING aDllName);
|
||||
MFBT_API void DllBlocklist_SetDllLoadHook(DllLoadHookType aHook);
|
||||
typedef void (*CreateThreadHookType)(bool aWasAllowed, void *aStartAddress);
|
||||
MFBT_API void DllBlocklist_SetCreateThreadHook(CreateThreadHookType aHook);
|
||||
#endif // ENABLE_TESTS
|
||||
|
||||
// Forward declaration
|
||||
namespace mozilla {
|
||||
namespace glue {
|
||||
|
|
|
|||
50
mozglue/tests/gtest/Injector/Injector.cpp
Normal file
50
mozglue/tests/gtest/Injector/Injector.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 4) {
|
||||
fprintf(stderr,
|
||||
"Not enough command line arguments.\n"
|
||||
"Command line syntax:\n"
|
||||
"Injector.exe [pid] [startAddr] [threadParam]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
DWORD pid = strtoul(argv[1], 0, 0);
|
||||
#ifdef HAVE_64BIT_BUILD
|
||||
void* startAddr = (void*)strtoull(argv[2], 0, 0);
|
||||
void* threadParam = (void*)strtoull(argv[3], 0, 0);
|
||||
#else
|
||||
void* startAddr = (void*)strtoul(argv[2], 0, 0);
|
||||
void* threadParam = (void*)strtoul(argv[3], 0, 0);
|
||||
#endif
|
||||
HANDLE targetProc = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
|
||||
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
|
||||
FALSE,
|
||||
pid);
|
||||
if (targetProc == nullptr) {
|
||||
fprintf(stderr, "Error %lu opening target process, PID %lu \n", GetLastError(), pid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
HANDLE hThread = CreateRemoteThread(targetProc, nullptr, 0,
|
||||
(LPTHREAD_START_ROUTINE)startAddr,
|
||||
threadParam, 0, nullptr);
|
||||
if (hThread == nullptr) {
|
||||
fprintf(stderr, "Error %lu in CreateRemoteThread\n", GetLastError());
|
||||
CloseHandle(targetProc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CloseHandle(hThread);
|
||||
CloseHandle(targetProc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
mozglue/tests/gtest/Injector/moz.build
Normal file
9
mozglue/tests/gtest/Injector/moz.build
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIST_INSTALL = False
|
||||
|
||||
SimplePrograms(['Injector'])
|
||||
|
||||
TEST_HARNESS_FILES.gtest += ['!Injector.exe']
|
||||
11
mozglue/tests/gtest/InjectorDLL/InjectorDLL.cpp
Normal file
11
mozglue/tests/gtest/InjectorDLL/InjectorDLL.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD aReason, LPVOID)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
14
mozglue/tests/gtest/InjectorDLL/moz.build
Normal file
14
mozglue/tests/gtest/InjectorDLL/moz.build
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIST_INSTALL = False
|
||||
|
||||
SharedLibrary('InjectorDLL')
|
||||
|
||||
UNIFIED_SOURCES = [
|
||||
'InjectorDLL.cpp',
|
||||
]
|
||||
|
||||
TEST_HARNESS_FILES.gtest += ['!InjectorDLL.dll']
|
||||
277
mozglue/tests/gtest/TestDLLEject.cpp
Normal file
277
mozglue/tests/gtest/TestDLLEject.cpp
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include "gtest/gtest.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WindowsDllBlocklist.h"
|
||||
|
||||
static HANDLE sThreadWasBlocked = 0;
|
||||
static HANDLE sThreadWasAllowed = 0;
|
||||
static HANDLE sDllWasLoaded = 0;
|
||||
static uintptr_t sStartAddress = 0;
|
||||
|
||||
static const int sTimeoutMS = 10000;
|
||||
|
||||
#define DLL_LEAF_NAME (u"InjectorDLL.dll")
|
||||
|
||||
static nsString
|
||||
makeString(PUNICODE_STRING aOther)
|
||||
{
|
||||
size_t numChars = aOther->Length / sizeof(WCHAR);
|
||||
return nsString((const char16_t *)aOther->Buffer, numChars);
|
||||
}
|
||||
|
||||
static void
|
||||
DllLoadHook(bool aDllLoaded, NTSTATUS aStatus, HANDLE aDllBase,
|
||||
PUNICODE_STRING aDllName)
|
||||
{
|
||||
nsString str = makeString(aDllName);
|
||||
|
||||
nsString dllName = nsString(DLL_LEAF_NAME);
|
||||
if (StringEndsWith(str, dllName, nsCaseInsensitiveStringComparator())) {
|
||||
if (aDllLoaded) {
|
||||
SetEvent(sDllWasLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CreateThreadHook(bool aWasAllowed, void* aStartAddress)
|
||||
{
|
||||
if (sStartAddress == (uintptr_t)aStartAddress) {
|
||||
if (!aWasAllowed) {
|
||||
SetEvent(sThreadWasBlocked);
|
||||
} else {
|
||||
SetEvent(sThreadWasAllowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tests that we correctly block DLLs injected into this process
|
||||
* via an injection technique which calls CreateRemoteThread with LoadLibrary*()
|
||||
* as the thread start address, and the path to the DLL as the thread param.
|
||||
*
|
||||
* We prevent this technique by blocking threads with a start address in any
|
||||
* LoadLibrary*() APIs.
|
||||
*
|
||||
* This function launches Injector.exe which simulates a 3rd-party application
|
||||
* executing this technique.
|
||||
*
|
||||
* @param aGetArgsProc A callable procedure that specifies the thread start
|
||||
* address and thread param passed as arguments to
|
||||
* Injector.exe, which are in turn passed as arguments to
|
||||
* CreateRemoteThread. This procedure is defined as such:
|
||||
*
|
||||
* void (*aGetArgsProc)(const nsString& aDllPath,
|
||||
* const nsCString& aDllPathC,
|
||||
* uintptr_t& startAddress,
|
||||
* uintptr_t& threadParam);
|
||||
*
|
||||
* aDllPath is a WCHAR-friendly path to InjectorDLL.dll.
|
||||
* Its memory will persist during the injection attempt.
|
||||
*
|
||||
* aDllPathC is the equivalent char-friendly path.
|
||||
*
|
||||
* startAddress and threadParam are passed into
|
||||
* CreateRemoteThread as arguments.
|
||||
*/
|
||||
template<typename TgetArgsProc>
|
||||
static void
|
||||
DoTest_CreateRemoteThread_LoadLibrary(TgetArgsProc aGetArgsProc)
|
||||
{
|
||||
sThreadWasBlocked = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!sThreadWasBlocked) {
|
||||
EXPECT_TRUE(!"Unable to create sThreadWasBlocked event");
|
||||
ASSERT_EQ(GetLastError(), ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
sThreadWasAllowed = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!sThreadWasAllowed) {
|
||||
EXPECT_TRUE(!"Unable to create sThreadWasAllowed event");
|
||||
ASSERT_EQ(GetLastError(), ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
sDllWasLoaded = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!sDllWasLoaded) {
|
||||
EXPECT_TRUE(!"Unable to create sDllWasLoaded event");
|
||||
ASSERT_EQ(GetLastError(), ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
auto closeEvents = mozilla::MakeScopeExit([&](){
|
||||
CloseHandle(sThreadWasAllowed);
|
||||
CloseHandle(sThreadWasBlocked);
|
||||
CloseHandle(sDllWasLoaded);
|
||||
});
|
||||
|
||||
// Hook into our DLL and thread blocking routines during this test.
|
||||
DllBlocklist_SetDllLoadHook(DllLoadHook);
|
||||
DllBlocklist_SetCreateThreadHook(CreateThreadHook);
|
||||
auto undoHooks = mozilla::MakeScopeExit([&](){
|
||||
DllBlocklist_SetDllLoadHook(nullptr);
|
||||
DllBlocklist_SetCreateThreadHook(nullptr);
|
||||
});
|
||||
|
||||
// Launch Injector.exe.
|
||||
STARTUPINFOW si = { 0 };
|
||||
si.cb = sizeof(si);
|
||||
::GetStartupInfoW(&si);
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
nsString path(u"Injector.exe");
|
||||
nsString dllPath(DLL_LEAF_NAME);
|
||||
nsCString dllPathC = NS_ConvertUTF16toUTF8(dllPath);
|
||||
|
||||
uintptr_t threadParam;
|
||||
aGetArgsProc(dllPath, dllPathC, sStartAddress, threadParam);
|
||||
|
||||
path.AppendPrintf(" %lu 0x%p 0x%p", GetCurrentProcessId(), sStartAddress,
|
||||
threadParam);
|
||||
if (::CreateProcessW(NULL, path.get(), 0, 0, FALSE, 0, NULL, NULL,
|
||||
&si, &pi) == FALSE) {
|
||||
EXPECT_TRUE(!"Error in CreateProcessW() launching Injector.exe");
|
||||
ASSERT_EQ(GetLastError(), ERROR_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure Injector.exe doesn't stay running after this test finishes.
|
||||
auto cleanup = mozilla::MakeScopeExit([&](){
|
||||
CloseHandle(pi.hThread);
|
||||
EXPECT_TRUE("Shutting down.");
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
});
|
||||
|
||||
// Wait for information to come in and complete the test.
|
||||
HANDLE handles[] = {
|
||||
sThreadWasBlocked,
|
||||
sThreadWasAllowed,
|
||||
sDllWasLoaded,
|
||||
pi.hProcess
|
||||
};
|
||||
int handleCount = mozilla::ArrayLength(handles);
|
||||
bool keepGoing = true; // Set to false to signal that the test is over.
|
||||
|
||||
while(keepGoing) {
|
||||
switch(WaitForMultipleObjectsEx(handleCount, handles,
|
||||
FALSE, sTimeoutMS, FALSE)) {
|
||||
case WAIT_OBJECT_0: { // sThreadWasBlocked
|
||||
EXPECT_TRUE("Thread was blocked successfully.");
|
||||
// No need to continue testing; blocking was successful.
|
||||
keepGoing = false;
|
||||
break;
|
||||
}
|
||||
case WAIT_OBJECT_0 + 1: { // sThreadWasAllowed
|
||||
EXPECT_TRUE(!"Thread was allowed but should have been blocked.");
|
||||
// No need to continue testing; blocking failed.
|
||||
keepGoing = false;
|
||||
break;
|
||||
}
|
||||
case WAIT_OBJECT_0 + 2: { // sDllWasLoaded
|
||||
EXPECT_TRUE(!"DLL was loaded.");
|
||||
// No need to continue testing; blocking failed and the DLL was
|
||||
// consequently loaded. In theory we should never see this fire, because
|
||||
// the thread being allowed should already trigger a test failure.
|
||||
keepGoing = false;
|
||||
break;
|
||||
}
|
||||
case WAIT_OBJECT_0 + 3: { // pi.hProcess
|
||||
// Check to see if we got an error code from Injector.exe, in which case
|
||||
// fail the test and exit.
|
||||
DWORD exitCode;
|
||||
if (!GetExitCodeProcess(pi.hProcess, &exitCode)) {
|
||||
EXPECT_TRUE(!"Injector.exe exited but we were unable to get the exit code.");
|
||||
keepGoing = false;
|
||||
break;
|
||||
}
|
||||
EXPECT_EQ(exitCode, 0);
|
||||
if (exitCode != 0) {
|
||||
EXPECT_TRUE(!"Injector.exe returned non-zero exit code");
|
||||
keepGoing = false;
|
||||
break;
|
||||
}
|
||||
// Process exited successfully. This can be ignored; we expect to get an
|
||||
// event whether the DLL was loaded or blocked.
|
||||
EXPECT_TRUE("Process exited as expected.");
|
||||
handleCount--;
|
||||
break;
|
||||
}
|
||||
case WAIT_TIMEOUT:
|
||||
default: {
|
||||
EXPECT_TRUE(!"An error or timeout occurred while waiting for activity "
|
||||
"from Injector.exe");
|
||||
keepGoing = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Double-check that injectordll is not loaded.
|
||||
auto hExisting = GetModuleHandleW(dllPath.get());
|
||||
EXPECT_TRUE(!hExisting);
|
||||
|
||||
// If the DLL was erroneously loaded, attempt to unload it before exiting.
|
||||
if (hExisting) {
|
||||
FreeLibrary(hExisting);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TEST(TestInjectEject, CreateRemoteThread_LoadLibraryA)
|
||||
{
|
||||
DoTest_CreateRemoteThread_LoadLibrary([](const nsString& dllPath,
|
||||
const nsCString& dllPathC,
|
||||
uintptr_t& aStartAddress,
|
||||
uintptr_t& aThreadParam){
|
||||
HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
|
||||
aStartAddress = (uintptr_t)GetProcAddress(hKernel32, "LoadLibraryA");
|
||||
aThreadParam = (uintptr_t)dllPathC.get();
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestInjectEject, CreateRemoteThread_LoadLibraryW)
|
||||
{
|
||||
DoTest_CreateRemoteThread_LoadLibrary([](const nsString& dllPath,
|
||||
const nsCString& dllPathC,
|
||||
uintptr_t& aStartAddress,
|
||||
uintptr_t& aThreadParam){
|
||||
HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
|
||||
aStartAddress = (uintptr_t)GetProcAddress(hKernel32, "LoadLibraryW");
|
||||
aThreadParam = (uintptr_t)dllPath.get();
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestInjectEject, CreateRemoteThread_LoadLibraryExW)
|
||||
{
|
||||
DoTest_CreateRemoteThread_LoadLibrary([](const nsString& dllPath,
|
||||
const nsCString& dllPathC,
|
||||
uintptr_t& aStartAddress,
|
||||
uintptr_t& aThreadParam){
|
||||
HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
|
||||
// LoadLibraryEx requires three arguments so this injection method may not
|
||||
// be viable. It's certainly not an allowable thread start in any case.
|
||||
aStartAddress = (uintptr_t)GetProcAddress(hKernel32, "LoadLibraryExW");
|
||||
aThreadParam = (uintptr_t)dllPath.get();
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestInjectEject, CreateRemoteThread_LoadLibraryExA)
|
||||
{
|
||||
DoTest_CreateRemoteThread_LoadLibrary([](const nsString& dllPath,
|
||||
const nsCString& dllPathC,
|
||||
uintptr_t& aStartAddress,
|
||||
uintptr_t& aThreadParam){
|
||||
HMODULE hKernel32 = GetModuleHandleW(L"Kernel32");
|
||||
aStartAddress = (uintptr_t)GetProcAddress(hKernel32, "LoadLibraryExA");
|
||||
aThreadParam = (uintptr_t)dllPathC.get();
|
||||
});
|
||||
}
|
||||
14
mozglue/tests/gtest/moz.build
Normal file
14
mozglue/tests/gtest/moz.build
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'TestDLLEject.cpp'
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul-gtest'
|
||||
|
||||
TEST_DIRS += [
|
||||
'Injector',
|
||||
'InjectorDLL',
|
||||
]
|
||||
|
|
@ -17,4 +17,5 @@ CppUnitTests([
|
|||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
TEST_DIRS += [
|
||||
'interceptor',
|
||||
'gtest',
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in a new issue