diff --git a/MemoryModule/LoadDllMemoryApi.h b/MemoryModule/LoadDllMemoryApi.h
index 9987f57..f31a078 100644
--- a/MemoryModule/LoadDllMemoryApi.h
+++ b/MemoryModule/LoadDllMemoryApi.h
@@ -52,6 +52,7 @@ int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
*/
int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
+
NTSTATUS NTAPI NtLoadDllMemory(
OUT HMEMORYMODULE* BaseAddress,
IN LPVOID BufferAddress,
@@ -59,7 +60,7 @@ NTSTATUS NTAPI NtLoadDllMemory(
);
/*
- NtLoadDllMemoryEx dwFlags
+ NtLoadDllMemoryEx dwFlags
*/
//If this flag is specified, all subsequent flags will be ignored.
@@ -77,12 +78,15 @@ NTSTATUS NTAPI NtLoadDllMemory(
//If this flag is specified, DllName and DllFullName cannot be nullptr,
// they can be arbitrary strings without having to be correct file names and paths.
//Otherwise, DllName and DllFullName will use random names if they are nullptr.
-//For compatibility with GetModuleHandle, DllName and DllFullName should be guaranteed to always end in .dll
+//For compatibility with GetModuleHandle, DllName and DllFullName should be guaranteed to always end in ".dll"
#define LOAD_FLAGS_USE_DLL_NAME 0x00000004
+//Dont call LdrpHandleTlsData routine if this flag is specified.
+#define LOAD_FLAGS_NOT_HANDLE_TLS 0x00000008
+
NTSTATUS NTAPI NtLoadDllMemoryExW(
OUT HMEMORYMODULE* BaseAddress,
- OUT PLDR_DATA_TABLE_ENTRY* LdrEntry OPTIONAL,
+ OUT PVOID* LdrEntry OPTIONAL,
IN DWORD dwFlags,
IN LPVOID BufferAddress,
IN size_t BufferSize,
@@ -91,7 +95,7 @@ NTSTATUS NTAPI NtLoadDllMemoryExW(
);
NTSTATUS NTAPI NtLoadDllMemoryExA(
OUT HMEMORYMODULE* BaseAddress,
- OUT PLDR_DATA_TABLE_ENTRY* LdrEntry OPTIONAL,
+ OUT PVOID* LdrEntry OPTIONAL,
IN DWORD dwFlags,
IN LPVOID BufferAddress,
IN size_t BufferSize,
diff --git a/MemoryModule/MemoryModule.vcxproj b/MemoryModule/MemoryModule.vcxproj
index 50fcccf..4882657 100644
--- a/MemoryModule/MemoryModule.vcxproj
+++ b/MemoryModule/MemoryModule.vcxproj
@@ -30,6 +30,9 @@
+
+
+
16.0
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}
diff --git a/MemoryModule/MemoryModule.vcxproj.filters b/MemoryModule/MemoryModule.vcxproj.filters
index e397dd5..52ad386 100644
--- a/MemoryModule/MemoryModule.vcxproj.filters
+++ b/MemoryModule/MemoryModule.vcxproj.filters
@@ -42,4 +42,9 @@
Header Files
+
+
+ Resource Files
+
+
\ No newline at end of file
diff --git a/MemoryModule/NativeFunctionsInternal.cpp b/MemoryModule/NativeFunctionsInternal.cpp
index 557890e..d9af99d 100644
--- a/MemoryModule/NativeFunctionsInternal.cpp
+++ b/MemoryModule/NativeFunctionsInternal.cpp
@@ -274,15 +274,15 @@ static NTSTATUS NTAPI NtRemoveModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTR
static bool NTAPI NtInitializeLdrDataTableEntry(
OUT PLDR_DATA_TABLE_ENTRY LdrEntry,
+ IN DWORD dwFlags,
IN PVOID BaseAddress,
- IN ULONG SizeofImage,
- IN DWORD TimeDateStamp,
IN UNICODE_STRING &DllBaseName,
- IN UNICODE_STRING &DllFullName,
- IN PVOID EntryPoint) {
-
+ IN UNICODE_STRING &DllFullName) {
+ UNREFERENCED_PARAMETER(dwFlags);
RtlZeroMemory(LdrEntry, NtLdrDataTableEntrySize());
PIMAGE_NT_HEADERS headers = RtlImageNtHeader(BaseAddress);
+ if (!headers)return false;
+ bool FlagsProcessed = false;
switch (NtWindowsVersion()) {
case win10:
@@ -300,11 +300,16 @@ static bool NTAPI NtInitializeLdrDataTableEntry(
entry->LoadReason = LoadReasonDynamicLoad;
if (!NT_SUCCESS(NtInsertModuleBaseAddressIndexNode(LdrEntry, BaseAddress)))return false;
if (!(entry->DdagNode = (decltype(entry->DdagNode))NtAllocateLdrpHeap(sizeof(_LDR_DDAG_NODE))))return false;
- NtInitializeListEntry(&entry->NodeModuleLink);
- NtInitializeListEntry(&entry->DdagNode->Modules);
- NtInitializeSingleEntry(&entry->DdagNode->CondenseLink);
+ //NtInitializeListEntry(&entry->NodeModuleLink);
+ //NtInitializeListEntry(&entry->DdagNode->Modules);
+ entry->NodeModuleLink.Flink = &entry->DdagNode->Modules;
+ entry->NodeModuleLink.Blink = &entry->DdagNode->Modules;
+ entry->DdagNode->Modules.Flink = &entry->NodeModuleLink;
+ entry->DdagNode->Modules.Blink = &entry->NodeModuleLink;
entry->DdagNode->State = LdrModulesReadyToRun;
entry->DdagNode->LoadCount = 0;
+
+ NtInitializeSingleEntry(&entry->DdagNode->CondenseLink);
}
case win7: {
@@ -325,12 +330,13 @@ static bool NTAPI NtInitializeLdrDataTableEntry(
}
case xp: {
LdrEntry->DllBase = BaseAddress;
- LdrEntry->SizeOfImage = SizeofImage;
- LdrEntry->TimeDateStamp = TimeDateStamp;
+ LdrEntry->SizeOfImage = headers->OptionalHeader.SizeOfImage;
+ LdrEntry->TimeDateStamp = headers->FileHeader.TimeDateStamp;
LdrEntry->BaseDllName = DllBaseName;
LdrEntry->FullDllName = DllFullName;
- LdrEntry->EntryPoint = EntryPoint;
- if (headers->OptionalHeader.DllCharacteristics & IMAGE_FILE_DLL)LdrEntry->Flags |= LDRP_IMAGE_DLL;
+ LdrEntry->EntryPoint = (PVOID)((size_t)BaseAddress + headers->OptionalHeader.AddressOfEntryPoint);
+ if (!FlagsProcessed) LdrEntry->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_INSERTED | LDRP_ENTRY_PROCESSED | LDRP_PROCESS_ATTACH_CALLED;
+ NtInitializeListEntry(&LdrEntry->HashLinks);
return true;
}
default:return false;
@@ -355,6 +361,7 @@ static bool NTAPI NtFreeLdrDataTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
NtFreeLdrpHeap(LdrEntry->FullDllName.Buffer);
RemoveEntryList(&LdrEntry->InLoadOrderLinks);
RemoveEntryList(&LdrEntry->InMemoryOrderLinks);
+ RemoveEntryList(&LdrEntry->InInitializationOrderLinks);
RemoveEntryList(&LdrEntry->HashLinks);
NtFreeLdrpHeap(LdrEntry);
return true;
@@ -508,9 +515,10 @@ static VOID NTAPI NtInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) {
/* Insert into other lists */
InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks);
InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderLinks);
+ InsertTailList(&PebData->InInitializationOrderModuleList, &LdrEntry->InInitializationOrderLinks);
}
-static NTSTATUS NTAPI NtMapDllMemory(IN HMEMORYMODULE ViewBase, IN PCWSTR DllName OPTIONAL,
+static NTSTATUS NTAPI NtMapDllMemory(IN HMEMORYMODULE ViewBase, IN DWORD dwFlags, IN PCWSTR DllName OPTIONAL,
IN PCWSTR lpFullDllName OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY* DataTableEntry OPTIONAL) {
UNICODE_STRING FullDllName, BaseDllName;
@@ -526,11 +534,7 @@ static NTSTATUS NTAPI NtMapDllMemory(IN HMEMORYMODULE ViewBase, IN PCWSTR DllNam
return STATUS_NO_MEMORY;
}
- if (!NtInitializeLdrDataTableEntry(LdrEntry, ViewBase,
- NtHeaders->OptionalHeader.SizeOfImage,
- NtHeaders->FileHeader.TimeDateStamp,
- BaseDllName, FullDllName,
- (PVOID)(NtHeaders->OptionalHeader.AddressOfEntryPoint + NtHeaders->OptionalHeader.ImageBase))) {
+ if (!NtInitializeLdrDataTableEntry(LdrEntry, dwFlags, ViewBase, BaseDllName, FullDllName)) {
NtFreeLdrpHeap(LdrEntry);
NtFreeLdrpHeap(BaseDllName.Buffer);
NtFreeLdrpHeap(FullDllName.Buffer);
@@ -548,16 +552,25 @@ NTSTATUS NTAPI NtLoadDllMemory(OUT HMEMORYMODULE* BaseAddress, IN LPVOID BufferA
NTSTATUS NTAPI NtLoadDllMemoryExW(
OUT HMEMORYMODULE* BaseAddress,
- OUT PLDR_DATA_TABLE_ENTRY* LdrEntry OPTIONAL,
+ OUT PVOID* LdrEntry OPTIONAL,
IN DWORD dwFlags,
IN LPVOID BufferAddress,
IN size_t BufferSize,
IN LPCWSTR DllName OPTIONAL,
IN LPCWSTR DllFullName OPTIONAL) {
- if (IsBadReadPtr(BufferAddress, BufferSize) || IsBadWritePtr(BaseAddress, sizeof(HMEMORYMODULE)))return STATUS_ACCESS_VIOLATION;
- *BaseAddress = nullptr;
PMEMORYMODULE module = nullptr;
NTSTATUS status = STATUS_SUCCESS;
+ PLDR_DATA_TABLE_ENTRY ModuleEntry = nullptr;
+
+ __try {
+ if (IsBadReadPtr(BufferAddress, BufferSize))status = STATUS_ACCESS_VIOLATION;
+ *BaseAddress = nullptr;
+ if (LdrEntry)*LdrEntry = nullptr;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ status = GetExceptionCode();
+ }
+ if (!NT_SUCCESS(status))return status;
if (dwFlags & LOAD_FLAGS_NOT_MAP_DLL) {
dwFlags &= LOAD_FLAGS_NOT_MAP_DLL;
@@ -612,28 +625,44 @@ NTSTATUS NTAPI NtLoadDllMemoryExW(
}
module->loadFromNtLoadDllMemory = true;
if (dwFlags & LOAD_FLAGS_NOT_MAP_DLL) return STATUS_SUCCESS;
- status = NtMapDllMemory(*BaseAddress, DllName, DllFullName, LdrEntry);
+
+ status = NtMapDllMemory(*BaseAddress, dwFlags, DllName, DllFullName, &ModuleEntry);
if (!NT_SUCCESS(status)) {
NtUnloadDllMemory(*BaseAddress);
*BaseAddress = nullptr;
return status;
}
module->MappedDll = true;
+
+ if (LdrEntry)*LdrEntry = ModuleEntry;
+
if (!(dwFlags & LOAD_FLAGS_NOT_USE_REFERENCE_COUNT))module->UseReferenceCount = true;
+
if (dwFlags & LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION)return STATUS_SUCCESS;
status = RtlInsertInvertedFunctionTable((PVOID)module->codeBase, RtlImageNtHeader(*BaseAddress)->OptionalHeader.SizeOfImage);
if (!NT_SUCCESS(status)) {
NtUnloadDllMemory(*BaseAddress);
*BaseAddress = nullptr;
+ if (LdrEntry)*LdrEntry = nullptr;
return status;
}
module->InsertInvertedFunctionTableEntry = true;
+
+ if (dwFlags & LOAD_FLAGS_NOT_HANDLE_TLS)return STATUS_SUCCESS;
+ status = LdrpHandleTlsData(ModuleEntry);
+ if (!NT_SUCCESS(status)) {
+ NtUnloadDllMemory(*BaseAddress);
+ *BaseAddress = nullptr;
+ if (LdrEntry)*LdrEntry = nullptr;
+ return status;
+ }
+
return STATUS_SUCCESS;
}
NTSTATUS NtLoadDllMemoryExA(
OUT HMEMORYMODULE* BaseAddress,
- OUT PLDR_DATA_TABLE_ENTRY* LdrEntry OPTIONAL,
+ OUT PVOID* LdrEntry OPTIONAL,
IN DWORD dwFlags,
IN LPVOID BufferAddress,
IN size_t BufferSize,
@@ -907,7 +936,7 @@ static NTSTATUS NTAPI RtlProtectMrdata(IN SIZE_T Protect) {
NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t ImageSize) {
static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable());
if (!table)return STATUS_NOT_SUPPORTED;
- bool need_virtual_protect = RtlIsWindowsVersionOrGreater(10, 0, 0);
+ bool need_virtual_protect = RtlIsWindowsVersionOrGreater(8, 3, 0);
NTSTATUS status;
if (need_virtual_protect) {
@@ -940,3 +969,144 @@ NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase) {
return STATUS_SUCCESS;
}
+
+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);
+
+ 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
+ //RS6(19H1)
+ 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.Default = LdrpHandleTlsDataXp;
+ stdcall = true;
+ return LdrpHandleTlsDataXp(LdrEntry);
+ }
+ }
+
+ HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
+ PIMAGE_NT_HEADERS headers = RtlImageNtHeader(ntdll);
+ if (!Feature || !headers)return STATUS_NOT_SUPPORTED;
+ 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;
+ }
+ }
+ if (!_LdrpHandleTlsData)return STATUS_NOT_SUPPORTED;
+ stdcall = !RtlIsWindowsVersionOrGreater(6, 3, 0);
+ return stdcall ? _LdrpHandleTlsData.Default(LdrEntry) : _LdrpHandleTlsData.Win8_1_OrGreater(LdrEntry);
+}
diff --git a/MemoryModule/NativeFunctionsInternal.h b/MemoryModule/NativeFunctionsInternal.h
index 672a3ce..ef1ce73 100644
--- a/MemoryModule/NativeFunctionsInternal.h
+++ b/MemoryModule/NativeFunctionsInternal.h
@@ -393,6 +393,7 @@ NTSTATUS NTAPI NtLoadDllMemory(
/*
NtLoadDllMemoryEx dwFlags
*/
+
//If this flag is specified, all subsequent flags will be ignored.
//Also, will be incompatible with Win32 API.
#define LOAD_FLAGS_NOT_MAP_DLL 0x10000000
@@ -408,13 +409,16 @@ NTSTATUS NTAPI NtLoadDllMemory(
//If this flag is specified, DllName and DllFullName cannot be nullptr,
// they can be arbitrary strings without having to be correct file names and paths.
//Otherwise, DllName and DllFullName will use random names if they are nullptr.
-//For compatibility with GetModuleHandle, DllName and DllFullName should be guaranteed to always end in .dll
+//For compatibility with GetModuleHandle, DllName and DllFullName should be guaranteed to always end in ".dll"
#define LOAD_FLAGS_USE_DLL_NAME 0x00000004
+//Dont call LdrpHandleTlsData routine if this flag is specified.
+#define LOAD_FLAGS_NOT_HANDLE_TLS 0x00000008
+
NTSTATUS NTAPI NtLoadDllMemoryExW(
OUT HMEMORYMODULE* BaseAddress,
- OUT PLDR_DATA_TABLE_ENTRY* LdrEntry OPTIONAL,
+ OUT PVOID* LdrEntry OPTIONAL,
IN DWORD dwFlags,
IN LPVOID BufferAddress,
IN size_t BufferSize,
@@ -449,3 +453,4 @@ typedef struct _RTL_INVERTED_FUNCTION_TABLE {
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);
diff --git a/README.md b/README.md
index 4e56457..adec574 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,11 @@ 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
+
# Features
- Compatible with Win32 API (GetModuleHandleA/W/Ex GetModuleFileNameA/W/Ex GetProcAddress)
- Support for C ++ exceptions and SEH
diff --git a/test/Header.h b/test/Header.h
index 3843ac1..c1f17d6 100644
--- a/test/Header.h
+++ b/test/Header.h
@@ -1,35 +1,538 @@
-struct FuncInfoHeader
-{
- union
- {
- struct
- {
- uint8_t isCatch : 1; // 1 if this represents a catch funclet, 0 otherwise
- uint8_t isSeparated : 1; // 1 if this function has separated code segments, 0 otherwise
- uint8_t BBT : 1; // Flags set by Basic Block Transformations
- uint8_t UnwindMap : 1; // Existence of Unwind Map RVA
- uint8_t TryBlockMap : 1; // Existence of Try Block Map RVA
- uint8_t EHs : 1; // EHs flag set
- uint8_t NoExcept : 1; // NoExcept flag set
- uint8_t reserved : 1;
- };
- uint8_t value;
- };
-};
-struct FuncInfo4
-{
- FuncInfoHeader header;
- uint32_t bbtFlags; // flags that may be set by BBT processing
+#include
+#include "../MemoryModule/NativeFunctionsInternal.h"
- int32_t dispUnwindMap; // Image relative offset of the unwind map
- int32_t dispTryBlockMap; // Image relative offset of the handler map
- int32_t dispIPtoStateMap; // Image relative offset of the IP to state map
- uint32_t dispFrame; // displacement of address of function frame wrt establisher frame, only used for catch funclets
+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 "../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;
-};
-struct EHRegistrationNode {
- /* void * stackPtr */ // Stack ptr at entry to try (below address point)
- EHRegistrationNode* pNext; // Next node in the chain
- void* frameHandler; // The handler function for this frame
- int state; // The current state of this function
-};
diff --git a/test/test.cpp b/test/test.cpp
index 7b20cf7..c31a728 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -1,10 +1,16 @@
#include "../MemoryModule/NativeFunctionsInternal.h"
+//#include "../MemoryModule/LoadDllMemoryApi.h"
+#ifndef NT_SUCCESS
+#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+#endif
#include
+#pragma warning(disable:4996)
int main() {
+ //GetProcAddress(LoadLibraryA("a.dll"), "thread")();
LPVOID buffer;
size_t size;
- FILE* f = fopen("d.dll", "rb");
+ FILE* f = fopen("a.dll", "rb");
if (!f)return 0;
_fseeki64(f, 0, SEEK_END);
if (!(size = _ftelli64(f))) {
@@ -23,37 +29,105 @@ int main() {
_exception exception = nullptr;
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;
+ //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);
hModule = GetModuleHandleA("kernel64.dll");
GetModuleFileNameA(hModule, name, MAX_PATH);
- if (hModule)test = GetProcAddress(hModule, "test");
+ if (hModule)test = GetProcAddress(hModule, "thread");
printf("m1:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", m1, hModule, name, test);
- if (test)test();
+ if (test) test();
- GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)test, &hModule);
- GetModuleFileNameA(hModule, name, MAX_PATH);
- test = GetProcAddress(hModule, "test");
- printf("_m1:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", _m1, hModule, name, test);
- if (test)test();
+ //GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)test, &hModule);
+ //GetModuleFileNameA(hModule, name, MAX_PATH);
+ //test = GetProcAddress(hModule, "test");
+ //printf("_m1:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", _m1, hModule, name, test);
+ //if (test)test();
- hModule = GetModuleHandleA("kernel128");
- GetModuleFileNameA(hModule, name, MAX_PATH);
- if (hModule)exception = (_exception)GetProcAddress(hModule, "exception");
- printf("m2:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", m2, hModule, name, test);
- if (exception) {
- exception(0);
- exception(1);
- exception(2);
- exception(3);
- }
+ //hModule = GetModuleHandleA("kernel128");
+ //GetModuleFileNameA(hModule, name, MAX_PATH);
+ //if (hModule)exception = (_exception)GetProcAddress(hModule, "exception");
+ //printf("m2:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", m2, hModule, name, test);
+ //if (exception) {
+ // exception(0);
+ // exception(1);
+ // exception(2);
+ // exception(3);
+ //}
end:
delete[]buffer;
if (m1)NtUnloadDllMemory(m1);
- if (_m1)NtUnloadDllMemory(_m1);
- if (m2)NtUnloadDllMemory(m2);
+ //if (_m1)NtUnloadDllMemory(_m1);
+ //if (m2)NtUnloadDllMemory(m2);
return 0;
}
+
+//#include
+//#include "../MemoryModule/NativeFunctionsInternal.h"
+//
+//bool c;
+//static thread_local int x = -1;
+//
+//DWORD WINAPI Thread(PVOID) {
+// printf("[1] x = %d\n", x);
+// x = 0;
+// c = true;
+// while (c)Sleep(100);
+// return x;
+//}
+//
+//int main() {
+// x = 1;
+// c = false;
+// HANDLE hThread = CreateThread(nullptr, 0, Thread, nullptr, 0, nullptr);
+// DWORD ex = 0;
+// if (hThread) {
+// while (!c)Sleep(100);
+// printf("[0] x = %d\n", x);
+// c = false;
+// WaitForSingleObject(hThread, 0xffffffff);
+// GetExitCodeThread(hThread, &ex);
+// CloseHandle(hThread);
+// printf("[0] Exit = %d\n", ex);
+// }
+//
+// PLIST_ENTRY entry = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+// PLDR_DATA_TABLE_ENTRY_WIN7 data = nullptr;
+//
+// while (entry != entry->Flink) {
+// entry = entry->Flink;
+// data = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY_WIN7, InLoadOrderLinks);
+// }
+//
+// return 0;
+//}
+
+//#include "../MemoryModule/Native.h"
+//#include
+//
+//static thread_local int x = 0xffccffdd;
+//
+//DWORD WINAPI Thread(PVOID) {
+// printf("[1] ThreadLocalStoragePointer = %p\n", NtCurrentTeb()->ThreadLocalStoragePointer);
+// return x == 0xffccffdd ? 0 : 1;
+//}
+//
+//int main() {
+// x = 2;
+// printf("[0] ThreadLocalStoragePointer = %p\n", NtCurrentTeb()->ThreadLocalStoragePointer);
+// HANDLE hThread = CreateThread(nullptr, 0, Thread, nullptr, 0, nullptr);
+// DWORD ret = -1;
+// if (hThread) {
+// WaitForSingleObject(hThread, 0xffffffff);
+// GetExitCodeThread(hThread, &ret);
+// CloseHandle(hThread);
+// return ret;
+// }
+// return -1;
+//}