首页 > 系统相关 >驱动开发:内核枚举进程与线程ObCall回调

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

时间:2022-10-22 10:02:53浏览次数:53  
标签:ULONG Uint4B OBJECT ObCall 枚举 线程 Ptr64 PVOID TYPE

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

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

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

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;       // Ptr64     void
	PVOID OpenProcedure;      // Ptr64     long
	PVOID CloseProcedure;     // Ptr64     void
	PVOID DeleteProcedure;        // Ptr64     void
	PVOID ParseProcedure;     // Ptr64     long
	PVOID SecurityProcedure;      // Ptr64     long
	PVOID QueryNameProcedure;     // Ptr64     long
	PVOID OkayToCloseProcedure;     // Ptr64     unsigned 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: [email protected]
#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;       // Ptr64     void
	PVOID OpenProcedure;      // Ptr64     long
	PVOID CloseProcedure;     // Ptr64     void
	PVOID DeleteProcedure;        // Ptr64     void
	PVOID ParseProcedure;     // Ptr64     long
	PVOID SecurityProcedure;      // Ptr64     long
	PVOID QueryNameProcedure;     // Ptr64     long
	PVOID OkayToCloseProcedure;     // Ptr64     unsigned 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;
}

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

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

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: [email protected]
#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;       // Ptr64     void
	PVOID OpenProcedure;      // Ptr64     long
	PVOID CloseProcedure;     // Ptr64     void
	PVOID DeleteProcedure;        // Ptr64     void
	PVOID ParseProcedure;     // Ptr64     long
	PVOID SecurityProcedure;      // Ptr64     long
	PVOID QueryNameProcedure;     // Ptr64     long
	PVOID OkayToCloseProcedure;     // Ptr64     unsigned 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)(*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;
}

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

标签:ULONG,Uint4B,OBJECT,ObCall,枚举,线程,Ptr64,PVOID,TYPE
From: https://blog.51cto.com/lyshark/5785662

相关文章

  • Java多线程(1):线程生命周期
    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~ 从事Java开发这些年来,如果要问我Java当中最难的部分是什么?最有意思的部分是什么?最多人讨论的部分是什么?那我会毫不犹豫......
  • 各种线程状态的打断方法
    一、方法方法名static功能说明注意run()新线程启动后会调用的方法,线程之间串行如果在构造Thread对象时传递了Runnable参数,则线程启动后会调用Runnabl......
  • 进程与线程的区别
    简单介绍一、线程的基本概念线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少......
  • 进程与线程的区别
    进程是操作系统分配资源的基本单位,而线程是操作系统调度的基本单位。一个进程中至少包含一个线程,线程不能独立于进程而存在。进程不能共享资源,而线程可以。线程可以看作是......
  • 线程和进程的区别
    一、进程和线程的概念 进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。 线程:是进程的一个执行单元,是进程......
  • 进程与线程的区别
    进程资源分配的最小单位。计算机的核心是cpu,进程和线程都是一个时间段的描述,是CPU工作时间段的描述。我们打开浏览器,实际上就是打开了一个进程,它就会被载入内存空间,并在......
  • 进程与线程的区别
    1、首先是定义进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单......
  • 多线程基础知识
    【单核处理器和多核处理器的多线程】单核处理器:为每个线程分配时间片。来模拟并发多核处理器:一核一线程,真正实现并发 【标志】线程一致性,IsAlive就为true,否则为fals......
  • 多线程技术总结
    csdn上笔记也多,但是用的不多,不用就忘了。博客线程笔记——技术笔记:.Net全套就业班视频教程在多线程中的跨线程的方法调用就得用委托。一个进程的多个线程间可相互......
  • Leetcode 2440 -- dfs&&枚举
    题目描述创建价值相同的连通块思路代码拓展:统计子树的大小当图是一棵树(无环)的时候,如果树有向,什么都不用设置,否则,额外传入一个fa如果有环,设置一个st数组。......