mirror of
https://github.com/BeneficialCode/WinArk.git
synced 2026-10-17 04:40:35 +08:00
848 lines
22 KiB
C
848 lines
22 KiB
C
#pragma once
|
|
|
|
#include "NtMmApi.h"
|
|
|
|
#define DEBUG_OBJECT_DELETE_PENDING (0x1) // Debug object is delete pending.
|
|
#define DEBUG_OBJECT_KILL_ON_CLOSE (0x2) // Kill all debugged processes on close
|
|
|
|
#define DEBUG_KILL_ON_CLOSE (0x01)
|
|
#define PROCESS_SUSPEND_RESUME (0x0800)
|
|
|
|
#define DEBUG_EVENT_READ (0x01) // Event had been seen by win32 app
|
|
#define DEBUG_EVENT_NOWAIT (0x02) // No waiter one this. Just free the pool
|
|
#define DEBUG_EVENT_INACTIVE (0x04) // The message is in inactive. It may be activated or deleted later
|
|
#define DEBUG_EVENT_RELEASE (0x08) // Release rundown protection on this thread
|
|
#define DEBUG_EVENT_PROTECT_FAILED (0x10) // Rundown protection failed to be acquired on this thread
|
|
#define DEBUG_EVENT_SUSPEND (0x20) // Resume thread on continue
|
|
|
|
// Used to signify that the delete APC has been queued or the
|
|
// thread has called PspExitThread itself.
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_TERMINATED 0x00000001UL
|
|
//
|
|
// Thread create failed
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_DEADTHREAD 0x00000002UL
|
|
//
|
|
// Debugger isn't shown this thread
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_HIDEFROMDBG 0x00000004UL
|
|
//
|
|
// Thread is impersonating
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_IMPERSONATING 0x00000008UL
|
|
//
|
|
// This is a system thread
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL
|
|
//
|
|
// Hard errors are disabled for this thread
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_HARD_ERRORS_DISABLED 0x00000020UL
|
|
//
|
|
// We should break in when this thread is terminated
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION 0x00000040UL
|
|
//
|
|
// This thread should skip sending its create thread message
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_SKIP_CREATION_MSG 0x00000080UL
|
|
//
|
|
// This thread should skip sending its final thread termination message
|
|
//
|
|
#define PS_CROSS_THREAD_FLAGS_SKIP_TERMINATION_MSG 0x00000100UL
|
|
|
|
#define IS_SYSTEM_THREAD(CrossThreadFlags) ((CrossThreadFlags&PS_CROSS_THREAD_FLAGS_SYSTEM)!=0)
|
|
//
|
|
// Debug Object Access Masks
|
|
//
|
|
#define DEBUG_OBJECT_WAIT_STATE_CHANGE 0x0001
|
|
#define DEBUG_OBJECT_ADD_REMOVE_PROCESS 0x0002
|
|
#define DEBUG_OBJECT_SET_INFORMATION 0x0004
|
|
#define DEBUG_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x0F)
|
|
|
|
#define PS_PROCESS_FLAGS_CREATE_REPORTED 0x00000001UL // Create process debug call has occurred
|
|
#define PS_PROCESS_FLAGS_NO_DEBUG_INHERIT 0x00000002UL // Don't inherit debug port
|
|
#define PS_PROCESS_FLAGS_PROCESS_EXITING 0x00000004UL // PspExitProcess entered
|
|
#define PS_PROCESS_FLAGS_PROCESS_DELETE 0x00000008UL // Delete process has been issued
|
|
#define PS_PROCESS_FLAGS_WOW64_SPLIT_PAGES 0x00000010UL // Wow64 split pages
|
|
#define PS_PROCESS_FLAGS_VM_DELETED 0x00000020UL // VM is deleted
|
|
#define PS_PROCESS_FLAGS_OUTSWAP_ENABLED 0x00000040UL // Outswap enabled
|
|
#define PS_PROCESS_FLAGS_OUTSWAPPED 0x00000080UL // Outswapped
|
|
#define PS_PROCESS_FLAGS_FORK_FAILED 0x00000100UL // Fork status
|
|
#define PS_PROCESS_FLAGS_WOW64_4GB_VA_SPACE 0x00000200UL // Wow64 process with 4gb virtual address space
|
|
#define PS_PROCESS_FLAGS_ADDRESS_SPACE1 0x00000400UL // Addr space state1
|
|
#define PS_PROCESS_FLAGS_ADDRESS_SPACE2 0x00000800UL // Addr space state2
|
|
#define PS_PROCESS_FLAGS_SET_TIMER_RESOLUTION 0x00001000UL // SetTimerResolution has been called
|
|
#define PS_PROCESS_FLAGS_BREAK_ON_TERMINATION 0x00002000UL // Break on process termination
|
|
#define PS_PROCESS_FLAGS_CREATING_SESSION 0x00004000UL // Process is creating a session
|
|
#define PS_PROCESS_FLAGS_USING_WRITE_WATCH 0x00008000UL // Process is using the write watch APIs
|
|
#define PS_PROCESS_FLAGS_IN_SESSION 0x00010000UL // Process is in a session
|
|
#define PS_PROCESS_FLAGS_OVERRIDE_ADDRESS_SPACE 0x00020000UL // Process must use native address space (Win64 only)
|
|
#define PS_PROCESS_FLAGS_HAS_ADDRESS_SPACE 0x00040000UL // This process has an address space
|
|
#define PS_PROCESS_FLAGS_LAUNCH_PREFETCHED 0x00080000UL // Process launch was prefetched
|
|
#define PS_PROCESS_INJECT_INPAGE_ERRORS 0x00100000UL // Process should be given inpage errors - hardcoded in trap.asm too
|
|
#define PS_PROCESS_FLAGS_VM_TOP_DOWN 0x00200000UL // Process memory allocations default to top-down
|
|
#define PS_PROCESS_FLAGS_IMAGE_NOTIFY_DONE 0x00400000UL // We have sent a message for this image
|
|
#define PS_PROCESS_FLAGS_PDE_UPDATE_NEEDED 0x00800000UL // The system PDEs need updating for this process (NT32 only)
|
|
#define PS_PROCESS_FLAGS_VDM_ALLOWED 0x01000000UL // Process allowed to invoke NTVDM support
|
|
#define PS_PROCESS_FLAGS_SMAP_ALLOWED 0x02000000UL // Process allowed to invoke SMAP support
|
|
#define PS_PROCESS_FLAGS_CREATE_FAILED 0x04000000UL // Process create failed
|
|
|
|
#define PS_PROCESS_FLAGS_DEFAULT_IO_PRIORITY 0x38000000UL // The default I/O priority for created threads. (3 bits)
|
|
|
|
#define PS_PROCESS_FLAGS_PRIORITY_SHIFT 27
|
|
|
|
#define PS_SET_BITS(Flags, Flag) \
|
|
RtlInterlockedSetBitsDiscardReturn(Flags, Flag)
|
|
|
|
#define PS_TEST_SET_BITS(Flags, Flag) \
|
|
RtlInterlockedSetBits(Flags, Flag)
|
|
|
|
#define LPC_REQUEST 1
|
|
#define LPC_REPLY 2
|
|
#define LPC_DATAGRAM 3
|
|
#define LPC_LOST_REPLY 4
|
|
#define LPC_PORT_CLOSED 5
|
|
#define LPC_CLIENT_DIED 6
|
|
#define LPC_EXCEPTION 7
|
|
#define LPC_DEBUG_EVENT 8
|
|
#define LPC_ERROR_EVENT 9
|
|
#define LPC_CONNECTION_REQUEST 10
|
|
|
|
#define THREAD_QUERY_INFORMATION (0x0040)
|
|
|
|
|
|
|
|
#define DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER(hdrs,field) \
|
|
((hdrs)->OptionalHeader.##field)
|
|
|
|
#define DBGKM_MSG_OVERHEAD \
|
|
(FIELD_OFFSET(DBGKM_APIMSG, u.Exception) - sizeof(PORT_MESSAGE))
|
|
|
|
#define DBGKM_API_MSG_LENGTH(TypeSize) \
|
|
((sizeof(DBGKM_APIMSG) << 16) | (DBGKM_MSG_OVERHEAD + (TypeSize)))
|
|
|
|
#define DBGKM_FORMAT_API_MSG(m,Number,TypeSize) \
|
|
(m).h.u1.Length = DBGKM_API_MSG_LENGTH((TypeSize)); \
|
|
(m).h.u2.ZeroInit = LPC_DEBUG_EVENT; \
|
|
(m).ApiNumber = (Number)
|
|
|
|
#define DBGKP_API_SEND_ALL_FLAGS (0x3)
|
|
|
|
//
|
|
// Portable LPC Types for 32/64-bit compatibility
|
|
//
|
|
#ifdef USE_LPC6432
|
|
#define LPC_CLIENT_ID CLIENT_ID64
|
|
#define LPC_SIZE_T ULONGLONG
|
|
#define LPC_PVOID ULONGLONG
|
|
#define LPC_HANDLE ULONGLONG
|
|
#else
|
|
#define LPC_CLIENT_ID CLIENT_ID
|
|
#define LPC_SIZE_T SIZE_T
|
|
#define LPC_PVOID PVOID
|
|
#define LPC_HANDLE HANDLE
|
|
#endif
|
|
|
|
//
|
|
// Debug Object Information Structures
|
|
//
|
|
typedef struct _DEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION
|
|
{
|
|
ULONG KillProcessOnExit;
|
|
} DEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION, * PDEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION;
|
|
|
|
//调试对象
|
|
typedef struct _DEBUG_OBJECT
|
|
{
|
|
KEVENT EventsPresent; // 指示有调试事件发生
|
|
FAST_MUTEX Mutex; // 用于同步的互斥对象
|
|
LIST_ENTRY EventList; // 保持调试事件的链表,调试消息队列
|
|
union
|
|
{
|
|
ULONG Flags;
|
|
struct
|
|
{
|
|
UCHAR DebuggerInactive : 1;
|
|
UCHAR KillProcessOnExit : 1;
|
|
};
|
|
};
|
|
} DEBUG_OBJECT, * PDEBUG_OBJECT;
|
|
|
|
//
|
|
// Debug Message API Number
|
|
//
|
|
// 指定是哪种事件
|
|
typedef enum _DBGKM_APINUMBER
|
|
{
|
|
DbgKmExceptionApi = 0, // 异常
|
|
DbgKmCreateThreadApi = 1, // 创建线程
|
|
DbgKmCreateProcessApi = 2, // 创建进程
|
|
DbgKmExitThreadApi = 3, // 线程退出
|
|
DbgKmExitProcessApi = 4, // 进程退出
|
|
DbgKmLoadDllApi = 5, // 加载DLL
|
|
DbgKmUnloadDllApi = 6, // 卸载DLL
|
|
DbgKmErrorReportApi = 7, // 内部错误
|
|
DbgKmMaxApiNumber = 8, // 这组常量的最大值
|
|
} DBGKM_APINUMBER;
|
|
|
|
// 异常消息
|
|
typedef struct _DBGKM_EXCEPTION
|
|
{
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
ULONG FirstChance;
|
|
} DBGKM_EXCEPTION, * PDBGKM_EXCEPTION;
|
|
|
|
// 创建线程消息
|
|
typedef struct _DBGKM_CREATE_THREAD
|
|
{
|
|
ULONG SubSystemKey;
|
|
PVOID StartAddress;
|
|
} DBGKM_CREATE_THREAD, * PDBGKM_CREATE_THREAD;
|
|
|
|
// 创建进程消息
|
|
typedef struct _DBGKM_CREATE_PROCESS
|
|
{
|
|
ULONG SubSystemKey;
|
|
HANDLE FileHandle;
|
|
PVOID BaseOfImage;
|
|
ULONG DebugInfoFileOffset;
|
|
ULONG DebugInfoSize;
|
|
DBGKM_CREATE_THREAD InitialThread;
|
|
} DBGKM_CREATE_PROCESS, * PDBGKM_CREATE_PROCESS;
|
|
|
|
// 退出线程消息
|
|
typedef struct _DBGKM_EXIT_THREAD
|
|
{
|
|
NTSTATUS ExitStatus;
|
|
} DBGKM_EXIT_THREAD, * PDBGKM_EXIT_THREAD;
|
|
|
|
// 退出进程消息
|
|
typedef struct _DBGKM_EXIT_PROCESS
|
|
{
|
|
NTSTATUS ExitStatus;
|
|
} DBGKM_EXIT_PROCESS, * PDBGKM_EXIT_PROCESS;
|
|
|
|
// 加载模块消息
|
|
typedef struct _DBGKM_LOAD_DLL
|
|
{
|
|
HANDLE FileHandle;
|
|
PVOID BaseOfDll;
|
|
ULONG DebugInfoFileOffset;
|
|
ULONG DebugInfoSize;
|
|
PVOID NamePointer;
|
|
} DBGKM_LOAD_DLL, * PDBGKM_LOAD_DLL;
|
|
|
|
// 卸载模块消息
|
|
typedef struct _DBGKM_UNLOAD_DLL
|
|
{
|
|
PVOID BaseAddress;
|
|
} DBGKM_UNLOAD_DLL, * PDBGKM_UNLOAD_DLL;
|
|
|
|
typedef struct _DBGKM_ERROR_MSG {
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
SECTION_IMAGE_INFORMATION ImageInfo;
|
|
union
|
|
{
|
|
ULONG Flags;
|
|
struct {
|
|
ULONG IsProtectedProcess : 1;
|
|
ULONG IsWow64Process : 1;
|
|
ULONG IsFilterMessage : 1;
|
|
ULONG SpareBits : 29;
|
|
};
|
|
};
|
|
}DBGKM_ERROR_MSG,*PDBGKM_ERROR_MSG;
|
|
|
|
//
|
|
// LPC Port Message
|
|
//
|
|
typedef struct _PORT_MESSAGE
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
CSHORT DataLength;
|
|
CSHORT TotalLength;
|
|
} s1;
|
|
ULONG Length;
|
|
} u1;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
CSHORT Type;
|
|
CSHORT DataInfoOffset;
|
|
} s2;
|
|
ULONG ZeroInit;
|
|
} u2;
|
|
union
|
|
{
|
|
CLIENT_ID ClientId;
|
|
double DoNotUseThisField;
|
|
};
|
|
ULONG MessageId;
|
|
union
|
|
{
|
|
LPC_SIZE_T ClientViewSize;
|
|
ULONG CallbackId;
|
|
};
|
|
} PORT_MESSAGE, * PPORT_MESSAGE;
|
|
|
|
// 消息结构
|
|
typedef struct _DBGKM_APIMSG
|
|
{
|
|
PORT_MESSAGE h;
|
|
DBGKM_APINUMBER ApiNumber;
|
|
NTSTATUS ReturnedStatus;
|
|
union
|
|
{
|
|
DBGKM_EXCEPTION Exception;
|
|
DBGKM_CREATE_THREAD CreateThread;
|
|
DBGKM_CREATE_PROCESS CreateProcess;
|
|
DBGKM_EXIT_THREAD ExitThread;
|
|
DBGKM_EXIT_PROCESS ExitProcess;
|
|
DBGKM_LOAD_DLL LoadDll;
|
|
DBGKM_UNLOAD_DLL UnloadDll;
|
|
DBGKM_ERROR_MSG ErrorMsg;
|
|
}u;
|
|
} DBGKM_APIMSG, * PDBGKM_APIMSG;
|
|
|
|
typedef struct _DEBUG_EVENT
|
|
{
|
|
LIST_ENTRY EventList;
|
|
KEVENT ContinueEvent;
|
|
CLIENT_ID ClientId;
|
|
PEPROCESS Process;
|
|
PETHREAD Thread;
|
|
NTSTATUS Status;
|
|
ULONG Flags;
|
|
PETHREAD BackoutThread; // 产生fake message的线程
|
|
DBGKM_APIMSG ApiMsg;
|
|
} DEBUG_EVENT, * PDEBUG_EVENT;
|
|
|
|
//
|
|
// Debug States
|
|
//
|
|
typedef enum _DBG_STATE
|
|
{
|
|
DbgIdle,
|
|
DbgReplyPending,
|
|
DbgCreateThreadStateChange,
|
|
DbgCreateProcessStateChange,
|
|
DbgExitThreadStateChange,
|
|
DbgExitProcessStateChange,
|
|
DbgExceptionStateChange,
|
|
DbgBreakpointStateChange,
|
|
DbgSingleStepStateChange,
|
|
DbgLoadDllStateChange,
|
|
DbgUnloadDllStateChange
|
|
} DBG_STATE, * PDBG_STATE;
|
|
|
|
typedef struct _DBGUI_CREATE_THREAD {
|
|
HANDLE HandleToThread;
|
|
DBGKM_CREATE_THREAD NewThread;
|
|
} DBGUI_CREATE_THREAD, * PDBGUI_CREATE_THREAD;
|
|
|
|
typedef struct _DBGUI_CREATE_PROCESS {
|
|
HANDLE HandleToProcess;
|
|
HANDLE HandleToThread;
|
|
DBGKM_CREATE_PROCESS NewProcess;
|
|
} DBGUI_CREATE_PROCESS, * PDBGUI_CREATE_PROCESS;
|
|
|
|
//
|
|
// User-Mode Debug State Change Structure
|
|
//
|
|
typedef struct _DBGUI_WAIT_STATE_CHANGE
|
|
{
|
|
DBG_STATE NewState;
|
|
CLIENT_ID AppClientId;
|
|
union
|
|
{
|
|
DBGUI_CREATE_THREAD CreateThread;
|
|
DBGUI_CREATE_PROCESS CreateProcessInfo;
|
|
DBGKM_EXIT_THREAD ExitThread;
|
|
DBGKM_EXIT_PROCESS ExitProcess;
|
|
DBGKM_EXCEPTION Exception;
|
|
DBGKM_LOAD_DLL LoadDll;
|
|
DBGKM_UNLOAD_DLL UnloadDll;
|
|
} StateInfo;
|
|
} DBGUI_WAIT_STATE_CHANGE, * PDBGUI_WAIT_STATE_CHANGE;
|
|
|
|
typedef enum _DEBUG_OBJECT_INFORMATION_CLASS {
|
|
DebugObjectFlagsInformation = 1,
|
|
DebugObjectMaximumInfomation
|
|
}DEBUG_OBJECT_INFORMATION_CLASS, *PDEBUG_OBJECT_INFORMATION_CLASS;
|
|
|
|
#if defined(_AMD64_)
|
|
FORCEINLINE
|
|
VOID
|
|
ProbeForWriteUlong(
|
|
IN PULONG Address
|
|
){
|
|
if (Address >= (ULONG* const)MM_USER_PROBE_ADDRESS) {
|
|
Address = (ULONG* const)MM_USER_PROBE_ADDRESS;
|
|
}
|
|
|
|
*((volatile ULONG*)Address) = *Address;
|
|
return;
|
|
}
|
|
#else
|
|
#define ProbeForWriteUlong(Address) { \
|
|
if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \
|
|
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
|
|
} \
|
|
\
|
|
*(volatile ULONG *)(Address) = *(volatile ULONG *)(Address); \
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
FORCEINLINE
|
|
VOID
|
|
ProbeForWriteHandle(
|
|
IN PHANDLE Address
|
|
)
|
|
|
|
{
|
|
|
|
if (Address >= (HANDLE* const)MM_USER_PROBE_ADDRESS) {
|
|
Address = (HANDLE* const)MM_USER_PROBE_ADDRESS;
|
|
}
|
|
|
|
*((volatile HANDLE*)Address) = *Address;
|
|
return;
|
|
}
|
|
|
|
#else
|
|
|
|
#define ProbeForWriteHandle(Address) { \
|
|
if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
|
|
*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
|
|
} \
|
|
\
|
|
*(volatile HANDLE *)(Address) = *(volatile HANDLE *)(Address); \
|
|
}
|
|
|
|
#endif
|
|
|
|
typedef enum _SYSTEM_DLL_TYPE // 7 elements, 0x4 bytes
|
|
{
|
|
PsNativeSystemDll = 0 /*0x0*/,
|
|
PsWowX86SystemDll = 1 /*0x1*/,
|
|
PsWowArm32SystemDll = 2 /*0x2*/,
|
|
PsWowAmd64SystemDll = 3 /*0x3*/,
|
|
PsWowChpeX86SystemDll = 4 /*0x4*/,
|
|
PsVsmEnclaveRuntimeDll = 5 /*0x5*/,
|
|
PsSystemDllTotalTypes = 6 /*0x6*/
|
|
}SYSTEM_DLL_TYPE, * PSYSTEM_DLL_TYPE;
|
|
|
|
typedef struct _PEB_LDR_DATA // 9 elements, 0x58 bytes (sizeof)
|
|
{
|
|
ULONG32 Length;
|
|
UINT8 Initialized;
|
|
VOID* SsHandle;
|
|
struct _LIST_ENTRY InLoadOrderModuleList;
|
|
struct _LIST_ENTRY InMemoryOrderModuleList;
|
|
struct _LIST_ENTRY InInitializationOrderModuleList;
|
|
VOID* EntryInProgress;
|
|
UINT8 ShutdownInProgress;
|
|
VOID* ShutdownThreadId;
|
|
}PEB_LDR_DATA, * PPEB_LDR_DATA;
|
|
|
|
typedef BOOLEAN(NTAPI* PLDR_INIT_ROUTINE)(
|
|
_In_ PVOID DllHandle,
|
|
_In_ ULONG Reason,
|
|
_In_opt_ PVOID Context
|
|
);
|
|
|
|
// symbols
|
|
typedef struct _LDR_SERVICE_TAG_RECORD
|
|
{
|
|
struct _LDR_SERVICE_TAG_RECORD* Next;
|
|
ULONG ServiceTag;
|
|
} LDR_SERVICE_TAG_RECORD, * PLDR_SERVICE_TAG_RECORD;
|
|
|
|
// symbols
|
|
typedef struct _LDRP_CSLIST
|
|
{
|
|
PSINGLE_LIST_ENTRY Tail;
|
|
} LDRP_CSLIST, * PLDRP_CSLIST;
|
|
|
|
|
|
// symbols
|
|
typedef 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
|
|
} LDR_DDAG_STATE;
|
|
|
|
// symbols
|
|
typedef struct _LDR_DDAG_NODE
|
|
{
|
|
LIST_ENTRY Modules;
|
|
PLDR_SERVICE_TAG_RECORD ServiceTagList;
|
|
ULONG LoadCount;
|
|
ULONG LoadWhileUnloadingCount;
|
|
ULONG LowestLink;
|
|
union
|
|
{
|
|
LDRP_CSLIST Dependencies;
|
|
SINGLE_LIST_ENTRY RemovalLink;
|
|
};
|
|
LDRP_CSLIST IncomingDependencies;
|
|
LDR_DDAG_STATE State;
|
|
SINGLE_LIST_ENTRY CondenseLink;
|
|
ULONG PreorderNumber;
|
|
} LDR_DDAG_NODE, * PLDR_DDAG_NODE;
|
|
|
|
// rev
|
|
typedef struct _LDR_DEPENDENCY_RECORD
|
|
{
|
|
SINGLE_LIST_ENTRY DependencyLink;
|
|
PLDR_DDAG_NODE DependencyNode;
|
|
SINGLE_LIST_ENTRY IncomingDependencyLink;
|
|
PLDR_DDAG_NODE IncomingDependencyNode;
|
|
} LDR_DEPENDENCY_RECORD, * PLDR_DEPENDENCY_RECORD;
|
|
|
|
// symbols
|
|
typedef enum _LDR_DLL_LOAD_REASON
|
|
{
|
|
LoadReasonStaticDependency,
|
|
LoadReasonStaticForwarderDependency,
|
|
LoadReasonDynamicForwarderDependency,
|
|
LoadReasonDelayloadDependency,
|
|
LoadReasonDynamicLoad,
|
|
LoadReasonAsImageLoad,
|
|
LoadReasonAsDataLoad,
|
|
LoadReasonEnclavePrimary, // REDSTONE3
|
|
LoadReasonEnclaveDependency,
|
|
LoadReasonUnknown = -1
|
|
} LDR_DLL_LOAD_REASON, * PLDR_DLL_LOAD_REASON;
|
|
|
|
typedef struct _LDR_DATA_TABLE_ENTRY
|
|
{
|
|
LIST_ENTRY InLoadOrderLinks;
|
|
LIST_ENTRY InMemoryOrderLinks;
|
|
union
|
|
{
|
|
LIST_ENTRY InInitializationOrderLinks;
|
|
LIST_ENTRY InProgressLinks;
|
|
};
|
|
PVOID DllBase;
|
|
PLDR_INIT_ROUTINE EntryPoint;
|
|
ULONG SizeOfImage;
|
|
UNICODE_STRING FullDllName;
|
|
UNICODE_STRING BaseDllName;
|
|
union
|
|
{
|
|
UCHAR FlagGroup[4];
|
|
ULONG Flags;
|
|
struct
|
|
{
|
|
ULONG PackagedBinary : 1;
|
|
ULONG MarkedForRemoval : 1;
|
|
ULONG ImageDll : 1;
|
|
ULONG LoadNotificationsSent : 1;
|
|
ULONG TelemetryEntryProcessed : 1;
|
|
ULONG ProcessStaticImport : 1;
|
|
ULONG InLegacyLists : 1;
|
|
ULONG InIndexes : 1;
|
|
ULONG ShimDll : 1;
|
|
ULONG InExceptionTable : 1;
|
|
ULONG ReservedFlags1 : 2;
|
|
ULONG LoadInProgress : 1;
|
|
ULONG LoadConfigProcessed : 1;
|
|
ULONG EntryProcessed : 1;
|
|
ULONG ProtectDelayLoad : 1;
|
|
ULONG ReservedFlags3 : 2;
|
|
ULONG DontCallForThreads : 1;
|
|
ULONG ProcessAttachCalled : 1;
|
|
ULONG ProcessAttachFailed : 1;
|
|
ULONG CorDeferredValidate : 1;
|
|
ULONG CorImage : 1;
|
|
ULONG DontRelocate : 1;
|
|
ULONG CorILOnly : 1;
|
|
ULONG ChpeImage : 1;
|
|
ULONG ReservedFlags5 : 2;
|
|
ULONG Redirected : 1;
|
|
ULONG ReservedFlags6 : 2;
|
|
ULONG CompatDatabaseProcessed : 1;
|
|
};
|
|
};
|
|
USHORT ObsoleteLoadCount;
|
|
USHORT TlsIndex;
|
|
LIST_ENTRY HashLinks;
|
|
ULONG TimeDateStamp;
|
|
struct _ACTIVATION_CONTEXT* EntryPointActivationContext;
|
|
PVOID Lock; // RtlAcquireSRWLockExclusive
|
|
PLDR_DDAG_NODE DdagNode;
|
|
LIST_ENTRY NodeModuleLink;
|
|
struct _LDRP_LOAD_CONTEXT* LoadContext;
|
|
PVOID ParentDllBase;
|
|
PVOID SwitchBackContext;
|
|
RTL_BALANCED_NODE BaseAddressIndexNode;
|
|
RTL_BALANCED_NODE MappingInfoIndexNode;
|
|
ULONG_PTR OriginalBase;
|
|
LARGE_INTEGER LoadTime;
|
|
ULONG BaseNameHashValue;
|
|
LDR_DLL_LOAD_REASON LoadReason;
|
|
ULONG ImplicitPathOptions;
|
|
ULONG ReferenceCount;
|
|
ULONG DependentLoadFlags;
|
|
UCHAR SigningLevel; // since REDSTONE2
|
|
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
|
|
|
|
|
|
//
|
|
// Push lock definitions
|
|
//
|
|
typedef struct _EX_PUSH_LOCK_S {
|
|
|
|
//
|
|
// LOCK bit is set for both exclusive and shared acquires
|
|
//
|
|
#define EX_PUSH_LOCK_LOCK_V ((ULONG_PTR)0x0)
|
|
#define EX_PUSH_LOCK_LOCK ((ULONG_PTR)0x1)
|
|
|
|
//
|
|
// Waiting bit designates that the pointer has chained waiters
|
|
//
|
|
|
|
#define EX_PUSH_LOCK_WAITING ((ULONG_PTR)0x2)
|
|
|
|
//
|
|
// Waking bit designates that we are either traversing the list
|
|
// to wake threads or optimizing the list
|
|
//
|
|
|
|
#define EX_PUSH_LOCK_WAKING ((ULONG_PTR)0x4)
|
|
|
|
//
|
|
// Set if the lock is held shared by multiple owners and there are waiters
|
|
//
|
|
|
|
#define EX_PUSH_LOCK_MULTIPLE_SHARED ((ULONG_PTR)0x8)
|
|
|
|
//
|
|
// Total shared Acquires are incremented using this
|
|
//
|
|
#define EX_PUSH_LOCK_SHARE_INC ((ULONG_PTR)0x10)
|
|
#define EX_PUSH_LOCK_PTR_BITS ((ULONG_PTR)0xf)
|
|
|
|
union {
|
|
struct {
|
|
ULONG_PTR Locked : 1;
|
|
ULONG_PTR Waiting : 1;
|
|
ULONG_PTR Waking : 1;
|
|
ULONG_PTR MultipleShared : 1;
|
|
ULONG_PTR Shared : sizeof(ULONG_PTR) * 8 - 4;
|
|
};
|
|
ULONG_PTR Value;
|
|
PVOID Ptr;
|
|
};
|
|
} EX_PUSH_LOCK_S, * PEX_PUSH_LOCK_S;
|
|
/*
|
|
// like GetProcAddress
|
|
PVOID
|
|
RtlFindExportedRoutineByName (
|
|
PVOID DllBase,
|
|
PCHAR RoutineName);
|
|
*/
|
|
|
|
|
|
typedef struct _EX_FAST_REF {
|
|
union {
|
|
PVOID Object;
|
|
#if defined (_WIN64)
|
|
ULONG_PTR RefCnt : 4;
|
|
#else
|
|
ULONG_PTR RefCnt : 3;
|
|
#endif
|
|
ULONG_PTR Value;
|
|
};
|
|
} EX_FAST_REF, * PEX_FAST_REF;
|
|
|
|
typedef struct _PS_SYSTEM_DLL {
|
|
//
|
|
// _SECTION* object of the DLL.
|
|
// Initialized at runtime by PspLocateSystemDll.
|
|
//
|
|
union {
|
|
EX_FAST_REF SectionObjectFastRef;
|
|
PVOID SectionObject;
|
|
};
|
|
|
|
//
|
|
// Push lock.
|
|
//
|
|
|
|
EX_PUSH_LOCK PushLock;
|
|
|
|
//
|
|
// System DLL information.
|
|
// This part is returned by PsQuerySystemDllInfo.
|
|
//
|
|
|
|
PS_SYSTEM_DLL_INFO SystemDllInfo;
|
|
}PS_SYSTEM_DLL, * PPS_SYSTEM_DLL;
|
|
|
|
typedef struct _WOW64_PROCESS {
|
|
PVOID Wow64;
|
|
}WOW64_PROCESS,*PWOW64_PROCESS;
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
FORCEINLINE
|
|
VOID
|
|
ProbeForReadSmallStructure(
|
|
IN PVOID Address,
|
|
IN SIZE_T Size,
|
|
IN ULONG Alignment
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
Probes a structure for read access whose size is known at compile time.
|
|
N.B. A NULL structure address is not allowed.
|
|
Arguments:
|
|
Address - Supples a pointer to the structure.
|
|
Size - Supplies the size of the structure.
|
|
Alignment - Supplies the alignment of structure.
|
|
Return Value:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
ASSERT((Alignment == 1) || (Alignment == 2) ||
|
|
(Alignment == 4) || (Alignment == 8) ||
|
|
(Alignment == 16));
|
|
|
|
if ((Size == 0) || (Size >= 0x10000)) {
|
|
|
|
ASSERT(0);
|
|
|
|
ProbeForRead(Address, Size, Alignment);
|
|
|
|
}
|
|
else {
|
|
if (((ULONG_PTR)Address & (Alignment - 1)) != 0) {
|
|
ExRaiseDatatypeMisalignment();
|
|
}
|
|
|
|
if ((PUCHAR)Address >= (UCHAR* const)MM_USER_PROBE_ADDRESS) {
|
|
Address = (UCHAR* const)MM_USER_PROBE_ADDRESS;
|
|
}
|
|
|
|
_ReadWriteBarrier();
|
|
*(volatile UCHAR*)Address;
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#define ProbeForReadSmallStructure(Address, Size, Alignment) { \
|
|
ASSERT(((Alignment) == 1) || ((Alignment) == 2) || \
|
|
((Alignment) == 4) || ((Alignment) == 8) || \
|
|
((Alignment) == 16)); \
|
|
if ((Size == 0) || (Size > 0x10000)) { \
|
|
ASSERT(0); \
|
|
ProbeForRead(Address, Size, Alignment); \
|
|
} else { \
|
|
if (((ULONG_PTR)(Address) & ((Alignment) - 1)) != 0) { \
|
|
ExRaiseDatatypeMisalignment(); \
|
|
} \
|
|
if ((ULONG_PTR)(Address) >= (ULONG_PTR)MM_USER_PROBE_ADDRESS) { \
|
|
*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
FORCEINLINE
|
|
VOID
|
|
ProbeForWriteSmallStructure(
|
|
IN PVOID Address,
|
|
IN SIZE_T Size,
|
|
IN ULONG Alignment
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
Probes a structure for write access whose size is known at compile time.
|
|
Arguments:
|
|
Address - Supples a pointer to the structure.
|
|
Size - Supplies the size of the structure.
|
|
Alignment - Supplies the alignment of structure.
|
|
Return Value:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
ASSERT((Alignment == 1) || (Alignment == 2) ||
|
|
(Alignment == 4) || (Alignment == 8) ||
|
|
(Alignment == 16));
|
|
|
|
//
|
|
// If the size of the structure is > 4k then call the standard routine.
|
|
// wow64 uses a page size of 4k even on ia64.
|
|
//
|
|
|
|
if ((Size == 0) || (Size >= 0x1000)) {
|
|
|
|
ASSERT(0);
|
|
|
|
ProbeForWrite(Address, Size, Alignment);
|
|
|
|
}
|
|
else {
|
|
if (((ULONG_PTR)(Address) & (Alignment - 1)) != 0) {
|
|
ExRaiseDatatypeMisalignment();
|
|
}
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
if ((ULONG_PTR)(Address) >= (ULONG_PTR)MM_USER_PROBE_ADDRESS) {
|
|
Address = (UCHAR* const)MM_USER_PROBE_ADDRESS;
|
|
}
|
|
|
|
((volatile UCHAR*)(Address))[0] = ((volatile UCHAR*)(Address))[0];
|
|
((volatile UCHAR*)(Address))[Size - 1] = ((volatile UCHAR*)(Address))[Size - 1];
|
|
|
|
#else
|
|
|
|
if ((ULONG_PTR)(Address) >= (ULONG_PTR)MM_USER_PROBE_ADDRESS) {
|
|
*((volatile UCHAR* const)MM_USER_PROBE_ADDRESS) = 0;
|
|
}
|
|
|
|
*(volatile UCHAR*)(Address) = *(volatile UCHAR*)(Address);
|
|
if (Size > Alignment) {
|
|
((volatile UCHAR*)(Address))[(Size - 1) & ~(SIZE_T)(Alignment - 1)] =
|
|
((volatile UCHAR*)(Address))[(Size - 1) & ~(SIZE_T)(Alignment - 1)];
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
} |