———– Rootkit 宗旨技术之绕过 IopParseDevice() 调用源检测逻辑 —————

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

除此以外,由于
IopAllocateOpenPacket() 等价于
ExAllocatePoolWithTag(),而后人平常再次回到泛型指针(“ PVOID ,亦即 void
”),
从而自个儿强制把它转型为与
“openPacket” 一致的项目。
齐全,“东风”
就在于调用 ObReferenceObjectByName() 时,为第5个参数字传送入“openPacket”
即可,上海体育场地展现的很明亮了。

———– Rootkit 宗旨技术之绕过 IopParseDevice() 调用源检查和测试逻辑,

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

在上一篇小说中,大家曾经看到 IopParseDevice() 如何对传播的 OPEN_PACKET
结构实行求证。假使 ObReferenceObjectByName()
的调用者没有分配并伊始化第几个参数 ParseContext,而仅是简单地传播 “NULL”
,那么当调用链深刻到 IopParseDevice()
内部时,就会因验证战败重临 C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

大家依照源码中的暗示来追踪 OPEN_PACKET
结构毕竟在哪分配的,如前所述,调用链
NtCreateFile->IoCreateFile()->IopCreateFile() 的结尾,也正是在
IopCreateFile() 内部,实际负责 OPEN_PACKET
的初叶化。下边贴出的代码片段以 NT 5.2 版内核源码为样例:

 

365bet手机版客户端 1

相当于说,大家向来复制 IopCreateFile() 中的 OPEN_PACKET
结构开端化部分逻辑就行了?

此间还有贰个难题,负责分配该组织体内核内部存款和储蓄器的例程 IopAllocateOpenPacket()
是一个宏,Visual C++ 2014 中付出它是用 ExAllocatePoolWithTag()
定义的。那就好办了,在我们自身的驱动力源码中,添加相应定义即可,如下图:

 

365bet手机版客户端 2

 

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

因为 OPEN_PACKET
结构同样没有领悟的文书档案来描述,所以还是在我们的驱动力源码中用 
#include
包蕴定义它的头文件,要么直接复制定义的那有个别黏贴进来。很扎眼,后者相比轻松——OPEN_PACKET
在基本源码的 “iomgr.h
中定义,而该头文件又嵌套包括了一堆杂七杂八的内核头文件,要清理那几个嵌套包涵关系很劳累,而且最根本的是,内部一部分头文件定义的数据类型会与驱动开发中用的 “ntddk.h”
和“wdm.h”重复,引起编写翻译器的埋怨。
由此直接在 “iomgr.h” 中搜索字串
“typedef struct _OPEN_PACKET”,把找到的定义块拷贝进来即可。

然而,OPEN_PACKET 结构中可是三个字段不是 “原生” 定义的——那就是“PDUMMY_FILE_OBJECT” 类型,需求包括别的头文件才不造成编写翻译器报错。

自己的消除方案是,直接把该字段的扬言所在行注释掉,下图展现了该字段具体的职位(在
iomgr.h” 中的行号),方便各位飞快搜索:

 

365bet手机版客户端 3

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

注意,NT 6.1 版内核在编译时刻的 OPEN_PACKET 结构分明是未经 “恶意
修改的,所以编写翻译器为其 “sizeof(OPEN_PACKET)” 表达式总计 0x70
的值,而作者辈在协调的驱动中拿掉了 OPEN_PACKET
当中二个字段使得编写翻译器为表明式 “sizeof(OPEN_PACKET)” 预总括 0x58
的值(前边的调节阶段会注解),那会招致 “Size” 字段不是
IopParseDevice() 内部逻辑预期的 0x70,从而致使重临C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

消除办法也很简单,我们的驱动中,不要借助理编辑译时刻的一个钱打二16个结,直接把
Size” 字段的值硬编码为 0x70 不就好了?

一般来说图所示,你还会小心到,小编把 “Type” 字段的常量
“IO_TYPE_OPEN_PACKET” 改成了相应的数值,以保障一旦。

 

