mirror of
https://github.com/bb107/MemoryModulePP
synced 2026-06-08 13:15:33 +00:00
Adjust code file structure
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemory(PVOID BufferAddress) {
|
||||
HMEMORYMODULE hMemoryModule = nullptr;
|
||||
NTSTATUS status = NtLoadDllMemory(&hMemoryModule, BufferAddress, 0);
|
||||
NTSTATUS status = LdrLoadDllMemory(&hMemoryModule, BufferAddress, 0);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
}
|
||||
@@ -12,7 +12,7 @@ HMEMORYMODULE WINAPI LoadLibraryMemory(PVOID BufferAddress) {
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExA(PVOID BufferAddress, size_t Reserved, LPCSTR DllBaseName, LPCSTR DllFullName, DWORD Flags) {
|
||||
HMEMORYMODULE hMemoryModule = nullptr;
|
||||
NTSTATUS status = NtLoadDllMemoryExA(&hMemoryModule, nullptr, Flags, BufferAddress, Reserved, DllBaseName, DllFullName);
|
||||
NTSTATUS status = LdrLoadDllMemoryExA(&hMemoryModule, nullptr, Flags, BufferAddress, Reserved, DllBaseName, DllFullName);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
}
|
||||
@@ -21,7 +21,7 @@ HMEMORYMODULE WINAPI LoadLibraryMemoryExA(PVOID BufferAddress, size_t Reserved,
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExW(PVOID BufferAddress, size_t Reserved, LPCWSTR DllBaseName, LPCWSTR DllFullName, DWORD Flags) {
|
||||
HMEMORYMODULE hMemoryModule = nullptr;
|
||||
NTSTATUS status = NtLoadDllMemoryExW(&hMemoryModule, nullptr, Flags, BufferAddress, Reserved, DllBaseName, DllFullName);
|
||||
NTSTATUS status = LdrLoadDllMemoryExW(&hMemoryModule, nullptr, Flags, BufferAddress, Reserved, DllBaseName, DllFullName);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
}
|
||||
@@ -29,7 +29,7 @@ HMEMORYMODULE WINAPI LoadLibraryMemoryExW(PVOID BufferAddress, size_t Reserved,
|
||||
}
|
||||
|
||||
BOOL WINAPI FreeLibraryMemory(HMEMORYMODULE hMemoryModule) {
|
||||
NTSTATUS status = NtUnloadDllMemory(hMemoryModule);
|
||||
NTSTATUS status = LdrUnloadDllMemory(hMemoryModule);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
SetLastError(RtlNtStatusToDosError(status));
|
||||
return FALSE;
|
||||
|
||||
+14
-135
@@ -1,142 +1,13 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
typedef HMODULE HMEMORYMODULE;
|
||||
typedef PVOID HMEMORYRSRC;
|
||||
#define _HIDE_INTERNAL_
|
||||
#include "NativeFunctionsInternal.h"
|
||||
|
||||
#define MemoryModuleToModule(_hMemoryModule_) (HMODULE(_hMemoryModule_))
|
||||
#define MemoryModuleToModule(_hMemoryModule_) (_hMemoryModule_)
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
#endif
|
||||
|
||||
//Deprecated API
|
||||
#ifndef _DEPRECATED
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadLibraryMemory", "Deprecated. Use LoadLibraryMemory.")
|
||||
HMEMORYMODULE MemoryLoadLibrary(const void*);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("GetProcAddress", "Deprecated. Use Win32API GetProcAddress.")
|
||||
FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("FreeLibrayMemory", "Deprecated. Use FreeLibrayMemory.")
|
||||
bool MemoryFreeLibrary(HMEMORYMODULE);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("FindResource", "Deprecated. Use Win32API FindResource.")
|
||||
HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("FindResourceEx", "Deprecated. Use Win32API FindResourceEx.")
|
||||
HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("SizeofResource", "Deprecated. Use Win32API SizeofResource.")
|
||||
DWORD MemorySizeofResource(HMEMORYMODULE, HMEMORYRSRC);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadResource", "Deprecated. Use Win32API LoadResource.")
|
||||
LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadString*", "Deprecated. Use Win32API LoadStringA or LoadStringW.")
|
||||
int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
|
||||
|
||||
NOT_BUILD_WINDOWS_DEPRECATE
|
||||
__drv_preferredFunction("LoadString*", "Deprecated. Use Win32API LoadStringA or LoadStringW.")
|
||||
int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
|
||||
#endif
|
||||
|
||||
|
||||
#define MEMORY_FEATURE_SUPPORT_VERSION 0x00000001
|
||||
#define MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX 0x00000002 /* Windows8 and greater */
|
||||
#define MEMORY_FEATURE_LDRP_HEAP 0x00000004
|
||||
#define MEMORY_FEATURE_LDRP_HASH_TABLE 0x00000008
|
||||
#define MEMORY_FEATURE_INVERTED_FUNCTION_TABLE 0x00000010
|
||||
#define MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA 0x00000020
|
||||
#define MEMORY_FEATURE_ALL 0x0000003f
|
||||
|
||||
//Get the implementation of the currently running operating system.
|
||||
NTSTATUS NTAPI NtQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures);
|
||||
|
||||
|
||||
//Load dll from the provided buffer.
|
||||
NTSTATUS NTAPI NtLoadDllMemory(
|
||||
OUT HMEMORYMODULE* BaseAddress, // Output module base address
|
||||
IN LPVOID BufferAddress, // Pointer to the dll file data buffer
|
||||
IN size_t Reserved // Reserved parameter, must be 0
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
//If this flag is specified, this routine will not fail even if the call to LdrpTlsData fails.
|
||||
#define LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS 0x20000000
|
||||
|
||||
//If this flag is specified, the input image buffer will not be checked before loading.
|
||||
#define LOAD_FLAGS_PASS_IMAGE_CHECK 0x40000000
|
||||
|
||||
//If this flag is specified, exception handling will not be supported.
|
||||
#define LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION 0x00000001
|
||||
|
||||
//If this flag is specified, NtLoadDllMemory and NtUnloadDllMemory will not use reference counting.
|
||||
//If you try to load the same module, it will fail. When you unload the module,
|
||||
// it will be unloaded without checking the reference count.
|
||||
#define LOAD_FLAGS_NOT_USE_REFERENCE_COUNT 0x00000002
|
||||
|
||||
//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"
|
||||
#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, // Output module base address
|
||||
OUT PVOID* LdrEntry OPTIONAL, // Receive a pointer to the LDR node of the module
|
||||
IN DWORD dwFlags, // Flags
|
||||
IN LPVOID BufferAddress, // Pointer to the dll file data buffer
|
||||
IN size_t Reserved, // Reserved parameter, must be 0
|
||||
IN LPCWSTR DllName OPTIONAL, // Module file name
|
||||
IN LPCWSTR DllFullName OPTIONAL // Module file full path
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI NtLoadDllMemoryExA(
|
||||
OUT HMEMORYMODULE* BaseAddress,
|
||||
OUT PVOID* LdrEntry OPTIONAL,
|
||||
IN DWORD dwFlags,
|
||||
IN LPVOID BufferAddress,
|
||||
IN size_t Reserved,
|
||||
IN LPCSTR DllName OPTIONAL,
|
||||
IN LPCSTR DllFullName OPTIONAL
|
||||
);
|
||||
|
||||
//Unload modules previously loaded from memory
|
||||
NTSTATUS NTAPI NtUnloadDllMemory(IN HMEMORYMODULE BaseAddress);
|
||||
|
||||
#ifdef _WIN64
|
||||
#pragma comment(linker,"/export:NtUnloadDllMemoryAndExitThread")
|
||||
#pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=NtUnloadDllMemoryAndExitThread")
|
||||
#else
|
||||
#pragma comment(linker,"/export:NtUnloadDllMemoryAndExitThread=_NtUnloadDllMemoryAndExitThread@8")
|
||||
#pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=_NtUnloadDllMemoryAndExitThread@8")
|
||||
#endif
|
||||
//FreeLibraryMemoryAndExitThread = GetProcAddress(GetModuleHandleW(nullptr), "FreeLibraryMemoryAndExitThread");
|
||||
//FreeLibraryMemoryAndExitThread(hModule, 0);
|
||||
extern "C" {
|
||||
__declspec(noreturn) VOID NTAPI NtUnloadDllMemoryAndExitThread(IN HMEMORYMODULE BaseAddress, IN DWORD dwExitCode);
|
||||
}
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemory(PVOID BufferAddress);
|
||||
|
||||
HMEMORYMODULE WINAPI LoadLibraryMemoryExA(PVOID BufferAddress, size_t Reserved, LPCSTR DllBaseName, LPCSTR DllFullName, DWORD Flags);
|
||||
@@ -145,14 +16,22 @@ HMEMORYMODULE WINAPI LoadLibraryMemoryExW(PVOID BufferAddress, size_t Reserved,
|
||||
|
||||
BOOL WINAPI FreeLibraryMemory(HMEMORYMODULE hMemoryModule);
|
||||
|
||||
#define FreeLibraryMemoryAndExitThread NtUnloadDllMemoryAndExitThread
|
||||
#define NtLoadDllMemory LdrLoadDllMemory
|
||||
#define NtLoadDllMemoryExA LdrLoadDllMemoryExA
|
||||
#define NtLoadDllMemoryExW LdrLoadDllMemoryExW
|
||||
#define NtUnloadDllMemory LdrUnloadDllMemory
|
||||
#define NtUnloadDllMemoryAndExitThread LdrUnloadDllMemoryAndExitThread
|
||||
#define FreeLibraryMemoryAndExitThread LdrUnloadDllMemoryAndExitThread
|
||||
#define NtQuerySystemMemoryModuleFeatures LdrQuerySystemMemoryModuleFeatures
|
||||
|
||||
#ifdef UNICODE
|
||||
#define NtLoadDllMemoryEx NtLoadDllMemoryExW
|
||||
#define LdrLoadDllMemoryEx LdrLoadDllMemoryExW
|
||||
#define LoadLibraryMemoryEx LoadLibraryMemoryExW
|
||||
#else
|
||||
#define NtLoadDllMemoryEx NtLoadDllMemoryExA
|
||||
#define LdrLoadDllMemoryEx LdrLoadDllMemoryExA
|
||||
#define LoadLibraryMemoryEx LoadLibraryMemoryExA
|
||||
#endif
|
||||
#define NtLoadDllMemoryEx LdrLoadDllMemoryEx
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
#include <stddef.h>
|
||||
#include "stdafx.h"
|
||||
#include <tchar.h>
|
||||
#include "rtltype.h"
|
||||
#include "ntstatus.h"
|
||||
#include "Native.h"
|
||||
#include <algorithm>
|
||||
|
||||
#if _MSC_VER
|
||||
@@ -21,7 +16,6 @@
|
||||
#define HOST_MACHINE IMAGE_FILE_MACHINE_I386
|
||||
#endif
|
||||
|
||||
#include "MemoryModule.h"
|
||||
#define GET_HEADER_DICTIONARY(headers, idx) &headers->OptionalHeader.DataDirectory[idx]
|
||||
|
||||
static PIMAGE_NT_HEADERS WINAPI GetImageNtHeaders(PMEMORYMODULE pModule) {
|
||||
|
||||
@@ -23,13 +23,23 @@
|
||||
<ClCompile Include="MemoryModule.cpp" />
|
||||
<ClCompile Include="Native.cpp" />
|
||||
<ClCompile Include="NativeFunctionsInternal.cpp" />
|
||||
<ClCompile Include="rtlinv.cpp" />
|
||||
<ClCompile Include="rtlldr.cpp" />
|
||||
<ClCompile Include="rtlsearch.cpp" />
|
||||
<ClCompile Include="rtltls.cpp" />
|
||||
<ClCompile Include="rtlver.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="LoadDllMemoryApi.h" />
|
||||
<ClInclude Include="MemoryModule.h" />
|
||||
<ClInclude Include="Native.h" />
|
||||
<ClInclude Include="NativeFunctionsInternal.h" />
|
||||
<ClInclude Include="rtltype.h" />
|
||||
<ClInclude Include="rtlinv.h" />
|
||||
<ClInclude Include="rtlldr.h" />
|
||||
<ClInclude Include="rtlsearch.h" />
|
||||
<ClInclude Include="rtltls.h" />
|
||||
<ClInclude Include="rtlver.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md" />
|
||||
|
||||
@@ -27,6 +27,21 @@
|
||||
<ClCompile Include="LoadDllMemoryApi.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rtlver.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rtlldr.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rtlinv.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rtltls.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rtlsearch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MemoryModule.h">
|
||||
@@ -35,15 +50,30 @@
|
||||
<ClInclude Include="Native.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtltype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NativeFunctionsInternal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LoadDllMemoryApi.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtlver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtlldr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtlinv.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtltls.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtlsearch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,417 +1,33 @@
|
||||
#pragma once
|
||||
#ifndef _HIDE_INTERNAL_
|
||||
#include "stdafx.h"
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#include "rtltype.h"
|
||||
#include "ntstatus.h"
|
||||
#include "MemoryModule.h"
|
||||
typedef HMODULE HMEMORYMODULE;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Loader Data Table Entry Flags
|
||||
//
|
||||
#define LDRP_STATIC_LINK 0x00000002
|
||||
#define LDRP_IMAGE_DLL 0x00000004
|
||||
#define LDRP_SHIMENG_SUPPRESSED_ENTRY 0x00000008
|
||||
#define LDRP_IMAGE_INTEGRITY_FORCED 0x00000020
|
||||
#define LDRP_LOAD_IN_PROGRESS 0x00001000
|
||||
#define LDRP_UNLOAD_IN_PROGRESS 0x00002000
|
||||
#define LDRP_ENTRY_PROCESSED 0x00004000
|
||||
#define LDRP_ENTRY_INSERTED 0x00008000
|
||||
#define LDRP_CURRENT_LOAD 0x00010000
|
||||
#define LDRP_FAILED_BUILTIN_LOAD 0x00020000
|
||||
#define LDRP_DONT_CALL_FOR_THREADS 0x00040000
|
||||
#define LDRP_PROCESS_ATTACH_CALLED 0x00080000
|
||||
#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000
|
||||
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000
|
||||
#define LDRP_COR_IMAGE 0x00400000
|
||||
#define LDR_COR_OWNS_UNMAP 0x00800000
|
||||
#define LDRP_SYSTEM_MAPPED 0x01000000
|
||||
#define LDRP_IMAGE_VERIFYING 0x02000000
|
||||
#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000
|
||||
#define LDRP_ENTRY_NATIVE 0x08000000
|
||||
#define LDRP_REDIRECTED 0x10000000
|
||||
#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000
|
||||
#define LDRP_MM_LOADED 0x40000000
|
||||
#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000
|
||||
|
||||
#define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1))
|
||||
#define LDR_HASH_TABLE_ENTRIES 32
|
||||
#define InsertTailList(ListHead,Entry) {\
|
||||
PLIST_ENTRY _EX_Blink;\
|
||||
PLIST_ENTRY _EX_ListHead;\
|
||||
_EX_ListHead = (ListHead);\
|
||||
_EX_Blink = _EX_ListHead->Blink;\
|
||||
(Entry)->Flink = _EX_ListHead;\
|
||||
(Entry)->Blink = _EX_Blink;\
|
||||
_EX_Blink->Flink = (Entry);\
|
||||
_EX_ListHead->Blink = (Entry);\
|
||||
}
|
||||
|
||||
//0x18 bytes (sizeof)
|
||||
typedef struct _RTL_BALANCED_NODE {
|
||||
union {
|
||||
_RTL_BALANCED_NODE* Children[2]; //0x0
|
||||
struct {
|
||||
_RTL_BALANCED_NODE* Left; //0x0
|
||||
_RTL_BALANCED_NODE* Right; //0x8
|
||||
};
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
UCHAR Red : 1; //0x10
|
||||
UCHAR Balance : 2; //0x10
|
||||
};
|
||||
size_t ParentValue; //0x10
|
||||
};
|
||||
}RTL_BALANCED_NODE, * PRTL_BALANCED_NODE;
|
||||
|
||||
enum _LDR_DLL_LOAD_REASON {
|
||||
LoadReasonStaticDependency = 0,
|
||||
LoadReasonStaticForwarderDependency = 1,
|
||||
LoadReasonDynamicForwarderDependency = 2,
|
||||
LoadReasonDelayloadDependency = 3,
|
||||
LoadReasonDynamicLoad = 4,
|
||||
LoadReasonAsImageLoad = 5,
|
||||
LoadReasonAsDataLoad = 6,
|
||||
LoadReasonUnknown = -1
|
||||
};
|
||||
|
||||
//0x10 bytes (sizeof)
|
||||
struct _LDR_SERVICE_TAG_RECORD {
|
||||
_LDR_SERVICE_TAG_RECORD* Next; //0x0
|
||||
ULONG ServiceTag; //0x8
|
||||
};
|
||||
//0x8 bytes (sizeof)
|
||||
struct _LDRP_CSLIST {
|
||||
struct _LDRP_CSLIST_DEPENDENT {
|
||||
_SINGLE_LIST_ENTRY* NextDependentEntry; //0x0
|
||||
struct _LDR_DDAG_NODE* DependentDdagNode;
|
||||
}Dependent;
|
||||
struct _LDRP_CSLIST_INCOMMING {
|
||||
_SINGLE_LIST_ENTRY* NextIncommingEntry;
|
||||
struct _LDR_DDAG_NODE* IncommingDdagNode;
|
||||
}Incomming;
|
||||
};
|
||||
//0x4 bytes (sizeof)
|
||||
enum _LDR_DDAG_STATE {
|
||||
LdrModulesMerged = -5,
|
||||
LdrModulesInitError = -4,
|
||||
LdrModulesSnapError = -3,
|
||||
LdrModulesUnloaded = -2,
|
||||
LdrModulesUnloading = -1,
|
||||
LdrModulesPlaceHolder = 0,
|
||||
LdrModulesMapping = 1,
|
||||
LdrModulesMapped = 2,
|
||||
LdrModulesWaitingForDependencies = 3,
|
||||
LdrModulesSnapping = 4,
|
||||
LdrModulesSnapped = 5,
|
||||
LdrModulesCondensed = 6,
|
||||
LdrModulesReadyToInit = 7,
|
||||
LdrModulesInitializing = 8,
|
||||
LdrModulesReadyToRun = 9
|
||||
};
|
||||
//0x50 bytes (sizeof)
|
||||
struct _LDR_DDAG_NODE {
|
||||
_LIST_ENTRY Modules; //0x0
|
||||
_LDR_SERVICE_TAG_RECORD* ServiceTagList; //0x10
|
||||
ULONG LoadCount; //0x18
|
||||
ULONG LoadWhileUnloadingCount; //0x1c
|
||||
ULONG LowestLink; //0x20
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_DEPENDENT* Dependencies; //0x28
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_INCOMMING* IncomingDependencies; //0x30
|
||||
_LDR_DDAG_STATE State; //0x38
|
||||
_SINGLE_LIST_ENTRY CondenseLink; //0x40
|
||||
ULONG PreorderNumber; //0x48
|
||||
};
|
||||
struct _LDR_DDAG_NODE_WIN8 {
|
||||
_LIST_ENTRY Modules; //0x0
|
||||
_LDR_SERVICE_TAG_RECORD* ServiceTagList; //0x10
|
||||
ULONG LoadCount; //0x18
|
||||
ULONG ReferenceCount; //0x1c
|
||||
ULONG DependencyCount; //0x20
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_DEPENDENT* Dependencies; //0x28
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_INCOMMING* IncomingDependencies; //0x30
|
||||
_LDR_DDAG_STATE State; //0x38
|
||||
_SINGLE_LIST_ENTRY CondenseLink; //0x40
|
||||
ULONG PreorderNumber; //0x48
|
||||
ULONG LowestLink; //0x4c
|
||||
};
|
||||
|
||||
//5.1.2600 Windows XP SP3
|
||||
//5.2.3790 Windows XP | 2003 SP2
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_XP {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
ULONG Flags; //0x68
|
||||
USHORT LoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
union {
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
struct {
|
||||
VOID* SectionPointer; //0x70
|
||||
ULONG CheckSum; //0x78
|
||||
};
|
||||
};
|
||||
union {
|
||||
ULONG TimeDateStamp; //0x80
|
||||
VOID* LoadedImports; //0x80
|
||||
};
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* PatchInformation; //0x90
|
||||
}LDR_DATA_TABLE_ENTRY_XP, * PLDR_DATA_TABLE_ENTRY_XP;
|
||||
|
||||
//6.0.6000 Vista | 2008 RTM
|
||||
//6.0.6001 Vista | 2008 SP1
|
||||
//6.0.6002 Vista | 2008 SP2
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_VISTA :public _LDR_DATA_TABLE_ENTRY_XP {
|
||||
_LIST_ENTRY ForwarderLinks; //0x98
|
||||
_LIST_ENTRY ServiceTagLinks; //0xa8
|
||||
_LIST_ENTRY StaticLinks; //0xb8
|
||||
}LDR_DATA_TABLE_ENTRY_VISTA, * PLDR_DATA_TABLE_ENTRY_VISTA;
|
||||
|
||||
//6.1.7600 Windows 7 | 2008R2 SP1
|
||||
//6.1.7601 Windows 7 | 2008R2 RTM
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN7 :public _LDR_DATA_TABLE_ENTRY_VISTA {
|
||||
VOID* ContextInformation; //0xc8
|
||||
ULONGLONG OriginalBase; //0xd0
|
||||
_LARGE_INTEGER LoadTime; //0xd8
|
||||
}LDR_DATA_TABLE_ENTRY_WIN7, * PLDR_DATA_TABLE_ENTRY_WIN7;
|
||||
|
||||
//6.2.9200 Windows 8 | 2012 RTM
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN8 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
union {
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
_LIST_ENTRY InProgressLinks; //0x20
|
||||
};
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
union {
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
struct {
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG ReservedFlags2 : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ReservedFlags3 : 3; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ReservedFlags5 : 3; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* PatchInformation; //0x90
|
||||
_LDR_DDAG_NODE_WIN8* DdagNode; //0x98
|
||||
_LIST_ENTRY NodeModuleLink; //0xa0
|
||||
VOID* SnapContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
_LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
_LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
}LDR_DATA_TABLE_ENTRY_WIN8, * PLDR_DATA_TABLE_ENTRY_WIN8;
|
||||
|
||||
//6.3.9600 Windows 8.1 | 2012R2 RTM | 2012R2 Update 1
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN8_1 :public _LDR_DATA_TABLE_ENTRY_WIN8 {
|
||||
ULONG ImplicitPathOptions;
|
||||
}LDR_DATA_TABLE_ENTRY_WIN8_1, * PLDR_DATA_TABLE_ENTRY_WIN8_1;
|
||||
|
||||
//10.0.10240 Windows 10 | 2016 1507 Threshold 1
|
||||
//10.0.10586 Windows 10 | 2016 1511 Threshold 2
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
union {
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
struct {
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG LoadConfigProcessed : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ProtectDelayLoad : 1; //0x68
|
||||
ULONG ReservedFlags3 : 2; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ReservedFlags5 : 3; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* Lock; //0x90
|
||||
_LDR_DDAG_NODE* DdagNode; //0x98
|
||||
_LIST_ENTRY NodeModuleLink; //0xa0
|
||||
VOID* LoadContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
_LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
_LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
ULONG ImplicitPathOptions; //0x110
|
||||
ULONG ReferenceCount; //0x114
|
||||
}LDR_DATA_TABLE_ENTRY_WIN10, * PLDR_DATA_TABLE_ENTRY_WIN10;
|
||||
|
||||
//10.0.14393 Windows 10 | 2016 1607 Redstone 1 (Anniversary Update)
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_1 :public _LDR_DATA_TABLE_ENTRY_WIN10 {
|
||||
ULONG DependentLoadFlags; //0x118
|
||||
}LDR_DATA_TABLE_ENTRY_WIN10_1,*PLDR_DATA_TABLE_ENTRY_WIN10_1;
|
||||
|
||||
//10.0.15063 Windows 10 | 2016 1703 Redstone 2 (Creators Update)
|
||||
//10.0.16299 Windows 10 | 2016 1709 Redstone 3 (Fall Creators Update)
|
||||
//10.0.17134 Windows 10 | 2016 1803 Redstone 4 (Spring Creators Update)
|
||||
//10.0.17763 Windows 10 | 2016 1809 Redstone 5 (October Update)
|
||||
//10.0.18362 Windows 10 | 2016 1903 19H1 (May 2019 Update) | 2016 1909 19H2 (November 2019 Update)
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_2 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
union {
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
struct {
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG LoadConfigProcessed : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ProtectDelayLoad : 1; //0x68
|
||||
ULONG ReservedFlags3 : 2; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ReservedFlags5 : 3; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* Lock; //0x90
|
||||
_LDR_DDAG_NODE* DdagNode; //0x98
|
||||
_LIST_ENTRY NodeModuleLink; //0xa0
|
||||
VOID* LoadContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
_LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
_LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
ULONG ImplicitPathOptions; //0x110
|
||||
ULONG ReferenceCount; //0x114
|
||||
ULONG DependentLoadFlags; //0x118
|
||||
UCHAR SigningLevel; //0x11c
|
||||
}LDR_DATA_TABLE_ENTRY_WIN10_2, * PLDR_DATA_TABLE_ENTRY_WIN10_2;
|
||||
|
||||
typedef enum _WINDOWS_VERSION {
|
||||
null,
|
||||
xp,
|
||||
vista,
|
||||
win7,
|
||||
win8,
|
||||
win8_1,
|
||||
win10,
|
||||
win10_1,
|
||||
win10_2,
|
||||
invalid
|
||||
}WINDOWS_VERSION;
|
||||
|
||||
NTSTATUS NTAPI NtLoadDllMemory(
|
||||
OUT HMEMORYMODULE* BaseAddress,
|
||||
IN LPVOID BufferAddress,
|
||||
IN size_t BufferSize
|
||||
//Load dll from the provided buffer.
|
||||
NTSTATUS NTAPI LdrLoadDllMemory(
|
||||
OUT HMEMORYMODULE* BaseAddress, // Output module base address
|
||||
IN LPVOID BufferAddress, // Pointer to the dll file data buffer
|
||||
IN size_t Reserved // Reserved parameter, must be 0
|
||||
);
|
||||
|
||||
#define MEMORY_FEATURE_SUPPORT_VERSION 0x00000001
|
||||
#define MEMORY_FEATURE_MODULE_BASEADDRESS_INDEX 0x00000002 /* Windows8 and greater */
|
||||
#define MEMORY_FEATURE_LDRP_HEAP 0x00000004
|
||||
#define MEMORY_FEATURE_LDRP_HASH_TABLE 0x00000008
|
||||
#define MEMORY_FEATURE_INVERTED_FUNCTION_TABLE 0x00000010
|
||||
#define MEMORY_FEATURE_LDRP_HANDLE_TLS_DATA 0x00000020
|
||||
#define MEMORY_FEATURE_ALL 0x0000003f
|
||||
|
||||
//Get the implementation of the currently running operating system.
|
||||
NTSTATUS NTAPI LdrQuerySystemMemoryModuleFeatures(OUT PDWORD pFeatures);
|
||||
|
||||
|
||||
/*
|
||||
NtLoadDllMemoryEx dwFlags
|
||||
LdrLoadDllMemoryEx dwFlags
|
||||
*/
|
||||
|
||||
//If this flag is specified, all subsequent flags will be ignored.
|
||||
@@ -427,7 +43,7 @@ NTSTATUS NTAPI NtLoadDllMemory(
|
||||
//If this flag is specified, exception handling will not be supported.
|
||||
#define LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION 0x00000001
|
||||
|
||||
//If this flag is specified, NtLoadDllMemory and NtUnloadDllMemory will not use reference counting.
|
||||
//If this flag is specified, LdrLoadDllMemory and LdrUnloadDllMemory will not use reference counting.
|
||||
//If you try to load the same module, it will fail. When you unload the module,
|
||||
// it will be unloaded without checking the reference count.
|
||||
#define LOAD_FLAGS_NOT_USE_REFERENCE_COUNT 0x00000002
|
||||
@@ -442,109 +58,38 @@ NTSTATUS NTAPI NtLoadDllMemory(
|
||||
#define LOAD_FLAGS_NOT_HANDLE_TLS 0x00000008
|
||||
|
||||
|
||||
NTSTATUS NTAPI NtLoadDllMemoryExW(
|
||||
NTSTATUS NTAPI LdrLoadDllMemoryExW(
|
||||
OUT HMEMORYMODULE* BaseAddress, // Output module base address
|
||||
OUT PVOID* LdrEntry OPTIONAL, // Receive a pointer to the LDR node of the module
|
||||
IN DWORD dwFlags, // Flags
|
||||
IN LPVOID BufferAddress, // Pointer to the dll file data buffer
|
||||
IN size_t Reserved, // Reserved parameter, must be 0
|
||||
IN LPCWSTR DllName OPTIONAL, // Module file name
|
||||
IN LPCWSTR DllFullName OPTIONAL // Module file full path
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI LdrLoadDllMemoryExA(
|
||||
OUT HMEMORYMODULE* BaseAddress,
|
||||
OUT PVOID* LdrEntry OPTIONAL,
|
||||
IN DWORD dwFlags,
|
||||
IN LPVOID BufferAddress,
|
||||
IN size_t BufferSize,
|
||||
IN LPCWSTR DllName OPTIONAL,
|
||||
IN LPCWSTR DllFullName OPTIONAL
|
||||
IN size_t Reserved,
|
||||
IN LPCSTR DllName OPTIONAL,
|
||||
IN LPCSTR DllFullName OPTIONAL
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI NtUnloadDllMemory(IN HMEMORYMODULE BaseAddress);
|
||||
|
||||
extern "C" {
|
||||
__declspec(noreturn) VOID NTAPI NtUnloadDllMemoryAndExitThread(IN HMEMORYMODULE BaseAddress, IN DWORD dwExitCode);
|
||||
}
|
||||
|
||||
|
||||
typedef struct _RTL_RB_TREE {
|
||||
PRTL_BALANCED_NODE Root;
|
||||
PRTL_BALANCED_NODE Min;
|
||||
} RTL_RB_TREE, * PRTL_RB_TREE;
|
||||
// RtlRbInsertNodeEx
|
||||
VOID NTAPI RtlRbInsertNodeEx(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Parent, IN BOOLEAN Right, OUT PRTL_BALANCED_NODE Node);
|
||||
// RtlRbRemoveNode
|
||||
VOID NTAPI RtlRbRemoveNode(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Node);
|
||||
|
||||
typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 {
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY ExceptionDirectory;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
ULONG ExceptionDirectorySize;
|
||||
} 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_64 Entries[0x200];
|
||||
} RTL_INVERTED_FUNCTION_TABLE_64, * PRTL_INVERTED_FUNCTION_TABLE_64;
|
||||
|
||||
// The correct data structure should be this.
|
||||
//
|
||||
//typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 {
|
||||
// PVOID EntrySEHandlerTableEncoded;
|
||||
// PVOID ImageBase;
|
||||
// ULONG ImageSize;
|
||||
// ULONG SEHandlerCount;
|
||||
//} 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;
|
||||
// RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 Entries[0x200];
|
||||
//} RTL_INVERTED_FUNCTION_TABLE_WIN7_32, * PRTL_INVERTED_FUNCTION_TABLE_WIN7_32;
|
||||
//
|
||||
//
|
||||
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;
|
||||
//Unload modules previously loaded from memory
|
||||
NTSTATUS NTAPI LdrUnloadDllMemory(IN HMEMORYMODULE BaseAddress);
|
||||
|
||||
#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;
|
||||
#pragma comment(linker,"/export:LdrUnloadDllMemoryAndExitThread")
|
||||
#pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=LdrUnloadDllMemoryAndExitThread")
|
||||
#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;
|
||||
#pragma comment(linker,"/export:LdrUnloadDllMemoryAndExitThread=_NtUnloadDllMemoryAndExitThread@8")
|
||||
#pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=_NtUnloadDllMemoryAndExitThread@8")
|
||||
#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);
|
||||
|
||||
typedef struct _SEARCH_CONTEXT {
|
||||
union {
|
||||
IN PVOID MemoryBuffer;
|
||||
size_t InBufferPtr;
|
||||
};
|
||||
union {
|
||||
IN DWORD BufferLength;
|
||||
size_t reserved0;
|
||||
};
|
||||
|
||||
union {
|
||||
OUT PVOID MemoryBlockInSection;
|
||||
size_t OutBufferPtr;
|
||||
};
|
||||
union {
|
||||
DWORD RemainingLength;
|
||||
size_t reserved1;
|
||||
};
|
||||
}SEARCH_CONTEXT, * PSEARCH_CONTEXT;
|
||||
NTSTATUS NTAPI RtlFindMemoryBlockFromModuleSection(
|
||||
IN HMODULE hModule OPTIONAL,
|
||||
IN LPCSTR lpSectionName OPTIONAL,
|
||||
IN OUT PSEARCH_CONTEXT SearchContext);
|
||||
//FreeLibraryMemoryAndExitThread = GetProcAddress(GetModuleHandleW(nullptr), "FreeLibraryMemoryAndExitThread");
|
||||
//FreeLibraryMemoryAndExitThread(hModule, 0);
|
||||
extern "C" {
|
||||
__declspec(noreturn) VOID NTAPI LdrUnloadDllMemoryAndExitThread(IN HMEMORYMODULE BaseAddress, IN DWORD dwExitCode);
|
||||
}
|
||||
|
||||
-23288
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,350 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
static __forceinline bool NTAPI RtlIsModuleUnloaded(PLDR_DATA_TABLE_ENTRY entry) {
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0)) {
|
||||
return PLDR_DATA_TABLE_ENTRY_WIN8(entry)->DdagNode->State == LdrModulesUnloaded;
|
||||
}
|
||||
else {
|
||||
return entry->DllBase == nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABLE InvertedTable, IN PVOID ImageBase, IN ULONG SizeOfImage) {
|
||||
#ifdef _WIN64
|
||||
ULONG CurrentSize;
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionTable;
|
||||
ULONG Index;
|
||||
ULONG SizeOfTable = 0;
|
||||
bool IsWin8OrGreater = RtlIsWindowsVersionOrGreater(6, 2, 0);
|
||||
|
||||
Index = (ULONG)IsWin8OrGreater;
|
||||
CurrentSize = InvertedTable->Count;
|
||||
if (CurrentSize != InvertedTable->MaxCount) {
|
||||
if (CurrentSize != 0) {
|
||||
while (Index < CurrentSize) {
|
||||
if (ImageBase < InvertedTable->Entries[Index].ImageBase)break;
|
||||
++Index;
|
||||
}
|
||||
|
||||
if (Index != CurrentSize) {
|
||||
RtlMoveMemory(&InvertedTable->Entries[Index + 1],
|
||||
&InvertedTable->Entries[Index],
|
||||
(CurrentSize - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY));
|
||||
}
|
||||
}
|
||||
|
||||
FunctionTable = (decltype(FunctionTable))RtlImageDirectoryEntryToData(ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &SizeOfTable);
|
||||
InvertedTable->Entries[Index].ExceptionDirectory = FunctionTable;
|
||||
InvertedTable->Entries[Index].ImageBase = ImageBase;
|
||||
InvertedTable->Entries[Index].ImageSize = SizeOfImage;
|
||||
InvertedTable->Entries[Index].ExceptionDirectorySize = SizeOfTable;
|
||||
InvertedTable->Count++;
|
||||
}
|
||||
else {
|
||||
IsWin8OrGreater ? (InvertedTable->Overflow = TRUE) : (InvertedTable->Epoch = TRUE);
|
||||
}
|
||||
|
||||
#else
|
||||
DWORD ptr, count;
|
||||
bool IsWin8OrGreater = RtlIsWindowsVersionOrGreater(6, 2, 0);
|
||||
ULONG Index = IsWin8OrGreater ? 1 : 0;
|
||||
|
||||
if (InvertedTable->Count == InvertedTable->MaxCount) {
|
||||
if (IsWin8OrGreater)InvertedTable->NextEntrySEHandlerTableEncoded = TRUE;
|
||||
else InvertedTable->Overflow = TRUE;
|
||||
return;
|
||||
}
|
||||
while (Index < InvertedTable->Count) {
|
||||
if (ImageBase < (IsWin8OrGreater ?
|
||||
((PRTL_INVERTED_FUNCTION_TABLE_ENTRY_64)&InvertedTable->Entries[Index])->ImageBase :
|
||||
InvertedTable->Entries[Index].ImageBase))
|
||||
break;
|
||||
Index++;
|
||||
}
|
||||
if (Index != InvertedTable->Count) {
|
||||
if (IsWin8OrGreater) {
|
||||
RtlMoveMemory(&InvertedTable->Entries[Index + 1], &InvertedTable->Entries[Index],
|
||||
(InvertedTable->Count - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY));
|
||||
}
|
||||
else {
|
||||
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 (IsWin8OrGreater) {
|
||||
//memory layout is same as x64
|
||||
PRTL_INVERTED_FUNCTION_TABLE_ENTRY_64 entry = (decltype(entry))&InvertedTable->Entries[Index];
|
||||
entry->ExceptionDirectory = (PIMAGE_RUNTIME_FUNCTION_ENTRY)RtlEncodeSystemPointer((PVOID)ptr);
|
||||
entry->ExceptionDirectorySize = count;
|
||||
entry->ImageBase = ImageBase;
|
||||
entry->ImageSize = SizeOfImage;
|
||||
}
|
||||
else {
|
||||
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 IsWin8OrGreater = RtlIsWindowsVersionOrGreater(6, 2, 0);
|
||||
|
||||
CurrentSize = InvertedTable->Count;
|
||||
for (Index = 0; Index < CurrentSize; Index += 1) {
|
||||
if (ImageBase == (IsWin8OrGreater ?
|
||||
((PRTL_INVERTED_FUNCTION_TABLE_ENTRY_64)&InvertedTable->Entries[Index])->ImageBase :
|
||||
InvertedTable->Entries[Index].ImageBase))
|
||||
break;
|
||||
}
|
||||
|
||||
if (Index != CurrentSize) {
|
||||
//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
|
||||
if (IsWin8OrGreater) {
|
||||
RtlMoveMemory(&InvertedTable->Entries[Index], &InvertedTable->Entries[Index + 1],
|
||||
(CurrentSize - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY));
|
||||
}
|
||||
else {
|
||||
RtlMoveMemory(
|
||||
Index ? &InvertedTable->Entries[Index - 1].NextEntrySEHandlerTableEncoded : (PVOID)&InvertedTable->NextEntrySEHandlerTableEncoded,
|
||||
&InvertedTable->Entries[Index].NextEntrySEHandlerTableEncoded,
|
||||
(CurrentSize - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
InvertedTable->Count--;
|
||||
//if (need)_InterlockedIncrement(&InvertedTable->Epoch);
|
||||
}
|
||||
|
||||
if (InvertedTable->Count != InvertedTable->MaxCount) {
|
||||
if (IsWin8OrGreater) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_64(InvertedTable)->Overflow = FALSE;
|
||||
}
|
||||
else {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_WIN7_32(InvertedTable)->Overflow = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
PVOID FindLdrpInvertedFunctionTable32() {
|
||||
// _RTL_INVERTED_FUNCTION_TABLE x86
|
||||
// Count +0x0 ????????
|
||||
// MaxCount +0x4 0x00000200
|
||||
// Overflow +0x8 0x00000000(Win7) ????????(Win10)
|
||||
// NextEntrySEHandlerTableEncoded +0xc 0x00000000(Win10) ++++++++(Win7)
|
||||
// _RTL_INVERTED_FUNCTION_TABLE_ENTRY[0] +0x10 ntdll.dll(win10) or The smallest base module
|
||||
// ImageBase +0x10 ++++++++
|
||||
// ImageSize +0x14 ++++++++
|
||||
// SEHandlerCount +0x18 ++++++++
|
||||
// NextEntrySEHandlerTableEncoded +0x1c ++++++++(Win10) ????????(Win7)
|
||||
// _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_WIN7_32 entry{};
|
||||
LPCSTR lpSectionName = ".data";
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof(entry) };
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InMemoryOrderModuleList,
|
||||
ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
DWORD SEHTable, SEHCount;
|
||||
BYTE Offset = 0x20; //sizeof(_RTL_INVERTED_FUNCTION_TABLE_ENTRY)*2
|
||||
|
||||
if (RtlIsWindowsVersionOrGreater(6, 3, 0)) lpSectionName = ".mrdata";
|
||||
else if (!RtlIsWindowsVersionOrGreater(6, 2, 0)) Offset = 0xC;
|
||||
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (RtlIsModuleUnloaded(CurEntry))continue; //skip unloaded module
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue; //skip our memory module.
|
||||
if (CurEntry->DllBase == hNtdll && Offset == 0x20)continue; //Win10 skip first entry, if the base of ntdll is smallest.
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return nullptr;
|
||||
|
||||
RtlCaptureImageExceptionValues(hModule, &SEHTable, &SEHCount);
|
||||
entry = { RtlEncodeSystemPointer((PVOID)SEHTable),(DWORD)hModule,ModuleHeaders->OptionalHeader.SizeOfImage,(PVOID)SEHCount };
|
||||
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(hNtdll, lpSectionName, &SearchContext))) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_WIN7_32 tab = decltype(tab)(SearchContext.OutBufferPtr - Offset);
|
||||
|
||||
//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 tab;
|
||||
else if (tab->MaxCount == 0x200 && !tab->Overflow) return tab;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
PVOID FindLdrpInvertedFunctionTable64() {
|
||||
// _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_64 entry{};
|
||||
LPCSTR lpSectionName = ".data";
|
||||
PIMAGE_DATA_DIRECTORY dir = nullptr;
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = &entry,SearchContext.BufferLength = sizeof(entry) };
|
||||
|
||||
//Windows 8
|
||||
if (RtlVerifyVersion(6, 2, 0, RTL_VERIFY_FLAGS_MAJOR_VERSION | RTL_VERIFY_FLAGS_MINOR_VERSION)) {
|
||||
hModule = hNtdll;
|
||||
ModuleHeaders = NtdllHeaders;
|
||||
//lpSectionName = ".data";
|
||||
}
|
||||
//Windows 8.1 ~ Windows 10
|
||||
else if (RtlIsWindowsVersionOrGreater(6, 3, 0)) {
|
||||
hModule = hNtdll;
|
||||
ModuleHeaders = NtdllHeaders;
|
||||
lpSectionName = ".mrdata";
|
||||
}
|
||||
else {
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList,
|
||||
ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
//Make sure the smallest base address is not our memory module
|
||||
if (IsValidMemoryModuleHandle((HMEMORYMODULE)CurEntry->DllBase))continue;
|
||||
hModule = (HMODULE)(hModule ? min(hModule, CurEntry->DllBase) : CurEntry->DllBase);
|
||||
}
|
||||
ModuleHeaders = RtlImageNtHeader(hModule);
|
||||
}
|
||||
|
||||
if (!hModule || !ModuleHeaders || !hNtdll || !NtdllHeaders)return 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
|
||||
};
|
||||
|
||||
while (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(hNtdll, lpSectionName, &SearchContext))) {
|
||||
PRTL_INVERTED_FUNCTION_TABLE_64 tab = decltype(tab)(SearchContext.OutBufferPtr - 0x10);
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0) && tab->MaxCount == 0x200 && !tab->Overflow) return tab;
|
||||
else if (tab->MaxCount == 0x200 && !tab->Epoch) return tab;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
PVOID NTAPI RtlFindLdrpInvertedFunctionTable() {
|
||||
static PVOID LdrpInvertedFunctionTable = FindLdrpInvertedFunctionTable();
|
||||
return LdrpInvertedFunctionTable;
|
||||
}
|
||||
static NTSTATUS NTAPI RtlProtectMrdata(IN SIZE_T Protect) {
|
||||
static PVOID MrdataBase = nullptr;
|
||||
static SIZE_T size = 0;
|
||||
NTSTATUS status;
|
||||
PVOID tmp;
|
||||
SIZE_T tmp_len;
|
||||
SIZE_T old;
|
||||
|
||||
if (!MrdataBase) {
|
||||
MEMORY_BASIC_INFORMATION mbi{};
|
||||
status = NtQueryVirtualMemory(GetCurrentProcess(), RtlFindLdrpInvertedFunctionTable(), MemoryBasicInformation, &mbi, sizeof(mbi), nullptr);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
MrdataBase = mbi.BaseAddress;
|
||||
size = mbi.RegionSize;
|
||||
}
|
||||
|
||||
tmp = MrdataBase;
|
||||
tmp_len = size;
|
||||
return NtProtectVirtualMemory(GetCurrentProcess(), &tmp, &tmp_len, Protect, &old);
|
||||
}
|
||||
|
||||
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(6, 3, 0);
|
||||
NTSTATUS status;
|
||||
|
||||
if (need_virtual_protect) {
|
||||
status = RtlProtectMrdata(PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
}
|
||||
RtlpInsertInvertedFunctionTable(table, BaseAddress, ImageSize);
|
||||
if (need_virtual_protect) {
|
||||
status = RtlProtectMrdata(PAGE_READONLY);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
}
|
||||
return (RtlIsWindowsVersionOrGreater(6, 2, 0) ? PRTL_INVERTED_FUNCTION_TABLE_64(table)->Overflow : PRTL_INVERTED_FUNCTION_TABLE_WIN7_32(table)->Overflow) ?
|
||||
STATUS_NO_MEMORY : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase) {
|
||||
static auto table = PRTL_INVERTED_FUNCTION_TABLE(RtlFindLdrpInvertedFunctionTable());
|
||||
bool need_virtual_protect = RtlIsWindowsVersionOrGreater(6, 3, 0);
|
||||
NTSTATUS status;
|
||||
|
||||
if (need_virtual_protect) {
|
||||
status = RtlProtectMrdata(PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
}
|
||||
RtlpRemoveInvertedFunctionTable(table, ImageBase);
|
||||
if (need_virtual_protect) {
|
||||
status = RtlProtectMrdata(PAGE_READONLY);
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_64 {
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY ExceptionDirectory;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
ULONG ExceptionDirectorySize;
|
||||
} 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_64 Entries[0x200];
|
||||
} RTL_INVERTED_FUNCTION_TABLE_64, * PRTL_INVERTED_FUNCTION_TABLE_64;
|
||||
|
||||
// The correct data structure should be this.
|
||||
//
|
||||
//typedef struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 {
|
||||
// PVOID EntrySEHandlerTableEncoded;
|
||||
// PVOID ImageBase;
|
||||
// ULONG ImageSize;
|
||||
// ULONG SEHandlerCount;
|
||||
//} 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;
|
||||
// RTL_INVERTED_FUNCTION_TABLE_ENTRY_WIN7_32 Entries[0x200];
|
||||
//} RTL_INVERTED_FUNCTION_TABLE_WIN7_32, * PRTL_INVERTED_FUNCTION_TABLE_WIN7_32;
|
||||
//
|
||||
//
|
||||
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
|
||||
|
||||
PVOID NTAPI RtlFindLdrpInvertedFunctionTable();
|
||||
|
||||
NTSTATUS NTAPI RtlInsertInvertedFunctionTable(IN PVOID BaseAddress, IN size_t ImageSize);
|
||||
NTSTATUS NTAPI RtlRemoveInvertedFunctionTable(IN PVOID ImageBase);
|
||||
|
||||
|
||||
#ifdef _WIN64
|
||||
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable64
|
||||
#else
|
||||
#define FindLdrpInvertedFunctionTable FindLdrpInvertedFunctionTable32
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "rtlldr.h"
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
VOID NTAPI RtlRbInsertNodeEx(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Parent, IN BOOLEAN Right, OUT PRTL_BALANCED_NODE Node) {
|
||||
decltype(&RtlRbInsertNodeEx)_RtlRbInsertNodeEx = decltype(_RtlRbInsertNodeEx)(RtlGetNtProcAddress("RtlRbInsertNodeEx"));
|
||||
if (!_RtlRbInsertNodeEx)return;
|
||||
return _RtlRbInsertNodeEx(Tree, Parent, Right, Node);
|
||||
}
|
||||
VOID NTAPI RtlRbRemoveNode(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Node) {
|
||||
decltype(&RtlRbRemoveNode)_RtlRbRemoveNode = decltype(_RtlRbRemoveNode)(RtlGetNtProcAddress("RtlRbRemoveNode"));
|
||||
if (!_RtlRbRemoveNode)return;
|
||||
return _RtlRbRemoveNode(Tree, Node);
|
||||
}
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByHandle(PVOID BaseAddress) {
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList, ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry;
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (CurEntry->DllBase == BaseAddress) {
|
||||
return CurEntry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByBaseName(PCWSTR BaseName) {
|
||||
PLIST_ENTRY ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList, ListEntry = ListHead->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry;
|
||||
while (ListEntry != ListHead) {
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
ListEntry = ListEntry->Flink;
|
||||
if (!wcsnicmp(BaseName, CurEntry->BaseDllName.Buffer, (CurEntry->BaseDllName.Length / sizeof(wchar_t)) - 4) ||
|
||||
!wcsnicmp(BaseName, CurEntry->BaseDllName.Buffer, CurEntry->BaseDllName.Length / sizeof(wchar_t))) {
|
||||
return CurEntry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ULONG NTAPI LdrHashEntry(IN const UNICODE_STRING& str, IN bool _xor) {
|
||||
ULONG result = 0;
|
||||
if (RtlIsWindowsVersionOrGreater(6, 2, 0)) {
|
||||
RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_DEFAULT, &result);
|
||||
}
|
||||
else {
|
||||
for (USHORT i = 0; i < (str.Length / sizeof(wchar_t)); ++i)
|
||||
result += 0x1003F * RtlUpcaseUnicodeChar(str.Buffer[i]);
|
||||
}
|
||||
if (_xor)result &= (LDR_HASH_TABLE_ENTRIES - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
HANDLE NTAPI RtlFindLdrpHeap() {
|
||||
PLIST_ENTRY ListHead, ListEntry;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry;
|
||||
MEMORY_BASIC_INFORMATION mbi{};
|
||||
static HANDLE result = nullptr;
|
||||
if (result)return result;
|
||||
|
||||
ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
|
||||
ListEntry = ListHead->Flink;
|
||||
if (ListHead == ListEntry)return result;
|
||||
CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||
NtQueryVirtualMemory(NtCurrentProcess(), CurEntry, MemoryBasicInformation, &mbi, sizeof(mbi), (PSIZE_T)&ListHead);
|
||||
return result = mbi.AllocationBase;
|
||||
}
|
||||
|
||||
PLIST_ENTRY NTAPI RtlFindLdrpHashTable() {
|
||||
static PLIST_ENTRY list = nullptr;
|
||||
if (list) return list;
|
||||
|
||||
PLIST_ENTRY head = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList, entry = head->Flink;
|
||||
PLDR_DATA_TABLE_ENTRY CurEntry = nullptr;
|
||||
while (head != entry) {
|
||||
CurEntry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, LDR_DATA_TABLE_ENTRY::InInitializationOrderLinks);
|
||||
entry = entry->Flink;
|
||||
if (CurEntry->HashLinks.Flink == &CurEntry->HashLinks)continue;
|
||||
list = CurEntry->HashLinks.Flink;
|
||||
if (list->Flink == &CurEntry->HashLinks) {
|
||||
list = (decltype(list))((size_t)CurEntry->HashLinks.Flink - LdrHashEntry(CurEntry->BaseDllName) * sizeof(_LIST_ENTRY));
|
||||
break;
|
||||
}
|
||||
list = nullptr;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
PVOID NTAPI RtlAllocateLdrpHeap(IN size_t size) {
|
||||
HANDLE heap = RtlFindLdrpHeap();
|
||||
if (!heap)return nullptr;
|
||||
|
||||
return RtlAllocateHeap(heap, HEAP_ZERO_MEMORY, size);
|
||||
}
|
||||
|
||||
BOOL NTAPI RtlFreeLdrpHeap(IN PVOID buffer) {
|
||||
HANDLE LdrpHeap = RtlFindLdrpHeap();
|
||||
if (!LdrpHeap)return FALSE;
|
||||
return RtlFreeHeap(LdrpHeap, 0, buffer);
|
||||
}
|
||||
|
||||
|
||||
size_t NTAPI LdrpDataTableEntrySize() {
|
||||
static size_t size = 0;
|
||||
if (size)return size;
|
||||
|
||||
switch (NtWindowsVersion()) {
|
||||
case xp:return size = sizeof(LDR_DATA_TABLE_ENTRY_XP);
|
||||
case vista:return size = sizeof(LDR_DATA_TABLE_ENTRY_VISTA);
|
||||
case win7:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN7);
|
||||
case win8:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN8);
|
||||
case win8_1:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN8_1);
|
||||
case win10:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN10);
|
||||
case win10_1:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_1);
|
||||
case win10_2:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_2);
|
||||
default:return size = sizeof(LDR_DATA_TABLE_ENTRY_WIN10_2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByHandle(PVOID BaseAddress);
|
||||
|
||||
PLDR_DATA_TABLE_ENTRY NTAPI RtlFindLdrTableEntryByBaseName(PCWSTR BaseName);
|
||||
|
||||
#define RtlFindNtdllLdrEntry() RtlFindLdrTableEntryByBaseName(L"ntdll.dll")
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Loader Data Table Entry Flags
|
||||
//
|
||||
#define LDRP_STATIC_LINK 0x00000002
|
||||
#define LDRP_IMAGE_DLL 0x00000004
|
||||
#define LDRP_SHIMENG_SUPPRESSED_ENTRY 0x00000008
|
||||
#define LDRP_IMAGE_INTEGRITY_FORCED 0x00000020
|
||||
#define LDRP_LOAD_IN_PROGRESS 0x00001000
|
||||
#define LDRP_UNLOAD_IN_PROGRESS 0x00002000
|
||||
#define LDRP_ENTRY_PROCESSED 0x00004000
|
||||
#define LDRP_ENTRY_INSERTED 0x00008000
|
||||
#define LDRP_CURRENT_LOAD 0x00010000
|
||||
#define LDRP_FAILED_BUILTIN_LOAD 0x00020000
|
||||
#define LDRP_DONT_CALL_FOR_THREADS 0x00040000
|
||||
#define LDRP_PROCESS_ATTACH_CALLED 0x00080000
|
||||
#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000
|
||||
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000
|
||||
#define LDRP_COR_IMAGE 0x00400000
|
||||
#define LDR_COR_OWNS_UNMAP 0x00800000
|
||||
#define LDRP_SYSTEM_MAPPED 0x01000000
|
||||
#define LDRP_IMAGE_VERIFYING 0x02000000
|
||||
#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000
|
||||
#define LDRP_ENTRY_NATIVE 0x08000000
|
||||
#define LDRP_REDIRECTED 0x10000000
|
||||
#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000
|
||||
#define LDRP_MM_LOADED 0x40000000
|
||||
#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000
|
||||
|
||||
#define LDR_GET_HASH_ENTRY(x) (RtlUpcaseUnicodeChar((x)) & (LDR_HASH_TABLE_ENTRIES - 1))
|
||||
#define LDR_HASH_TABLE_ENTRIES 32
|
||||
|
||||
//0x18 bytes (sizeof)
|
||||
typedef struct _RTL_BALANCED_NODE {
|
||||
union {
|
||||
_RTL_BALANCED_NODE* Children[2]; //0x0
|
||||
struct {
|
||||
_RTL_BALANCED_NODE* Left; //0x0
|
||||
_RTL_BALANCED_NODE* Right; //0x8
|
||||
};
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
UCHAR Red : 1; //0x10
|
||||
UCHAR Balance : 2; //0x10
|
||||
};
|
||||
size_t ParentValue; //0x10
|
||||
};
|
||||
}RTL_BALANCED_NODE, * PRTL_BALANCED_NODE;
|
||||
|
||||
typedef struct _RTL_RB_TREE {
|
||||
PRTL_BALANCED_NODE Root;
|
||||
PRTL_BALANCED_NODE Min;
|
||||
} RTL_RB_TREE, * PRTL_RB_TREE;
|
||||
|
||||
// RtlRbInsertNodeEx
|
||||
VOID NTAPI RtlRbInsertNodeEx(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Parent, IN BOOLEAN Right, OUT PRTL_BALANCED_NODE Node);
|
||||
// RtlRbRemoveNode
|
||||
VOID NTAPI RtlRbRemoveNode(IN PRTL_RB_TREE Tree, IN PRTL_BALANCED_NODE Node);
|
||||
|
||||
enum _LDR_DLL_LOAD_REASON {
|
||||
LoadReasonStaticDependency = 0,
|
||||
LoadReasonStaticForwarderDependency = 1,
|
||||
LoadReasonDynamicForwarderDependency = 2,
|
||||
LoadReasonDelayloadDependency = 3,
|
||||
LoadReasonDynamicLoad = 4,
|
||||
LoadReasonAsImageLoad = 5,
|
||||
LoadReasonAsDataLoad = 6,
|
||||
LoadReasonUnknown = -1
|
||||
};
|
||||
|
||||
//0x10 bytes (sizeof)
|
||||
struct _LDR_SERVICE_TAG_RECORD {
|
||||
_LDR_SERVICE_TAG_RECORD* Next; //0x0
|
||||
ULONG ServiceTag; //0x8
|
||||
};
|
||||
//0x8 bytes (sizeof)
|
||||
struct _LDRP_CSLIST {
|
||||
struct _LDRP_CSLIST_DEPENDENT {
|
||||
_SINGLE_LIST_ENTRY* NextDependentEntry; //0x0
|
||||
struct _LDR_DDAG_NODE* DependentDdagNode;
|
||||
}Dependent;
|
||||
struct _LDRP_CSLIST_INCOMMING {
|
||||
_SINGLE_LIST_ENTRY* NextIncommingEntry;
|
||||
struct _LDR_DDAG_NODE* IncommingDdagNode;
|
||||
}Incomming;
|
||||
};
|
||||
//0x4 bytes (sizeof)
|
||||
enum _LDR_DDAG_STATE {
|
||||
LdrModulesMerged = -5,
|
||||
LdrModulesInitError = -4,
|
||||
LdrModulesSnapError = -3,
|
||||
LdrModulesUnloaded = -2,
|
||||
LdrModulesUnloading = -1,
|
||||
LdrModulesPlaceHolder = 0,
|
||||
LdrModulesMapping = 1,
|
||||
LdrModulesMapped = 2,
|
||||
LdrModulesWaitingForDependencies = 3,
|
||||
LdrModulesSnapping = 4,
|
||||
LdrModulesSnapped = 5,
|
||||
LdrModulesCondensed = 6,
|
||||
LdrModulesReadyToInit = 7,
|
||||
LdrModulesInitializing = 8,
|
||||
LdrModulesReadyToRun = 9
|
||||
};
|
||||
//0x50 bytes (sizeof)
|
||||
struct _LDR_DDAG_NODE {
|
||||
_LIST_ENTRY Modules; //0x0
|
||||
_LDR_SERVICE_TAG_RECORD* ServiceTagList; //0x10
|
||||
ULONG LoadCount; //0x18
|
||||
ULONG LoadWhileUnloadingCount; //0x1c
|
||||
ULONG LowestLink; //0x20
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_DEPENDENT* Dependencies; //0x28
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_INCOMMING* IncomingDependencies; //0x30
|
||||
_LDR_DDAG_STATE State; //0x38
|
||||
_SINGLE_LIST_ENTRY CondenseLink; //0x40
|
||||
ULONG PreorderNumber; //0x48
|
||||
};
|
||||
struct _LDR_DDAG_NODE_WIN8 {
|
||||
_LIST_ENTRY Modules; //0x0
|
||||
_LDR_SERVICE_TAG_RECORD* ServiceTagList; //0x10
|
||||
ULONG LoadCount; //0x18
|
||||
ULONG ReferenceCount; //0x1c
|
||||
ULONG DependencyCount; //0x20
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_DEPENDENT* Dependencies; //0x28
|
||||
_LDRP_CSLIST::_LDRP_CSLIST_INCOMMING* IncomingDependencies; //0x30
|
||||
_LDR_DDAG_STATE State; //0x38
|
||||
_SINGLE_LIST_ENTRY CondenseLink; //0x40
|
||||
ULONG PreorderNumber; //0x48
|
||||
ULONG LowestLink; //0x4c
|
||||
};
|
||||
|
||||
//5.1.2600 Windows XP SP3
|
||||
//5.2.3790 Windows XP | 2003 SP2
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_XP {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
ULONG Flags; //0x68
|
||||
USHORT LoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
union {
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
struct {
|
||||
VOID* SectionPointer; //0x70
|
||||
ULONG CheckSum; //0x78
|
||||
};
|
||||
};
|
||||
union {
|
||||
ULONG TimeDateStamp; //0x80
|
||||
VOID* LoadedImports; //0x80
|
||||
};
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* PatchInformation; //0x90
|
||||
}LDR_DATA_TABLE_ENTRY_XP, * PLDR_DATA_TABLE_ENTRY_XP;
|
||||
|
||||
//6.0.6000 Vista | 2008 RTM
|
||||
//6.0.6001 Vista | 2008 SP1
|
||||
//6.0.6002 Vista | 2008 SP2
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_VISTA :public _LDR_DATA_TABLE_ENTRY_XP {
|
||||
_LIST_ENTRY ForwarderLinks; //0x98
|
||||
_LIST_ENTRY ServiceTagLinks; //0xa8
|
||||
_LIST_ENTRY StaticLinks; //0xb8
|
||||
}LDR_DATA_TABLE_ENTRY_VISTA, * PLDR_DATA_TABLE_ENTRY_VISTA;
|
||||
|
||||
//6.1.7600 Windows 7 | 2008R2 SP1
|
||||
//6.1.7601 Windows 7 | 2008R2 RTM
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN7 :public _LDR_DATA_TABLE_ENTRY_VISTA {
|
||||
VOID* ContextInformation; //0xc8
|
||||
ULONGLONG OriginalBase; //0xd0
|
||||
_LARGE_INTEGER LoadTime; //0xd8
|
||||
}LDR_DATA_TABLE_ENTRY_WIN7, * PLDR_DATA_TABLE_ENTRY_WIN7;
|
||||
|
||||
//6.2.9200 Windows 8 | 2012 RTM
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN8 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
union {
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
_LIST_ENTRY InProgressLinks; //0x20
|
||||
};
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
union {
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
struct {
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG ReservedFlags2 : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ReservedFlags3 : 3; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ReservedFlags5 : 3; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* PatchInformation; //0x90
|
||||
_LDR_DDAG_NODE_WIN8* DdagNode; //0x98
|
||||
_LIST_ENTRY NodeModuleLink; //0xa0
|
||||
VOID* SnapContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
_LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
_LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
}LDR_DATA_TABLE_ENTRY_WIN8, * PLDR_DATA_TABLE_ENTRY_WIN8;
|
||||
|
||||
//6.3.9600 Windows 8.1 | 2012R2 RTM | 2012R2 Update 1
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN8_1 :public _LDR_DATA_TABLE_ENTRY_WIN8 {
|
||||
ULONG ImplicitPathOptions;
|
||||
}LDR_DATA_TABLE_ENTRY_WIN8_1, * PLDR_DATA_TABLE_ENTRY_WIN8_1;
|
||||
|
||||
//10.0.10240 Windows 10 | 2016 1507 Threshold 1
|
||||
//10.0.10586 Windows 10 | 2016 1511 Threshold 2
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
union {
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
struct {
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG LoadConfigProcessed : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ProtectDelayLoad : 1; //0x68
|
||||
ULONG ReservedFlags3 : 2; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ReservedFlags5 : 3; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* Lock; //0x90
|
||||
_LDR_DDAG_NODE* DdagNode; //0x98
|
||||
_LIST_ENTRY NodeModuleLink; //0xa0
|
||||
VOID* LoadContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
_LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
_LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
ULONG ImplicitPathOptions; //0x110
|
||||
ULONG ReferenceCount; //0x114
|
||||
}LDR_DATA_TABLE_ENTRY_WIN10, * PLDR_DATA_TABLE_ENTRY_WIN10;
|
||||
|
||||
//10.0.14393 Windows 10 | 2016 1607 Redstone 1 (Anniversary Update)
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_1 :public _LDR_DATA_TABLE_ENTRY_WIN10 {
|
||||
ULONG DependentLoadFlags; //0x118
|
||||
}LDR_DATA_TABLE_ENTRY_WIN10_1, * PLDR_DATA_TABLE_ENTRY_WIN10_1;
|
||||
|
||||
//10.0.15063 Windows 10 | 2016 1703 Redstone 2 (Creators Update)
|
||||
//10.0.16299 Windows 10 | 2016 1709 Redstone 3 (Fall Creators Update)
|
||||
//10.0.17134 Windows 10 | 2016 1803 Redstone 4 (Spring Creators Update)
|
||||
//10.0.17763 Windows 10 | 2016 1809 Redstone 5 (October Update)
|
||||
//10.0.18362 Windows 10 | 2016 1903 19H1 (May 2019 Update) | 2016 1909 19H2 (November 2019 Update)
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY_WIN10_2 {
|
||||
_LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
_LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
_LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
_UNICODE_STRING FullDllName; //0x48
|
||||
_UNICODE_STRING BaseDllName; //0x58
|
||||
union {
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
struct {
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG LoadConfigProcessed : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ProtectDelayLoad : 1; //0x68
|
||||
ULONG ReservedFlags3 : 2; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ReservedFlags5 : 3; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
_LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
_ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* Lock; //0x90
|
||||
_LDR_DDAG_NODE* DdagNode; //0x98
|
||||
_LIST_ENTRY NodeModuleLink; //0xa0
|
||||
VOID* LoadContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
_LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
_LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
ULONG ImplicitPathOptions; //0x110
|
||||
ULONG ReferenceCount; //0x114
|
||||
ULONG DependentLoadFlags; //0x118
|
||||
UCHAR SigningLevel; //0x11c
|
||||
}LDR_DATA_TABLE_ENTRY_WIN10_2, * PLDR_DATA_TABLE_ENTRY_WIN10_2;
|
||||
|
||||
ULONG NTAPI LdrHashEntry(IN const UNICODE_STRING& str, IN bool _xor = true);
|
||||
|
||||
HANDLE NTAPI RtlFindLdrpHeap();
|
||||
|
||||
PLIST_ENTRY NTAPI RtlFindLdrpHashTable();
|
||||
|
||||
PVOID NTAPI RtlAllocateLdrpHeap(IN size_t size);
|
||||
|
||||
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();
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#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
|
||||
|
||||
NTSTATUS NTAPI RtlFindMemoryBlockFromModuleSection(
|
||||
IN HMODULE hModule OPTIONAL,
|
||||
IN LPCSTR lpSectionName OPTIONAL,
|
||||
IN OUT PSEARCH_CONTEXT SearchContext) {
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
size_t begin = 0, buffer = 0;
|
||||
DWORD Length = 0, bufferLength = 0;
|
||||
|
||||
__try {
|
||||
begin = SearchContext->OutBufferPtr;
|
||||
Length = SearchContext->RemainingLength;
|
||||
buffer = SearchContext->InBufferPtr;
|
||||
bufferLength = SearchContext->BufferLength;
|
||||
if (!buffer || !bufferLength) {
|
||||
SearchContext->OutBufferPtr = 0;
|
||||
SearchContext->RemainingLength = 0;
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (!begin) {
|
||||
PIMAGE_NT_HEADERS headers = RtlImageNtHeader(hModule);
|
||||
PIMAGE_SECTION_HEADER section = nullptr;
|
||||
if (!headers)return STATUS_INVALID_PARAMETER_1;
|
||||
section = IMAGE_FIRST_SECTION(headers);
|
||||
for (WORD i = 0; i < headers->FileHeader.NumberOfSections; ++i) {
|
||||
if (!_stricmp(lpSectionName, (LPCSTR)section->Name)) {
|
||||
begin = SearchContext->OutBufferPtr = (size_t)hModule + section->VirtualAddress;
|
||||
Length = SearchContext->RemainingLength = section->Misc.VirtualSize;
|
||||
break;
|
||||
}
|
||||
++section;
|
||||
}
|
||||
if (!begin || !Length || Length < bufferLength) {
|
||||
SearchContext->OutBufferPtr = 0;
|
||||
SearchContext->RemainingLength = 0;
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else {
|
||||
begin++;
|
||||
Length--;
|
||||
}
|
||||
status = STATUS_NOT_FOUND;
|
||||
for (DWORD i = 0; i < Length - bufferLength; ++begin, ++i) {
|
||||
if (RtlCompareMemory((PVOID)begin, (PVOID)buffer, bufferLength) == bufferLength) {
|
||||
SearchContext->OutBufferPtr = begin;
|
||||
--SearchContext->RemainingLength;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
}
|
||||
|
||||
SearchContext->OutBufferPtr = 0;
|
||||
SearchContext->RemainingLength = 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _WIN64
|
||||
#undef RtlCompareMemory
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
typedef struct _SEARCH_CONTEXT {
|
||||
union {
|
||||
IN PVOID MemoryBuffer;
|
||||
size_t InBufferPtr;
|
||||
};
|
||||
union {
|
||||
IN DWORD BufferLength;
|
||||
size_t reserved0;
|
||||
};
|
||||
|
||||
union {
|
||||
OUT PVOID MemoryBlockInSection;
|
||||
size_t OutBufferPtr;
|
||||
};
|
||||
union {
|
||||
DWORD RemainingLength;
|
||||
size_t reserved1;
|
||||
};
|
||||
}SEARCH_CONTEXT, * PSEARCH_CONTEXT;
|
||||
|
||||
NTSTATUS NTAPI RtlFindMemoryBlockFromModuleSection(
|
||||
IN HMODULE hModule OPTIONAL,
|
||||
IN LPCSTR lpSectionName OPTIONAL,
|
||||
IN OUT PSEARCH_CONTEXT SearchContext
|
||||
);
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
static NTSTATUS NTAPI LdrpHandleTlsDataXp(PLDR_DATA_TABLE_ENTRY LdrEntry) {
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall) {
|
||||
static PVOID _LdrpHandleTlsData_ = (PVOID)~0;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
__try {
|
||||
if (_LdrpHandleTlsData_ != (PVOID)~0) {
|
||||
*_LdrpHandleTlsData = _LdrpHandleTlsData_;
|
||||
if (_LdrpHandleTlsData_ == nullptr)status = STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
else {
|
||||
*_LdrpHandleTlsData = _LdrpHandleTlsData_ = nullptr;
|
||||
*stdcall = false;
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
status = GetExceptionCode();
|
||||
}
|
||||
if (!NT_SUCCESS(status))return status;
|
||||
|
||||
DWORD Versions[3]{};
|
||||
LPCVOID Feature = nullptr;
|
||||
BYTE Size = 0;
|
||||
WORD OffsetOfFunctionBegin = 0;
|
||||
RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2);
|
||||
switch (Versions[0]) {
|
||||
case 10: {
|
||||
if (Versions[1])return STATUS_NOT_SUPPORTED;
|
||||
|
||||
//RS3
|
||||
if (Versions[2] >= 16299) {
|
||||
Size = 7;
|
||||
//19H2
|
||||
if (Versions[2] >= 18363)Feature = "\x74\x33\x44\x8D\x43\x09";
|
||||
//RS5
|
||||
else if (Versions[2] >= 17763) Feature = "\x8b\xc1\x8d\x4d\xbc\x51";
|
||||
//RS4
|
||||
else if (Versions[2] >= 17134) Feature = "\x33\xf6\x85\xc0\x79\x03";
|
||||
//RS3
|
||||
else Feature = "\x8b\xc1\x8d\x4d\xac\x51";
|
||||
#ifdef _WIN64
|
||||
//RS6(19H1)
|
||||
if (Versions[2] >= 18362) OffsetOfFunctionBegin = 0x46;
|
||||
//RS4
|
||||
else if (Versions[2] >= 17134) OffsetOfFunctionBegin = 0x44;
|
||||
//RS3
|
||||
else OffsetOfFunctionBegin = 0x43;
|
||||
#else
|
||||
//19H2
|
||||
if (Versions[2] == 18363) {
|
||||
Feature = "\x74\x25\x8b\xc1\x8d\x4d\xbc";
|
||||
OffsetOfFunctionBegin = 0x16;
|
||||
}
|
||||
//RS6(19H1)
|
||||
else if (Versions[2] == 18362) OffsetOfFunctionBegin = 0x2E;
|
||||
//RS5
|
||||
else if (Versions[2] >= 17763) OffsetOfFunctionBegin = 0x2C;
|
||||
//RS3,4
|
||||
else OffsetOfFunctionBegin = 0x18;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
//RS2
|
||||
else if (Versions[2] >= 15063) {
|
||||
Size = 7;
|
||||
#ifdef _WIN64
|
||||
OffsetOfFunctionBegin = 0x43;
|
||||
Feature = "\x74\x33\x44\x8d\x43\x09";
|
||||
#else
|
||||
OffsetOfFunctionBegin = 0x18;
|
||||
Feature = "\x8b\xc1\x8d\x4d\xbc\x51";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
// NO BREAK
|
||||
}
|
||||
case 6: {
|
||||
switch (Versions[1]) {
|
||||
//8.1
|
||||
case 3: {
|
||||
#ifdef _WIN64
|
||||
Size = 10;
|
||||
OffsetOfFunctionBegin = 0x43;
|
||||
Feature = "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38";
|
||||
#else
|
||||
Size = 8;
|
||||
OffsetOfFunctionBegin = 0x1B;
|
||||
Feature = "\x50\x6a\x09\x6a\x01\x8b\xc1";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
//8
|
||||
case 2: {
|
||||
#ifdef _WIN64
|
||||
Size = 9;
|
||||
OffsetOfFunctionBegin = 0x49;
|
||||
Feature = "\x48\x8b\x79\x30\x45\x8d\x66\x01";
|
||||
#else
|
||||
Size = 7;
|
||||
OffsetOfFunctionBegin = 0xC;
|
||||
Feature = "\x8b\x45\x08\x89\x45\xa0";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
//7
|
||||
case 1: {
|
||||
#ifdef _WIN64
|
||||
Size = 12;
|
||||
OffsetOfFunctionBegin = 0x27;
|
||||
Feature = "\x41\xb8\x09\x00\x00\x00\x48\x8d\x44\x24\x38";
|
||||
#else
|
||||
Size = 9;
|
||||
OffsetOfFunctionBegin = 0x14;
|
||||
Feature = "\x74\x20\x8d\x45\xd4\x50\x6a\x09";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
*_LdrpHandleTlsData = LdrpHandleTlsDataXp;
|
||||
*stdcall = true;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
SEARCH_CONTEXT SearchContext{ SearchContext.MemoryBuffer = const_cast<PVOID>(Feature),SearchContext.BufferLength = Size - 1 };
|
||||
if (NT_SUCCESS(RtlFindMemoryBlockFromModuleSection(GetModuleHandleW(L"ntdll.dll"), ".text", &SearchContext)))
|
||||
SearchContext.OutBufferPtr -= OffsetOfFunctionBegin;
|
||||
if (!(*_LdrpHandleTlsData = _LdrpHandleTlsData_ = SearchContext.MemoryBlockInSection))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);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
NTSTATUS NTAPI RtlFindLdrpHandleTlsData(PVOID* _LdrpHandleTlsData, bool* stdcall);
|
||||
|
||||
NTSTATUS NTAPI LdrpHandleTlsData(IN PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
bool NTAPI RtlVerifyVersion(IN DWORD MajorVersion, IN DWORD MinorVersion OPTIONAL, IN DWORD BuildNumber OPTIONAL, IN BYTE Flags) {
|
||||
DWORD Versions[3];
|
||||
RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2);
|
||||
if (Versions[0] == MajorVersion &&
|
||||
((Flags & RTL_VERIFY_FLAGS_MINOR_VERSION) ? Versions[1] == MinorVersion : true) &&
|
||||
((Flags & RTL_VERIFY_FLAGS_BUILD_NUMBERS) ? Versions[2] == BuildNumber : true))return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NTAPI RtlIsWindowsVersionOrGreater(IN DWORD MajorVersion, IN DWORD MinorVersion, IN DWORD BuildNumber) {
|
||||
static DWORD Versions[3]{};
|
||||
if (!Versions[0])RtlGetNtVersionNumbers(Versions, Versions + 1, Versions + 2);
|
||||
|
||||
if (Versions[0] == MajorVersion) {
|
||||
if (Versions[1] == MinorVersion) return Versions[2] >= BuildNumber;
|
||||
else return (Versions[1] > MinorVersion);
|
||||
}
|
||||
else return Versions[0] > MajorVersion;
|
||||
}
|
||||
|
||||
bool NTAPI RtlIsWindowsVersionInScope(
|
||||
IN DWORD MinMajorVersion, IN DWORD MinMinorVersion, IN DWORD MinBuildNumber,
|
||||
IN DWORD MaxMajorVersion, IN DWORD MaxMinorVersion, IN DWORD MaxBuildNumber) {
|
||||
return RtlIsWindowsVersionOrGreater(MinMajorVersion, MinMinorVersion, MinBuildNumber) &&
|
||||
!RtlIsWindowsVersionOrGreater(MaxMajorVersion, MaxMinorVersion, MaxBuildNumber);
|
||||
}
|
||||
|
||||
WINDOWS_VERSION NTAPI NtWindowsVersion() {
|
||||
static WINDOWS_VERSION version = null;
|
||||
DWORD versions[3]{};
|
||||
if (version)return version;
|
||||
RtlGetNtVersionNumbers(versions, versions + 1, versions + 2);
|
||||
|
||||
switch (versions[0]) {
|
||||
case 5: {
|
||||
switch (versions[1]) {
|
||||
case 1:return version = versions[2] == 2600 ? xp : invalid;
|
||||
case 2:return version = versions[2] == 3790 ? xp : invalid;
|
||||
default:break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6: {
|
||||
switch (versions[1]) {
|
||||
case 0: {
|
||||
switch (versions[2]) {
|
||||
case 6000:
|
||||
case 6001:
|
||||
case 6002:
|
||||
return version = vista;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1: {
|
||||
switch (versions[2]) {
|
||||
case 7600:
|
||||
case 7601:
|
||||
return version = win7;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: {
|
||||
if (versions[2] == 9200)return version = win8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: {
|
||||
if (versions[2] == 9600)return version = win8_1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10: {
|
||||
if (versions[1])break;
|
||||
switch (versions[2]) {
|
||||
case 10240:
|
||||
case 10586: return version = win10;
|
||||
case 14393: return version = win10_1;
|
||||
case 15063:
|
||||
case 16299:
|
||||
case 17134:
|
||||
case 17763:
|
||||
case 18362:return version = win10_2;
|
||||
default:if (RtlIsWindowsVersionOrGreater(versions[0], versions[1], 15063))return version = win10_2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return version = invalid;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
#define RTL_VERIFY_FLAGS_MAJOR_VERSION 0
|
||||
#define RTL_VERIFY_FLAGS_MINOR_VERSION 1
|
||||
#define RTL_VERIFY_FLAGS_BUILD_NUMBERS 2
|
||||
#define RTL_VERIFY_FLAGS_DEFAULT RTL_VERIFY_FLAGS_MAJOR_VERSION|RTL_VERIFY_FLAGS_MINOR_VERSION|RTL_VERIFY_FLAGS_BUILD_NUMBERS
|
||||
|
||||
bool NTAPI RtlVerifyVersion(IN DWORD MajorVersion, IN DWORD MinorVersion OPTIONAL, IN DWORD BuildNumber OPTIONAL, IN BYTE Flags);
|
||||
|
||||
bool NTAPI RtlIsWindowsVersionOrGreater(IN DWORD MajorVersion, IN DWORD MinorVersion, IN DWORD BuildNumber);
|
||||
|
||||
bool NTAPI RtlIsWindowsVersionInScope(
|
||||
IN DWORD MinMajorVersion, IN DWORD MinMinorVersion, IN DWORD MinBuildNumber,
|
||||
IN DWORD MaxMajorVersion, IN DWORD MaxMinorVersion, IN DWORD MaxBuildNumber
|
||||
);
|
||||
|
||||
|
||||
typedef enum _WINDOWS_VERSION {
|
||||
null,
|
||||
xp,
|
||||
vista,
|
||||
win7,
|
||||
win8,
|
||||
win8_1,
|
||||
win10,
|
||||
win10_1,
|
||||
win10_2,
|
||||
invalid
|
||||
}WINDOWS_VERSION;
|
||||
|
||||
WINDOWS_VERSION NTAPI NtWindowsVersion();
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#pragma warning (disable:4005)
|
||||
#ifndef WIN32_NO_STATUS
|
||||
#define WIN32_NO_STATUS
|
||||
#include <Windows.h>
|
||||
#undef WIN32_NO_STATUS
|
||||
#include <ntstatus.h>
|
||||
#endif
|
||||
#pragma warning (default:4005)
|
||||
|
||||
//memory module base support
|
||||
#include "MemoryModule.h"
|
||||
|
||||
//nt layer support
|
||||
#include "Native.h"
|
||||
|
||||
//memory block pattern search support
|
||||
#include "rtlsearch.h"
|
||||
|
||||
//windows nt version support
|
||||
#include "rtlver.h"
|
||||
|
||||
//LDR_DATA_TABLE_ENTRY
|
||||
#include "rtlldr.h"
|
||||
|
||||
//rtl inverted function table for exception handling
|
||||
#include "rtlinv.h"
|
||||
|
||||
//tls support
|
||||
#include "rtltls.h"
|
||||
|
||||
//MemoryModulePP api interface
|
||||
#include "NativeFunctionsInternal.h"
|
||||
|
||||
Reference in New Issue
Block a user