驱动开发:内核枚举进程与线程ObCall回调

【驱动开发:内核枚举进程与线程ObCall回调】在笔者上一篇文章《驱动开发:内核枚举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;}

经验总结扩展阅读