365bet手机版客户端 4

 

另外,由于 IopAllocateOpenPacket() 等价于
ExAllocatePoolWithTag(),而后人经常重返泛型指针(“ PVOID ,亦即 
void * ”),
于是作者强制把它转型为与 “openPacket” 一致的类型。
齐全,“东风” 就在于调用 ObReferenceObjectByName()
时,为第多个参数字传送入“openPacket” 即可,上海体育地方展现的很领悟了。

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

很不好的是,笔者把编写翻译出来的驱动放到虚拟机(Windows 7,基于 NT 6.1
版内核)里面动态加载测试,照旧不可能获得到

“\Device\QQProtect” 相应的装备对象指针,ObReferenceObjectByName() 再次来到C0000024。

为了找出故障原因,小编在分配 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

 

参数 “logo” 内定要把全副调节和测试进度的输出新闻写入日志;

“-y”
内定符号文件的职责(机器指令中从不内核函数与变量的标志,所以调节和测试器须求查找额外的记号以向用户体现人类可读的名目);
“-k” 参数内定调节和测试类型为
取名管道模拟串口1”,波特率数值越高,响应越快。

把重新编译好的驱动放到虚拟机中,在晋级权限后的一声令下提醒符中执行
bcdedit.exe,启用调节和测试情势,那样重启虚拟机后,就会进来调节和测试方式(无需在开发银行进度中按下
F8 采取菜单)。

作者把自个儿的驱动实现成按需加载,也便是应用劳动控制管理器sc.exe)发出命令来动态加载和卸载,完毕此意义的相应批处理公事内容如下图,注意该文件要放在虚拟机中推行,“start=
demand” 申明通过 sc.exe 按需运维
;“binpath”
正是驱动文件存放的磁盘路径
,假使本身的驱动名为
hideprocess.sys,执行该批处理职分后,就在连锁的注册表地点添加了一项,将来只需在
cmd.exe 中实施 “sc.exe start/stop hideprocess” 就能够动态加卸载。

365bet手机版客户端 5

 

根据上述方法加载时,就会自动触发我们设定好的软件断点,即可在宿主机中检查虚拟机的基础空间。
此外还需注意一点:编写翻译驱动时的 “营造” 环境应该选用 Check
Build
,那样会一并生成同名称的记号文件,后缀为
.pdb”,从而调节和测试器可以呈现咱们协调驱动中的函数与变量名称,进步调节和测试功用,如下图:

 

365bet手机版客户端 6

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

接触软件断点后,我们一般会用 “kv
命令查看栈回溯音信,它披表露大家的驱动入口点 DriverEntry() 是由 I/O
管理器的 IopLoadDriver() 调用的:

 

365bet手机版客户端 7

栈的顶层函数 “ReferenceDeviceAndHookI奥迪Q7PdispatchRoutine+0x56
是自家添加软中断的位置。执行 “r” 命令查看当前的 x86
通用寄存器状态,EIP 指向地址 0x8f4a3196 ,执行 “u
hideprocess!ReferenceDeviceAndHookIRPdispatchRoutine+0x56
L2”,反汇编输出的第二行地址正是 0x8f4a3196,与 EIP
的值相符;第叁行是把二个 16 进制值 “ 704F6F49h” 压栈,实际上它是
ASCII 字符 “pOoI” 的 16
进制编码,换言之,那是在经过内核栈传递 ExAllocatePoolWithTag()
的第三个参数(从右往左传递,请纪念以前的 IopAllocateOpenPacket()
宏定义那张图)。

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

持续按下 “t
单步执行,如下图所示,你能够看到,ExAllocatePoolWithTag()
的第①个参数,分配的基行业内部部存款和储蓄器大小为 0x70
字节,因为本身在宏定义中硬编码了这些值,而不是用 sizeof(OPEN_PACKET)
表明式让编写翻译器总括;另一方面,图中的 “dt” 命令也表达了它的深浅为
0x70 字节。

