Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Windows Kernel-仿pchunter获得系统回调列表

Windows Kernel-仿pchunter获得系统回调列表

原创
作者头像
franket
发布于 2020-05-10 05:33:23
发布于 2020-05-10 05:33:23
13.8K00
代码可运行
举报
文章被收录于专栏:技术杂记技术杂记
运行总次数:0
代码可运行

1、创建进程、创建线程、加载模块回调

(1)创建进程回调

注册创建进程回调使用函数 PsSetCreateProcessNotifyRoutine,调用这个函数会将注册的信息保存到一个数组里面。

反汇编这个函数,会发现以下片段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
805d0c27 56			  push	esi
805d0c28 57			  push	edi
805d0c29 7464			  je	  nt!PsSetCreateProcessNotifyRoutine+0x73 (805d0c8f)
805d0c2b bf404a5680	          mov	 edi,offset nt!PspCreateProcessNotifyRoutine (80564a40)
805d0c30 57			  push	edi
 
PspCreateProcessNotifyRoutine (80564a40)即这个数组的地址,这个数组是以下结构:
ypedef struct _EX_FAST_REF
{
	union
	{
		PVOID Object;
		ULONG_PTR RefCnt:3;
		ULONG_PTR Value;
	};
} EX_FAST_REF, *PEX_FAST_REF;
 
低三位RefCnt是引用指针,Value指向一个结构,如下:
typedef struct _EX_CALLBACK_ROUTINE_BLOCK
{
	EX_RUNDOWN_REF RundownProtect;
	PEX_CALLBACK_FUNCTION Function;
	PVOID Context;
} EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;

可以看到保存了回调函数的地址

因而采用搜索数组的方式在进行遍历即可,因为在WIN XP SP3中数组元素为8个,所以遍历的时候就按八个来的,WIN 7就不是了

(2)创建线程和加载模块一样,略过。。。

2、注册表回调

一开始真不知道哪个函数是注册注册表回调,尝试着在MSDN以cm(Xuetr回调类型里就是cmpCallBack)开头看到了CmRegisterCallback,大致看了一下,跟上面的原理一样。。不过是不是八个元素没注意,按八个处理的

3、错误检测回调

函数是:

KeRegisterBugCheckCallback

KeRegisterBugCheckReasonCallback

反汇编KeRegisterBugCheckCallback :

查看WRK ,这里没有考虑WRK与WIN XP 在该函数上可能的差异。。。得到以下信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NTKERNELAPI
BOOLEAN
KeRegisterBugCheckCallback (
	__out PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
	__in PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
	__in PVOID Buffer,
	__in ULONG Length,
	__in PUCHAR Component
	)
typedef struct _KBUGCHECK_CALLBACK_RECORD {
	LIST_ENTRY Entry;
	PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine;
	PVOID Buffer;
	ULONG Length;
	PUCHAR Component;
	ULONG_PTR Checksum;
	UCHAR State;
} KBUGCHECK_CALLBACK_RECORD, *PKBUGCHECK_CALLBACK_RECORD;
 
LIST_ENTRY KeBugCheckCallbackListHead;
LIST_ENTRY KeBugCheckReasonCallbackListHead;

结构类型就很清楚了,得到链表头,按照双向链表便利即可

4、Lego回调

刚从XUETR里面看到这个还真不知道是什么,搜索一番后,得到了MJ的一些说明:

ULONG PsSetLegoNotifyRoutine(PVOID notifyroutine)

notifyroutine为需要设置的回调函数地址

返回值是_ETHREAD->Tcb->LegoData的偏移量

调用此函数,系统会将一个未导出的全局变量_PspLegoNotifyRoutine设置为你设定的回调函数地址

当一个线程的_ETHREAD->Tcb->LegoData不为空,且_PspLegoNotifyRoutine不为空,那么当这个线程调用PspExitThread退出时,会调用PspLegoNotifyRoutine中的回调函数

系统中只允许设置一个这样的回调函数

有人跟着给出具体结构和定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef VOID (*PLEGO_NOTIFY_ROUTINE)( PKTHREAD Thread );
ULONG PsSetLegoNotifyRoutine( PLEGO_NOTIFY_ROUTINE LegoNotifyRoutine )
{
	PAGED_CODE();
	PspLegoNotifyRoutine = LegoNotifyRoutine;
	return FIELD_OFFSET(KTHREAD,LegoData);
}

