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

我们来看一款闭源ARK工具是如何实现的:

首先我们需要定义好结构体,结构体是微软公开的,如果有其它需要请自行去微软官方去查。

typedef struct _OBJECT_TYPE_INITIALIZER{USHORT Length;                // Uint2BUCHAR ObjectTypeFlags;            // UCharULONG ObjectTypeCode;             // Uint4BULONG InvalidAttributes;          // Uint4BGENERIC_MAPPING GenericMapping;   // _GENERIC_MAPPINGULONG ValidAccessMask;       // Uint4BULONG RetainAccess;         // Uint4BPOOL_TYPE PoolType;        // _POOL_TYPEULONG DefaultPagedPoolCharge;  // Uint4BULONG DefaultNonPagedPoolCharge; // Uint4BPVOID DumpProcedure;       // Ptr64     voidPVOID OpenProcedure;      // Ptr64     longPVOID CloseProcedure;     // Ptr64     voidPVOID DeleteProcedure;        // Ptr64     voidPVOID ParseProcedure;     // Ptr64     longPVOID SecurityProcedure;      // Ptr64     longPVOID QueryNameProcedure;     // Ptr64     longPVOID OkayToCloseProcedure;     // Ptr64     unsigned charULONG WaitObjectFlagMask;     // Uint4BUSHORT WaitObjectFlagOffset;    // Uint2BUSHORT WaitObjectPointerOffset;   // Uint2B}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE{LIST_ENTRY TypeList;           // _LIST_ENTRYUNICODE_STRING Name;         // _UNICODE_STRINGPVOID DefaultObject;         // Ptr64 VoidUCHAR Index;             // UCharULONG TotalNumberOfObjects;      // Uint4BULONG TotalNumberOfHandles;      // Uint4BULONG HighWaterNumberOfObjects;    // Uint4BULONG HighWaterNumberOfHandles;    // Uint4BOBJECT_TYPE_INITIALIZER TypeInfo;  // _OBJECT_TYPE_INITIALIZEREX_PUSH_LOCK TypeLock;         // _EX_PUSH_LOCKULONG Key;                 // Uint4BLIST_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 #include #include typedef struct _OBJECT_TYPE_INITIALIZER{USHORT Length;                // Uint2BUCHAR ObjectTypeFlags;            // UCharULONG ObjectTypeCode;             // Uint4BULONG InvalidAttributes;          // Uint4BGENERIC_MAPPING GenericMapping;   // _GENERIC_MAPPINGULONG ValidAccessMask;       // Uint4BULONG RetainAccess;         // Uint4BPOOL_TYPE PoolType;        // _POOL_TYPEULONG DefaultPagedPoolCharge;  // Uint4BULONG DefaultNonPagedPoolCharge; // Uint4BPVOID DumpProcedure;       // Ptr64     voidPVOID OpenProcedure;      // Ptr64     longPVOID CloseProcedure;     // Ptr64     voidPVOID DeleteProcedure;        // Ptr64     voidPVOID ParseProcedure;     // Ptr64     longPVOID SecurityProcedure;      // Ptr64     longPVOID QueryNameProcedure;     // Ptr64     longPVOID OkayToCloseProcedure;     // Ptr64     unsigned charULONG WaitObjectFlagMask;     // Uint4BUSHORT WaitObjectFlagOffset;    // Uint2BUSHORT WaitObjectPointerOffset;   // Uint2B}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE{LIST_ENTRY TypeList;           // _LIST_ENTRYUNICODE_STRING Name;         // _UNICODE_STRINGPVOID DefaultObject;         // Ptr64 VoidUCHAR Index;             // UCharULONG TotalNumberOfObjects;      // Uint4BULONG TotalNumberOfHandles;      // Uint4BULONG HighWaterNumberOfObjects;    // Uint4BULONG HighWaterNumberOfHandles;    // Uint4BOBJECT_TYPE_INITIALIZER TypeInfo;  // _OBJECT_TYPE_INITIALIZEREX_PUSH_LOCK TypeLock;         // _EX_PUSH_LOCKULONG Key;                 // Uint4BLIST_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;}

运行这段驱动程序,即可得到进程句柄回调:

当然了如上是进程句柄的枚举,如果是想要输出线程句柄,则只需要替换代码中的PsProcessType((POBJECT_TYPE)(*PsThreadType))->CallbackList即可,修改后的代码如下。

// 署名权// right to sign one's name on a piece of work// PowerBy: LyShark// Email: me@lyshark.com#include #include #include typedef struct _OBJECT_TYPE_INITIALIZER{USHORT Length;                // Uint2BUCHAR ObjectTypeFlags;            // UCharULONG ObjectTypeCode;             // Uint4BULONG InvalidAttributes;          // Uint4BGENERIC_MAPPING GenericMapping;   // _GENERIC_MAPPINGULONG ValidAccessMask;       // Uint4BULONG RetainAccess;         // Uint4BPOOL_TYPE PoolType;        // _POOL_TYPEULONG DefaultPagedPoolCharge;  // Uint4BULONG DefaultNonPagedPoolCharge; // Uint4BPVOID DumpProcedure;       // Ptr64     voidPVOID OpenProcedure;      // Ptr64     longPVOID CloseProcedure;     // Ptr64     voidPVOID DeleteProcedure;        // Ptr64     voidPVOID ParseProcedure;     // Ptr64     longPVOID SecurityProcedure;      // Ptr64     longPVOID QueryNameProcedure;     // Ptr64     longPVOID OkayToCloseProcedure;     // Ptr64     unsigned charULONG WaitObjectFlagMask;     // Uint4BUSHORT WaitObjectFlagOffset;    // Uint2BUSHORT WaitObjectPointerOffset;   // Uint2B}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;typedef struct _OBJECT_TYPE{LIST_ENTRY TypeList;           // _LIST_ENTRYUNICODE_STRING Name;         // _UNICODE_STRINGPVOID DefaultObject;         // Ptr64 VoidUCHAR Index;             // UCharULONG TotalNumberOfObjects;      // Uint4BULONG TotalNumberOfHandles;      // Uint4BULONG HighWaterNumberOfObjects;    // Uint4BULONG HighWaterNumberOfHandles;    // Uint4BOBJECT_TYPE_INITIALIZER TypeInfo;  // _OBJECT_TYPE_INITIALIZEREX_PUSH_LOCK TypeLock;         // _EX_PUSH_LOCKULONG Key;                 // Uint4BLIST_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)(*PsThreadType))->CallbackList;// 开始遍历pObCallback = (POB_CALLBACK)CallbackList.Flink;do{if (FALSE == MmIsAddressValid(pObCallback)){break;}if (NULL != pObCallback->ObHandle){// 显示DbgPrint("[LyShark] 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;}

运行这段驱动程序,即可得到线程句柄回调:

文章作者:lyshark (王瑞)
文章出处:https://www.cnblogs.com/LyShark/p/16813905.html
版权声明:本博客文章与代码均为学习时整理的笔记,文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!

转载文章请遵守《中华人民共和国著作权法》相关法律规定或遵守《署名CC BY-ND 4.0国际》规范,合理合规携带原创出处转载,如果不携带文章出处,并恶意转载多篇原创文章被本人发现,本人保留起诉权!