首个传入的参数 “NonPagedPool
为不可换页池,其内的数码不能够被换出物理内部存款和储蓄器,该常量对应的数值为 “0”:

365bet手机版客户端 8

 

小编不想浪费时间在翻看内核内部存款和储蓄器的分红细节上,所以本人按下 “p”,步过
ExAllocatePoolWithTag() 函数调用,接下去的 cmp/jne
汇编系列
对应源码中检查是否成功分配了内部存款和储蓄器并用于 openPacket
指针,实际的履行结果是跳转到地址 0x8f4a31c6 ,对应源码中伊始化
OPEN_PACKET 结构前八个字段的逻辑:

365bet手机版客户端 9

接下来直白单步执行到调用 ObReferenceObjectByName()
前夕,在此地大家要 “步入” 它的当中,实行故障排查,所以按下 “t
跟进,那里有一个小技巧,我们已经分析过 ObReferenceObjectByName()
的源码,知道它会调用很多函数,而且大约了然难题出现在
ObpLookupObjectName() 里面,所以指令
tc”能够跟踪到各样函数调用处甘休,再由用户决定是或不是跟进该函数内部。

那是本人的光明期待,但实际总是残酷的,在自家跟踪到原子操作体系函数

nt!ExInterlockedPopEntrySList() 调用时,kd.exe
就卡住了,不可能持续追踪此后的调用链。从稍早的栈回溯新闻来看,与源码大壮我们推断的调用连串大概相符,只是不驾驭为什么在
nt!ObpAllocateObjectNameBuffer() 中,为了给传入的驱动对象名称
“\Device\QQProtect”
分配内核内部存款和储蓄器,调用 nt!ExInterlockedPopEntrySList(),而后者却无力回天追踪。。。。是虚拟机环境的由来,照旧原子操作类函数的不可分割性质?

 

365bet手机版客户端 10

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

讲一些废话,一般我们在栈回溯中看到的顶层表明行,有3个 “Args to Child”
项目,表示调用者传递给它的参数,不过最多也只可以彰显前四个。
以下图为例子吗,传递给 nt!ExAllocatePoolWithTag()
的多少个参数(从左到右)就是00000000(NonPagedPool),00000070(小编硬编码的值),704f6f49(ASCII
字符串“pOoI”)
,同理,传递给 hideprocess!DriverEntry() 的率先个参数
867c3550 是 _DRIVER_OBJECT 结构的地址,由I/O
管理器加载它时为它分配(注意与源码中 DriverEntry() 定义的一枚
_DRIVER_OBJECT 指针分裂,“Args to Child”

列出的数码一定于履行解引操作符 * 后的结果),第③个参数是
UNICODE_STQashqaiING 结构的地址,对应源码定义中的一枚 _UNICODE_ST凯雷德ING
指针,该组织中贮存的是大家驱动在注册表中的完整路径:

 

365bet手机版客户端 11
——————————————————————————————————————————————————————————————————

简单来说 ,基于上述理由我无能为力持续跟进到 ObpLookupObjectName()
里面查看它是或不是实施了 IopParseDevice()
回调,从而无法明确到底为啥后者再次回到 C0000024。

自家想可能是因为根本源码版本的变更,导致相关例程的判定逻辑也不雷同了,不可能依据前一版源码的逻辑来编排估计运维在后一版内核上的驱动。
其实消除方案也许有个别,相比较花时间而已,正是选择 “u” 指令反汇编
ObpLookupObjectName() 初阶处对应的机器指令,再反编写翻译成类似的 C 伪码,与
NT 5.2
版内核源码比较,找出在那之中改动的地点,但那是3个费时费劲的办事,且收入甚微,还不如直接在网络上搜释出的
NT 6.1 版内核源码,可能接近的本子,再想想绕过的措施。