硬编码搜索到这个全局变量,查看地址是否为0即可(不知是否有误,或者加上地址有效检测?)

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nt!PsSetLegoNotifyRoutine:
805d299a 8bff			  mov	 edi,edi
805d299c 55			  push	ebp
805d299d 8bec			  mov	 ebp,esp
805d299f 8b4508		          mov	 eax,dword ptr [ebp+8]
805d29a2 a3c0d26780	          mov	 dword ptr [nt!PspLegoNotifyRoutine (8067d2c0)],eax//这里
805d29a7 b8d0000000	          mov	 eax,0D0h
805d29ac 5d			  pop	 ebp
805d29ad c20400		          ret	 4

5、关机回调

有两个函数:

IoRegisterShutdownNotification

IoRegisterLastChanceShutdownNotification

来看第一个:

相关结构和定义也是参考了WRK。。。。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LIST_ENTRY IopNotifyShutdownQueueHead;
LIST_ENTRY IopNotifyLastChanceShutdownQueueHead;
 
typedef struct _SHUTDOWN_PACKET {
	LIST_ENTRY ListEntry;
	PDEVICE_OBJECT DeviceObject;
} SHUTDOWN_PACKET, *PSHUTDOWN_PACKET;

要得到回调函数地址,需要得到设备对象,回调函数地址即IRP_MJ_SHUTDOWN的例程地址

//#define IRP_MJ_SHUTDOWN 0x10

代码如下:

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ULONG GetNotifyAddr(PDEVICE_OBJECT Device_Object)
{
  ULONG Addr;
  PDRIVER_OBJECT Driver_Object;
  Driver_Object=Device_Object->DriverObject;
  Addr=*(ULONG*)((ULONG)Driver_Object+0x38+0x40);
  return Addr;
}

6、注销回调

搜了N久也不知道是哪个函数,于是看了看Xuetr,只有mrxsmb.sys注册了注销回调,查看其导入表看看有没有跟注册相关的字眼,于是找到了SeRegisterLogonSessionTerminatedRoutine

,查了一下,果然是。

也是一个链表头的形式,相关结构和定义:

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef NTSTATUS (*PSE_LOGON_SESSION_TERMINATED_ROUTINE) (
  IN PLUID LogonId
  );
typedef struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION {
	struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION *Next;
	PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine;
} SEP_LOGON_SESSION_TERMINATED_NOTIFICATION, *PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION;
 
NTSTATUS
SeRegisterLogonSessionTerminatedRoutine(
	IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
	);

7、文件系统改变回调

相关的注册函数是:IoRegisterFsRegistrationChange

结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef struct _NOTIFICATION_PACKET
{
	LIST_ENTRY ListEntry;
	PDRIVER_OBJECT DriverObject;
	ULONG NotificationRoutine;
} NOTIFICATION_PACKET, *PNOTIFICATION_PACKET;

8、即插即用回调

(1)注册的函数应该是IoRegisterPlugPlayNotification

今天下了一份2000源代码回来,找到了IoRegisterPlugPlayNotification函数的实现部分,发现了一个链表IopDeviceClassNotifyList,用Windbg查看这个链表,得到如下信息:

|————————|

1.8067d080 -> e1dd7698 ->–^

8067d080 <- e1dd7698 <---- |________________________| |------------------------------------------------| 2.e1336d98 -> e1036468 -> e1307548 -> 8067d090 ->–^

e1307548 <- 8067d090 <- e1336d98 <- e1036468 <---- |________________________________________________| |------------------------------------------------| 4.e1000888 -> e1f58478 -> e1bc04a0 -> 8067d0a0 ->–^

e1bc04a0 <- 8067d0a0 <- e1000888 <- e1f58478 <---- |________________________________________________| |------------------------| 5.e1537858 -> 8067d0a8 ->–^

e1537858 <- 8067d0a8 <---- |________________________| |------------------------| 6.e156e7c8 -> 8067d0b0 ->–^

e156e7c8 <- 8067d0b0 <---- |________________________| |------------------------| 10.e1315d60 -> 8067d0d0 ->–^

e1315d60 <- 8067d0d0 <---- |________________________| |------------------------------------------------| 11.e1002ad8 -> e156fc48 -> e1301258 -> 8067d0d8 ->–^

e1301258 <- 8067d0d8 <- e1002ad8 <- e156fc48 <---- |________________________________________________| |------------------------------------------------------------| 12.e1023c40 -> e131ae08 -> e101ea20 -> e1f752c8 -> 8067d0e0 ->–^

