diff --git a/MemoryModule/MemoryModule.cpp b/MemoryModule/MemoryModule.cpp index ca95ab3..f975b08 100644 --- a/MemoryModule/MemoryModule.cpp +++ b/MemoryModule/MemoryModule.cpp @@ -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 { // diff --git a/MemoryModule/MemoryModule.h b/MemoryModule/MemoryModule.h index 22716ff..c1d9b4b 100644 --- a/MemoryModule/MemoryModule.h +++ b/MemoryModule/MemoryModule.h @@ -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); diff --git a/MemoryModule/MemoryModule.vcxproj b/MemoryModule/MemoryModule.vcxproj index 043c7a3..08eed4f 100644 --- a/MemoryModule/MemoryModule.vcxproj +++ b/MemoryModule/MemoryModule.vcxproj @@ -31,6 +31,7 @@ + @@ -45,6 +46,7 @@ + diff --git a/MemoryModule/MemoryModule.vcxproj.filters b/MemoryModule/MemoryModule.vcxproj.filters index 6e4fbe6..e8bf299 100644 --- a/MemoryModule/MemoryModule.vcxproj.filters +++ b/MemoryModule/MemoryModule.vcxproj.filters @@ -87,6 +87,9 @@ Source Files\3rdparty\Detours + + Source Files + @@ -125,6 +128,9 @@ Header Files\3rdparty\Detours + + Header Files + diff --git a/MemoryModule/MmpDotNet.cpp b/MemoryModule/MmpDotNet.cpp new file mode 100644 index 0000000..aef1f91 --- /dev/null +++ b/MemoryModule/MmpDotNet.cpp @@ -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; +} diff --git a/MemoryModule/MmpDotNet.h b/MemoryModule/MmpDotNet.h new file mode 100644 index 0000000..d3f463f --- /dev/null +++ b/MemoryModule/MmpDotNet.h @@ -0,0 +1,2 @@ +#pragma once +BOOL WINAPI MmpInitializeHooksForDotNet(); \ No newline at end of file diff --git a/MemoryModule/MmpTls.cpp b/MemoryModule/MmpTls.cpp index 5bbb7ab..ea69900 100644 --- a/MemoryModule/MmpTls.cpp +++ b/MemoryModule/MmpTls.cpp @@ -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()) { diff --git a/MemoryModule/NativeFunctionsInternal.cpp b/MemoryModule/NativeFunctionsInternal.cpp index ba44c0f..bcecb66 100644 --- a/MemoryModule/NativeFunctionsInternal.cpp +++ b/MemoryModule/NativeFunctionsInternal.cpp @@ -1,17 +1,6 @@ #include "stdafx.h" #include -#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; } diff --git a/MemoryModule/NativeFunctionsInternal.h b/MemoryModule/NativeFunctionsInternal.h index a01620a..b171318 100644 --- a/MemoryModule/NativeFunctionsInternal.h +++ b/MemoryModule/NativeFunctionsInternal.h @@ -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 diff --git a/MemoryModule/rtltls.cpp b/MemoryModule/rtltls.cpp index cd23461..6f76371 100644 --- a/MemoryModule/rtltls.cpp +++ b/MemoryModule/rtltls.cpp @@ -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(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(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); } diff --git a/MemoryModule/rtltls.h b/MemoryModule/rtltls.h index 83930d2..859d586 100644 --- a/MemoryModule/rtltls.h +++ b/MemoryModule/rtltls.h @@ -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); diff --git a/MemoryModule/stdafx.h b/MemoryModule/stdafx.h index 08f8722..47f99b8 100644 --- a/MemoryModule/stdafx.h +++ b/MemoryModule/stdafx.h @@ -30,6 +30,9 @@ //tls support #include "rtltls.h" +//DotNet support +#include "MmpDotNet.h" + //MemoryModulePP api interface #include "NativeFunctionsInternal.h" diff --git a/test/test.cpp b/test/test.cpp index 879dd29..2c06461 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1,4 +1,4 @@ -#include "../MemoryModule/LoadDllMemoryApi.h" +#include "../MemoryModule/stdafx.h" #include #pragma warning(disable:4996) @@ -21,22 +21,28 @@ static PVOID ReadDllFile(LPCSTR FileName) { int main() { HMEMORYMODULE hModule; NTSTATUS status; - PVOID buffer = ReadDllFile("System.Data.dll"); + PVOID buffer = ReadDllFile("lib.dll"); if (!buffer) { return 0; } status = LdrLoadDllMemoryExW( - &hModule, // ModuleHandle - nullptr, // LdrEntry - 0, // Flags - buffer, // Buffer - 0, // Reserved - nullptr, // DllBaseName - nullptr // DllFullName + &hModule, // ModuleHandle + nullptr, // LdrEntry + LOAD_FLAGS_HOOK_DOT_NET, // Flags + buffer, // Buffer + 0, // Reserved + nullptr, // DllBaseName + nullptr // DllFullName ); - if (NT_SUCCESS(status)) { + if (NT_SUCCESS(status) && status != STATUS_IMAGE_MACHINE_TYPE_MISMATCH) { + int result = 0; + typedef int(WINAPI* func)(int, int); + + func f = (func)GetProcAddress(hModule, "Add"); + if (f)result = f(128, 256); + LdrUnloadDllMemory(hModule); }