mirror of
https://github.com/bb107/MemoryModulePP
synced 2026-06-08 13:15:33 +00:00
add MmpTls.cpp
This commit is contained in:
@@ -19,8 +19,19 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\3rdparty\Detours\creatwth.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\detours.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\disasm.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\disolarm.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\disolarm64.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\disolia64.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\disolx64.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\disolx86.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\image.cpp" />
|
||||
<ClCompile Include="..\3rdparty\Detours\modules.cpp" />
|
||||
<ClCompile Include="LoadDllMemoryApi.cpp" />
|
||||
<ClCompile Include="MemoryModule.cpp" />
|
||||
<ClCompile Include="MmpTls.cpp" />
|
||||
<ClCompile Include="Native.cpp" />
|
||||
<ClCompile Include="NativeFunctionsInternal.cpp" />
|
||||
<ClCompile Include="rtlinv.cpp" />
|
||||
@@ -30,6 +41,8 @@
|
||||
<ClCompile Include="rtlver.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\3rdparty\Detours\detours.h" />
|
||||
<ClInclude Include="..\3rdparty\Detours\detver.h" />
|
||||
<ClInclude Include="LoadDllMemoryApi.h" />
|
||||
<ClInclude Include="MemoryModule.h" />
|
||||
<ClInclude Include="Native.h" />
|
||||
@@ -101,15 +114,19 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
||||
@@ -13,6 +13,18 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\3rdparty">
|
||||
<UniqueIdentifier>{8baeecde-ca9b-43da-b847-c24b02413572}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\3rdparty\Detours">
|
||||
<UniqueIdentifier>{21335c89-8359-427a-a6c6-d621b31be2ce}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\3rdparty">
|
||||
<UniqueIdentifier>{22e60119-4e33-49c4-81c4-b95ea98501e3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\3rdparty\Detours">
|
||||
<UniqueIdentifier>{10bf9b0e-09d4-473b-a4bb-d7c4cecc65b4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MemoryModule.cpp">
|
||||
@@ -42,6 +54,39 @@
|
||||
<ClCompile Include="rtlsearch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MmpTls.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\creatwth.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\detours.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\disasm.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\disolarm.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\disolarm64.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\disolia64.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\disolx64.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\disolx86.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\image.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\3rdparty\Detours\modules.cpp">
|
||||
<Filter>Source Files\3rdparty\Detours</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MemoryModule.h">
|
||||
@@ -74,6 +119,12 @@
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\3rdparty\Detours\detours.h">
|
||||
<Filter>Header Files\3rdparty\Detours</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\3rdparty\Detours\detver.h">
|
||||
<Filter>Header Files\3rdparty\Detours</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md">
|
||||
|
||||
@@ -0,0 +1,868 @@
|
||||
#include "stdafx.h"
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <3rdparty/Detours/detours.h>
|
||||
|
||||
//
|
||||
// ThreadLocalStoragePointer Tls indexs
|
||||
// [0, MMP_START_TLS_INDEX) Reserved for ntdll loader
|
||||
// [MMP_START_TLS_INDEX, MMP_MAXIMUM_TLS_INDEX) Reserved for MemoryModule
|
||||
//
|
||||
|
||||
#define MMP_START_TLS_INDEX 0x50
|
||||
|
||||
#define MMP_MAXIMUM_TLS_INDEX 0x100
|
||||
|
||||
#define MmpAllocateTlsp() (RtlAllocateHeap(\
|
||||
RtlProcessHeap(),\
|
||||
HEAP_ZERO_MEMORY,\
|
||||
sizeof(PVOID)* MMP_MAXIMUM_TLS_INDEX\
|
||||
))
|
||||
|
||||
typedef struct _TLS_VECTOR {
|
||||
union
|
||||
{
|
||||
ULONG Length;
|
||||
HANDLE ThreadId;
|
||||
};
|
||||
|
||||
struct _TLS_VECTOR* PreviousDeferredTlsVector;
|
||||
PVOID ModuleTlsData[ANYSIZE_ARRAY];
|
||||
} TLS_VECTOR, * PTLS_VECTOR;
|
||||
|
||||
typedef struct _TLS_ENTRY {
|
||||
LIST_ENTRY TlsEntryLinks;
|
||||
IMAGE_TLS_DIRECTORY TlsDirectory;
|
||||
PLDR_DATA_TABLE_ENTRY ModuleEntry;
|
||||
} TLS_ENTRY, * PTLS_ENTRY;
|
||||
|
||||
LIST_ENTRY MmpTlsList;
|
||||
RTL_BITMAP MmpTlsBitmap;
|
||||
SRWLOCK MmpTlsListLock;
|
||||
|
||||
|
||||
typedef struct _MMP_TLSP_RECORD {
|
||||
|
||||
LIST_ENTRY InMmpThreadLocalStoragePointer;
|
||||
|
||||
HANDLE UniqueThread;
|
||||
|
||||
// PEB->ThreadLocalStoragePointer allocated by ntdll!Ldr
|
||||
PVOID* TlspLdrBlock;
|
||||
|
||||
// PEB->ThreadLocalStoragePointer allocated by MemoryModulePP
|
||||
PVOID* TlspMmpBlock;
|
||||
}MMP_TLSP_RECORD, * PMMP_TLSP_RECORD;
|
||||
|
||||
CRITICAL_SECTION MmpTlspLock;
|
||||
LIST_ENTRY MmpThreadLocalStoragePointer;
|
||||
|
||||
|
||||
decltype(&NtCreateThread) OriginNtCreateThread = NtCreateThread;
|
||||
decltype(&NtCreateThreadEx) OriginNtCreateThreadEx = NtCreateThreadEx;
|
||||
decltype(&NtSetInformationProcess) OriginNtSetInformationProcess = NtSetInformationProcess;
|
||||
decltype(&LdrShutdownThread) OriginLdrShutdownThread = LdrShutdownThread;
|
||||
|
||||
|
||||
typedef struct _THREAD_TLS_INFORMATION {
|
||||
ULONG Flags;
|
||||
|
||||
union {
|
||||
PVOID* TlsVector;
|
||||
PVOID TlsModulePointer;
|
||||
};
|
||||
|
||||
HANDLE ThreadId;
|
||||
} THREAD_TLS_INFORMATION, * PTHREAD_TLS_INFORMATION;
|
||||
|
||||
typedef struct _PROCESS_TLS_INFORMATION {
|
||||
ULONG Reserved;
|
||||
PROCESS_TLS_INFORMATION_TYPE OperationType;
|
||||
ULONG ThreadDataCount;
|
||||
|
||||
union {
|
||||
ULONG TlsIndex;
|
||||
ULONG TlsVectorLength;
|
||||
};
|
||||
|
||||
THREAD_TLS_INFORMATION ThreadData[ANYSIZE_ARRAY];
|
||||
} PROCESS_TLS_INFORMATION, * PPROCESS_TLS_INFORMATION;
|
||||
|
||||
typedef struct _THREAD_CONTEXT {
|
||||
PTHREAD_START_ROUTINE ThreadStartRoutine;
|
||||
LPVOID ThreadParameter;
|
||||
}THREAD_CONTEXT, * PTHREAD_CONTEXT;
|
||||
|
||||
PVOID NTAPI MmpQuerySystemInformation(
|
||||
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
||||
_Out_opt_ LPDWORD ReturnLength) {
|
||||
|
||||
if (ReturnLength)*ReturnLength = 0;
|
||||
|
||||
NTSTATUS status;
|
||||
PVOID buffer = nullptr;
|
||||
ULONG len = 0;
|
||||
|
||||
|
||||
do {
|
||||
|
||||
RtlFreeHeap(
|
||||
RtlProcessHeap(),
|
||||
0,
|
||||
buffer
|
||||
);
|
||||
buffer = nullptr;
|
||||
|
||||
if (len) {
|
||||
len *= 2;
|
||||
buffer = RtlAllocateHeap(
|
||||
RtlProcessHeap(),
|
||||
0,
|
||||
len
|
||||
);
|
||||
if (!buffer)return nullptr;
|
||||
}
|
||||
|
||||
status = NtQuerySystemInformation(
|
||||
SystemInformationClass,
|
||||
buffer,
|
||||
len,
|
||||
&len
|
||||
);
|
||||
if (NT_SUCCESS(status))break;
|
||||
} while (status == STATUS_INFO_LENGTH_MISMATCH);
|
||||
|
||||
if (ReturnLength)*ReturnLength = len;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PSYSTEM_PROCESS_INFORMATION NTAPI MmpGetProcessInformation() {
|
||||
auto pid = NtCurrentProcessId();
|
||||
|
||||
auto spi = PSYSTEM_PROCESS_INFORMATION(MmpQuerySystemInformation(SystemProcessInformation, nullptr));
|
||||
PSYSTEM_PROCESS_INFORMATION result = nullptr;
|
||||
if (spi) {
|
||||
auto p = spi;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (p->UniqueProcessId == pid) {
|
||||
result = PSYSTEM_PROCESS_INFORMATION(RtlAllocateHeap(RtlProcessHeap(), 0, p->NextEntryOffset));
|
||||
if (!result)break;
|
||||
|
||||
RtlCopyMemory(
|
||||
result,
|
||||
p,
|
||||
p->NextEntryOffset
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!p->NextEntryOffset)break;
|
||||
p = PSYSTEM_PROCESS_INFORMATION(LPSTR(p) + p->NextEntryOffset);
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, spi);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DWORD NTAPI MmpGetThreadCount() {
|
||||
DWORD result = 0;
|
||||
auto p = MmpGetProcessInformation();
|
||||
|
||||
if (p) {
|
||||
result = p->NumberOfThreads;
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, p);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DWORD NTAPI MmpUserThreadStart(LPVOID lpThreadParameter) {
|
||||
|
||||
THREAD_CONTEXT Context;
|
||||
bool success = false;
|
||||
|
||||
__try {
|
||||
RtlCopyMemory(
|
||||
&Context,
|
||||
lpThreadParameter,
|
||||
sizeof(Context)
|
||||
);
|
||||
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, lpThreadParameter);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Allocate and replace ThreadLocalStoragePointer for new thread
|
||||
//
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
|
||||
auto record = PMMP_TLSP_RECORD(RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(MMP_TLSP_RECORD)));
|
||||
if (record) {
|
||||
record->TlspLdrBlock = (PVOID*)NtCurrentTeb()->ThreadLocalStoragePointer;
|
||||
record->TlspMmpBlock = (PVOID*)MmpAllocateTlsp();
|
||||
record->UniqueThread = NtCurrentThreadId();
|
||||
if (record->TlspMmpBlock) {
|
||||
|
||||
auto size = CONTAINING_RECORD(record->TlspLdrBlock, TLS_VECTOR, ModuleTlsData)->Length;
|
||||
RtlCopyMemory(
|
||||
record->TlspMmpBlock,
|
||||
record->TlspLdrBlock,
|
||||
size
|
||||
);
|
||||
|
||||
NtCurrentTeb()->ThreadLocalStoragePointer = record->TlspMmpBlock;
|
||||
|
||||
InsertTailList(&MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer);
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, record);
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
|
||||
//
|
||||
// Handle MemoryModule Tls data
|
||||
//
|
||||
if (success) {
|
||||
RtlAcquireSRWLockShared(&MmpTlsListLock);
|
||||
|
||||
auto ThreadLocalStoragePointer = (PVOID*)NtCurrentTeb()->ThreadLocalStoragePointer;
|
||||
PLIST_ENTRY entry = MmpTlsList.Flink;
|
||||
while (entry != &MmpTlsList) {
|
||||
|
||||
PTLS_ENTRY tls = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks);
|
||||
auto len = tls->TlsDirectory.EndAddressOfRawData - tls->TlsDirectory.StartAddressOfRawData;
|
||||
PVOID data = RtlAllocateHeap(RtlProcessHeap(), 0, len);
|
||||
if (!len) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(
|
||||
data,
|
||||
PVOID(tls->TlsDirectory.StartAddressOfRawData),
|
||||
len
|
||||
);
|
||||
|
||||
|
||||
ThreadLocalStoragePointer[tls->TlsDirectory.Characteristics] = data;
|
||||
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
RtlReleaseSRWLockShared(&MmpTlsListLock);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
return Context.ThreadStartRoutine(Context.ThreadParameter);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookNtCreateThread(
|
||||
_Out_ PHANDLE ThreadHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PCLIENT_ID ClientId,
|
||||
_In_ PCONTEXT ThreadContext,
|
||||
_In_ PINITIAL_TEB InitialTeb,
|
||||
_In_ BOOLEAN CreateSuspended) {
|
||||
CONTEXT Context = *ThreadContext;
|
||||
PTHREAD_CONTEXT _Context = PTHREAD_CONTEXT(RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(_Context)));
|
||||
NTSTATUS status;
|
||||
|
||||
if (!_Context)return STATUS_NO_MEMORY;
|
||||
|
||||
#ifndef _WIN64
|
||||
_Context->ThreadStartRoutine = PTHREAD_START_ROUTINE(Context.Eax);
|
||||
_Context->ThreadParameter = LPVOID(Context.Ebx);
|
||||
|
||||
Context.Eax = DWORD(MmpUserThreadStart);
|
||||
Context.Ebx = DWORD(_Context);
|
||||
|
||||
#else
|
||||
_Context->ThreadStartRoutine = PTHREAD_START_ROUTINE(Context.Rcx);
|
||||
_Context->ThreadParameter = LPVOID(Context.Rdx);
|
||||
|
||||
Context.Rcx = ULONG64(MmpUserThreadStart);
|
||||
Context.Rdx = ULONG64(_Context);
|
||||
#endif
|
||||
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
|
||||
status = OriginNtCreateThread(
|
||||
ThreadHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
ProcessHandle,
|
||||
ClientId,
|
||||
&Context,
|
||||
InitialTeb,
|
||||
CreateSuspended
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, _Context);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookNtCreateThreadEx(
|
||||
_Out_ PHANDLE ThreadHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PVOID StartRoutine,
|
||||
_In_opt_ PVOID Argument,
|
||||
_In_ ULONG CreateFlags,
|
||||
_In_ SIZE_T ZeroBits,
|
||||
_In_ SIZE_T StackSize,
|
||||
_In_ SIZE_T MaximumStackSize,
|
||||
_In_opt_ PVOID AttributeList) {
|
||||
PTHREAD_CONTEXT Context = PTHREAD_CONTEXT(RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(Context)));
|
||||
if (!Context) {
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Context->ThreadStartRoutine = PTHREAD_START_ROUTINE(StartRoutine);
|
||||
Context->ThreadParameter = Argument;
|
||||
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
|
||||
NTSTATUS status = OriginNtCreateThreadEx(
|
||||
ThreadHandle,
|
||||
DesiredAccess,
|
||||
ObjectAttributes,
|
||||
ProcessHandle,
|
||||
MmpUserThreadStart,
|
||||
Context,
|
||||
CreateFlags,
|
||||
ZeroBits,
|
||||
StackSize,
|
||||
MaximumStackSize,
|
||||
AttributeList
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, Context);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID NTAPI HookLdrShutdownThread(VOID) {
|
||||
|
||||
PLIST_ENTRY entry;
|
||||
PMMP_TLSP_RECORD record = nullptr;
|
||||
|
||||
//
|
||||
// Find our tlsp record
|
||||
//
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
|
||||
entry = MmpThreadLocalStoragePointer.Flink;
|
||||
while (entry != &MmpThreadLocalStoragePointer) {
|
||||
|
||||
auto p = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer);
|
||||
if (p->UniqueThread == NtCurrentThreadId()) {
|
||||
assert(p->TlspMmpBlock == NtCurrentTeb()->ThreadLocalStoragePointer);
|
||||
|
||||
//
|
||||
// Restore tlsp
|
||||
//
|
||||
NtCurrentTeb()->ThreadLocalStoragePointer = p->TlspLdrBlock;
|
||||
|
||||
RemoveEntryList(&p->InMmpThreadLocalStoragePointer);
|
||||
record = p;
|
||||
break;
|
||||
}
|
||||
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
|
||||
//
|
||||
// Free MemoryModule Tls data
|
||||
//
|
||||
RtlAcquireSRWLockExclusive(&MmpTlsListLock);
|
||||
|
||||
if (record) {
|
||||
auto TlspMmpBlock = (PVOID*)record->TlspMmpBlock;
|
||||
entry = MmpTlsList.Flink;
|
||||
while (entry != &MmpTlsList) {
|
||||
|
||||
auto p = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks);
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, TlspMmpBlock[p->TlsDirectory.Characteristics]);
|
||||
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, TlspMmpBlock);
|
||||
}
|
||||
else {
|
||||
if (MmpTlsList.Flink != &MmpTlsList) {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
RtlReleaseSRWLockExclusive(&MmpTlsListLock);
|
||||
|
||||
//
|
||||
// Call the original function
|
||||
//
|
||||
OriginLdrShutdownThread();
|
||||
}
|
||||
|
||||
BOOL NTAPI PreHookNtSetInformationProcess() {
|
||||
DWORD CurrentTlsPointerSize = CONTAINING_RECORD(NtCurrentTeb()->ThreadLocalStoragePointer, TLS_VECTOR, ModuleTlsData)->Length;
|
||||
DWORD CurrentThreadCount = MmpGetThreadCount();
|
||||
DWORD ProcessTlsInformationLength = sizeof(PROCESS_TLS_INFORMATION) + (CurrentThreadCount - 1) * sizeof(THREAD_TLS_INFORMATION);
|
||||
BOOL success = TRUE;
|
||||
NTSTATUS status;
|
||||
|
||||
auto ProcessTlsInformation = PPROCESS_TLS_INFORMATION(RtlAllocateHeap(
|
||||
RtlProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
ProcessTlsInformationLength * 2
|
||||
));
|
||||
if (ProcessTlsInformation) {
|
||||
|
||||
ProcessTlsInformation->OperationType = ProcessTlsReplaceVector;
|
||||
ProcessTlsInformation->Reserved = 0;
|
||||
ProcessTlsInformation->TlsVectorLength = CurrentTlsPointerSize;
|
||||
ProcessTlsInformation->ThreadDataCount = CurrentThreadCount;
|
||||
|
||||
for (DWORD i = 0; i < CurrentThreadCount; ++i) {
|
||||
auto& current = ProcessTlsInformation->ThreadData[i];
|
||||
current.TlsVector = (PVOID*)MmpAllocateTlsp();
|
||||
if (!current.TlsVector) {
|
||||
for (DWORD j = 0; j < i; ++j) {
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, ProcessTlsInformation->ThreadData[j].TlsVector);
|
||||
}
|
||||
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
auto tmpTlsInformation = PPROCESS_TLS_INFORMATION(LPBYTE(ProcessTlsInformation) + ProcessTlsInformationLength);
|
||||
RtlCopyMemory(
|
||||
tmpTlsInformation,
|
||||
ProcessTlsInformation,
|
||||
ProcessTlsInformationLength
|
||||
);
|
||||
|
||||
status = NtSetInformationProcess(
|
||||
NtCurrentProcess(),
|
||||
ProcessResourceManagement,
|
||||
ProcessTlsInformation,
|
||||
ProcessTlsInformationLength
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
for (DWORD i = 0; i < CurrentThreadCount; ++i) {
|
||||
auto const& LdrTls = ProcessTlsInformation->ThreadData[i];
|
||||
auto const& MmpTls = tmpTlsInformation->ThreadData[i];
|
||||
auto record = PMMP_TLSP_RECORD(RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(MMP_TLSP_RECORD)));
|
||||
assert(record);
|
||||
|
||||
record->TlspLdrBlock = LdrTls.TlsVector;
|
||||
record->TlspMmpBlock = MmpTls.TlsVector;
|
||||
record->UniqueThread = LdrTls.ThreadId;
|
||||
InsertTailList(&MmpThreadLocalStoragePointer, &record->InMmpThreadLocalStoragePointer);
|
||||
}
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, ProcessTlsInformation);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookNtSetInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PROCESSINFOCLASS ProcessInformationClass,
|
||||
_In_reads_bytes_(ProcessInformationLength) PVOID ProcessInformation,
|
||||
_In_ ULONG ProcessInformationLength) {
|
||||
|
||||
if (ProcessInformationClass != ProcessResourceManagement) {
|
||||
return OriginNtSetInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessInformationClass,
|
||||
ProcessInformation,
|
||||
ProcessInformationLength
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
auto ProcessTlsInformation = PPROCESS_TLS_INFORMATION(ProcessInformation);
|
||||
auto hProcess = ProcessHandle ? ProcessHandle : NtCurrentProcess();
|
||||
auto TlsLength = ProcessInformationLength;
|
||||
PPROCESS_TLS_INFORMATION Tls = nullptr;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
do {
|
||||
if (ProcessTlsInformation->OperationType >= MaxProcessTlsOperation) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate new buffer to change it
|
||||
//
|
||||
Tls = PPROCESS_TLS_INFORMATION(RtlAllocateHeap(RtlProcessHeap(), 0, ProcessInformationLength));
|
||||
if (Tls) {
|
||||
RtlCopyMemory(
|
||||
Tls,
|
||||
ProcessInformation,
|
||||
ProcessInformationLength
|
||||
);
|
||||
}
|
||||
else {
|
||||
status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert ReplaceVector to ReplaceIndex
|
||||
//
|
||||
if (ProcessTlsInformation->OperationType == ProcessTlsReplaceVector) {
|
||||
|
||||
// from MemoryModulePP
|
||||
if (!ProcessHandle) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
// reserved 0x50 PVOID for ntdll loader
|
||||
if (ProcessTlsInformation->TlsVectorLength >= MMP_START_TLS_INDEX) {
|
||||
status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
Tls->OperationType = ProcessTlsReplaceIndex;
|
||||
for (auto i = 0; i < Tls->ThreadDataCount; ++i) {
|
||||
Tls->ThreadData[i].TlsModulePointer = Tls->ThreadData[i].TlsVector[ProcessTlsInformation->TlsVectorLength];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ProcessHandle) {
|
||||
if (ProcessTlsInformation->TlsIndex >= MMP_START_TLS_INDEX) {
|
||||
status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ProcessTlsInformation->TlsIndex < MMP_START_TLS_INDEX || ProcessTlsInformation->TlsIndex >= MMP_MAXIMUM_TLS_INDEX) {
|
||||
status = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = OriginNtSetInformationProcess(
|
||||
hProcess,
|
||||
ProcessInformationClass,
|
||||
Tls,
|
||||
TlsLength
|
||||
);
|
||||
|
||||
//
|
||||
// Modify our mapping
|
||||
//
|
||||
EnterCriticalSection(&MmpTlspLock);
|
||||
for (auto i = 0; i < Tls->ThreadDataCount; ++i) {
|
||||
|
||||
bool found = false;
|
||||
PLIST_ENTRY entry = MmpThreadLocalStoragePointer.Flink;
|
||||
|
||||
// Find thread-spec tlsp
|
||||
while (entry != &MmpThreadLocalStoragePointer) {
|
||||
|
||||
PMMP_TLSP_RECORD j = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer);
|
||||
|
||||
if (ProcessTlsInformation->OperationType == ProcessTlsReplaceVector) {
|
||||
if (j->TlspMmpBlock[ProcessTlsInformation->TlsVectorLength] == ProcessTlsInformation->ThreadData->TlsVector[ProcessTlsInformation->TlsVectorLength]) {
|
||||
found = true;
|
||||
|
||||
// Copy old data to new pointer
|
||||
RtlCopyMemory(
|
||||
ProcessTlsInformation->ThreadData[i].TlsVector,
|
||||
j->TlspMmpBlock,
|
||||
sizeof(PVOID) * ProcessTlsInformation->TlsVectorLength
|
||||
);
|
||||
|
||||
// Swap the tlsp
|
||||
std::swap(
|
||||
j->TlspLdrBlock,
|
||||
ProcessTlsInformation->ThreadData[i].TlsVector
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (j->TlspMmpBlock[ProcessTlsInformation->TlsIndex] == ProcessTlsInformation->ThreadData[i].TlsModulePointer) {
|
||||
found = true;
|
||||
|
||||
j->TlspLdrBlock[ProcessTlsInformation->TlsIndex] = ProcessTlsInformation->ThreadData[i].TlsModulePointer;
|
||||
ProcessTlsInformation->ThreadData[i].TlsModulePointer = Tls->ThreadData[i].TlsModulePointer;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)break;
|
||||
entry = entry->Flink;
|
||||
}
|
||||
|
||||
assert(found);
|
||||
ProcessTlsInformation->ThreadData[i].Flags = Tls->ThreadData[i].Flags;
|
||||
ProcessTlsInformation->ThreadData[i].ThreadId = Tls->ThreadData[i].ThreadId;
|
||||
}
|
||||
LeaveCriticalSection(&MmpTlspLock);
|
||||
|
||||
} while (false);
|
||||
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, Tls);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI MmpAcquireTlsIndex(_Out_ PULONG TlsIndex) {
|
||||
|
||||
*TlsIndex = -1;
|
||||
|
||||
ULONG Index = RtlFindClearBitsAndSet(&MmpTlsBitmap, 1, 0);
|
||||
if (Index != -1) {
|
||||
*TlsIndex = Index;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI MmpAllocateTlsEntry(
|
||||
_In_ PIMAGE_TLS_DIRECTORY lpTlsDirectory,
|
||||
_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry,
|
||||
_Out_ PULONG lpTlsIndex,
|
||||
_Out_ PTLS_ENTRY* lpTlsEntry) {
|
||||
PTLS_ENTRY Entry = nullptr;
|
||||
IMAGE_TLS_DIRECTORY TlsDirectory;
|
||||
ULONG Length = 0;
|
||||
NTSTATUS status;
|
||||
DWORD TlsIndex;
|
||||
|
||||
__try {
|
||||
RtlCopyMemory(
|
||||
&TlsDirectory,
|
||||
lpTlsDirectory,
|
||||
sizeof(IMAGE_TLS_DIRECTORY)
|
||||
);
|
||||
|
||||
*PULONG(TlsDirectory.AddressOfIndex) = 0;
|
||||
|
||||
*lpTlsIndex = 0;
|
||||
*lpTlsEntry = nullptr;
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
Entry = (PTLS_ENTRY)RtlAllocateHeap(
|
||||
NtCurrentPeb()->ProcessHeap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(TLS_ENTRY)
|
||||
);
|
||||
if (!Entry) {
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = MmpAcquireTlsIndex(&TlsIndex);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Entry);
|
||||
return status;
|
||||
}
|
||||
|
||||
RtlCopyMemory(
|
||||
&Entry->TlsDirectory,
|
||||
&TlsDirectory,
|
||||
sizeof(IMAGE_TLS_DIRECTORY)
|
||||
);
|
||||
|
||||
Entry->ModuleEntry = lpModuleEntry;
|
||||
Entry->TlsDirectory.Characteristics =
|
||||
*PULONG(Entry->TlsDirectory.AddressOfIndex) = TlsIndex;
|
||||
|
||||
InsertTailList(&MmpTlsList, &Entry->TlsEntryLinks);
|
||||
|
||||
*lpTlsEntry = Entry;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI MmpReleaseTlsEntry(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
|
||||
|
||||
NTSTATUS status = STATUS_NOT_FOUND;
|
||||
|
||||
RtlAcquireSRWLockExclusive(&MmpTlsListLock);
|
||||
|
||||
for (auto entry = MmpTlsList.Flink; entry != &MmpTlsList; entry = entry->Flink) {
|
||||
auto p = CONTAINING_RECORD(entry, TLS_ENTRY, TlsEntryLinks);
|
||||
if (p->ModuleEntry == lpModuleEntry) {
|
||||
RemoveEntryList(&p->TlsEntryLinks);
|
||||
RtlClearBit(&MmpTlsBitmap, p->TlsDirectory.Characteristics);
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, p);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RtlReleaseSRWLockExclusive(&MmpTlsListLock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) {
|
||||
PIMAGE_TLS_DIRECTORY lpTlsDirectory;
|
||||
ULONG DirectorySize;
|
||||
NTSTATUS status;
|
||||
ULONG TlsIndex;
|
||||
PTLS_ENTRY TlsEntry;
|
||||
|
||||
lpTlsDirectory = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData(
|
||||
lpModuleEntry->DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_TLS,
|
||||
&DirectorySize
|
||||
);
|
||||
|
||||
if (!lpTlsDirectory || !DirectorySize) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
status = MmpAllocateTlsEntry(
|
||||
lpTlsDirectory,
|
||||
lpModuleEntry,
|
||||
&TlsIndex,
|
||||
&TlsEntry
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlAcquireSRWLockExclusive(&MmpTlsListLock);
|
||||
InsertTailList(&MmpTlsList, &TlsEntry->TlsEntryLinks);
|
||||
RtlReleaseSRWLockExclusive(&MmpTlsListLock);
|
||||
|
||||
auto ThreadCount = MmpGetThreadCount();
|
||||
auto success = true;
|
||||
auto Length = sizeof(PROCESS_TLS_INFORMATION) + (ThreadCount - 1) * sizeof(THREAD_TLS_INFORMATION);
|
||||
auto ProcessTlsInformation = PPROCESS_TLS_INFORMATION(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, Length));
|
||||
if (!ProcessTlsInformation) {
|
||||
MmpReleaseTlsEntry(lpModuleEntry);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
ProcessTlsInformation->OperationType = ProcessTlsReplaceIndex;
|
||||
ProcessTlsInformation->Reserved = 0;
|
||||
ProcessTlsInformation->TlsIndex = TlsIndex;
|
||||
ProcessTlsInformation->ThreadDataCount = ThreadCount;
|
||||
|
||||
for (DWORD i = 0; i < ThreadCount; ++i) {
|
||||
auto& current = ProcessTlsInformation->ThreadData[i];
|
||||
current.TlsModulePointer = RtlAllocateHeap(
|
||||
RtlProcessHeap(),
|
||||
0,
|
||||
lpTlsDirectory->EndAddressOfRawData - lpTlsDirectory->StartAddressOfRawData
|
||||
);
|
||||
if (!current.TlsModulePointer) {
|
||||
for (DWORD j = 0; j < i; ++j) {
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, ProcessTlsInformation->ThreadData[j].TlsModulePointer);
|
||||
}
|
||||
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
RtlCopyMemory(
|
||||
current.TlsModulePointer,
|
||||
PVOID(lpTlsDirectory->StartAddressOfRawData),
|
||||
lpTlsDirectory->EndAddressOfRawData - lpTlsDirectory->StartAddressOfRawData
|
||||
);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
MmpReleaseTlsEntry(lpModuleEntry);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = NtSetInformationProcess(
|
||||
nullptr, // hack
|
||||
ProcessResourceManagement,
|
||||
ProcessTlsInformation,
|
||||
Length
|
||||
);
|
||||
|
||||
RtlFreeHeap(RtlProcessHeap(), 0, ProcessTlsInformation);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
VOID NTAPI MmpInitialize() {
|
||||
|
||||
//
|
||||
// Initialize tlsp
|
||||
//
|
||||
InitializeCriticalSection(&MmpTlspLock);
|
||||
InitializeListHead(&MmpThreadLocalStoragePointer);
|
||||
|
||||
//
|
||||
// Initialize tls list
|
||||
//
|
||||
InitializeListHead(&MmpTlsList);
|
||||
RtlInitializeSRWLock(&MmpTlsListLock);
|
||||
|
||||
PULONG buffer = PULONG(RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ULONG) * 8));
|
||||
if (!buffer) {
|
||||
RtlRaiseStatus(STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
RtlFillMemory(buffer, sizeof(ULONG) * 4, -1);
|
||||
RtlInitializeBitMap(&MmpTlsBitmap, buffer, 0x100);
|
||||
|
||||
if (NtCurrentTeb()->ThreadLocalStoragePointer) {
|
||||
if (!PreHookNtSetInformationProcess()) {
|
||||
RtlRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Hook functions
|
||||
//
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(NtCurrentThread());
|
||||
DetourAttach((PVOID*)&OriginNtCreateThread, HookNtCreateThread);
|
||||
DetourAttach((PVOID*)&OriginNtCreateThreadEx, HookNtCreateThreadEx);
|
||||
DetourAttach((PVOID*)&OriginLdrShutdownThread, HookLdrShutdownThread);
|
||||
DetourAttach((PVOID*)&OriginNtSetInformationProcess, HookNtSetInformationProcess);
|
||||
DetourTransactionCommit();
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#pragma warning(disable:6387)
|
||||
#pragma warning(disable:26812)
|
||||
#pragma comment(lib,"Secur32.lib")
|
||||
#pragma comment(lib,"ntdll.lib")
|
||||
|
||||
FARPROC NTAPI RtlGetNtProcAddress(LPCSTR func_name) {
|
||||
return GetProcAddress(GetModuleHandleA("ntdll.dll"), func_name);
|
||||
|
||||
+184
-5
@@ -81,10 +81,10 @@ typedef struct _STRING {
|
||||
WORD MaximumLength;
|
||||
CHAR * Buffer;
|
||||
} STRING, *PSTRING;
|
||||
struct CLIENT_ID {
|
||||
HANDLE UniqueProcess;//Process ID
|
||||
HANDLE UniqueThread;//Thread ID
|
||||
};
|
||||
typedef struct _CLIENT_ID {
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID, * PCLIENT_ID;
|
||||
typedef struct _SYSTEM_THREAD {
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
@@ -1422,6 +1422,185 @@ NTSTATUS NTAPI LdrLockLoaderLock(size_t Flags, size_t* State, size_t* Cookie);
|
||||
NTSTATUS NTAPI LdrUnlockLoaderLock(size_t Flags, size_t Cookie);
|
||||
NTSTATUS NTAPI LdrUnloadDll(IN HANDLE ModuleHandle);
|
||||
|
||||
#define RtlRaiseStatus(_Status_) ((VOID(NTAPI*)(NTSTATUS Status))(RtlGetNtProcAddress("RtlRaiseStatus")))(_Status_)
|
||||
extern "C"
|
||||
NTSYSAPI
|
||||
DECLSPEC_NORETURN
|
||||
VOID
|
||||
NTAPI
|
||||
RtlRaiseStatus(
|
||||
_In_ NTSTATUS Status
|
||||
);
|
||||
|
||||
DECLSPEC_NORETURN VOID NTAPI RtlExitUserThread(IN NTSTATUS ExitStatus);
|
||||
|
||||
#define RtlProcessHeap() (NtCurrentPeb()->ProcessHeap)
|
||||
|
||||
#define NtCurrentProcessId() (NtCurrentTeb()->ClientId.UniqueProcess)
|
||||
#define NtCurrentThreadId() (NtCurrentTeb()->ClientId.UniqueThread)
|
||||
|
||||
typedef enum _PROCESS_TLS_INFORMATION_TYPE {
|
||||
ProcessTlsReplaceIndex,
|
||||
ProcessTlsReplaceVector,
|
||||
MaxProcessTlsOperation
|
||||
} PROCESS_TLS_INFORMATION_TYPE, * PPROCESS_TLS_INFORMATION_TYPE;
|
||||
|
||||
typedef struct _RTL_BITMAP {
|
||||
ULONG SizeOfBitMap;
|
||||
PULONG Buffer;
|
||||
} RTL_BITMAP, * PRTL_BITMAP;
|
||||
|
||||
FORCEINLINE VOID InitializeListHead(
|
||||
_Out_ PLIST_ENTRY ListHead
|
||||
)
|
||||
{
|
||||
ListHead->Flink = ListHead->Blink = ListHead;
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN RemoveEntryList(
|
||||
_In_ PLIST_ENTRY Entry
|
||||
)
|
||||
{
|
||||
PLIST_ENTRY Blink;
|
||||
PLIST_ENTRY Flink;
|
||||
|
||||
Flink = Entry->Flink;
|
||||
Blink = Entry->Blink;
|
||||
Blink->Flink = Flink;
|
||||
Flink->Blink = Blink;
|
||||
|
||||
return Flink == Blink;
|
||||
}
|
||||
|
||||
FORCEINLINE VOID InsertTailList(
|
||||
_Inout_ PLIST_ENTRY ListHead,
|
||||
_Inout_ PLIST_ENTRY Entry
|
||||
)
|
||||
{
|
||||
PLIST_ENTRY Blink;
|
||||
|
||||
Blink = ListHead->Blink;
|
||||
Entry->Flink = ListHead;
|
||||
Entry->Blink = Blink;
|
||||
Blink->Flink = Entry;
|
||||
ListHead->Blink = Entry;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtSetInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PROCESSINFOCLASS ProcessInformationClass,
|
||||
_In_reads_bytes_(ProcessInformationLength) PVOID ProcessInformation,
|
||||
_In_ ULONG ProcessInformationLength
|
||||
);
|
||||
|
||||
extern "C"
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LdrShutdownThread(
|
||||
VOID
|
||||
);
|
||||
|
||||
extern "C"
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtCreateThread(
|
||||
_Out_ PHANDLE ThreadHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PCLIENT_ID ClientId,
|
||||
_In_ PCONTEXT ThreadContext,
|
||||
_In_ PINITIAL_TEB InitialTeb,
|
||||
_In_ BOOLEAN CreateSuspended
|
||||
);
|
||||
|
||||
extern "C"
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtCreateThreadEx(
|
||||
_Out_ PHANDLE ThreadHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PVOID StartRoutine,
|
||||
_In_opt_ PVOID Argument,
|
||||
_In_ ULONG CreateFlags,
|
||||
_In_ SIZE_T ZeroBits,
|
||||
_In_ SIZE_T StackSize,
|
||||
_In_ SIZE_T MaximumStackSize,
|
||||
_In_opt_ PVOID AttributeList
|
||||
);
|
||||
|
||||
extern "C" {
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlInitializeSRWLock(
|
||||
_Out_ PRTL_SRWLOCK SRWLock
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlAcquireSRWLockExclusive(
|
||||
_Inout_ PRTL_SRWLOCK SRWLock
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlAcquireSRWLockShared(
|
||||
_Inout_ PRTL_SRWLOCK SRWLock
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlReleaseSRWLockExclusive(
|
||||
_Inout_ PRTL_SRWLOCK SRWLock
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlReleaseSRWLockShared(
|
||||
_Inout_ PRTL_SRWLOCK SRWLock
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlClearBits(
|
||||
_In_ PRTL_BITMAP BitMapHeader,
|
||||
_In_range_(0, BitMapHeader->SizeOfBitMap - NumberToClear) ULONG StartingIndex,
|
||||
_In_range_(0, BitMapHeader->SizeOfBitMap - StartingIndex) ULONG NumberToClear
|
||||
);
|
||||
|
||||
NTSYSAPI
|
||||
VOID
|
||||
NTAPI
|
||||
RtlInitializeBitMap(
|
||||
_Out_ PRTL_BITMAP BitMapHeader,
|
||||
_In_ PULONG BitMapBuffer,
|
||||
_In_ ULONG SizeOfBitMap
|
||||
);
|
||||
|
||||
_Success_(return != -1)
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
RtlFindClearBitsAndSet(
|
||||
_In_ PRTL_BITMAP BitMapHeader,
|
||||
_In_ ULONG NumberToFind,
|
||||
_In_ ULONG HintIndex
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#define RtlClearBit(BitMapHeader,BitNumber) RtlClearBits((BitMapHeader),(BitNumber),1)
|
||||
|
||||
@@ -412,16 +412,4 @@ BOOL NTAPI RtlFreeLdrpHeap(IN PVOID buffer);
|
||||
#define RtlInitializeListEntry(entry) ((entry)->Blink = (entry)->Flink = (entry))
|
||||
#define RtlInitializeSingleEntry(entry) ((entry->Next = (entry)))
|
||||
|
||||
FORCEINLINE BOOLEAN NTAPI RemoveEntryList(IN PLIST_ENTRY Entry) {
|
||||
PLIST_ENTRY OldFlink;
|
||||
PLIST_ENTRY OldBlink;
|
||||
|
||||
OldFlink = Entry->Flink;
|
||||
OldBlink = Entry->Blink;
|
||||
|
||||
OldFlink->Blink = OldBlink;
|
||||
OldBlink->Flink = OldFlink;
|
||||
return (BOOLEAN)(OldFlink == OldBlink);
|
||||
}
|
||||
|
||||
size_t NTAPI LdrpDataTableEntrySize();
|
||||
|
||||
Reference in New Issue
Block a user