e1f752c8 <- 8067d0e0 <- e1023c40 <- e131ae08 <- e101ea20 <---- |____________________________________________________________| 一共17个,正好跟Xuetr对应上 而参照2000代码,IopDeviceClassNotifyList是一个具有13个(XP也是)元素的数组,每个都是一个链表,数据格式: 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef struct _SETUP_NOTIFY_DATA
 {
	LIST_ENTRY ListEntry;
	IO_NOTIFICATION_EVENT_CATEGORY EventCategory;
	PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callback;
	PVOID Context;
	PDRIVER_OBJECT DriverObject;
	USHORT RefCount;
	BOOLEAN Unregistered;
	PFAST_MUTEX Lock;
} SETUP_NOTIFY_DATA, *PSETUP_NOTIFY_DATA;

但是偏移跟实际的对不上。。。应该有所更改了

通过计算注册时提供的ClassGuid得到不同的hash值,hash值相同的串在一个链表里

但是技术太烂,WinDbg在u IoRegisterPlugPlayNotification里面没看到IopDeviceClassNotifyList数组,但是发现还有一个函数:IopInitializePlugPlayNotification 这个函数没有导出,我用了最烂的方法,遍历内核模块空间,根据特征码得到函数地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
nt!IopInitializePlugPlayNotification:
8058a5b4 6a0d			push	0Dh
8058a5b6 b880d06780	  mov	 eax,offset nt!IopDeviceClassNotifyList (8067d080)
8058a5bb 59			  pop	 ecx
8058a5bc 894004		  mov	 dword ptr [eax+4],eax

再得到IopDeviceClassNotifyList 数组地址,遍历即可。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++实现俄罗斯方块(附代码)
  还记得俄罗斯方块吗?相信这是小时候我们每个人都喜欢玩的一个小游戏。顾名思义,俄罗斯方块自然是俄罗斯人发明的。这人叫阿列克谢·帕基特诺夫。他设置这个游戏的规则是:由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失,给新落下来的板块腾出空间,与此同时,玩家得到分数奖励。没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,玩家便告输,游戏结束。
