在笔者上一篇文章《驱动开发:内核枚举Registry注册表回调》中我们通过特征码定位实现了对注册表回调的枚举,本篇文章LyShark将教大家如何枚举系统中的ProcessObCall进程回调以及ThreadObCall线程回调,之所以放在一起来讲解是因为这两中回调在枚举是都需要使用通用结构体_OB_CALLBACK以及_OBJECT_TYPE所以放在一起来讲解最好不过 。
我们来看一款闭源ARK工具是如何实现的:

文章插图
【驱动开发:内核枚举进程与线程ObCall回调】首先我们需要定义好结构体 , 结构体是微软公开的 , 如果有其它需要请自行去微软官方去查 。
typedef struct _OBJECT_TYPE_INITIALIZER{	USHORT Length;// Uint2B	UCHAR ObjectTypeFlags;// UChar	ULONG ObjectTypeCode;// Uint4B	ULONG InvalidAttributes;// Uint4B	GENERIC_MAPPING GenericMapping;// _GENERIC_MAPPING	ULONG ValidAccessMask;// Uint4B	ULONG RetainAccess;// Uint4B	POOL_TYPE PoolType;// _POOL_TYPE	ULONG DefaultPagedPoolCharge;// Uint4B	ULONG DefaultNonPagedPoolCharge; // Uint4B	PVOID DumpProcedure;// Ptr64void	PVOID OpenProcedure;// Ptr64long	PVOID CloseProcedure;// Ptr64void	PVOID DeleteProcedure;// Ptr64void	PVOID ParseProcedure;// Ptr64long	PVOID SecurityProcedure;// Ptr64long	PVOID QueryNameProcedure;// Ptr64long	PVOID OkayToCloseProcedure;// Ptr64unsigned char	ULONG WaitObjectFlagMask;// Uint4B	USHORT WaitObjectFlagOffset;// Uint2B	USHORT WaitObjectPointerOffset;// Uint2B}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE{	LIST_ENTRY TypeList;// _LIST_ENTRY	UNICODE_STRING Name;// _UNICODE_STRING	PVOID DefaultObject;// Ptr64 Void	UCHAR Index;// UChar	ULONG TotalNumberOfObjects;// Uint4B	ULONG TotalNumberOfHandles;// Uint4B	ULONG HighWaterNumberOfObjects;// Uint4B	ULONG HighWaterNumberOfHandles;// Uint4B	OBJECT_TYPE_INITIALIZER TypeInfo;// _OBJECT_TYPE_INITIALIZER	EX_PUSH_LOCK TypeLock;// _EX_PUSH_LOCK	ULONG Key;// Uint4B	LIST_ENTRY CallbackList;// _LIST_ENTRY}OBJECT_TYPE, *POBJECT_TYPE;#pragma pack(1)typedef struct _OB_CALLBACK{	LIST_ENTRY ListEntry;	ULONGLONG Unknown;	HANDLE ObHandle;	PVOID ObTypeAddr;	PVOID PreCall;	PVOID PostCall;}OB_CALLBACK, *POB_CALLBACK;#pragma pack()代码部分的实现很容易,由于进程与线程句柄的枚举很容易,直接通过(POBJECT_TYPE)(*PsProcessType))->CallbackList就可以拿到链表头结构 , 得到后将其解析为POB_CALLBACK并循环输出即可 。// 署名权// right to sign one's name on a piece of work// PowerBy: LyShark// Email: me@lyshark.com#include <ntifs.h>#include <wdm.h>#include <ntddk.h>typedef struct _OBJECT_TYPE_INITIALIZER{	USHORT Length;// Uint2B	UCHAR ObjectTypeFlags;// UChar	ULONG ObjectTypeCode;// Uint4B	ULONG InvalidAttributes;// Uint4B	GENERIC_MAPPING GenericMapping;// _GENERIC_MAPPING	ULONG ValidAccessMask;// Uint4B	ULONG RetainAccess;// Uint4B	POOL_TYPE PoolType;// _POOL_TYPE	ULONG DefaultPagedPoolCharge;// Uint4B	ULONG DefaultNonPagedPoolCharge; // Uint4B	PVOID DumpProcedure;// Ptr64void	PVOID OpenProcedure;// Ptr64long	PVOID CloseProcedure;// Ptr64void	PVOID DeleteProcedure;// Ptr64void	PVOID ParseProcedure;// Ptr64long	PVOID SecurityProcedure;// Ptr64long	PVOID QueryNameProcedure;// Ptr64long	PVOID OkayToCloseProcedure;// Ptr64unsigned char	ULONG WaitObjectFlagMask;// Uint4B	USHORT WaitObjectFlagOffset;// Uint2B	USHORT WaitObjectPointerOffset;// Uint2B}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE{	LIST_ENTRY TypeList;// _LIST_ENTRY	UNICODE_STRING Name;// _UNICODE_STRING	PVOID DefaultObject;// Ptr64 Void	UCHAR Index;// UChar	ULONG TotalNumberOfObjects;// Uint4B	ULONG TotalNumberOfHandles;// Uint4B	ULONG HighWaterNumberOfObjects;// Uint4B	ULONG HighWaterNumberOfHandles;// Uint4B	OBJECT_TYPE_INITIALIZER TypeInfo;// _OBJECT_TYPE_INITIALIZER	EX_PUSH_LOCK TypeLock;// _EX_PUSH_LOCK	ULONG Key;// Uint4B	LIST_ENTRY CallbackList;// _LIST_ENTRY}OBJECT_TYPE, *POBJECT_TYPE;#pragma pack(1)typedef struct _OB_CALLBACK{	LIST_ENTRY ListEntry;	ULONGLONG Unknown;	HANDLE ObHandle;	PVOID ObTypeAddr;	PVOID PreCall;	PVOID PostCall;}OB_CALLBACK, *POB_CALLBACK;#pragma pack()VOID DriverUnload(PDRIVER_OBJECT pDriverObject){}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath){	NTSTATUS status = STATUS_SUCCESS;	DbgPrint("hello lyshark.com \n");	POB_CALLBACK pObCallback = NULL;	// 直接获取 CallbackList 链表	LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsProcessType))->CallbackList;	// 开始遍历	pObCallback = (POB_CALLBACK)CallbackList.Flink;	do	{if (FALSE == MmIsAddressValid(pObCallback)){break;}if (NULL != pObCallback->ObHandle){// 显示DbgPrint("[LyShark.com] ObHandle = %p | PreCall = %p | PostCall = %p \n", pObCallback->ObHandle, pObCallback->PreCall, pObCallback->PostCall);}// 获取下一链表信息pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink;	} while (CallbackList.Flink != (PLIST_ENTRY)pObCallback);	return status;}
		  	
    
     
    
    
    
推荐阅读
           - 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
- 
              
              
            
 
          
- 不妨试试更快更小更灵活Java开发框架Solon 
 
- 了解 Flutter 开发者们的 IDE 使用情况 
 
- 一 测试开发HTTP请求过程 
 
- 驱动开发:内核枚举Registry注册表回调 
 
- Teambition企业内部应用开发指南 
 
- Doris开发手记4:倍速性能提升,向量化导入的性能调优实践 
 
- 驱动开发:内核枚举LoadImage映像回调 
 
- 前端开发日常——CSS动画无限轮播 
 
- git clone开启云上AI开发 
 
- 驱动开发:内核枚举ShadowSSDT基址 
 
            
              
            
          