顺带说一下,根据 A 设备名取得 A 设备对象的指针,然后把
rootkit/本人驱动成立的恶心设备 attach 到 A
设备所在的装置栈,从而阻碍检查通过 A 设备的 IEnclaveP
内数据。。。。这种艺术已经比较过时了,因为后天反病毒软件的木本方式组件也会检查这么些设备栈,寻找别的匹配特征码的黑心设备,再者,内核调节和测试器的
“!devstack”
命令很不难遍历揭发出给定设备所在的配备栈内容,被广大用于总计机调查取证中,从
rootkit 的严重性指标——完结隐身——的角度来看, attach
到装备栈就不是多少个好规范。

相反,通过 ObReferenceObjectByName()
总是能够获取驱动对象的指针,进而可以 hook 该驱动的 I奥迪Q5P
分发例程,那种手段隐蔽性极高,而且不简单被检测出来。

延续的博文将研究哪边将那种技能用在 rootkit
中,同时适应当前风靡的相反相成多处理器(SMP)环境。

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

Rootkit 大旨技术之绕过
IopParseDevice() 调用源检查和测试逻辑,
—————————————————————————————————…

 

几次三番的博文将斟酌哪边将那种技能用在
rootkit 中,同时适应现阶段风靡的相反相成多处理器(SMP)环境。

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

 

 

365bet手机版客户端 12

 

栈的顶层函数
“ReferenceDeviceAndHookI路虎极光PdispatchRoutine+0x56
是本人添加软中断的位置。执行 “r” 命令查看当前的 x86
通用寄存器状态,EIP 指向地址 0x8f4a3196 ,执行 “u
hideprocess!ReferenceDeviceAndHookIRPdispatchRoutine+0x56
L2”,反汇编输出的首先行地址便是 0x8f4a3196,与 EIP
的值相符;第叁行是把1个 16 进制值 “ 704F6F49h” 压栈,实际上它是
ASCII 字符 “pOoI365bet手机版客户端,” 的 16
进制编码,换言之,那是在通过内核栈传递 ExAllocatePoolWithTag()
的第八个参数(从右往左传递,请记忆在此之前的 IopAllocateOpenPacket()
宏定义那张图)。

瞩目,NT
6.1 版内核在编写翻译时刻的 OPEN_PACKET 结构鲜明是未经 “恶意
修改的,所以编写翻译器为其 “sizeof(OPEN_PACKET)” 表明式计算 0x70
的值,而大家在投机的驱动中拿掉了 OPEN_PACKET
个中三个字段使得编写翻译器为发挥式 “sizeof(OPEN_PACKET)” 预总括 0x58
的值(前面包车型客车调节和测试阶段会表明),那会招致 “Size” 字段不是
IopParseDevice() 内部逻辑预期的 0x70,从而致使重返C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

 

然而,OPEN_PACKET
结构中只是八个字段不是 “原生” 定义的——那正是 “PDUMMY_FILE_OBJECT”
类型,须要包蕴别的头文件才不造成编写翻译器报错。

参数
“logo” 钦命要把全副调节和测试进度的出口新闻写入日志;

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

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

在上一篇小说中,大家已经观察IopParseDevice() 怎样对传播的 OPEN_PACKET 结构实行表明。假如ObReferenceObjectByName() 的调用者没有分配并开头化第三个参数
ParseContext,而仅是简约地流传 “NULL” ,那么当调用链深切到
IopParseDevice()
内部时,就会因验证战败再次来到 C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

恰恰手边有一份
NT 5.2 版内核的源码,它用来编写翻译 Windows XP/Server 2002使用的水源,就算与自作者的测试机器的 NT 6.1 版内核有所差别,可是
如故姑且来看下
ObReferenceObjectByName() 内部毕竟干了些什么。ObReference*()
系列的例程多数放在内核源码的“obref.c” 与“obdir.c
文本内。通过对有关调用链的辨析,如下图所示:

365bet手机版客户端 13

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