墨明棋妙27
2022/08/24
10.2K4
C++实现俄罗斯方块(附代码)
俄罗斯方块彩蛋(附星空表白彩蛋)
该文字主要讲解游戏逻辑代码实现,代码直接复制粘贴是无法直接运行的,直接运行可以在下文的传送门下载(0积分下载),下载好直接点击解决方案运行即可(需要按照要求安装easyx) ,或者去gitee查看源码,传送门在下文。
计算机魔术师
2022/08/20
4540
俄罗斯方块彩蛋(附星空表白彩蛋)
命令行之贪吃蛇_贪吃蛇蛇冲刺
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/10/03
8030
命令行之贪吃蛇_贪吃蛇蛇冲刺
【C++】基础:小游戏示例
DevFrank
2024/07/24
1.7K0
【C++】基础:小游戏示例
命令行之2048
2048挺火的游戏,在命令行实现是什么样呢?小尝试了下,这里感谢css大神给debug,还有就是游戏空格处採用特殊字符,因此程序在linux下跑可能会出现乱码,能够手动调整
全栈程序员站长
2022/07/08
5900
命令行之2048
C语言坦克大战
//里规格:长39*2=78 (真坐标)(假坐标宽为39) 高39
紫禁玄科
2022/03/24
1.1K0
C语言坦克大战
基于DOS的简易俄罗斯方块制作
制作一个简易的俄罗斯方块,未调用graphics库(装了半天不成功),完全的黑框操作 基本思路: 1.利二维数组表示地图(也可以利用一维数组,此处利用的是一维数组) 0.表示没有方格,1.表示正在下落的方格 2.表示墙壁 2.共有七种俄罗斯方块,但是有19种状态 (绘制方块处,总共有7种俄罗斯方块,旋转之后可以形成19种方块) 3.每个方块需设置一个中心方块 ,尽量与其他的方块有联系。中心方块用B[0]表示,其他的方块由1,2,3表示
用户7886150
2020/12/07
4080
windows下实现win32俄罗斯方块练手,编程的几点心得
一个运筹学者接到任务,设计末座大楼的电梯调度策略,使乘客等待的时间最短,在走访了这座大楼之后,他认识到雇主真正想要解决的问题是,尽量减少乘客的不适( 乘客不喜欢等电梯)。他这样解决问题:在每部电梯附近装上几面镜子。乘客在等电梯时候,可以自我欣赏一下,对电梯速度的抱怨大幅减少了。他发现了用户的真正需求
流川疯
2019/01/18
8590
Java---俄罗斯方块小游戏
去年就已经学了这个技术了,一直没去写,现在抽个时间写了个俄罗斯方块游戏。 只有简单的新游戏,暂停,继续,积分功能。简单的实现了俄罗斯的经典功能。 不介绍了,有兴趣的自己运行一下,后面贴出了图片。
谙忆
2021/01/21
8620
Java---俄罗斯方块小游戏
俄罗斯方块c语言源代码_俄罗斯方块C语言
思路: 1.初始化界面,用一个矩阵来保存界面的每一个位置,包括颜色跟数值,数值用来区分是墙还是方块还是空格,便于运行时的判断。
全栈程序员站长
2022/11/17
3.5K0
俄罗斯方块c语言源代码_俄罗斯方块C语言
C++从零开始实现俄罗斯方块,vc6.0就可以实现
2旋转,也就是按上下,图形变换而已。 按照上面的规则,条形只能变成下一个条形,方形不能变,L形只能变成L形。
全栈程序员站长
2021/04/07
4530
C语言俄罗斯方块(旧版本)
这个代码还是刚入坑写的,是新手时候的我,偶然间翻到,放到这里做个纪念,不打算写出来,只贴上代码,过几天会再写一个俄罗斯方块拿做一个对比。看看曾经的我和现在的我有什么区别。
花狗Fdog
2020/10/28
1.3K0
C语言俄罗斯方块(新版本完整代码)
旧版800行代码,这个只有500行,并且不闪屏,看着舒服。废话不多说,上图,上代码。
花狗Fdog
2020/10/28
8.9K1
C语言俄罗斯方块(新版本完整代码)
俄罗斯方块(C语言实现)
俄罗斯方块相信大家都知道,这里就不再介绍什么游戏背景了,我这里对本代码实现的俄罗斯方块作一些说明:
全栈程序员站长
2022/08/30
2K1
俄罗斯方块(C语言实现)
【C/C++】10分钟教你用C++写一个贪吃蛇附带AI功能(附源代码详解和下载)
刚学完C++。一时兴起,就花几天时间手动做了个贪吃蛇,后来觉得不过瘾,于是又加入了AI功能。希望大家Enjoy It.
短短的路走走停停
2019/05/14
1.5K0
Java实现俄罗斯方块小游戏。(附完整源代码)
俄罗斯方块是俄罗斯人发明的。这人叫阿列克谢·帕基特诺夫(Алексей Пажитнов 英文:Alexey Pazhitnov)。俄罗斯方块原名是俄语Тетрис(英语是Tetris),这个名字来源于希腊语tetra,意思是“四”,而游戏的作者最喜欢网球(tennis)。于是,他把两个词tetra和tennis合而为一,命名为Tetris,这也就是俄罗斯方块名字的由来。
百思不得小赵
2022/12/01
6.2K1
Java实现俄罗斯方块小游戏。(附完整源代码)
四个c语言小游戏
1、我使用的是编译软件是vc6.0 2、如果代码无法运行,你可以尝试吧文件xxx.c改为xxx.cpp 3、四个小游戏我都运行过,确保是可以运行的。虽然可玩性、操作性。。。
全栈程序员站长
2022/08/30
3.3K0
C语言小游戏——贪吃蛇—-小白专用
对于刚学完C语言的初学者,直接做这种小游戏也是一件非常困难的事情,中间还有很大的鸿沟。老师上课讲授的知识非常有限,大部分知识还需要同学们自己去探索。 如果你用的时vs2010,那估计以上程序一定会报错,两个版本在scanf函数上有所不同,在2019中必须要求使用scanf_s.
全栈程序员站长
2022/08/26
9090
C语言小游戏——贪吃蛇—-小白专用
贪吃蛇电脑代码能直接玩_贪吃蛇为什么能安装不能玩
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/10/04
4220
贪吃蛇电脑代码能直接玩_贪吃蛇为什么能安装不能玩
C++项目贪吃蛇游戏笔记-项目代码
.cpp main.cpp #include "controller.h" int main()//程序入口 { Controller c;//声明一个Controller类 c.Game();//整个游戏循环 return 0; } controller.cpp #include <iostream> #include <time.h> #include <conio.h> #include <windows.h> #include "controller.h" #includ
CtrlX
2022/09/26
6970
相关推荐
C++实现俄罗斯方块(附代码)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验