澳门新蒲京娱乐

新蒲京娱乐场777 10
【新蒲京娱乐场777】excel高手进来,寻Excel表格高手

两句命令搞定

核心技术之绕过,调用源检测逻辑

————————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————————

在上一篇文章中,我们已经看到
IopParseDevice() 如何对传入的 OPEN_PACKET 结构进行验证。假设
ObReferenceObjectByName() 的调用者没有分配并初始化第七个参数
ParseContext,而仅是简单地传入 “NULL” ,那么当调用链深入到
IopParseDevice()
内部时,就会因验证失败返回 C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

在上一篇文章中,我们已经看到
IopParseDevice() 如何对传入的 OPEN_PACKET 结构进行验证。假设
ObReferenceObjectByName() 的调用者没有分配并初始化第七个参数
ParseContext,而仅是简单地传入 “NULL” ,那么当调用链深入到
IopParseDevice()
内部时,就会因验证失败返回 C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

我们根据源码中的暗示来追踪
OPEN_PACKET 结构究竟在哪分配的,如前所述,调用链
NtCreateFile->IoCreateFile()->IopCreateFile() 的结尾,也就是在
IopCreateFile() 内部,实际负责 OPEN_PACKET
的初始化。下面贴出的代码片段以 NT 5.2 版内核源码为样例:

我们根据源码中的暗示来追踪
OPEN_PACKET 结构究竟在哪分配的,如前所述,调用链
NtCreateFile->IoCreateFile()->IopCreateFile() 的结尾,也就是在
IopCreateFile() 内部,实际负责 OPEN_PACKET
的初始化。下面贴出的代码片段以 NT 5.2 版内核源码为样例:

 

 

图片 1

图片 1

也就是说,我们直接复制
IopCreateFile() 中的 OPEN_PACKET 结构初始化部分逻辑就行了?

也就是说,我们直接复制
IopCreateFile() 中的 OPEN_PACKET 结构初始化部分逻辑就行了?

这里还有一个问题,负责分配该结构体内核内存的例程 IopAllocateOpenPacket()
是一个宏,Visual C++ 2015 中给出它是用 ExAllocatePoolWithTag()
定义的。这就好办了,在我们自己的驱动源码中,添加相应定义即可,如下图:

这里还有一个问题,负责分配该结构体内核内存的例程 IopAllocateOpenPacket()
是一个宏,Visual C++ 2015 中给出它是用 ExAllocatePoolWithTag()
定义的。这就好办了,在我们自己的驱动源码中,添加相应定义即可,如下图:

 

 

图片 3

图片 3

 

 

————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————

因为
OPEN_PACKET 结构同样没有公开的文档来描述,所以要么在我们的驱动源码中用 
#include
包含定义它的头文件,要么直接复制定义的那一部分黏贴进来。很显然,后者比较轻松——OPEN_PACKET
在内核源码的 “iomgr.h
中定义,而该头文件又嵌套包含了一堆杂七杂八的内核头文件,要理清这些嵌套包含关系很麻烦,而且最重要的是,其中一些头文件定义的数据类型会与驱动开发中用的 “ntddk.h”
和“wdm.h”重复,引起编译器的抱怨。
所以直接在 “iomgr.h
中搜索字串 “typedef struct
_OPEN_PACKET”,把找到的定义块拷贝进来即可。

因为
OPEN_PACKET 结构同样没有公开的文档来描述,所以要么在我们的驱动源码中用 
#include
包含定义它的头文件,要么直接复制定义的那一部分黏贴进来。很显然,后者比较轻松——OPEN_PACKET
在内核源码的 “iomgr.h
中定义,而该头文件又嵌套包含了一堆杂七杂八的内核头文件,要理清这些嵌套包含关系很麻烦,而且最重要的是,其中一些头文件定义的数据类型会与驱动开发中用的 “ntddk.h”
和“wdm.h”重复,引起编译器的抱怨。
所以直接在 “iomgr.h
中搜索字串 “typedef struct
_OPEN_PACKET”,把找到的定义块拷贝进来即可。

然而,OPEN_PACKET
结构中唯有一个字段不是 “原生” 定义的——这就是 “PDUMMY_FILE_OBJECT”
类型,需要包含其它头文件才不致使编译器报错。

然而,OPEN_PACKET
结构中唯有一个字段不是 “原生” 定义的——这就是 “PDUMMY_FILE_OBJECT”
类型,需要包含其它头文件才不致使编译器报错。

我的解决方案是,直接把该字段的声明所在行注释掉,下图展示了该字段具体的位置(在
iomgr.h” 中的行号),方便各位快速查找:

我的解决方案是,直接把该字段的声明所在行注释掉,下图展示了该字段具体的位置(在
iomgr.h” 中的行号),方便各位快速查找:

 

 

图片 5

图片 5

——————————————————————————————————————————————————————————————————

——————————————————————————————————————————————————————————————————

注意,NT
6.1 版内核在编译时刻的 OPEN_PACKET 结构显然是未经 “恶意
修改的,所以编译器为其 “sizeof(OPEN_PACKET)” 表达式计算 0x70
的值,而我们在自己的驱动中拿掉了 OPEN_PACKET
其中一个字段使得编译器为表达式 “sizeof(OPEN_PACKET)” 预计算 0x58
的值(后面的调试阶段会验证),这会造成 “Size” 字段不是
IopParseDevice() 内部逻辑预期的 0x70,从而导致返回
C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

