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


    在笔者上一篇文章《驱动开发:内核枚举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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    代码部分的实现很容易,由于进程与线程句柄的枚举很容易,直接通过(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;                // 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

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

    当然了如上是进程句柄的枚举,如果是想要输出线程句柄,则只需要替换代码中的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;                // 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

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

  • 相关阅读:
    【Elasticsearch教程17】Mapping字段类型之token_count
    Docker-consul容器服务更新与发现
    bugku misc disordered_zip
    ETL-使用kettle批量复制sqlserver数据到mysql数据库
    快速教程|如何在 AWS EC2上使用 Walrus 部署 GitLab
    终于拿到了2022阿里技术专家分享的552页大型网站架构实战PDF文档
    deepin安装MySQL5.7
    手写笔记教会你集成Spring和Mybatis框架(有详细注解)
    无涯教程-JavaScript - ASINH函数
    tailwindcss动态设置宽和高相等
  • 原文地址:https://blog.csdn.net/lyshark_csdn/article/details/127457835