驱动学习用到的API
内核全局变量
PsActiveProcessHead 所有活动进程的双向链表头 _eprocess+448
PsInitialSystemProcess 系统system进程的_eprocess地址
PsIdleProcess 系统idle进程的 _eprocess地址
PsLoadedModuleList 已加载内核模块(如驱动、系统组件)的全局双向链表头节点
KeServiceDescriptorTable SSDT
KeNumberProcessors 处理器数量
PspCidTable 变量记录的就是句柄表_HANDLE_TABLE
结构
KiProcessorBlock 第一个核的PRCB 减去0x180就是_kpcrPsNtosImageBase
内核中用于标识ntoskrnl.exe
(内核主模块)内存加载基址的关键变量KdVersionBlock
内核中与调试相关的关键全局变量,其本质是一个指向 DBGKD_GET_VERSION64
结构体 的指针KdDebuggerDataBlock
内核调试的核心数据结构, 本质为 KDDEBUGGER_DATA64
结构体指针ObpRootDirectoryObject
是 Windows 内核对象管理系统的核心全局变量,本质为 _OBJECT_DIRECTORY
结构体指针
ObOpenObjectByPointer 函数打开由指针引用的对象,并返回该对象的句柄
ObReferenceObjectByPointer 例程递增给定对象的指针引用计数。
ObDereferenceObject 例程递减给定对象的引用计数并执行保留检查
ObfReferenceObject 例程递增给定对象的引用计数
ObReferenceObjectByHandle 例程在对象句柄上提供访问验证,如果可以授予访问权限,则返回指向对象的正文的相应指针。
ObReferenceObjectByName ( 通过一个名字获得一个对象的指针(未公开)
__in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID *Object );
ObOpenObjectByName( 未公开
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ POBJECT_TYPE ObjectType,
_In_ KPROCESSOR_MODE AccessMode,
_Inout_opt_ PACCESS_STATE AccessState,
_In_opt_ ACCESS_MASK DesiredAccess,
_Inout_opt_ PVOID ParseContext,
_Out_ PHANDLE Handle );
// 手动声明(需根据目标系统验证参数和调用约定)
NTSTATUS NTAPI NtConvertBetweenAuxiliaryCounterAndPerformanceCounter(
_In_ BOOL ConvertToPerformanceCounter, 指定转换方向(TRUE 表示辅助计数器→性能计数器,FALSE 表示反向转换)
_Inout_ LARGE_INTEGER *AuxiliaryCounter, 输入/输出的辅助计数器数值
_Inout_ LARGE_INTEGER *PerformanceCounter, 输入/输出的性能计数器数值
_Out_opt_ ULONGLONG *ConversionOffset ; 可选参数,存储转换时的偏移量(用于补偿不同计数器的基准差异
IoEnumerateDeviceObjectList 例程枚举驱动程序下的所有的设备对象列表
PsSetLoadImageNotifyRoutine 例程注册驱动程序提供的回调,每当映像 ((例如,DLL 或 EXE) )加载 (或映射到内存) 时,该回调随后会收到通知。
PsLookupThreadByThreadId 例程接受线程的线程 ID,并将引用指针返回到线程的 ETHREAD 结构。
PsGetProcessImageFileName(IN PEPROCESS pProcess) 作用是可以通过EPROCESS的指针获取对应进程映像名。实际上直接从EPROCESS结构内自己获取也可以PsLookupProcessByProcessId(IN HANDLE PID,OUT PEPROCESS EProcess); 作用是通过PID获取对应进程的EPROCESS结构
ZwQueryInformationProcess 检索有关指定进程的信息
ZwCurrentProcess 宏返回当前进程的句柄。
ZwDuplicateObject 例程创建一个句柄,该句柄与指定的源句柄重复
ZwOpenThread( 未公开
_Out_ PHANDLE ThreadHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientId );
NtSystemDebugControl( 获取内核变量地址 物理内存读写 进程隐藏与调试 具体看控制命令是哪个
IN SYSDBG_COMMAND Command, // 控制命令(如 SysDbgReadVirtualMemory)
IN PVOID InputBuffer, // 输入缓冲区指针
IN ULONG InputBufferLength, // 输入缓冲区长度
OUT PVOID OutputBuffer, // 输出缓冲区指针
IN ULONG OutputBufferLength, // 输出缓冲区长度
OUT PULONG ReturnLength // 实际返回数据长度
);
NTSTATUS RtlQueryModuleInformation(
PULONG BufferSize,
ULONG UnitSize,
PVOID Buffer);
// 声明(需包含 <ntddk.h> 或 <wdm.h>)
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset; // 下一个进程信息的偏移量(链表结构)
ULONG NumberOfThreads; // 进程的线程数
LARGE_INTEGER WorkingSetPrivateSize;
ULONG HardFaultCount;
ULONG Reserved1;
ULONG Reserved2;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName; // 进程映像名称
KPRIORITY BasePriority;
HANDLE ProcessId; // 进程 PID
HANDLE ParentProcessId; // 父进程 PID
// ... 其他字段(具体结构可能因系统版本而异)
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
NTSTATUS ZwQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, // 要查询的信息类型
_Inout_ PVOID SystemInformation, // 接收数据的缓冲区
_In_ ULONG SystemInformationLength, // 缓冲区大小
_Out_opt_ PULONG ReturnLength // 实际返回的数据大小
);
NTSTATUS ZwQuerySystemInformationEx( Win10引用的
SYSTEM_INFORMATION_CLASS_EXTENDED SystemInformationClass, // 扩展的信息类别
PVOID InputBuffer, // 输入参数(可选)
ULONG InputBufferLength, // 输入缓冲区大小
PVOID SystemInformation, // 输出缓冲区
ULONG SystemInformationLength, // 输出缓冲区大小
PULONG ReturnLength // 实际返回的数据大小
);
KiSystemStartup NT内核的入口函数
KiInitializePcr
KeStartAllProcessors 函数来初始化其他CPU
KiInitProcessor
PVOID MmGetSystemRoutineAddress( PUNICODE_STRING SystemRoutineName);例程返回指向由 SystemRoutineName 指定的函数的指针。只能找到导出的函数,不管公开与未公开。
__declspec(naked) 裸函数 声明
wcsrchr() strrchr () 扫描字符串以查找某个字符的末次出现位置的地址 区别在于单字节和宽字符
_wcsicmp() stricmp() 执行不区分大小写的字符串比较