注意,NT
6.1 版内核在编译时刻的 OPEN_PACKET 结构显然是未经 “恶意
修改的,所以编译器为其 “sizeof(OPEN_PACKET)” 表达式计算 0x70
的值,而我们在自己的驱动中拿掉了 OPEN_PACKET
其中一个字段使得编译器为表达式 “sizeof(OPEN_PACKET)” 预计算 0x58
的值(后面的调试阶段会验证),这会造成 “Size” 字段不是
IopParseDevice() 内部逻辑预期的 0x70,从而导致返回
C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

解决办法也很简单,我们的驱动中,不要依赖编译时刻的计算,直接把
Size” 字段的值硬编码为 0x70 不就好了?

解决办法也很简单,我们的驱动中,不要依赖编译时刻的计算,直接把
Size” 字段的值硬编码为 0x70 不就好了?

如下图所示,你还会注意到,我把
“Type” 字段的常量 “IO_TYPE_OPEN_PACKET”
改成了对应的数值,以确保万一。

如下图所示,你还会注意到,我把
“Type” 字段的常量 “IO_TYPE_OPEN_PACKET”
改成了对应的数值,以确保万一。

 

 

图片 7

图片 7

 

 

另外,由于
IopAllocateOpenPacket() 等价于
ExAllocatePoolWithTag(),而后者通常返回泛型指针(“ PVOID ,亦即 void
”),
所以我强制把它转型为与
“openPacket” 一致的类型。
万事俱备,“东风”
就在于调用 ObReferenceObjectByName() 时,为第七个参数传入“openPacket”
即可,上图显示的很清楚了。

另外,由于
IopAllocateOpenPacket() 等价于
ExAllocatePoolWithTag(),而后者通常返回泛型指针(“ PVOID ,亦即 void
”),
所以我强制把它转型为与
“openPacket” 一致的类型。
万事俱备,“东风”
就在于调用 ObReferenceObjectByName() 时,为第七个参数传入“openPacket”
即可,上图显示的很清楚了。

——————————————————————————————————————————————————————————————————

——————————————————————————————————————————————————————————————————

很不幸的是,我把编译出来的驱动放到虚拟机(Windows
7,基于 NT 6.1 版内核)里面动态加载测试,还是无法获取到

很不幸的是,我把编译出来的驱动放到虚拟机(Windows
7,基于 NT 6.1 版内核)里面动态加载测试,还是无法获取到

“\Device\QQProtect”
相应的设备对象指针,ObReferenceObjectByName() 返回 C0000024。

“\Device\QQProtect”
相应的设备对象指针,ObReferenceObjectByName() 返回 C0000024。

为了找出故障原因,我在分配
OPEN_PACKET 逻辑的前面利用内联汇编添加了一个软中断 “__asm{ int
3; } 

”,宿主机器上启动内核调试器 kd.exe,我的启动参数像是这样:

为了找出故障原因,我在分配
OPEN_PACKET 逻辑的前面利用内联汇编添加了一个软中断 “__asm{ int
3; } 

”,宿主机器上启动内核调试器 kd.exe,我的启动参数像是这样:

kd.exe
-n -v -logo d:\virtual_machine_debugging.txt -y
SRV*C:\Symbols* -k
com:pipe,port=\\.\pipe\com_1,baud=115200,reconnect

kd.exe
-n -v -logo d:\virtual_machine_debugging.txt -y
SRV*C:\Symbols* -k
com:pipe,port=\\.\pipe\com_1,baud=115200,reconnect

 

 

参数
“logo” 指定要把整个调试过程的输出信息写入日志;

参数
“logo” 指定要把整个调试过程的输出信息写入日志;

“-y”
指定符号文件的位置(机器指令中没有内核函数与变量的符号,所以调试器需要查找额外的符号以向用户显示人类可读的名称);
“-k”
参数指定调试类型为
命名管道模拟串口1”,波特率数值越高,响应越快。

“-y”
指定符号文件的位置(机器指令中没有内核函数与变量的符号,所以调试器需要查找额外的符号以向用户显示人类可读的名称);
“-k”
参数指定调试类型为
命名管道模拟串口1”,波特率数值越高,响应越快。

把重新编译好的驱动放到虚拟机中,在提升权限后的命令提示符中执行
bcdedit.exe,启用调试模式,这样重启虚拟机后,就会进入调试模式(无需在启动过程中按下
F8 选择菜单)。

把重新编译好的驱动放到虚拟机中,在提升权限后的命令提示符中执行
bcdedit.exe,启用调试模式,这样重启虚拟机后,就会进入调试模式(无需在启动过程中按下
F8 选择菜单)。

我把自己的驱动实现成按需加载,也就是利用服务控制管理器sc.exe)发出命令来动态加载和卸载,实现此功能的相应批处理文件内容如下图,注意该文件要放在虚拟机中执行,“start=
demand” 表明通过 sc.exe 按需启动
;“binpath”
就是驱动文件存放的磁盘路径
,假设我的驱动名为
hideprocess.sys,执行该批处理任务后,就在相关的注册表位置添加了一项,往后只需在
cmd.exe 中执行 “sc.exe start/stop hideprocess” 就能够动态加卸载。

我把自己的驱动实现成按需加载,也就是利用服务控制管理器sc.exe)发出命令来动态加载和卸载,实现此功能的相应批处理文件内容如下图,注意该文件要放在虚拟机中执行,“start=
demand” 表明通过 sc.exe 按需启动
;“binpath”
就是驱动文件存放的磁盘路径
,假设我的驱动名为
hideprocess.sys,执行该批处理任务后,就在相关的注册表位置添加了一项,往后只需在
cmd.exe 中执行 “sc.exe start/stop hideprocess” 就能够动态加卸载。

图片 9

图片 9

相关文章

No Comments, Be The First!
近期评论
    功能
    网站地图xml地图