diff --git a/MemoryModule/Native.cpp b/MemoryModule/Native.cpp index 50fb85e..6cfaba7 100644 --- a/MemoryModule/Native.cpp +++ b/MemoryModule/Native.cpp @@ -306,15 +306,15 @@ NTSTATUS NTAPI NtQueryVirtualMemory( (ProcessHandle, BaseAddress, MemoryInformationClass, Buffer, Length, ResultLength); } -PVOID RtlImageDirectoryEntryToData(PVOID BaseAddress, BOOLEAN MappedAsImage, USHORT Directory, PULONG Size) { - return ((decltype(&RtlImageDirectoryEntryToData))RtlGetNtProcAddress("RtlImageDirectoryEntryToData"))(BaseAddress, MappedAsImage, Directory, Size); +PVOID NTAPI RtlImageDirectoryEntryToData(PVOID BaseAddress, BOOLEAN MappedAsImage, USHORT Directory, PULONG Size) { + return ((decltype(&RtlImageDirectoryEntryToData))(RtlGetNtProcAddress("RtlImageDirectoryEntryToData")))(BaseAddress, MappedAsImage, Directory, Size); } -VOID RtlInitAnsiString(PANSI_STRING DestinationString, LPCSTR SourceString) { +VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, LPCSTR SourceString) { return ((decltype(&RtlInitAnsiString))RtlGetNtProcAddress("RtlInitAnsiString"))(DestinationString, SourceString); } -NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString) { +NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString) { return ((decltype(&RtlAnsiStringToUnicodeString))RtlGetNtProcAddress("RtlAnsiStringToUnicodeString"))(DestinationString, SourceString, AllocateDestinationString); } @@ -339,9 +339,9 @@ NTSTATUS NTAPI RtlHashUnicodeString(IN PCUNICODE_STRING String, IN BOOLEAN CaseI return (decltype(&RtlHashUnicodeString)(RtlGetNtProcAddress("RtlHashUnicodeString")))(String, CaseInSensitive, HashAlgorithm, HashValue); } -VOID RtlGetNtVersionNumbers(OUT DWORD* MajorVersion, OUT DWORD* MinorVersion, OUT DWORD* BuildNumber) { +VOID NTAPI RtlGetNtVersionNumbers(OUT DWORD* MajorVersion, OUT DWORD* MinorVersion, OUT DWORD* BuildNumber) { static DWORD Versions[3]{ 0 }; - static auto _RtlGetNtVersionNumbers = (decltype(&RtlGetNtVersionNumbers))RtlGetNtProcAddress("RtlGetNtVersionNumbers"); + static auto _RtlGetNtVersionNumbers = (decltype(&RtlGetNtVersionNumbers))(RtlGetNtProcAddress("RtlGetNtVersionNumbers")); if (Versions[0] || !_RtlGetNtVersionNumbers) goto ret; _RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2); @@ -358,3 +358,9 @@ NTSTATUS NTAPI NtQuerySystemTime(PLARGE_INTEGER SystemTime) { return (decltype(&NtQuerySystemTime)(RtlGetNtProcAddress("NtQuerySystemTime")))(SystemTime); } +PVOID NTAPI RtlEncodeSystemPointer(PVOID Pointer) { + return decltype(&RtlEncodeSystemPointer)(RtlGetNtProcAddress("RtlEncodeSystemPointer"))(Pointer); +} +PVOID NTAPI RtlDecodeSystemPointer(PVOID Pointer) { + return decltype(&RtlDecodeSystemPointer)(RtlGetNtProcAddress("RtlDecodeSystemPointer"))(Pointer); +} diff --git a/MemoryModule/Native.h b/MemoryModule/Native.h index 0e8e1c8..beb0121 100644 --- a/MemoryModule/Native.h +++ b/MemoryModule/Native.h @@ -1251,7 +1251,7 @@ NTSTATUS NTAPI NtQueryVirtualMemory( OUT PSIZE_T ResultLength OPTIONAL); -PVOID RtlImageDirectoryEntryToData( +PVOID NTAPI RtlImageDirectoryEntryToData( PVOID BaseAddress, BOOLEAN MappedAsImage, USHORT Directory, @@ -1338,3 +1338,5 @@ typedef struct _UNWIND_INFO { #define GetExceptionDataPtr(info) ((PVOID)((PULONG)GetLanguageSpecificData(info) + 1) NTSTATUS NTAPI NtQuerySystemTime(PLARGE_INTEGER SystemTime); +PVOID NTAPI RtlEncodeSystemPointer(PVOID Pointer); +PVOID NTAPI RtlDecodeSystemPointer(PVOID Pointer); diff --git a/MemoryModule/NativeFunctionsInternal.cpp b/MemoryModule/NativeFunctionsInternal.cpp index d9af99d..0bc66dc 100644 --- a/MemoryModule/NativeFunctionsInternal.cpp +++ b/MemoryModule/NativeFunctionsInternal.cpp @@ -3,6 +3,15 @@ #pragma warning(disable:6328) #pragma warning(disable:4267) #pragma warning(disable:26812) +#ifndef _WIN64 +SIZE_T NTAPI _RtlCompareMemory( + const VOID* Source1, + const VOID* Source2, + SIZE_T Length) { + return decltype(&_RtlCompareMemory)(RtlGetNtProcAddress("RtlCompareMemory"))(Source1, Source2, Length); +} +#define RtlCompareMemory _RtlCompareMemory +#endif #define RTL_VERIFY_FLAGS_MAJOR_VERSION 0 #define RTL_VERIFY_FLAGS_MINOR_VERSION 1 @@ -660,7 +669,7 @@ NTSTATUS NTAPI NtLoadDllMemoryExW( return STATUS_SUCCESS; } -NTSTATUS NtLoadDllMemoryExA( +NTSTATUS NTAPI NtLoadDllMemoryExA( OUT HMEMORYMODULE* BaseAddress, OUT PVOID* LdrEntry OPTIONAL, IN DWORD dwFlags, @@ -751,9 +760,10 @@ VOID NTAPI RtlRbRemoveNode(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Node) { } static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABLE InvertedTable, IN PVOID ImageBase, IN ULONG SizeOfImage) { +#ifdef _WIN64 ULONG CurrentSize; - PRUNTIME_FUNCTION FunctionTable; - ULONG Index = 1; + PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable; + ULONG Index; ULONG SizeOfTable = 0; PIMAGE_NT_HEADERS headers = RtlImageNtHeader(ImageBase); PIMAGE_DATA_DIRECTORY dir = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; @@ -762,13 +772,9 @@ static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL Index = (ULONG)need; CurrentSize = InvertedTable->Count; if (CurrentSize != InvertedTable->MaxCount) { - if (need)_InterlockedIncrement(&InvertedTable->Epoch); + //if (need)_InterlockedIncrement(&InvertedTable->Epoch); if (CurrentSize != 0) { - for (Index = 1; Index < CurrentSize; ++Index) { - if (ImageBase < InvertedTable->Entries[Index].ImageBase) { - break; - } - } + while (Index < CurrentSize)if (ImageBase < InvertedTable->Entries[Index].ImageBase)break; if (Index != CurrentSize) { RtlMoveMemory(&InvertedTable->Entries[Index + 1], @@ -788,18 +794,44 @@ static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL InvertedTable->Entries[Index].ImageSize = SizeOfImage; InvertedTable->Entries[Index].ExceptionDirectorySize = SizeOfTable; InvertedTable->Count++; - if (need)_InterlockedIncrement(&InvertedTable->Epoch); + //if (need)_InterlockedIncrement(&InvertedTable->Epoch); } else { need ? (InvertedTable->Overflow = TRUE) : (InvertedTable->Epoch = TRUE); } +#else + DWORD ptr, count; + ULONG Index = RtlIsWindowsVersionOrGreater(10, 0, 0) ? 1 : 0; + + if (InvertedTable->Count == InvertedTable->MaxCount) { + InvertedTable->Overflow = TRUE; + return; + } + while (Index < InvertedTable->Count) { + if (ImageBase < InvertedTable->Entries[Index].ImageBase)break; + Index++; + } + if (Index != InvertedTable->Count) { + RtlMoveMemory(&InvertedTable->Entries[Index].NextEntrySEHandlerTableEncoded, + Index ? &InvertedTable->Entries[Index - 1].NextEntrySEHandlerTableEncoded : (PVOID)&InvertedTable->NextEntrySEHandlerTableEncoded, + (InvertedTable->Count - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY)); + } + + RtlCaptureImageExceptionValues(ImageBase, &ptr, &count); + if (Index) InvertedTable->Entries[Index - 1].NextEntrySEHandlerTableEncoded = RtlEncodeSystemPointer((PVOID)ptr); + else InvertedTable->NextEntrySEHandlerTableEncoded = (DWORD)RtlEncodeSystemPointer((PVOID)ptr); + InvertedTable->Entries[Index].ImageBase = ImageBase; + InvertedTable->Entries[Index].ImageSize = SizeOfImage; + InvertedTable->Entries[Index].SEHandlerCount = count; + ++InvertedTable->Count; +#endif return; } static VOID NTAPI RtlpRemoveInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABLE InvertedTable, IN PVOID ImageBase) { ULONG CurrentSize; ULONG Index; - bool need = RtlIsWindowsVersionOrGreater(6, 2, 0); + //bool need = RtlIsWindowsVersionOrGreater(6, 2, 0); CurrentSize = InvertedTable->Count; for (Index = 0; Index < CurrentSize; Index += 1) { @@ -809,40 +841,61 @@ static VOID NTAPI RtlpRemoveInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL } if (Index != CurrentSize) { - if (need)_InterlockedIncrement(&InvertedTable->Epoch); + //if (need)_InterlockedIncrement(&InvertedTable->Epoch); if (CurrentSize != 1) { +#ifdef _WIN64 RtlMoveMemory(&InvertedTable->Entries[Index], &InvertedTable->Entries[Index + 1], (CurrentSize - Index - 1) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY)); +#else + RtlMoveMemory( + Index ? &InvertedTable->Entries[Index - 1].NextEntrySEHandlerTableEncoded : (PVOID)&InvertedTable->NextEntrySEHandlerTableEncoded, + &InvertedTable->Entries[Index].NextEntrySEHandlerTableEncoded, + (CurrentSize - Index) * sizeof(PRTL_INVERTED_FUNCTION_TABLE_ENTRY)); +#endif } - InvertedTable->Count -= 1; - if (need)_InterlockedIncrement(&InvertedTable->Epoch); + InvertedTable->Count--; + //if (need)_InterlockedIncrement(&InvertedTable->Epoch); } return; } -static PVOID NTAPI RtlFindLdrpInvertedFunctionTable() { +PVOID NTAPI RtlFindLdrpInvertedFunctionTable() { static PVOID LdrpInvertedFunctionTable = nullptr; if (LdrpInvertedFunctionTable)return LdrpInvertedFunctionTable; - // _RTL_INVERTED_FUNCTION_TABLE x64 x86 - // Count +0x0 +0x0 ???????? - // MaxCount +0x4 +0x4 0x00000200 - // Epoch +0x8 +0x8 ???????? - // OverFlow +0xc +0xc 0x00000000 - // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 +0x10 ntdll.dll(win10) or The smallest base module - // ExceptionDirectory +0x10 +0x10 ++++++++ - // ImageBase +0x18 +0x14 ++++++++ - // ImageSize +0x20 +0x18 ++++++++ - // ExceptionDirectorySize +0x24 +0x1c ++++++++ - // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ... ... + //x68 + // _RTL_INVERTED_FUNCTION_TABLE x86 + // Count +0x0 ???????? + // MaxCount +0x4 0x00000200 + // Overflow +0x8 0x00000000 + // NextEntrySEHandlerTableEncoded +0xc ++++++++ + // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module + // ImageBase +0x10 ++++++++ + // ImageSize +0x14 ++++++++ + // SEHandlerCount +0x18 ++++++++ + // NextEntrySEHandlerTableEncoded +0x1c ++++++++ + // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ... + // ...... + + // x64 + // _RTL_INVERTED_FUNCTION_TABLE x64 + // Count +0x0 ???????? + // MaxCount +0x4 0x00000200 + // Epoch +0x8 ???????? + // OverFlow +0xc 0x00000000 + // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module + // ExceptionDirectory +0x10 ++++++++ + // ImageBase +0x18 ++++++++ + // ImageSize +0x20 ++++++++ + // ExceptionDirectorySize +0x24 ++++++++ + // _RTL_INVERTED_FUNCTION_TABLE_ENTRY[1] ... ... // ...... HMODULE hModule = nullptr, hNtdll = GetModuleHandleW(L"ntdll.dll"); PIMAGE_NT_HEADERS NtdllHeaders = RtlImageNtHeader(hNtdll), ModuleHeaders = nullptr; _RTL_INVERTED_FUNCTION_TABLE_ENTRY entry{}; - PIMAGE_DATA_DIRECTORY dir = nullptr; LPCSTR lpSectionName = ".data"; PIMAGE_SECTION_HEADER section = nullptr; struct _SEARCH_DATA { @@ -880,11 +933,19 @@ static PVOID NTAPI RtlFindLdrpInvertedFunctionTable() { } if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return LdrpInvertedFunctionTable; +#ifdef _WIN64 + PIMAGE_DATA_DIRECTORY dir = nullptr; dir = &ModuleHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; entry = { dir->Size ? decltype(entry.ExceptionDirectory)((size_t)hModule + dir->VirtualAddress) : nullptr , (PVOID)hModule, ModuleHeaders->OptionalHeader.SizeOfImage,dir->Size }; +#else + PVOID tmp = &ModuleHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]; + DWORD SEHTable, SEHCount; + RtlCaptureImageExceptionValues(hModule, &SEHTable, &SEHCount); + entry = { RtlEncodeSystemPointer((PVOID)SEHTable),(DWORD)hModule,ModuleHeaders->OptionalHeader.SizeOfImage,(PVOID)SEHCount }; +#endif section = IMAGE_FIRST_SECTION(NtdllHeaders); for (WORD i = 0; i < NtdllHeaders->FileHeader.NumberOfSections; ++i) { if (!_stricmp(lpSectionName, (LPCSTR)section->Name)) { @@ -897,6 +958,7 @@ static PVOID NTAPI RtlFindLdrpInvertedFunctionTable() { while (data.Size && (data.Size - EntrySize)) { if (RtlCompareMemory(data.BaseAddress, &entry, EntrySize) == EntrySize) { +#ifdef _WIN64 PRTL_INVERTED_FUNCTION_TABLE tab = decltype(tab)((size_t)data.BaseAddress - 0x10); if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->Overflow) { return LdrpInvertedFunctionTable = tab; @@ -905,6 +967,21 @@ static PVOID NTAPI RtlFindLdrpInvertedFunctionTable() { if (tab->MaxCount == 0x200 && !tab->Epoch) return LdrpInvertedFunctionTable = tab; } +#else + PRTL_INVERTED_FUNCTION_TABLE tab = decltype(tab)((size_t)data.BaseAddress - 0xC); + + //Does Windows 8 need fix? + if (RtlIsWindowsVersionOrGreater(10, 0, 0)) tab = decltype(tab)((DWORD)tab - 0x4); + + //Note: Same memory layout for RTL_INVERTED_FUNCTION_TABLE_ENTRY in Windows 10 x86 and x64. + if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->NextEntrySEHandlerTableEncoded) { + return LdrpInvertedFunctionTable = tab; + } + else { + if (tab->MaxCount == 0x200 && !tab->Overflow) + return LdrpInvertedFunctionTable = tab; + } +#endif } ++data; --data.Size; @@ -949,8 +1026,12 @@ NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t Im if (!NT_SUCCESS(status))return status; } +#ifdef _WIN64 if (RtlIsWindowsVersionOrGreater(6, 2, 0)) return table->Overflow ? STATUS_INVALID_ADDRESS : STATUS_SUCCESS; else return table->Epoch ? STATUS_INVALID_ADDRESS : STATUS_SUCCESS; +#else + return table->Overflow ? STATUS_INVALID_ADDRESS : STATUS_SUCCESS; +#endif } NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase) { static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable()); @@ -973,24 +1054,17 @@ NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase) { static NTSTATUS NTAPI LdrpHandleTlsDataXp(PLDR_DATA_TABLE_ENTRY LdrEntry) { return STATUS_NOT_SUPPORTED; } -NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { - typedef NTSTATUS(__thiscall* _PTR_WIN8_1)(PLDR_DATA_TABLE_ENTRY LdrEntry); - typedef NTSTATUS(__stdcall* _PTR_WIN)(PLDR_DATA_TABLE_ENTRY LdrEntry); - union _FUNCTION_SET { - _PTR_WIN8_1 Win8_1_OrGreater; - _PTR_WIN Default; - _FUNCTION_SET() { - this->Default = nullptr; - } - operator bool() { - return this->Default != nullptr; - } - }; - static _FUNCTION_SET _LdrpHandleTlsData{}; - static bool stdcall = false; - if (_LdrpHandleTlsData) - return stdcall ? _LdrpHandleTlsData.Default(LdrEntry) : _LdrpHandleTlsData.Win8_1_OrGreater(LdrEntry); - +static NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall) { + NTSTATUS status = STATUS_SUCCESS; + __try { + *_LdrpHandleTlsData = nullptr; + *stdcall = false; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + } + if (!NT_SUCCESS(status))return status; + DWORD Versions[3]{}; LPCVOID Feature = nullptr; BYTE Size = 0; @@ -1013,9 +1087,9 @@ NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { else Feature = "\x8b\xc1\x8d\x4d\xac\x51"; #ifdef _WIN64 //RS6(19H1) - if (Versions[2] >= 18362) OffsetOfFunctionBegin = 0x46; + if (Versions[2] >= 18362) OffsetOfFunctionBegin = 0x46; //RS4 - else if (Versions[2] >= 17134) OffsetOfFunctionBegin = 0x44; + else if (Versions[2] >= 17134) OffsetOfFunctionBegin = 0x44; //RS3 else OffsetOfFunctionBegin = 0x43; #else @@ -1045,7 +1119,7 @@ NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { } case 6: { switch (Versions[1]) { - //8.1 + //8.1 case 3: { #ifdef _WIN64 Size = 10; @@ -1058,7 +1132,7 @@ NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { #endif break; } - //8 + //8 case 2: { #ifdef _WIN64 Size = 9; @@ -1071,7 +1145,7 @@ NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { #endif break; } - //7 + //7 case 1: { #ifdef _WIN64 Size = 12; @@ -1088,25 +1162,86 @@ NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { } break; } - + default: { - _LdrpHandleTlsData.Default = LdrpHandleTlsDataXp; - stdcall = true; - return LdrpHandleTlsDataXp(LdrEntry); + *_LdrpHandleTlsData = LdrpHandleTlsDataXp; + *stdcall = true; + return status; } } HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); PIMAGE_NT_HEADERS headers = RtlImageNtHeader(ntdll); if (!Feature || !headers)return STATUS_NOT_SUPPORTED; + ntdll = (HMODULE)(headers->OptionalHeader.ImageBase + headers->OptionalHeader.BaseOfCode); Size--; - for (size_t i = 0; i < headers->OptionalHeader.SizeOfCode - Size; ++i) { - if (RtlCompareMemory((PBYTE)ntdll + i, Feature, Size) == Size) { - _LdrpHandleTlsData.Default = (_PTR_WIN)((PBYTE)ntdll + i - OffsetOfFunctionBegin); - break; + __try { + for (size_t i = 0; i < headers->OptionalHeader.SizeOfCode - Size; ++i) { + if (RtlCompareMemory((PBYTE)ntdll + i, Feature, Size) == Size) { + *_LdrpHandleTlsData = ((PBYTE)ntdll + i - OffsetOfFunctionBegin); + break; + } } } - if (!_LdrpHandleTlsData)return STATUS_NOT_SUPPORTED; - stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0); + __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + } + if (!NT_SUCCESS(status))return status; + if (!*_LdrpHandleTlsData)return STATUS_NOT_SUPPORTED; + *stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0); + return status; +} +NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { + typedef NTSTATUS(__thiscall* _PTR_WIN8_1)(PLDR_DATA_TABLE_ENTRY LdrEntry); + typedef NTSTATUS(__stdcall* _PTR_WIN)(PLDR_DATA_TABLE_ENTRY LdrEntry); + union _FUNCTION_SET { + _PTR_WIN8_1 Win8_1_OrGreater; + _PTR_WIN Default; + _FUNCTION_SET() { + this->Default = nullptr; + } + operator bool() { + return this->Default != nullptr; + } + }; + static _FUNCTION_SET _LdrpHandleTlsData{}; + static bool stdcall = false; + NTSTATUS status; + if (!_LdrpHandleTlsData) { + status = RtlFindLdrpHandleTlsData((PVOID*)&_LdrpHandleTlsData.Default, &stdcall); + if (!NT_SUCCESS(status))return status; + } return stdcall ? _LdrpHandleTlsData.Default(LdrEntry) : _LdrpHandleTlsData.Win8_1_OrGreater(LdrEntry); } + +int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount) { + PIMAGE_LOAD_CONFIG_DIRECTORY pLoadConfigDirectory; + PIMAGE_COR20_HEADER pCor20; + ULONG Size; + + //check if no seh + if (RtlImageNtHeader(BaseAddress)->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH) { + *SEHandlerTable = *SEHandlerCount = -1; + return 0; + } + + //get seh table and count + pLoadConfigDirectory = (decltype(pLoadConfigDirectory))RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &Size); + if (pLoadConfigDirectory) { + if (Size == 0x40 && pLoadConfigDirectory->Size >= 0x48u) { + if (pLoadConfigDirectory->SEHandlerTable && pLoadConfigDirectory->SEHandlerCount) { + *SEHandlerTable = pLoadConfigDirectory->SEHandlerTable; + return *SEHandlerCount = pLoadConfigDirectory->SEHandlerCount; + } + } + } + + //is .net core ? + pCor20 = (decltype(pCor20))RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &Size); + *SEHandlerTable = *SEHandlerCount = ((pCor20 && pCor20->Flags & 1) ? -1 : 0); + return 0; +} + +#ifndef _WIN64 +#undef RtlCompareMemory +#endif diff --git a/MemoryModule/NativeFunctionsInternal.h b/MemoryModule/NativeFunctionsInternal.h index ef1ce73..0fff502 100644 --- a/MemoryModule/NativeFunctionsInternal.h +++ b/MemoryModule/NativeFunctionsInternal.h @@ -59,7 +59,7 @@ typedef struct _RTL_BALANCED_NODE { UCHAR Red : 1; //0x10 UCHAR Balance : 2; //0x10 }; - ULONGLONG ParentValue; //0x10 + size_t ParentValue; //0x10 }; }RTL_BALANCED_NODE, * PRTL_BALANCED_NODE; @@ -437,20 +437,43 @@ VOID NTAPI RtlRbInsertNodeEx(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Parent, // RtlRbRemoveNode VOID NTAPI RtlRbRemoveNode(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Node); -typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY { +typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 { PIMAGE_RUNTIME_FUNCTION_ENTRY ExceptionDirectory; PVOID ImageBase; ULONG ImageSize; ULONG ExceptionDirectorySize; -} RTL_INVERTED_FUNCTION_TABLE_ENTRY, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY; -typedef struct _RTL_INVERTED_FUNCTION_TABLE { +} RTL_INVERTED_FUNCTION_TABLE_ENTRY_64, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY_64; +typedef struct _RTL_INVERTED_FUNCTION_TABLE_64 { ULONG Count; ULONG MaxCount; ULONG Epoch; ULONG Overflow; - RTL_INVERTED_FUNCTION_TABLE_ENTRY Entries[0x200]; -} RTL_INVERTED_FUNCTION_TABLE, * PRTL_INVERTED_FUNCTION_TABLE; + RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 Entries[0x200]; +} RTL_INVERTED_FUNCTION_TABLE_64, * PRTL_INVERTED_FUNCTION_TABLE_64; + +typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 { + PVOID ImageBase; + ULONG ImageSize; + ULONG SEHandlerCount; + PVOID NextEntrySEHandlerTableEncoded; +} RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32; +typedef struct _RTL_INVERTED_FUNCTION_TABLE_WIN7_32 { + ULONG Count; + ULONG MaxCount; + ULONG Overflow; + ULONG NextEntrySEHandlerTableEncoded; + RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 Entries[0x200]; +} RTL_INVERTED_FUNCTION_TABLE_WIN7_32, * PRTL_INVERTED_FUNCTION_TABLE_WIN7_32; + +#ifdef _WIN64 +typedef _RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 _RTL_INVERTED_FUNCTION_TABLE_ENTRY, RTL_INVERTED_FUNCTION_TABLE_ENTRY, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY; +typedef RTL_INVERTED_FUNCTION_TABLE_64 _RTL_INVERTED_FUNCTION_TABLE, RTL_INVERTED_FUNCTION_TABLE, * PRTL_INVERTED_FUNCTION_TABLE; +#else +typedef RTL_INVERTED_FUNCTION_TABLE_WIN7_32 _RTL_INVERTED_FUNCTION_TABLE, RTL_INVERTED_FUNCTION_TABLE, * PRTL_INVERTED_FUNCTION_TABLE; +typedef _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 _RTL_INVERTED_FUNCTION_TABLE_ENTRY, RTL_INVERTED_FUNCTION_TABLE_ENTRY, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY; +#endif NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t ImageSize); NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase); NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry); +int NTAPI RtlCaptureImageExceptionValues(PVOID BaseAddress, PDWORD SEHandlerTable, PDWORD SEHandlerCount); diff --git a/README.md b/README.md index adec574..804facb 100644 --- a/README.md +++ b/README.md @@ -8,18 +8,18 @@ MemoryModulePP, used to load a DLL from memory. MemoryModulePP is compatible wit **This repository is under development.** -# NewFeatures - - Compatible with Win32 API: LoadStringA/W - - Support for TLS(Thread Local Storage) - - DllMain can receive four types of notifications +## New Features + - Compatible with Win7(x86) -# Features - - Compatible with Win32 API (GetModuleHandleA/W/Ex GetModuleFileNameA/W/Ex GetProcAddress) +## Features + - Compatible with Win32 API (GetModuleHandleA/W/Ex GetModuleFileNameA/W/Ex GetProcAddress and any Resource API) - Support for C ++ exceptions and SEH - Compatible with Win7(x64) and Win10(x64) - Optimized MEMORYMODULE structure - Use reference counting, repeated loading of the same module will update the reference counting, please refer to NtLoadDllMemoryExW - The above features can be turned off through the dwFlags parameter of NtLoadDllMemoryExW + - Support for TLS(Thread Local Storage) + - DllMain can receive four types of notifications ## Tech diff --git a/test/Header.h b/test/Header.h index c1f17d6..92cb518 100644 --- a/test/Header.h +++ b/test/Header.h @@ -1,538 +1,553 @@ -#include -#include "../MemoryModule/NativeFunctionsInternal.h" - -typedef struct _THREAD_TLS_INFORMATION { - ULONG Flags; - union { - PVOID* TlsVector; - PVOID TlsModulePointer; - }; - HANDLE ThreadId; -} THREAD_TLS_INFORMATION, * PTHREAD_TLS_INFORMATION; - -typedef enum _PROCESS_TLS_INFORMATION_TYPE { - ProcessTlsReplaceIndex, - ProcessTlsReplaceVector, - MaxProcessTlsOperation -} PROCESS_TLS_INFORMATION_TYPE, * PPROCESS_TLS_INFORMATION_TYPE; - -typedef struct _PROCESS_TLS_INFORMATION { - ULONG Reserved; // Reserved bitmask - ULONG OperationType; - ULONG ThreadDataCount; - union { - ULONG TlsIndex; - ULONG TlsVectorLength; - }; - THREAD_TLS_INFORMATION ThreadData[ANYSIZE_ARRAY]; -} PROCESS_TLS_INFORMATION, * PPROCESS_TLS_INFORMATION; - -// Need struct name -typedef struct _TLS_VECTOR { - union { - ULONG Length; - HANDLE ThreadId; - }; - - struct _TLS_VECTOR* PreviousDeferredTlsVector; - PVOID ModuleTlsData[ANYSIZE_ARRAY]; -} TLS_VECTOR, * PTLS_VECTOR; - -// Need struct name -typedef struct _TLS_RECLAIM_TABLE_ENTRY { - PTLS_VECTOR TlsVector; - RTL_SRWLOCK Lock; -} TLS_RECLAIM_TABLE_ENTRY, * PTLS_RECLAIM_TABLE_ENTRY; - -// Need struct name -typedef struct _TLS_ENTRY { - LIST_ENTRY TlsEntryLinks; - IMAGE_TLS_DIRECTORY TlsDirectory; - PLDR_DATA_TABLE_ENTRY ModuleEntry; -} TLS_ENTRY, * PTLS_ENTRY; - -//0x10 bytes (sizeof) -typedef struct _RTL_BITMAP { - ULONG SizeOfBitMap; //0x0 - ULONG* Buffer; //0x8 -}RTL_BITMAP, * PRTL_BITMAP; - -VOID RtlClearBit( - PRTL_BITMAP BitMapHeader, - ULONG BitNumber -); - -VOID RtlInitializeBitMap( - PRTL_BITMAP BitMapHeader, - PULONG BitMapBuffer, - ULONG SizeOfBitMap -); - -ULONG RtlFindClearBitsAndSet( - PRTL_BITMAP BitMapHeader, - ULONG NumberToFind, - ULONG HintIndex -); - -VOID RtlClearBits( - PRTL_BITMAP BitMapHeader, - ULONG StartingIndex, - ULONG NumberToClear -); - -VOID RtlSetBit( - PRTL_BITMAP BitMapHeader, - ULONG BitNumber -); - -BOOLEAN RemoveEntryList( - PLIST_ENTRY Entry -); - -VOID NTAPI RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock); -VOID NTAPI RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock); - -NTSTATUS NTAPI NtSetInformationProcess( - IN HANDLE ProcessHandle, - IN ULONG ProcessInformationClass, - IN PVOID ProcessInformation, - IN ULONG ProcessInformationLength); - -#define ProcessTlsInformation ProcessResourceManagement - -PUCHAR NtdllBaseTag = 0; -ULONG LdrpActiveThreadCount = 0; -ULONG LdrpPotentialTlsLeaks = 0; -RTL_BITMAP LdrpTlsBitmap; -LIST_ENTRY LdrpTlsList; - -TLS_RECLAIM_TABLE_ENTRY LdrpDelayedTlsReclaimTable[16]; - -ULONG LdrpStaticTlsBitmapVector[4]; -ULONG LdrpActualBitmapSize = 0; - - -VOID LdrpInit() { - RtlCopyMemory(&LdrpTlsBitmap, NtCurrentPeb()->TlsBitmap, sizeof(RTL_BITMAP)); - PROCESS_TLS_INFORMATION pti; - -} - -VOID LdrpReleaseTlsIndex(ULONG TlsIndex) { - RtlClearBit(&LdrpTlsBitmap, TlsIndex); -} - -#define LDRP_BITMAP_INCREMENT (0x27 - sizeof( PVOID )) - -NTSTATUS LdrpAcquireTlsIndex(PULONG TlsIndex, PBOOLEAN AllocatedBitmap) { - ULONG Length; - ULONG Index; - PULONG NewBitmapBuffer; - - Length = LdrpTlsBitmap.SizeOfBitMap; - - if (Length == 0) { - // - // If we're the first caller, then we shall need to be initializing the - // bitmap. - // - // This implies that we don't need to expand as by definition, there - // shall exist space for ourselves at the start of the bitmap now. - // - RtlInitializeBitMap(&LdrpTlsBitmap, LdrpStaticTlsBitmapVector, 4); - LdrpActualBitmapSize = 1; - } - else { - Index = RtlFindClearBitsAndSet(&LdrpTlsBitmap, 1, 0); - - // - // If we found space in the existing bitmap then there is no reason to - // expand buffers, so we'll just return with the existing data. - // - if (Index != 0xFFFFFFFF) { - *TlsIndex = Index; - *AllocatedBitmap = FALSE; - return STATUS_SUCCESS; - } - - // - // Check if we need to grow the bitmap itself or if the bitmap still - // has space. - // - if (((LdrpTlsBitmap.SizeOfBitMap + LDRP_BITMAP_INCREMENT) >> 5) > LdrpActualBitmapSize) { - // - // We'll need to grow it. Let's go do so now. - // - - // - // BUG: We set the new size before checking the allocation. If we - // fail, then we leave the TLS variables in an inconsistant state. - // - LdrpActualBitmapSize = (Length + LDRP_BITMAP_INCREMENT) >> 5; - NewBitmapBuffer = (PULONG)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), LdrpActualBitmapSize); - if (!NewBitmapBuffer) return STATUS_NO_MEMORY; - - // - // Copy the contents of the previous buffer into the new one. - // - RtlCopyMemory(NewBitmapBuffer, LdrpTlsBitmap.Buffer, Length + 7); - - // - // Free the old buffer if it wasn't the initial static buffer. - // - if (LdrpTlsBitmap.Buffer != LdrpStaticTlsBitmapVector) { - RtlFreeHeap(GetProcessHeap(), 0, LdrpTlsBitmap.Buffer); - } - - // - // Reinitialize the bitmap as we've changed the buffer pointer. - // - RtlInitializeBitMap(&LdrpTlsBitmap, NewBitmapBuffer, Length + 4); - } - else { - LdrpTlsBitmap.SizeOfBitMap += 4; - } - } - - RtlClearBits(&LdrpTlsBitmap, Length + 1, 3); - RtlSetBit(&LdrpTlsBitmap, Length); - - *TlsIndex = Index; - *AllocatedBitmap = TRUE; - - return STATUS_SUCCESS; -} - -NTSTATUS LdrpAllocateTlsEntry(PIMAGE_TLS_DIRECTORY TlsDirectory, PLDR_DATA_TABLE_ENTRY ModuleEntry, PULONG TlsIndex, PBOOLEAN AllocatedBitmap, PTLS_ENTRY* TlsEntry) { - - PTLS_ENTRY Entry = nullptr; - NTSTATUS Status; - - __try { - Entry = (PTLS_ENTRY)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), sizeof(TLS_ENTRY)); - if (!Entry) return STATUS_NO_MEMORY; - Status = STATUS_SUCCESS; - RtlCopyMemory(&Entry->TlsDirectory, TlsDirectory, sizeof(IMAGE_TLS_DIRECTORY)); - } - __except (EXCEPTION_EXECUTE_HANDLER) { - // - // Also print string and complain. - // - Status = GetExceptionCode(); - } - - if (!NT_SUCCESS(Status)) { - RtlFreeHeap(GetProcessHeap(), 0, Entry); - return Status; - } - - // - // Validate that the TLS directory entry is sane. - // - if (Entry->TlsDirectory.StartAddressOfRawData < Entry->TlsDirectory.EndAddressOfRawData) { - RtlFreeHeap(GetProcessHeap(), 0, Entry); - return STATUS_INVALID_IMAGE_FORMAT; - } - Entry->ModuleEntry = ModuleEntry; - - // - // Insert the entry into our list. - // - - InsertTailList(&LdrpTlsList, &Entry->TlsEntryLinks); - if (AllocatedBitmap) { - Status = LdrpAcquireTlsIndex(TlsIndex, AllocatedBitmap); - if (!NT_SUCCESS(Status)) { - // - // BUG: We don't remove the entry from LdrpTlsList - // - RtlFreeHeap(GetProcessHeap(), 0, Entry); - return Status; - } - } - else { - *TlsIndex += 1; - } - - // - // We reuse the 'Characteristics' field for the real TLS index. - // - Entry->TlsDirectory.Characteristics = *TlsIndex; - __try { - *(PULONG)Entry->TlsDirectory.AddressOfIndex = *TlsIndex; - } - __except (EXCEPTION_EXECUTE_HANDLER) { - Status = GetExceptionCode(); - } - if (!NT_SUCCESS(Status)) { - if (AllocatedBitmap) { - LdrpReleaseTlsIndex(*TlsIndex); - if (*AllocatedBitmap) LdrpTlsBitmap.SizeOfBitMap -= 4; - } - - // - // BUG: We don't remove the entry from LdrpTlsList - // - RtlFreeHeap(GetProcessHeap(), 0, Entry); - return Status; - } - - if (TlsEntry) *TlsEntry = Entry; - return STATUS_SUCCESS; -} - -PTLS_ENTRY __fastcall LdrpFindTlsEntry(PLDR_DATA_TABLE_ENTRY ModuleEntry) { - PTLS_ENTRY TlsEntry; - PLIST_ENTRY ListHead; - - ListHead = &LdrpTlsList; - - for (TlsEntry = CONTAINING_RECORD(LdrpTlsList.Flink, TLS_ENTRY, TlsEntryLinks); - &TlsEntry->TlsEntryLinks != ListHead; - TlsEntry = CONTAINING_RECORD(TlsEntry->TlsEntryLinks.Flink, TLS_ENTRY, TlsEntryLinks)) { - - if (TlsEntry->ModuleEntry == ModuleEntry) return TlsEntry; - } - - return 0; -} - -NTSTATUS LdrpReleaseTlsEntry(PLDR_DATA_TABLE_ENTRY ModuleEntry) { - PTLS_ENTRY TlsEntry; - - // - // Find the corresponding TLS_ENTRY for this module entry. - // - TlsEntry = LdrpFindTlsEntry(ModuleEntry); - if (!TlsEntry) return STATUS_NOT_FOUND; - - // - // Remove it from the global list of outstanding TLS entries. - // - RemoveEntryList(&TlsEntry->TlsEntryLinks); - - // - // Deallocate the TLS index. - // - LdrpReleaseTlsIndex(TlsEntry->TlsDirectory.Characteristics); - - // - // Deallocate the TLS_ENTRY object itself. - // - RtlFreeHeap(GetProcessHeap(), 0, TlsEntry); - - // - // We're done. - // - return STATUS_SUCCESS; -} - -PVOID* __fastcall LdrpGetNewTlsVector(ULONG TlsBitmapLength) { - PTLS_VECTOR TlsVector; - - TlsVector = (PTLS_VECTOR)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), - sizeof(TLS_VECTOR) + (sizeof(PVOID) * TlsBitmapLength) - sizeof(PVOID)); - if (!TlsVector) return 0; - TlsVector->Length = TlsBitmapLength; - RtlZeroMemory(TlsVector->ModuleTlsData, TlsBitmapLength * sizeof(PVOID)); - return TlsVector->ModuleTlsData; -} - -VOID LdrpQueueDeferredTlsData(PVOID TlsVector, PVOID ThreadId) { - PTLS_VECTOR RealTlsVector; - PTLS_RECLAIM_TABLE_ENTRY ReclaimEntry; - - RealTlsVector = CONTAINING_RECORD(TlsVector, TLS_VECTOR, ModuleTlsData); - - RealTlsVector->ThreadId = ThreadId; - - ReclaimEntry = &LdrpDelayedTlsReclaimTable[((ULONG_PTR)(ThreadId) >> 2) & 0xF]; - - RtlAcquireSRWLockExclusive(&ReclaimEntry->Lock); - - RealTlsVector->PreviousDeferredTlsVector = ReclaimEntry->TlsVector; - ReclaimEntry->TlsVector = RealTlsVector; - - RtlReleaseSRWLockExclusive(&ReclaimEntry->Lock); -} - -#define SIZEOF_TLS_INFO(_ThreadCount_) (_ThreadCount_==0)?sizeof(PROCESS_TLS_INFORMATION)-sizeof(THREAD_TLS_INFORMATION):(_ThreadCount_-1)*sizeof(THREAD_TLS_INFORMATION)+sizeof(PROCESS_TLS_INFORMATION) -NTSTATUS LdrpHandleTlsData(PLDR_DATA_TABLE_ENTRY ModuleEntry) { - PIMAGE_TLS_DIRECTORY TlsDirectory; - ULONG DirectorySize; - ULONG TlsIndex; - HANDLE Heap; - PPROCESS_TLS_INFORMATION TlsInfo; - PROCESS_TLS_INFORMATION OneThreadTlsInfo; - NTSTATUS Status; - BOOLEAN AllocatedBitmap; - PTLS_ENTRY TlsEntry; - ULONG TlsBitmapLength; - SIZE_T TlsRawDataLength; - ULONG ThreadIndex; - PVOID TlsData = nullptr; - PVOID* TlsVector; - PTHREAD_TLS_INFORMATION ThreadTlsData; - ULONG ThreadsCleanedUp; - - if (LdrpActiveThreadCount == 0) return STATUS_SUCCESS; - TlsDirectory = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData(ModuleEntry->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &DirectorySize); - if (!TlsDirectory) return STATUS_SUCCESS; - Heap = NtCurrentPeb()->ProcessHeap; - - TlsInfo = LdrpActiveThreadCount == 1 ? &OneThreadTlsInfo : - (decltype(TlsInfo))RtlAllocateHeap(Heap, (ULONG)NtdllBaseTag + 0x000C0000, SIZEOF_TLS_INFO(LdrpActiveThreadCount)); - if (!TlsInfo) return STATUS_NO_MEMORY; - - do { - TlsBitmapLength = LdrpTlsBitmap.SizeOfBitMap; - Status = LdrpAllocateTlsEntry(TlsDirectory, ModuleEntry, &TlsIndex, &AllocatedBitmap, &TlsEntry); - if (!NT_SUCCESS(Status)) break; - TlsInfo->ThreadDataCount = LdrpActiveThreadCount; - if (AllocatedBitmap) { - TlsInfo->OperationType = ProcessTlsReplaceVector; - TlsInfo->TlsVectorLength = TlsBitmapLength; - TlsBitmapLength = LdrpTlsBitmap.SizeOfBitMap; - } - else { - TlsInfo->OperationType = ProcessTlsReplaceIndex; - TlsInfo->TlsIndex = TlsIndex; - } - Status = STATUS_SUCCESS; - ThreadsCleanedUp = 0; - - // - // Calculate the size of the raw TLS data for this module. - // - TlsRawDataLength = TlsEntry->TlsDirectory.EndAddressOfRawData - TlsEntry->TlsDirectory.StartAddressOfRawData; - - // - // Prepare data for each running thread. - // - for (ThreadIndex = 0; ThreadIndex < TlsInfo->ThreadDataCount; ++ThreadIndex) { - TlsData = RtlAllocateHeap(Heap, (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), TlsRawDataLength); - if (!TlsData) { - Status = STATUS_NO_MEMORY; - break; - } - __try { - RtlCopyMemory(TlsData, (PVOID)TlsEntry->TlsDirectory.StartAddressOfRawData, TlsRawDataLength); - } - __except (EXCEPTION_EXECUTE_HANDLER) { - Status = GetExceptionCode(); - } - if (!NT_SUCCESS(Status)) { - RtlFreeHeap(Heap, 0, TlsData); - break; - } - - if (AllocatedBitmap) { - TlsVector = LdrpGetNewTlsVector(TlsBitmapLength); - if (!TlsVector) { - RtlFreeHeap(Heap, 0, TlsData); - break; - } - TlsVector[TlsIndex] = TlsData; - TlsInfo->ThreadData[ThreadIndex].TlsVector = TlsVector; - } - else { - TlsInfo->ThreadData[ThreadIndex].TlsModulePointer = TlsData; - } - - TlsInfo->ThreadData[ThreadIndex].Flags = 0; - } - - // - // This is awkward; all the 'break' above really are either goto or - // __leave, but we aren't using those. This is really supposed to - // just happen on normal for loop exit. - // - if (ThreadIndex == TlsInfo->ThreadDataCount) { - TlsInfo->Reserved = 0; - Status = NtSetInformationProcess(GetCurrentProcess(), ProcessTlsInformation, TlsInfo, - TlsInfo->ThreadDataCount * sizeof(THREAD_TLS_INFORMATION) + sizeof(PROCESS_TLS_INFORMATION) - sizeof(THREAD_TLS_INFORMATION)); - } - - // - // Let's handle each thread that we replaced, as the - // ProcessTlsInformation call fills our buffer with the old data - // after performing a swap. - // - for (ThreadTlsData = &TlsInfo->ThreadData[ThreadIndex]; ThreadIndex > 0;) { - ThreadIndex -= 1; - ThreadTlsData -= 1; - - if (ThreadTlsData->Flags & 0x2) { - if (!ThreadTlsData->TlsVector) continue; - - if (!AllocatedBitmap) { - RtlFreeHeap(Heap, 0, ThreadTlsData->TlsVector); - continue; - } - else { - LdrpQueueDeferredTlsData(ThreadTlsData->TlsVector, ThreadTlsData->ThreadId); - continue; - } - } - else { - if (ThreadTlsData->Flags & 0x1) { - ++LdrpPotentialTlsLeaks; - continue; - } - else { - ++ThreadsCleanedUp; - if (AllocatedBitmap) { - TlsData = ThreadTlsData->TlsVector[TlsIndex]; - RtlFreeHeap(Heap, 0, CONTAINING_RECORD(ThreadTlsData->TlsVector, TLS_VECTOR, ModuleTlsData)); - } - RtlFreeHeap(Heap, 0, TlsData); - continue; - } - } - } - - if (!NT_SUCCESS(Status)) { - LdrpReleaseTlsEntry(ModuleEntry); - if (AllocatedBitmap) LdrpTlsBitmap.SizeOfBitMap -= 4; - } - else if (ThreadsCleanedUp > 0) { - LdrpActiveThreadCount -= ThreadsCleanedUp; - } - } while (0); - - if (TlsInfo != &OneThreadTlsInfo) RtlFreeHeap(Heap, 0, TlsInfo); - if (!NT_SUCCESS(Status)) return Status; - ModuleEntry->TlsIndex = 0xFFFF; - return STATUS_SUCCESS; -} - -//struct UNKNOWN { -// PVOID unknown1; //+0x0 -// PVOID unknown2; //+0x8 -// PVOID unknown3; //+0x10 -// struct { -// DWORD dwFlags; //+0x14 -// DWORD unknown4; //+0x18 -// }; -// PWSTR DllName; //+0x20 -// PVOID unknown[11]; -//}; +//#include +//#include "../MemoryModule/NativeFunctionsInternal.h" // -////#include "../MemoryModule/Native.h" -// -////size = 0xC0 + DllName->Length + sizeof(wchar_t) -//typedef struct _ALLOCATE_ENTRY_PARAMETER { -// UNICODE_STRING DllName; //+0x0 -// UNKNOWN* unknown_structure; //+0x10 -// PVOID reserved1; //+0x18 -// struct { -// DWORD ProcessStatus; //+0x20 -// DWORD reserved2; //+0x24 +//typedef struct _THREAD_TLS_INFORMATION { +// ULONG Flags; +// union { +// PVOID* TlsVector; +// PVOID TlsModulePointer; // }; -// PVOID reserved3; //+0x28 -// PVOID reserved4; //+0x30 -// PVOID LdrEntry; //+0x38 -// PVOID reserved[16]; //+0x40 -// BYTE UnicodeStringBuffer[1]; //+0xC0 -//}ALLOCATE_ENTRY_PARAMETER, * PALLOCATE_ENTRY_PARAMETER; +// HANDLE ThreadId; +//} THREAD_TLS_INFORMATION, * PTHREAD_TLS_INFORMATION; +// +//typedef enum _PROCESS_TLS_INFORMATION_TYPE { +// ProcessTlsReplaceIndex, +// ProcessTlsReplaceVector, +// MaxProcessTlsOperation +//} PROCESS_TLS_INFORMATION_TYPE, * PPROCESS_TLS_INFORMATION_TYPE; +// +//typedef struct _PROCESS_TLS_INFORMATION { +// ULONG Reserved; // Reserved bitmask +// ULONG OperationType; +// ULONG ThreadDataCount; +// union { +// ULONG TlsIndex; +// ULONG TlsVectorLength; +// }; +// THREAD_TLS_INFORMATION ThreadData[ANYSIZE_ARRAY]; +//} PROCESS_TLS_INFORMATION, * PPROCESS_TLS_INFORMATION; +// +//// Need struct name +//typedef struct _TLS_VECTOR { +// union { +// ULONG Length; +// HANDLE ThreadId; +// }; +// +// struct _TLS_VECTOR* PreviousDeferredTlsVector; +// PVOID ModuleTlsData[ANYSIZE_ARRAY]; +//} TLS_VECTOR, * PTLS_VECTOR; +// +//// Need struct name +//typedef struct _TLS_RECLAIM_TABLE_ENTRY { +// PTLS_VECTOR TlsVector; +// RTL_SRWLOCK Lock; +//} TLS_RECLAIM_TABLE_ENTRY, * PTLS_RECLAIM_TABLE_ENTRY; +// +//// Need struct name +//typedef struct _TLS_ENTRY { +// LIST_ENTRY TlsEntryLinks; +// IMAGE_TLS_DIRECTORY TlsDirectory; +// PLDR_DATA_TABLE_ENTRY ModuleEntry; +//} TLS_ENTRY, * PTLS_ENTRY; +// +////0x10 bytes (sizeof) +//typedef struct _RTL_BITMAP { +// ULONG SizeOfBitMap; //0x0 +// ULONG* Buffer; //0x8 +//}RTL_BITMAP, * PRTL_BITMAP; +// +//VOID RtlClearBit( +// PRTL_BITMAP BitMapHeader, +// ULONG BitNumber +//); +// +//VOID RtlInitializeBitMap( +// PRTL_BITMAP BitMapHeader, +// PULONG BitMapBuffer, +// ULONG SizeOfBitMap +//); +// +//ULONG RtlFindClearBitsAndSet( +// PRTL_BITMAP BitMapHeader, +// ULONG NumberToFind, +// ULONG HintIndex +//); +// +//VOID RtlClearBits( +// PRTL_BITMAP BitMapHeader, +// ULONG StartingIndex, +// ULONG NumberToClear +//); +// +//VOID RtlSetBit( +// PRTL_BITMAP BitMapHeader, +// ULONG BitNumber +//); +// +//BOOLEAN RemoveEntryList( +// PLIST_ENTRY Entry +//); +// +//VOID NTAPI RtlAcquireSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock); +//VOID NTAPI RtlReleaseSRWLockExclusive(IN OUT PRTL_SRWLOCK SRWLock); +// +//NTSTATUS NTAPI NtSetInformationProcess( +// IN HANDLE ProcessHandle, +// IN ULONG ProcessInformationClass, +// IN PVOID ProcessInformation, +// IN ULONG ProcessInformationLength); +// +//#define ProcessTlsInformation ProcessResourceManagement +// +//PUCHAR NtdllBaseTag = 0; +//ULONG LdrpActiveThreadCount = 0; +//ULONG LdrpPotentialTlsLeaks = 0; +//RTL_BITMAP LdrpTlsBitmap; +//LIST_ENTRY LdrpTlsList; +// +//TLS_RECLAIM_TABLE_ENTRY LdrpDelayedTlsReclaimTable[16]; +// +//ULONG LdrpStaticTlsBitmapVector[4]; +//ULONG LdrpActualBitmapSize = 0; +// +// +//VOID LdrpInit() { +// RtlCopyMemory(&LdrpTlsBitmap, NtCurrentPeb()->TlsBitmap, sizeof(RTL_BITMAP)); +// PROCESS_TLS_INFORMATION pti; +// +//} +// +//VOID LdrpReleaseTlsIndex(ULONG TlsIndex) { +// RtlClearBit(&LdrpTlsBitmap, TlsIndex); +//} +// +//#define LDRP_BITMAP_INCREMENT (0x27 - sizeof( PVOID )) +// +//NTSTATUS LdrpAcquireTlsIndex(PULONG TlsIndex, PBOOLEAN AllocatedBitmap) { +// ULONG Length; +// ULONG Index; +// PULONG NewBitmapBuffer; +// +// Length = LdrpTlsBitmap.SizeOfBitMap; +// +// if (Length == 0) { +// // +// // If we're the first caller, then we shall need to be initializing the +// // bitmap. +// // +// // This implies that we don't need to expand as by definition, there +// // shall exist space for ourselves at the start of the bitmap now. +// // +// RtlInitializeBitMap(&LdrpTlsBitmap, LdrpStaticTlsBitmapVector, 4); +// LdrpActualBitmapSize = 1; +// } +// else { +// Index = RtlFindClearBitsAndSet(&LdrpTlsBitmap, 1, 0); +// +// // +// // If we found space in the existing bitmap then there is no reason to +// // expand buffers, so we'll just return with the existing data. +// // +// if (Index != 0xFFFFFFFF) { +// *TlsIndex = Index; +// *AllocatedBitmap = FALSE; +// return STATUS_SUCCESS; +// } +// +// // +// // Check if we need to grow the bitmap itself or if the bitmap still +// // has space. +// // +// if (((LdrpTlsBitmap.SizeOfBitMap + LDRP_BITMAP_INCREMENT) >> 5) > LdrpActualBitmapSize) { +// // +// // We'll need to grow it. Let's go do so now. +// // +// +// // +// // BUG: We set the new size before checking the allocation. If we +// // fail, then we leave the TLS variables in an inconsistant state. +// // +// LdrpActualBitmapSize = (Length + LDRP_BITMAP_INCREMENT) >> 5; +// NewBitmapBuffer = (PULONG)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), LdrpActualBitmapSize); +// if (!NewBitmapBuffer) return STATUS_NO_MEMORY; +// +// // +// // Copy the contents of the previous buffer into the new one. +// // +// RtlCopyMemory(NewBitmapBuffer, LdrpTlsBitmap.Buffer, Length + 7); +// +// // +// // Free the old buffer if it wasn't the initial static buffer. +// // +// if (LdrpTlsBitmap.Buffer != LdrpStaticTlsBitmapVector) { +// RtlFreeHeap(GetProcessHeap(), 0, LdrpTlsBitmap.Buffer); +// } +// +// // +// // Reinitialize the bitmap as we've changed the buffer pointer. +// // +// RtlInitializeBitMap(&LdrpTlsBitmap, NewBitmapBuffer, Length + 4); +// } +// else { +// LdrpTlsBitmap.SizeOfBitMap += 4; +// } +// } +// +// RtlClearBits(&LdrpTlsBitmap, Length + 1, 3); +// RtlSetBit(&LdrpTlsBitmap, Length); +// +// *TlsIndex = Index; +// *AllocatedBitmap = TRUE; +// +// return STATUS_SUCCESS; +//} +// +//NTSTATUS LdrpAllocateTlsEntry(PIMAGE_TLS_DIRECTORY TlsDirectory, PLDR_DATA_TABLE_ENTRY ModuleEntry, PULONG TlsIndex, PBOOLEAN AllocatedBitmap, PTLS_ENTRY* TlsEntry) { +// +// PTLS_ENTRY Entry = nullptr; +// NTSTATUS Status; +// +// __try { +// Entry = (PTLS_ENTRY)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), sizeof(TLS_ENTRY)); +// if (!Entry) return STATUS_NO_MEMORY; +// Status = STATUS_SUCCESS; +// RtlCopyMemory(&Entry->TlsDirectory, TlsDirectory, sizeof(IMAGE_TLS_DIRECTORY)); +// } +// __except (EXCEPTION_EXECUTE_HANDLER) { +// // +// // Also print string and complain. +// // +// Status = GetExceptionCode(); +// } +// +// if (!NT_SUCCESS(Status)) { +// RtlFreeHeap(GetProcessHeap(), 0, Entry); +// return Status; +// } +// +// // +// // Validate that the TLS directory entry is sane. +// // +// if (Entry->TlsDirectory.StartAddressOfRawData < Entry->TlsDirectory.EndAddressOfRawData) { +// RtlFreeHeap(GetProcessHeap(), 0, Entry); +// return STATUS_INVALID_IMAGE_FORMAT; +// } +// Entry->ModuleEntry = ModuleEntry; +// +// // +// // Insert the entry into our list. +// // +// +// InsertTailList(&LdrpTlsList, &Entry->TlsEntryLinks); +// if (AllocatedBitmap) { +// Status = LdrpAcquireTlsIndex(TlsIndex, AllocatedBitmap); +// if (!NT_SUCCESS(Status)) { +// // +// // BUG: We don't remove the entry from LdrpTlsList +// // +// RtlFreeHeap(GetProcessHeap(), 0, Entry); +// return Status; +// } +// } +// else { +// *TlsIndex += 1; +// } +// +// // +// // We reuse the 'Characteristics' field for the real TLS index. +// // +// Entry->TlsDirectory.Characteristics = *TlsIndex; +// __try { +// *(PULONG)Entry->TlsDirectory.AddressOfIndex = *TlsIndex; +// } +// __except (EXCEPTION_EXECUTE_HANDLER) { +// Status = GetExceptionCode(); +// } +// if (!NT_SUCCESS(Status)) { +// if (AllocatedBitmap) { +// LdrpReleaseTlsIndex(*TlsIndex); +// if (*AllocatedBitmap) LdrpTlsBitmap.SizeOfBitMap -= 4; +// } +// +// // +// // BUG: We don't remove the entry from LdrpTlsList +// // +// RtlFreeHeap(GetProcessHeap(), 0, Entry); +// return Status; +// } +// +// if (TlsEntry) *TlsEntry = Entry; +// return STATUS_SUCCESS; +//} +// +//PTLS_ENTRY __fastcall LdrpFindTlsEntry(PLDR_DATA_TABLE_ENTRY ModuleEntry) { +// PTLS_ENTRY TlsEntry; +// PLIST_ENTRY ListHead; +// +// ListHead = &LdrpTlsList; +// +// for (TlsEntry = CONTAINING_RECORD(LdrpTlsList.Flink, TLS_ENTRY, TlsEntryLinks); +// &TlsEntry->TlsEntryLinks != ListHead; +// TlsEntry = CONTAINING_RECORD(TlsEntry->TlsEntryLinks.Flink, TLS_ENTRY, TlsEntryLinks)) { +// +// if (TlsEntry->ModuleEntry == ModuleEntry) return TlsEntry; +// } +// +// return 0; +//} +// +//NTSTATUS LdrpReleaseTlsEntry(PLDR_DATA_TABLE_ENTRY ModuleEntry) { +// PTLS_ENTRY TlsEntry; +// +// // +// // Find the corresponding TLS_ENTRY for this module entry. +// // +// TlsEntry = LdrpFindTlsEntry(ModuleEntry); +// if (!TlsEntry) return STATUS_NOT_FOUND; +// +// // +// // Remove it from the global list of outstanding TLS entries. +// // +// RemoveEntryList(&TlsEntry->TlsEntryLinks); +// +// // +// // Deallocate the TLS index. +// // +// LdrpReleaseTlsIndex(TlsEntry->TlsDirectory.Characteristics); +// +// // +// // Deallocate the TLS_ENTRY object itself. +// // +// RtlFreeHeap(GetProcessHeap(), 0, TlsEntry); +// +// // +// // We're done. +// // +// return STATUS_SUCCESS; +//} +// +//PVOID* __fastcall LdrpGetNewTlsVector(ULONG TlsBitmapLength) { +// PTLS_VECTOR TlsVector; +// +// TlsVector = (PTLS_VECTOR)RtlAllocateHeap(GetProcessHeap(), (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), +// sizeof(TLS_VECTOR) + (sizeof(PVOID) * TlsBitmapLength) - sizeof(PVOID)); +// if (!TlsVector) return 0; +// TlsVector->Length = TlsBitmapLength; +// RtlZeroMemory(TlsVector->ModuleTlsData, TlsBitmapLength * sizeof(PVOID)); +// return TlsVector->ModuleTlsData; +//} +// +//VOID LdrpQueueDeferredTlsData(PVOID TlsVector, PVOID ThreadId) { +// PTLS_VECTOR RealTlsVector; +// PTLS_RECLAIM_TABLE_ENTRY ReclaimEntry; +// +// RealTlsVector = CONTAINING_RECORD(TlsVector, TLS_VECTOR, ModuleTlsData); +// +// RealTlsVector->ThreadId = ThreadId; +// +// ReclaimEntry = &LdrpDelayedTlsReclaimTable[((ULONG_PTR)(ThreadId) >> 2) & 0xF]; +// +// RtlAcquireSRWLockExclusive(&ReclaimEntry->Lock); +// +// RealTlsVector->PreviousDeferredTlsVector = ReclaimEntry->TlsVector; +// ReclaimEntry->TlsVector = RealTlsVector; +// +// RtlReleaseSRWLockExclusive(&ReclaimEntry->Lock); +//} +// +//#define SIZEOF_TLS_INFO(_ThreadCount_) (_ThreadCount_==0)?sizeof(PROCESS_TLS_INFORMATION)-sizeof(THREAD_TLS_INFORMATION):(_ThreadCount_-1)*sizeof(THREAD_TLS_INFORMATION)+sizeof(PROCESS_TLS_INFORMATION) +//NTSTATUS LdrpHandleTlsData(PLDR_DATA_TABLE_ENTRY ModuleEntry) { +// PIMAGE_TLS_DIRECTORY TlsDirectory; +// ULONG DirectorySize; +// ULONG TlsIndex; +// HANDLE Heap; +// PPROCESS_TLS_INFORMATION TlsInfo; +// PROCESS_TLS_INFORMATION OneThreadTlsInfo; +// NTSTATUS Status; +// BOOLEAN AllocatedBitmap; +// PTLS_ENTRY TlsEntry; +// ULONG TlsBitmapLength; +// SIZE_T TlsRawDataLength; +// ULONG ThreadIndex; +// PVOID TlsData = nullptr; +// PVOID* TlsVector; +// PTHREAD_TLS_INFORMATION ThreadTlsData; +// ULONG ThreadsCleanedUp; +// +// if (LdrpActiveThreadCount == 0) return STATUS_SUCCESS; +// TlsDirectory = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData(ModuleEntry->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &DirectorySize); +// if (!TlsDirectory) return STATUS_SUCCESS; +// Heap = NtCurrentPeb()->ProcessHeap; +// +// TlsInfo = LdrpActiveThreadCount == 1 ? &OneThreadTlsInfo : +// (decltype(TlsInfo))RtlAllocateHeap(Heap, (ULONG)NtdllBaseTag + 0x000C0000, SIZEOF_TLS_INFO(LdrpActiveThreadCount)); +// if (!TlsInfo) return STATUS_NO_MEMORY; +// +// do { +// TlsBitmapLength = LdrpTlsBitmap.SizeOfBitMap; +// Status = LdrpAllocateTlsEntry(TlsDirectory, ModuleEntry, &TlsIndex, &AllocatedBitmap, &TlsEntry); +// if (!NT_SUCCESS(Status)) break; +// TlsInfo->ThreadDataCount = LdrpActiveThreadCount; +// if (AllocatedBitmap) { +// TlsInfo->OperationType = ProcessTlsReplaceVector; +// TlsInfo->TlsVectorLength = TlsBitmapLength; +// TlsBitmapLength = LdrpTlsBitmap.SizeOfBitMap; +// } +// else { +// TlsInfo->OperationType = ProcessTlsReplaceIndex; +// TlsInfo->TlsIndex = TlsIndex; +// } +// Status = STATUS_SUCCESS; +// ThreadsCleanedUp = 0; +// +// // +// // Calculate the size of the raw TLS data for this module. +// // +// TlsRawDataLength = TlsEntry->TlsDirectory.EndAddressOfRawData - TlsEntry->TlsDirectory.StartAddressOfRawData; +// +// // +// // Prepare data for each running thread. +// // +// for (ThreadIndex = 0; ThreadIndex < TlsInfo->ThreadDataCount; ++ThreadIndex) { +// TlsData = RtlAllocateHeap(Heap, (ULONG_PTR)((PUCHAR)NtdllBaseTag + 0x000C0000), TlsRawDataLength); +// if (!TlsData) { +// Status = STATUS_NO_MEMORY; +// break; +// } +// __try { +// RtlCopyMemory(TlsData, (PVOID)TlsEntry->TlsDirectory.StartAddressOfRawData, TlsRawDataLength); +// } +// __except (EXCEPTION_EXECUTE_HANDLER) { +// Status = GetExceptionCode(); +// } +// if (!NT_SUCCESS(Status)) { +// RtlFreeHeap(Heap, 0, TlsData); +// break; +// } +// +// if (AllocatedBitmap) { +// TlsVector = LdrpGetNewTlsVector(TlsBitmapLength); +// if (!TlsVector) { +// RtlFreeHeap(Heap, 0, TlsData); +// break; +// } +// TlsVector[TlsIndex] = TlsData; +// TlsInfo->ThreadData[ThreadIndex].TlsVector = TlsVector; +// } +// else { +// TlsInfo->ThreadData[ThreadIndex].TlsModulePointer = TlsData; +// } +// +// TlsInfo->ThreadData[ThreadIndex].Flags = 0; +// } +// +// // +// // This is awkward; all the 'break' above really are either goto or +// // __leave, but we aren't using those. This is really supposed to +// // just happen on normal for loop exit. +// // +// if (ThreadIndex == TlsInfo->ThreadDataCount) { +// TlsInfo->Reserved = 0; +// Status = NtSetInformationProcess(GetCurrentProcess(), ProcessTlsInformation, TlsInfo, +// TlsInfo->ThreadDataCount * sizeof(THREAD_TLS_INFORMATION) + sizeof(PROCESS_TLS_INFORMATION) - sizeof(THREAD_TLS_INFORMATION)); +// } +// +// // +// // Let's handle each thread that we replaced, as the +// // ProcessTlsInformation call fills our buffer with the old data +// // after performing a swap. +// // +// for (ThreadTlsData = &TlsInfo->ThreadData[ThreadIndex]; ThreadIndex > 0;) { +// ThreadIndex -= 1; +// ThreadTlsData -= 1; +// +// if (ThreadTlsData->Flags & 0x2) { +// if (!ThreadTlsData->TlsVector) continue; +// +// if (!AllocatedBitmap) { +// RtlFreeHeap(Heap, 0, ThreadTlsData->TlsVector); +// continue; +// } +// else { +// LdrpQueueDeferredTlsData(ThreadTlsData->TlsVector, ThreadTlsData->ThreadId); +// continue; +// } +// } +// else { +// if (ThreadTlsData->Flags & 0x1) { +// ++LdrpPotentialTlsLeaks; +// continue; +// } +// else { +// ++ThreadsCleanedUp; +// if (AllocatedBitmap) { +// TlsData = ThreadTlsData->TlsVector[TlsIndex]; +// RtlFreeHeap(Heap, 0, CONTAINING_RECORD(ThreadTlsData->TlsVector, TLS_VECTOR, ModuleTlsData)); +// } +// RtlFreeHeap(Heap, 0, TlsData); +// continue; +// } +// } +// } +// +// if (!NT_SUCCESS(Status)) { +// LdrpReleaseTlsEntry(ModuleEntry); +// if (AllocatedBitmap) LdrpTlsBitmap.SizeOfBitMap -= 4; +// } +// else if (ThreadsCleanedUp > 0) { +// LdrpActiveThreadCount -= ThreadsCleanedUp; +// } +// } while (0); +// +// if (TlsInfo != &OneThreadTlsInfo) RtlFreeHeap(Heap, 0, TlsInfo); +// if (!NT_SUCCESS(Status)) return Status; +// ModuleEntry->TlsIndex = 0xFFFF; +// return STATUS_SUCCESS; +//} +// +////struct UNKNOWN { +//// PVOID unknown1; //+0x0 +//// PVOID unknown2; //+0x8 +//// PVOID unknown3; //+0x10 +//// struct { +//// DWORD dwFlags; //+0x14 +//// DWORD unknown4; //+0x18 +//// }; +//// PWSTR DllName; //+0x20 +//// PVOID unknown[11]; +////}; +//// +//////#include "../MemoryModule/Native.h" +//// +//////size = 0xC0 + DllName->Length + sizeof(wchar_t) +////typedef struct _ALLOCATE_ENTRY_PARAMETER { +//// UNICODE_STRING DllName; //+0x0 +//// UNKNOWN* unknown_structure; //+0x10 +//// PVOID reserved1; //+0x18 +//// struct { +//// DWORD ProcessStatus; //+0x20 +//// DWORD reserved2; //+0x24 +//// }; +//// PVOID reserved3; //+0x28 +//// PVOID reserved4; //+0x30 +//// PVOID LdrEntry; //+0x38 +//// PVOID reserved[16]; //+0x40 +//// BYTE UnicodeStringBuffer[1]; //+0xC0 +////}ALLOCATE_ENTRY_PARAMETER, * PALLOCATE_ENTRY_PARAMETER; +// + +typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 { + PVOID ImageBase; + ULONG ImageSize; + ULONG SEHandlerCount; + PVOID NextEntrySEHandlerTableEncoded; +} RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32, * PRTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32; +typedef struct _RTL_INVERTED_FUNCTION_TABLE { + ULONG Count; + ULONG MaxCount; + ULONG Overflow; + ULONG NextEntrySEHandlerTableEncoded; + RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 Entries[0x200]; +} RTL_INVERTED_FUNCTION_TABLE, * PRTL_INVERTED_FUNCTION_TABLE; diff --git a/test/test.cpp b/test/test.cpp index c31a728..8096d11 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -6,8 +6,21 @@ #include #pragma warning(disable:4996) +//void TravelInvertedFunctionTable() { +// PRTL_INVERTED_FUNCTION_TABLE tab = decltype(tab)(0x770D2200); +// DWORD t = 0, tt = t; +// DWORD s = 0; +// for (DWORD i = 0; i < tab->Count; ++i) { +// PVOID exc = RtlDecodeSystemPointer(i ? tab->Entries[i - 1].NextEntrySEHandlerTableEncoded : (PVOID)&tab->NextEntrySEHandlerTableEncoded); +// RtlCaptureImageExceptionValues(tab->Entries[i].ImageBase, &t, &s); +// tt = (DWORD)RtlEncodeSystemPointer((PVOID)t); +// tab->Entries[i].ImageSize; +// i = i; +// } +//} + int main() { - //GetProcAddress(LoadLibraryA("a.dll"), "thread")(); + //TravelInvertedFunctionTable(); LPVOID buffer; size_t size; FILE* f = fopen("a.dll", "rb"); @@ -27,14 +40,34 @@ int main() { FARPROC test = nullptr; typedef int(*_exception)(int type); _exception exception = nullptr; + PWSTR t; + DWORD tableSize; + DWORD offset = 0, index = 0; + HRSRC res; + HGLOBAL hRes; + PWSTR str; if (!NT_SUCCESS(NtLoadDllMemoryExW(&m1, nullptr, 0, buffer, size, L"kernel64", nullptr))) goto end; //if (!NT_SUCCESS(NtLoadDllMemoryExW(&_m1, nullptr, 0, buffer, size, L"kernel64.dll", nullptr))) goto end; //if (!NT_SUCCESS(NtLoadDllMemoryExW(&m2, nullptr, 0, buffer, size, L"kernel128.dll", L"\\?\\kernel512.dll"))) goto end; - char t[100]; - LoadStringA((HINSTANCE)m1, 101, t, 100); - printf("%s\n", t); + //Load string using FindResource + hModule = (HMODULE)m1; + if (!(res = FindResourceW(hModule, MAKEINTRESOURCEW((101 >> 4) + 1), MAKEINTRESOURCEW(6))))goto end; + if (!(hRes = LoadResource(hModule, res)))goto end; + if (!(t = (PWSTR)LockResource(hRes)))goto end; + tableSize = SizeofResource(hModule, res); + while (offset < tableSize) { + if (index == 101 % 0x10) { + if (t[offset] != 0x0000) { + str = &t[offset + 1]; + wprintf(L"Size = %d, String = %s\n", t[offset], str); + } + break; + } + offset += t[offset] + 1; + index++; + } hModule = GetModuleHandleA("kernel64.dll"); GetModuleFileNameA(hModule, name, MAX_PATH);