add hooks for .net

This commit is contained in:
Boring
2021-12-15 10:18:45 +08:00
parent bb83bf0cc0
commit b54c17f00f
13 changed files with 433 additions and 319 deletions
+5 -3
View File
@@ -64,7 +64,8 @@ static SYSTEM_INFO sysInfo = []()->SYSTEM_INFO {
NTSTATUS MemoryLoadLibrary(
_Out_ HMEMORYMODULE* MemoryModuleHandle,
_In_ LPCVOID data) {
_In_ LPCVOID data,
_In_ DWORD size) {
PIMAGE_DOS_HEADER dos_header = nullptr;
PIMAGE_NT_HEADERS old_header = nullptr;
@@ -122,7 +123,7 @@ NTSTATUS MemoryLoadLibrary(
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
if (!NT_SUCCESS(status)) return status;
if (!NT_SUCCESS(status) || status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)return status;
//
// Reserve the address range of image
@@ -178,9 +179,10 @@ NTSTATUS MemoryLoadLibrary(
PMEMORYMODULE hMemoryModule = (PMEMORYMODULE)(base + old_header->OptionalHeader.SizeOfHeaders);
RtlZeroMemory(hMemoryModule, sizeof(MEMORYMODULE));
hMemoryModule->codeBase = base;
hMemoryModule->pageSize = sysInfo.dwPageSize;
hMemoryModule->dwImageFileSize = size;
hMemoryModule->Signature = MEMORY_MODULE_SIGNATURE;
hMemoryModule->SizeofHeaders = old_header->OptionalHeader.SizeOfHeaders;
hMemoryModule->lpReserved = (LPVOID)data;
do {
//
+3 -2
View File
@@ -52,7 +52,7 @@ typedef struct _MEMORYMODULE {
DWORD dwModulesCount; //number of module handles
DWORD dwReserved;
DWORD pageSize; //SYSTEM_INFO::dwPageSize
DWORD dwImageFileSize;
DWORD headers_align; //headers_align == OptionalHeaders.BaseOfCode;
} MEMORYMODULE, * PMEMORYMODULE;
@@ -66,7 +66,8 @@ extern "C" {
NTSTATUS MemoryLoadLibrary(
_Out_ HMEMORYMODULE* MemoryModuleHandle,
_In_ LPCVOID data
_In_ LPCVOID data,
_In_ DWORD size
);
bool MemoryFreeLibrary(HMEMORYMODULE);
+2
View File
@@ -31,6 +31,7 @@
<ClCompile Include="..\3rdparty\Detours\modules.cpp" />
<ClCompile Include="LoadDllMemoryApi.cpp" />
<ClCompile Include="MemoryModule.cpp" />
<ClCompile Include="MmpDotNet.cpp" />
<ClCompile Include="MmpTls.cpp" />
<ClCompile Include="Native.cpp" />
<ClCompile Include="NativeFunctionsInternal.cpp" />
@@ -45,6 +46,7 @@
<ClInclude Include="..\3rdparty\Detours\detver.h" />
<ClInclude Include="LoadDllMemoryApi.h" />
<ClInclude Include="MemoryModule.h" />
<ClInclude Include="MmpDotNet.h" />
<ClInclude Include="Native.h" />
<ClInclude Include="NativeFunctionsInternal.h" />
<ClInclude Include="rtlinv.h" />
@@ -87,6 +87,9 @@
<ClCompile Include="..\3rdparty\Detours\modules.cpp">
<Filter>Source Files\3rdparty\Detours</Filter>
</ClCompile>
<ClCompile Include="MmpDotNet.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="MemoryModule.h">
@@ -125,6 +128,9 @@
<ClInclude Include="..\3rdparty\Detours\detver.h">
<Filter>Header Files\3rdparty\Detours</Filter>
</ClInclude>
<ClInclude Include="MmpDotNet.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\README.md">
+357
View File
@@ -0,0 +1,357 @@
#include "stdafx.h"
#include <3rdparty/Detours/detours.h>
typedef HRESULT (WINAPI* GetFileVersion_T)(
LPCWSTR szFilename,
LPWSTR szBuffer,
DWORD cchBuffer,
DWORD* dwLength
);
typedef struct _MMP_FAKE_HANDLE_LIST_ENTRY {
LIST_ENTRY InMmpFakeHandleList;
HANDLE hObject;
PVOID value;
}MMP_FAKE_HANDLE_LIST_ENTRY, * PMMP_FAKE_HANDLE_LIST_ENTRY;
static decltype(&CreateFileW) OriginCreateFileW = CreateFileW;
static decltype(&GetFileInformationByHandle) OriginGetFileInformationByHandle = GetFileInformationByHandle;
static decltype(&GetFileAttributesExW) OriginGetFileAttributesExW = GetFileAttributesExW;
static decltype(&CreateFileMappingW) OriginCreateFileMappingW = CreateFileMappingW;
static decltype(&MapViewOfFileEx) OriginMapViewOfFileEx = MapViewOfFileEx;
static decltype(&UnmapViewOfFile)OriginUnmapViewOfFile = UnmapViewOfFile;
static decltype(&CloseHandle)OriginCloseHandle = CloseHandle;
static GetFileVersion_T OriginGetFileVersion = nullptr;
FILETIME AssemblyTimes;
CRITICAL_SECTION MmpFakeHandleListLock;
LIST_ENTRY MmpFakeHandleListHead;
static BOOL Initialized = FALSE;
BOOL MmpIsMemoryModuleFileName(
_In_ LPCWSTR lpFileName,
_Out_opt_ PLDR_DATA_TABLE_ENTRY *LdrEntry) {
__try {
if (LdrEntry)*LdrEntry = nullptr;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
BOOL result = FALSE;
EnterCriticalSection(NtCurrentPeb()->LoaderLock);
for (auto entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
entry != &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
entry = entry->Flink) {
PLDR_DATA_TABLE_ENTRY CurEntry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InLoadOrderLinks);
if (!wcsncmp(CurEntry->FullDllName.Buffer, lpFileName, CurEntry->FullDllName.Length) &&
wcslen(lpFileName) * 2 == CurEntry->FullDllName.Length) {
result = IsValidMemoryModuleHandle((HMODULE)CurEntry->DllBase);
if (result) {
if (LdrEntry) {
__try {
*LdrEntry = CurEntry;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
;
}
}
}
break;
}
}
LeaveCriticalSection(NtCurrentPeb()->LoaderLock);
return result;
}
VOID MmpInsertHandleEntry(
_In_ HANDLE hObject,
_In_ PVOID value) {
auto entry = (PMMP_FAKE_HANDLE_LIST_ENTRY)RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(MMP_FAKE_HANDLE_LIST_ENTRY));
entry->hObject = hObject;
entry->value = value;
EnterCriticalSection(&MmpFakeHandleListLock);
InsertTailList(&MmpFakeHandleListHead, &entry->InMmpFakeHandleList);
LeaveCriticalSection(&MmpFakeHandleListLock);
}
PMMP_FAKE_HANDLE_LIST_ENTRY MmpFindHandleEntry(HANDLE hObject) {
PMMP_FAKE_HANDLE_LIST_ENTRY result = nullptr;
EnterCriticalSection(&MmpFakeHandleListLock);
for (auto entry = MmpFakeHandleListHead.Flink; entry != &MmpFakeHandleListHead; entry = entry->Flink) {
auto CurEntry = CONTAINING_RECORD(entry, MMP_FAKE_HANDLE_LIST_ENTRY, MMP_FAKE_HANDLE_LIST_ENTRY::InMmpFakeHandleList);
if (CurEntry->hObject == hObject) {
result = CurEntry;
break;
}
}
LeaveCriticalSection(&MmpFakeHandleListLock);
return result;
}
VOID MmpFreeHandleEntry(PMMP_FAKE_HANDLE_LIST_ENTRY lpHandleEntry) {
EnterCriticalSection(&MmpFakeHandleListLock);
RemoveEntryList(&lpHandleEntry->InMmpFakeHandleList);
RtlFreeHeap(RtlProcessHeap(), 0, lpHandleEntry);
LeaveCriticalSection(&MmpFakeHandleListLock);
}
HANDLE WINAPI HookCreateFileW(
_In_ LPCWSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile) {
PLDR_DATA_TABLE_ENTRY entry;
if (MmpIsMemoryModuleFileName(lpFileName, &entry)) {
HANDLE hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
MmpInsertHandleEntry(hEvent, entry);
return hEvent;
}
return OriginCreateFileW(
lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile
);
}
BOOL WINAPI HookGetFileInformationByHandle(
_In_ HANDLE hFile,
_Out_ LPBY_HANDLE_FILE_INFORMATION lpFileInformation) {
auto iter = MmpFindHandleEntry(hFile);
if (iter) {
RtlZeroMemory(lpFileInformation, sizeof(BY_HANDLE_FILE_INFORMATION));
auto entry = (PLDR_DATA_TABLE_ENTRY)iter->value;
auto module = MapMemoryModuleHandle((HMEMORYMODULE)entry->DllBase);
lpFileInformation->ftCreationTime = lpFileInformation->ftLastAccessTime = lpFileInformation->ftLastWriteTime = AssemblyTimes;
lpFileInformation->nFileSizeLow = module->dwImageFileSize;
return TRUE;
}
else {
return OriginGetFileInformationByHandle(
hFile,
lpFileInformation
);
}
}
BOOL WINAPI HookGetFileAttributesExW(
_In_ LPCWSTR lpFileName,
_In_ GET_FILEEX_INFO_LEVELS fInfoLevelId,
_Out_writes_bytes_(sizeof(WIN32_FILE_ATTRIBUTE_DATA)) LPVOID lpFileInformation) {
PLDR_DATA_TABLE_ENTRY entry;
if (MmpIsMemoryModuleFileName(lpFileName, &entry)) {
__try {
RtlZeroMemory(
lpFileInformation,
sizeof(WIN32_FILE_ATTRIBUTE_DATA)
);
LPWIN32_FILE_ATTRIBUTE_DATA data = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation;
auto module = MapMemoryModuleHandle((HMEMORYMODULE)entry->DllBase);
data->ftCreationTime = data->ftLastAccessTime = data->ftLastWriteTime = AssemblyTimes;
data->nFileSizeLow = module->dwImageFileSize;
return TRUE;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
}
return OriginGetFileAttributesExW(
lpFileName,
fInfoLevelId,
lpFileInformation
);
}
HANDLE WINAPI HookCreateFileMappingW(
_In_ HANDLE hFile,
_In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
_In_ DWORD flProtect,
_In_ DWORD dwMaximumSizeHigh,
_In_ DWORD dwMaximumSizeLow,
_In_opt_ LPCWSTR lpName) {
auto iter = MmpFindHandleEntry(hFile);
if (iter) {
HANDLE hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
MmpInsertHandleEntry(hEvent, iter->value);
return hEvent;
}
return OriginCreateFileMappingW(
hFile,
lpFileMappingAttributes,
flProtect,
dwMaximumSizeHigh,
dwMaximumSizeLow,
lpName
);
}
LPVOID WINAPI HookMapViewOfFileEx(
_In_ HANDLE hFileMappingObject,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwFileOffsetHigh,
_In_ DWORD dwFileOffsetLow,
_In_ SIZE_T dwNumberOfBytesToMap,
_In_opt_ LPVOID lpBaseAddress) {
auto iter = MmpFindHandleEntry(hFileMappingObject);
if (iter) {
HMEMORYMODULE hModule = nullptr;
auto entry = (PLDR_DATA_TABLE_ENTRY)iter->value;
auto pModule = MapMemoryModuleHandle((HMEMORYMODULE)entry->DllBase);
if (pModule) {
MemoryLoadLibrary(&hModule, pModule->lpReserved, pModule->dwImageFileSize);
if (hModule) MmpInsertHandleEntry(hModule, hModule);
}
return hModule;
}
return OriginMapViewOfFileEx(
hFileMappingObject,
dwDesiredAccess,
dwFileOffsetHigh,
dwFileOffsetLow,
dwNumberOfBytesToMap,
lpBaseAddress
);
}
BOOL WINAPI HookUnmapViewOfFile(_In_ LPCVOID lpBaseAddress) {
auto iter = MmpFindHandleEntry((HANDLE)lpBaseAddress);
if (iter) {
MemoryFreeLibrary((HMEMORYMODULE)lpBaseAddress);
MmpFreeHandleEntry(iter);
return TRUE;
}
return OriginUnmapViewOfFile(lpBaseAddress);
}
BOOL WINAPI HookCloseHandle(_In_ _Post_ptr_invalid_ HANDLE hObject) {
auto iter = MmpFindHandleEntry(hObject);
if (iter)MmpFreeHandleEntry(iter);
return OriginCloseHandle(hObject);
}
HRESULT WINAPI HookGetFileVersion(
LPCWSTR szFilename,
LPWSTR szBuffer,
DWORD cchBuffer,
DWORD* dwLength) {
typedef struct _COR20_METADATA {
DWORD Signature;
WORD MajorVersion;
WORD MinorVersion;
DWORD Reserved;
DWORD VersionLength;
CHAR VersionString[ANYSIZE_ARRAY];
}COR20_METADATA, * PCOR20_METADATA;
PLDR_DATA_TABLE_ENTRY entry = nullptr;
if (MmpIsMemoryModuleFileName(szFilename, &entry)) {
__try {
PIMAGE_NT_HEADERS headers = RtlImageNtHeader(entry->DllBase);
auto dir = headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
if (!dir.Size || !dir.VirtualAddress)__leave;
PIMAGE_COR20_HEADER cor2 = PIMAGE_COR20_HEADER(LPBYTE(entry->DllBase) + dir.VirtualAddress);
if (!cor2->MetaData.Size || !cor2->MetaData.VirtualAddress) __leave;
PCOR20_METADATA meta = PCOR20_METADATA(LPBYTE(entry->DllBase) + cor2->MetaData.VirtualAddress);
if (dwLength)*dwLength = meta->VersionLength;
if (cchBuffer < meta->VersionLength)return 0x8007007A;
MultiByteToWideChar(CP_ACP, 0, meta->VersionString, meta->VersionLength, szBuffer, cchBuffer);
return 0;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
;
}
}
return OriginGetFileVersion(
szFilename,
szBuffer,
cchBuffer,
dwLength
);
}
BOOL WINAPI MmpInitializeHooksForDotNet() {
HMODULE hModule = GetModuleHandleW(L"mscoreei.dll");
if (!hModule) {
RtlRaiseStatus(STATUS_NOT_SUPPORTED);
return FALSE;
}
OriginGetFileVersion = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion");
if (!OriginGetFileVersion) {
RtlRaiseStatus(STATUS_NOT_SUPPORTED);
return FALSE;
}
GetSystemTimeAsFileTime(&AssemblyTimes);
EnterCriticalSection(NtCurrentPeb()->FastPebLock);
if (!Initialized) {
InitializeCriticalSection(&MmpFakeHandleListLock);
InitializeListHead(&MmpFakeHandleListHead);
DetourTransactionBegin();
DetourUpdateThread(NtCurrentThread());
DetourAttach((PVOID*)&OriginCreateFileW, HookCreateFileW);
DetourAttach((PVOID*)&OriginGetFileInformationByHandle, HookGetFileInformationByHandle);
DetourAttach((PVOID*)&OriginGetFileAttributesExW, HookGetFileAttributesExW);
DetourAttach((PVOID*)&OriginCreateFileMappingW, HookCreateFileMappingW);
DetourAttach((PVOID*)&OriginMapViewOfFileEx, HookMapViewOfFileEx);
DetourAttach((PVOID*)&OriginUnmapViewOfFile, HookUnmapViewOfFile);
DetourAttach((PVOID*)&OriginCloseHandle, HookCloseHandle);
DetourAttach((PVOID*)&OriginGetFileVersion, HookGetFileVersion);
DetourTransactionCommit();
Initialized = TRUE;
}
LeaveCriticalSection(NtCurrentPeb()->FastPebLock);
return TRUE;
}
+2
View File
@@ -0,0 +1,2 @@
#pragma once
BOOL WINAPI MmpInitializeHooksForDotNet();
+20 -28
View File
@@ -9,9 +9,15 @@
// [MMP_START_TLS_INDEX, MMP_MAXIMUM_TLS_INDEX) Reserved for MemoryModule
//
#define MMP_START_TLS_INDEX 0x80 //128
#define MMP_START_TLS_INDEX 0x80 //128
#define MMP_MAXIMUM_TLS_INDEX 0x100 //256
#define MMP_MAXIMUM_TLS_INDEX 0x100 //256
#define MMP_TLSP_INDEX_BUFFER_SIZE (MMP_MAXIMUM_TLS_INDEX / 8) //32
#if (((MMP_START_TLS_INDEX | MMP_MAXIMUM_TLS_INDEX) & 7) || (MMP_START_TLS_INDEX >= MMP_MAXIMUM_TLS_INDEX))
#error "MMP_START_TLS_INDEX must be smaller than MMP_MAXIMUM_TLS_INDEX, and both are 8-bit aligned."
#endif
#define MmpAllocateTlsp() (RtlAllocateHeap(\
RtlProcessHeap(),\
@@ -137,26 +143,18 @@ PVOID NTAPI MmpQuerySystemInformation(
return buffer;
}
PSYSTEM_PROCESS_INFORMATION NTAPI MmpGetProcessInformation() {
DWORD NTAPI MmpGetThreadCount() {
DWORD result = 0;
auto pid = NtCurrentProcessId();
auto spi = PSYSTEM_PROCESS_INFORMATION(MmpQuerySystemInformation(SystemProcessInformation, nullptr));
PSYSTEM_PROCESS_INFORMATION result = nullptr;
if (spi) {
auto p = spi;
while (true) {
if (p->UniqueProcessId == pid) {
result = PSYSTEM_PROCESS_INFORMATION(RtlAllocateHeap(RtlProcessHeap(), 0, p->NextEntryOffset));
if (!result)break;
RtlCopyMemory(
result,
p,
p->NextEntryOffset
);
result = p->NumberOfThreads;
break;
}
@@ -170,18 +168,6 @@ PSYSTEM_PROCESS_INFORMATION NTAPI MmpGetProcessInformation() {
return result;
}
DWORD NTAPI MmpGetThreadCount() {
DWORD result = 0;
auto p = MmpGetProcessInformation();
if (p) {
result = p->NumberOfThreads;
RtlFreeHeap(RtlProcessHeap(), 0, p);
}
return result;
}
DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) {
THREAD_CONTEXT Context;
@@ -838,6 +824,12 @@ NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
BOOL NTAPI MmpInitialize() {
auto tls = CONTAINING_RECORD(NtCurrentTeb()->ThreadLocalStoragePointer, TLS_VECTOR, TLS_VECTOR::ModuleTlsData);
if (tls && tls->Length > MMP_START_TLS_INDEX) {
RtlRaiseStatus(STATUS_NOT_SUPPORTED);
return FALSE;
}
//
// Capture thread count
//
@@ -855,13 +847,13 @@ BOOL NTAPI MmpInitialize() {
InitializeListHead(&MmpTlsList);
RtlInitializeSRWLock(&MmpTlsListLock);
PULONG buffer = PULONG(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ULONG) * 8));
PULONG buffer = PULONG(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, MMP_TLSP_INDEX_BUFFER_SIZE));
if (!buffer) {
RtlRaiseStatus(STATUS_NO_MEMORY);
}
RtlFillMemory(buffer, sizeof(ULONG) * 4, -1);
RtlInitializeBitMap(&MmpTlsBitmap, buffer, 0x100);
RtlFillMemory(buffer, MMP_START_TLS_INDEX / 8, -1);
RtlInitializeBitMap(&MmpTlsBitmap, buffer, MMP_MAXIMUM_TLS_INDEX);
if (NtCurrentTeb()->ThreadLocalStoragePointer) {
if (!PreHookNtSetInformationProcess()) {
+16 -17
View File
@@ -1,17 +1,6 @@
#include "stdafx.h"
#include <random>
#define InsertTailList(ListHead,Entry) {\
PLIST_ENTRY _EX_Blink;\
PLIST_ENTRY _EX_ListHead;\
_EX_ListHead = (ListHead);\
_EX_Blink = _EX_ListHead->Blink;\
(Entry)->Flink = _EX_ListHead;\
(Entry)->Blink = _EX_Blink;\
_EX_Blink->Flink = (Entry);\
_EX_ListHead->Blink = (Entry);\
}
typedef BOOL(WINAPI* PDLL_STARTUP_ROUTINE)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
static PRTL_RB_TREE NTAPI RtlFindLdrpModuleBaseAddressIndex() {
@@ -491,10 +480,15 @@ BOOLEAN __forceinline WINAPI CheckSumBufferedFile(LPVOID BaseAddress, DWORD Buff
return HdrSum == CalcSum;
}
#endif
BOOLEAN NTAPI RtlIsValidImageBuffer(PVOID Buffer) {
BOOLEAN NTAPI RtlIsValidImageBuffer(
_In_ PVOID Buffer,
_Out_opt_ size_t* Size) {
BOOLEAN result = FALSE;
__try {
if (Size)*Size = 0;
union {
PIMAGE_NT_HEADERS32 nt32;
PIMAGE_NT_HEADERS64 nt64;
@@ -532,6 +526,7 @@ BOOLEAN NTAPI RtlIsValidImageBuffer(PVOID Buffer) {
}
IMAGE_FIRST_SECTION(headers.nt32);
ProbeForRead(Buffer, SizeofImage);
if (Size)*Size = SizeofImage;
result = CheckSumBufferedFile(Buffer, SizeofImage);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
@@ -602,7 +597,7 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW(
__try {
*BaseAddress = nullptr;
if (LdrEntry)*LdrEntry = nullptr;
if (!(dwFlags & LOAD_FLAGS_PASS_IMAGE_CHECK) && !RtlIsValidImageBuffer(BufferAddress))status = STATUS_INVALID_IMAGE_FORMAT;
if (!(dwFlags & LOAD_FLAGS_PASS_IMAGE_CHECK) && !RtlIsValidImageBuffer(BufferAddress, &BufferSize))status = STATUS_INVALID_IMAGE_FORMAT;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
@@ -645,8 +640,8 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW(
}
}
status = MemoryLoadLibrary(BaseAddress, BufferAddress);
if (!NT_SUCCESS(status))return status;
status = MemoryLoadLibrary(BaseAddress, BufferAddress, BufferSize);
if (!NT_SUCCESS(status) || status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)return status;
if (!(module = MapMemoryModuleHandle(*BaseAddress))) {
__fastfail(FAST_FAIL_FATAL_APP_EXIT);
@@ -714,6 +709,10 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW(
LdrUnloadDllMemory(*BaseAddress);
}
if (dwFlags & LOAD_FLAGS_HOOK_DOT_NET) {
MmpInitializeHooksForDotNet();
}
return status;
}
@@ -827,8 +826,8 @@ NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures) {
if (RtlFindLdrpHeap())features |= MEMORY_FEATURE_LDRP_HEAP;
if (RtlFindLdrpHashTable())features |= MEMORY_FEATURE_LDRP_HASH_TABLE;
if (RtlFindLdrpInvertedFunctionTable())features |= MEMORY_FEATURE_INVERTED_FUNCTION_TABLE;
if (NT_SUCCESS(RtlFindLdrpHandleTlsData(&pfn, &value)) && pfn)features |= MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA;
if (NT_SUCCESS(RtlFindLdrpReleaseTlsEntry(&pfn, &value) && pfn))features |= MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY;
features |= MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA | MEMORY_FEATURE_LDRP_RELEASE_TLS_ENTRY;
if (features)features |= MEMORY_FEATURE_SUPPORT_VERSION;
*pFeatures = features;
}
+3
View File
@@ -51,6 +51,9 @@ NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures);
//Dont call LdrpHandleTlsData routine if this flag is specified.
#define LOAD_FLAGS_NOT_HANDLE_TLS 0x00000008
//Hook for dotnet dlls
#define LOAD_FLAGS_HOOK_DOT_NET 0x00000010
NTSTATUS NTAPI LdrLoadDllMemoryExW(
OUT HMEMORYMODULE* BaseAddress, // Output module base address
-255
View File
@@ -6,265 +6,10 @@ NTSTATUS NTAPI MmpReleaseTlsEntry(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry);
// MmpTls.cpp
NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry);
static NTSTATUS NTAPI LdrpHandleTlsDataXp(PLDR_DATA_TABLE_ENTRY LdrEntry) {
return STATUS_NOT_SUPPORTED;
}
NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall) {
*_LdrpHandleTlsData = MmpHandleTlsData;
*stdcall = true;
return STATUS_SUCCESS;
static PVOID _LdrpHandleTlsData_ = (PVOID)~0;
NTSTATUS status = STATUS_SUCCESS;
__try {
if (_LdrpHandleTlsData_ != (PVOID)~0) {
*_LdrpHandleTlsData = _LdrpHandleTlsData_;
if (_LdrpHandleTlsData_ == nullptr)status = STATUS_NOT_SUPPORTED;
}
else {
*_LdrpHandleTlsData = _LdrpHandleTlsData_ = nullptr;
if (stdcall) {
*stdcall = false;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
if (!NT_SUCCESS(status))return status;
DWORD Versions[3]{};
LPCVOID Feature = nullptr;
BYTE Size = 0;
WORD OffsetOfFunctionBegin = 0;
RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2);
switch (Versions[0]) {
case 10: {
if (Versions[1])return STATUS_NOT_SUPPORTED;
//RS3
if (Versions[2] >= 16299) {
Size = 7;
//19H2
if (Versions[2] >= 18363)Feature = "\x74\x33\x44\x8D\x43\x09";
//RS5
else if (Versions[2] >= 17763) Feature = "\x8b\xc1\x8d\x4d\xbc\x51";
//RS4
else if (Versions[2] >= 17134) Feature = "\x33\xf6\x85\xc0\x79\x03";
//RS3
else Feature = "\x8b\xc1\x8d\x4d\xac\x51";
#ifdef _WIN64
//RS6(19H1)
if (Versions[2] >= 18362) OffsetOfFunctionBegin = 0x46;
//RS4
else if (Versions[2] >= 17134) OffsetOfFunctionBegin = 0x44;
//RS3
else OffsetOfFunctionBegin = 0x43;
#else
//19H2
if (Versions[2] == 18363) {
Feature = "\x74\x25\x8b\xc1\x8d\x4d\xbc";
OffsetOfFunctionBegin = 0x16;
}
//RS6(19H1)
else if (Versions[2] == 18362) OffsetOfFunctionBegin = 0x2E;
//RS5
else if (Versions[2] >= 17763) OffsetOfFunctionBegin = 0x2C;
//RS3,4
else OffsetOfFunctionBegin = 0x18;
#endif
break;
}
//RS2
else if (Versions[2] >= 15063) {
Size = 7;
#ifdef _WIN64
OffsetOfFunctionBegin = 0x43;
Feature = "\x74\x33\x44\x8d\x43\x09";
#else
OffsetOfFunctionBegin = 0x18;
Feature = "\x8b\xc1\x8d\x4d\xbc\x51";
#endif
break;
}
// NO BREAK
}
case 6: {
switch (Versions[1]) {
//8.1
case 3: {
#ifdef _WIN64
Size = 10;
OffsetOfFunctionBegin = 0x43;
Feature = "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38";
#else
Size = 8;
OffsetOfFunctionBegin = 0x1B;
Feature = "\x50\x6a\x09\x6a\x01\x8b\xc1";
#endif
break;
}
//8
case 2: {
#ifdef _WIN64
Size = 9;
OffsetOfFunctionBegin = 0x49;
Feature = "\x48\x8b\x79\x30\x45\x8d\x66\x01";
#else
Size = 7;
OffsetOfFunctionBegin = 0xC;
Feature = "\x8b\x45\x08\x89\x45\xa0";
#endif
break;
}
//7
case 1: {
#ifdef _WIN64
Size = 12;
OffsetOfFunctionBegin = 0x27;
Feature = "\x41\xb8\x09\x00\x00\x00\x48\x8d\x44\x24\x38";
#else
Size = 9;
OffsetOfFunctionBegin = 0x14;
Feature = "\x74\x20\x8d\x45\xd4\x50\x6a\x09";
#endif
break;
}
default:return STATUS_NOT_SUPPORTED;
}
break;
}
default: {
*_LdrpHandleTlsData = LdrpHandleTlsDataXp;
*stdcall = true;
return status;
}
}
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = const_cast<PVOID>(Feature),SearchContext.BufferLength = Size - 1 };
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(HMODULE(RtlFindNtdllLdrEntry()->DllBase), ".text", &SearchContext)))
SearchContext.OutBufferPtr -= OffsetOfFunctionBegin;
if (!(*_LdrpHandleTlsData = _LdrpHandleTlsData_ = SearchContext.MemoryBlockInSection))return STATUS_NOT_SUPPORTED;
if (stdcall) *stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
return status;
}
NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry(PVOID* _LdrpReleaseTlsEntry, bool* stdcall) {
*_LdrpReleaseTlsEntry = MmpReleaseTlsEntry;
*stdcall = true;
return STATUS_SUCCESS;
static PVOID _LdrpReleaseTlsEntry_ = (PVOID)~0;
NTSTATUS status = STATUS_SUCCESS;
__try {
if (_LdrpReleaseTlsEntry_ != (PVOID)~0) {
*_LdrpReleaseTlsEntry = _LdrpReleaseTlsEntry_;
if (!_LdrpReleaseTlsEntry_)status = STATUS_NOT_SUPPORTED;
}
else {
*_LdrpReleaseTlsEntry = _LdrpReleaseTlsEntry_ = nullptr;
if (stdcall) {
*stdcall = false;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
if (!NT_SUCCESS(status))return status;
DWORD Versions[3]{};
LPCVOID Feature = nullptr;
BYTE Size = 0;
WORD OffsetOfFunctionBegin = 0;
RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2);
switch (Versions[0]) {
case 10: {
if (Versions[1]) {
status = STATUS_NOT_SUPPORTED;
break;
}
if (Versions[2] >= 18362) {
Size = 0x10;
OffsetOfFunctionBegin = 0x2F;
Feature = "\x74\x26\x48\x8B\x00\x48\x39\x58\x08\x75\x5D\x48\x8B\x4B\x08";
break;
}
}
default:
status = STATUS_NOT_SUPPORTED;
}
if (!NT_SUCCESS(status)) {
return status;
}
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = const_cast<PVOID>(Feature),SearchContext.BufferLength = Size - 1 };
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(HMODULE(RtlFindNtdllLdrEntry()->DllBase), ".text", &SearchContext)))
SearchContext.OutBufferPtr -= OffsetOfFunctionBegin;
if (!(*_LdrpReleaseTlsEntry = _LdrpReleaseTlsEntry_ = SearchContext.MemoryBlockInSection))return STATUS_NOT_SUPPORTED;
if (stdcall)*stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
return status;
}
static NTSTATUS NTAPI RtlInvokeTlsHandler(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN BOOLEAN Release) {
return STATUS_NOT_SUPPORTED;
struct _FUNCTION_SET {
bool stdcall;
union {
struct {
NTSTATUS(__stdcall* LdrpHandleTlsData)(PLDR_DATA_TABLE_ENTRY LdrEntry);
NTSTATUS(__stdcall* LdrpReleaseTlsEntry)(PLDR_DATA_TABLE_ENTRY LdrEntry, DWORD);
}Default;
struct {
NTSTATUS(__thiscall* LdrpHandleTlsData)(PLDR_DATA_TABLE_ENTRY LdrEntry);
NTSTATUS(__thiscall* LdrpReleaseTlsEntry)(PLDR_DATA_TABLE_ENTRY LdrEntry, DWORD);
}WinBlue;
};
_FUNCTION_SET() {
if (!NT_SUCCESS(RtlFindLdrpHandleTlsData((PVOID*)(&this->Default.LdrpHandleTlsData), &this->stdcall)) ||
!NT_SUCCESS(RtlFindLdrpReleaseTlsEntry((PVOID*)(&this->Default.LdrpReleaseTlsEntry), nullptr))) {
this->Default = {};
OutputDebugString(L"Can`t find both LdrpHandleTlsData and LdrpReleaseTlsEntry.\n");
}
}
NTSTATUS operator()(PLDR_DATA_TABLE_ENTRY LdrEntry) {
if (!Default.LdrpHandleTlsData) {
return STATUS_NOT_SUPPORTED;
}
return stdcall ? Default.LdrpHandleTlsData(LdrEntry) : WinBlue.LdrpHandleTlsData(LdrEntry);
}
NTSTATUS operator()(PLDR_DATA_TABLE_ENTRY LdrEntry, DWORD dwFlags) {
if (!Default.LdrpReleaseTlsEntry) {
return STATUS_NOT_SUPPORTED;
}
return stdcall ? Default.LdrpReleaseTlsEntry(LdrEntry,dwFlags) : WinBlue.LdrpReleaseTlsEntry(LdrEntry, dwFlags);
}
}static InvokeHandler;
return Release ? InvokeHandler(LdrEntry, 0) : InvokeHandler(LdrEntry);
}
NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
return MmpHandleTlsData(LdrEntry);
//return RtlInvokeTlsHandler(LdrEntry, FALSE);
}
NTSTATUS NTAPI LdrpReleaseTlsEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
return MmpReleaseTlsEntry(LdrEntry);
//return RtlInvokeTlsHandler(LdrEntry, TRUE);
}
-4
View File
@@ -1,9 +1,5 @@
#pragma once
NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall);
NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry(PVOID* _LdrpReleaseTlsEntry, bool* stdcall);
NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
NTSTATUS NTAPI LdrpReleaseTlsEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
+3
View File
@@ -30,6 +30,9 @@
//tls support
#include "rtltls.h"
//DotNet support
#include "MmpDotNet.h"
//MemoryModulePP api interface
#include "NativeFunctionsInternal.h"