先是种状态普通是由于创设目的
_DEVICE_OBJECT 时钦赐的 session id 与方今的 session id
不同,或然目的对象具备特殊的安全访问令牌/安全质量,所以大家无能为力以健康办法取得,而且那种颠倒是非频仍出现在
IoGetDeviceObjectPointer() 调用时,偏偏多数讲过滤驱动和 rootkit
的书籍都用 IoGetDeviceObjectPointer()
作为示范代码的一某些,真是有点误人子弟的象征。

 

大家根据源码中的暗示来追踪
OPEN_PACKET 结构终究在哪分配的,如前所述,调用链
NtCreateFile->IoCreateFile()->IopCreateFile() 的末梢,也便是在
IopCreateFile() 内部,实际负担 OPEN_PACKET
的初步化。上面贴出的代码片段以 NT 5.2 版内核源码为样例:

 

365bet手机版客户端 14

接触软件断点后,大家一般会用
kv” 命令查看栈回溯消息,它披揭示大家的驱动入口点 DriverEntry() 是由
I/O 管理器的 IopLoadDriver() 调用的:

本身在源码中提取了有关代码片段,如上边这个图所示,最CANON把它与地点的流程图相比加深理解,
后边笔者会拿虚拟机上的
Windows 7(基于 NT 6.1
版内核)调节和测试,你会惊奇地窥见,追踪栈回溯消息时,
居然与
NT 5.2
版内核源码中的调用链格外相似,这申明版本之间的动员搬迁并没有让对象名查找和评释逻辑改动太大。
(至少从
Windows XP 到 7
而言是那样,之后的版本由于没测试过,就不知晓了!)

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

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

365bet手机版客户端 15

365bet手机版客户端 16
——————————————————————————————————————————————————————————————————

 

 

正如图所示,你还会注意到,作者把
“Type” 字段的常量 “IO_TYPE_OPEN_PACKET”
改成了对应的数值,以保险一旦。

那边还有一个难题,负责分配该组织体内核内部存储器的例程 IopAllocateOpenPacket()
是八个宏,Visual C++ 二〇一五 中付出它是用 ExAllocatePoolWithTag()
定义的。那就好办了,在大家协调的驱动源码中,添加相应定义即可,如下图:

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

那里还有一个难题,负责分配该协会体内核内部存款和储蓄器的例程 IopAllocateOpenPacket()
是3个宏,Visual C++ 贰零壹陆 中提交它是用 ExAllocatePoolWithTag()
定义的。这就好办了,在大家和好的驱动力源码中,添加相应定义即可,如下图:

 

365bet手机版客户端 17

 

把重新编写翻译好的驱动放到虚拟机中,在升级权限后的下令提醒符中执行
bcdedit.exe,启用调节和测试方式,那样重启虚拟机后,就会进来调节和测试形式(无需在运营进程中按下
F8 选拔菜单)。

 

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

化解办法也很简单,我们的驱动中,不要借助理编辑译时刻的预计,直接把
Size” 字段的值硬编码为 0x70 不就好了?

365bet手机版客户端 18

365bet手机版客户端 19

 

WInodws
内核使用二个数据结构——ObTypeIndexTable
存放有关各样“对象类型”的新闻,本质上 ObTypeIndexTable
是二个指南针数组,在 32 位种类布局上,各个指针大小
4 字节,而我们获取的索引号为(下标**
0
开始**)19,下图中的两条表明式据此总结出该“对象类型”的地点:

 

kd.exe
-n -v -logo d:\virtual_machine_debugging.txt -y
SRV*C:\Symbols* -k
com:pipe,port=\\.\pipe\com_365滚球投注网站,1,baud=115200,reconnect

 

 

列出的数量一定于实践解引操作符 *
后的结果
),首个参数是 UNICODE_bet体育在线,ST君越ING
结构的地点,对应源码定义中的一枚 _UNICODE_ST大切诺基ING
指针,该组织中存款和储蓄的是大家驱动在注册表中的完整路径:

365bet手机版客户端 20

发表评论

电子邮件地址不会被公开。 必填项已用*标注