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

首先我们需要定义好结构体,结构体是微软公开的,如果有其它需要请自行去微软官方去查。
typedef struct _OBJECT_TYPE_INITIALIZER { USHORT Length; UCHAR ObjectTypeFlags; ULONG ObjectTypeCode; ULONG InvalidAttributes; GENERIC_MAPPING GenericMapping; ULONG ValidAccessMask; ULONG RetainAccess; POOL_TYPE PoolType; ULONG DefaultPagedPoolCharge; ULONG DefaultNonPagedPoolCharge; PVOID DumpProcedure; PVOID OpenProcedure; PVOID CloseProcedure; PVOID DeleteProcedure; PVOID ParseProcedure; PVOID SecurityProcedure; PVOID QueryNameProcedure; PVOID OkayToCloseProcedure; ULONG WaitObjectFlagMask; USHORT WaitObjectFlagOffset; USHORT WaitObjectPointerOffset; }OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _OBJECT_TYPE { LIST_ENTRY TypeList; UNICODE_STRING Name; PVOID DefaultObject; UCHAR Index; ULONG TotalNumberOfObjects; ULONG TotalNumberOfHandles; ULONG HighWaterNumberOfObjects; ULONG HighWaterNumberOfHandles; OBJECT_TYPE_INITIALIZER TypeInfo; EX_PUSH_LOCK TypeLock; ULONG Key; LIST_ENTRY CallbackList; }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
并循环输出即可。
#include <ntifs.h> #include <wdm.h> #include <ntddk.h>
typedef struct _OBJECT_TYPE_INITIALIZER { USHORT Length; UCHAR ObjectTypeFlags; ULONG ObjectTypeCode; ULONG InvalidAttributes; GENERIC_MAPPING GenericMapping; ULONG ValidAccessMask; ULONG RetainAccess; POOL_TYPE PoolType; ULONG DefaultPagedPoolCharge; ULONG DefaultNonPagedPoolCharge; PVOID DumpProcedure; PVOID OpenProcedure; PVOID CloseProcedure; PVOID DeleteProcedure; PVOID ParseProcedure; PVOID SecurityProcedure; PVOID QueryNameProcedure; PVOID OkayToCloseProcedure; ULONG WaitObjectFlagMask; USHORT WaitObjectFlagOffset; USHORT WaitObjectPointerOffset; }OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _OBJECT_TYPE { LIST_ENTRY TypeList; UNICODE_STRING Name; PVOID DefaultObject; UCHAR Index; ULONG TotalNumberOfObjects; ULONG TotalNumberOfHandles; ULONG HighWaterNumberOfObjects; ULONG HighWaterNumberOfHandles; OBJECT_TYPE_INITIALIZER TypeInfo; EX_PUSH_LOCK TypeLock; ULONG Key; LIST_ENTRY CallbackList; }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;
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
即可,修改后的代码如下。
#include <ntifs.h> #include <wdm.h> #include <ntddk.h>
typedef struct _OBJECT_TYPE_INITIALIZER { USHORT Length; UCHAR ObjectTypeFlags; ULONG ObjectTypeCode; ULONG InvalidAttributes; GENERIC_MAPPING GenericMapping; ULONG ValidAccessMask; ULONG RetainAccess; POOL_TYPE PoolType; ULONG DefaultPagedPoolCharge; ULONG DefaultNonPagedPoolCharge; PVOID DumpProcedure; PVOID OpenProcedure; PVOID CloseProcedure; PVOID DeleteProcedure; PVOID ParseProcedure; PVOID SecurityProcedure; PVOID QueryNameProcedure; PVOID OkayToCloseProcedure; ULONG WaitObjectFlagMask; USHORT WaitObjectFlagOffset; USHORT WaitObjectPointerOffset; }OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _OBJECT_TYPE { LIST_ENTRY TypeList; UNICODE_STRING Name; PVOID DefaultObject; UCHAR Index; ULONG TotalNumberOfObjects; ULONG TotalNumberOfHandles; ULONG HighWaterNumberOfObjects; ULONG HighWaterNumberOfHandles; OBJECT_TYPE_INITIALIZER TypeInfo; EX_PUSH_LOCK TypeLock; ULONG Key; LIST_ENTRY CallbackList; }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()
NTSTATUS RemoveObCallback(PVOID RegistrationHandle) { ObUnRegisterCallbacks(RegistrationHandle);
return STATUS_SUCCESS; }
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;
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; }
|
运行这段驱动程序,即可得到线程句柄
回调:
