来自 品牌动态 2019-10-19 11:06 的文章
当前位置: 118kj开奖现场 > 品牌动态 > 正文

调用源检测逻辑

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

在上一篇文章中,大家已经看见IopParseDevice() 如何对传播的 OPEN_PACKET 结构实行认证。假诺ObReferenceObjectByName() 的调用者未有分配并最初化第三个参数 ParseContext,而仅是大约地传颂 “NULL” ,那么当调用链深切到 IopParseDevice() 内部时,就能够因验证退步再次回到 C0000024(STATUS_OBJECT_TYPE_MISMATCH)。

笔者们根据源码中的暗暗提示来追踪OPEN_PACKET 结构毕竟在哪分配的,如前所述,调用链 NtCreateFile->IoCreateFile()->IopCreateFile() 的末梢,也正是在 IopCreateFile() 内部,实际负担 OPEN_PACKET 的开头化。上边贴出的代码片段以 NT 5.2 版内核源码为样例:

 

图片 1

也正是说,大家直接复制 IopCreateFile() 中的 OPEN_PACKET 结构开端化部分逻辑就行了?

此间还会有贰个标题,担任分配该协会体内核内部存款和储蓄器的例程 IopAllocateOpenPacket() 是多个宏,Visual C++ 二零一五 中提交它是用 ExAllocatePoolWithTag() 定义的。那就好办了,在大家温馨的驱动力源码中,加多相应定义就可以,如下图:

 

图片 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” 中的行号),方便各位连忙寻觅:

 

图片 3

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

专心,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 不就好了?

如下图所示,你还恐怕会小心到,作者把 “Type” 字段的常量 “IO_TYPE_OPEN_PACKET” 改成了相应的数值,以有限支撑一旦。

 

图片 4

 

其余,由于 IopAllocateOpenPacket() 等价于 ExAllocatePoolWithTag(),而后人日常重返泛型指针(“ PVOID ,亦即 void * ”),
所以自身强制把它转型为与 “openPacket” 一致的项目。
万事俱备,“东风” 就在于调用 ObReferenceObjectByName() 时,为首个参数传入“openPacket” 就能够,上海体育地方展现的很精晓了。

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

很忧伤的是,作者把编写翻译出来的驱动放到设想机(Windows 7,基于 NT 6.1 版内核)里面动态加载测验,依旧无法获取到

“DeviceQQProtect” 相应的设备对象指针,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=\.pipecom_1,baud=115200,reconnect

 

参数 “logo” 钦点要把全体调节和测量检验进程的输出音信写入日志;

“-y” 钦定符号文件的岗位(机器指令中绝非内核函数与变量的标识,所以调节和测量试验器必要查找额外的暗记以向顾客突显人类可读的名称);
“-k” 参数钦命调节和测量试验类型为 “命名管道模拟串口1”,Porter率数值越高,响应越快。

把重新编写翻译好的驱动放到设想机中,在升级权限后的指令提醒符中试行 bcdedit.exe,启用调试形式,那样重启虚构机后,就能够进去调节和测验形式(没有须要在运维进度中按下 F8 选拔菜单)。

自个儿把团结的驱动完成成按需加载,相当于采纳劳务调节管理器sc.exe)发出指令来动态加载和卸载,达成此功用的呼应批管理公事内容如下图,注意该公文要放在设想机中实践,“start= demand” 评释通过 sc.exe 按需运行;“binpath” 正是驱动文件贮存的磁盘路线,假若本身的驱动名字为hideprocess.sys,推行该批管理职务后,就在有关的注册表地方增多了一项,以往只需在 cmd.exe 中进行 “sc.exe start/stop hideprocess” 就可知动态加卸载。

图片 5

 

坚守上述方法加载时,就能够活动触发大家设定好的软件断点,就能够在宿主机中反省设想机的基业空间。
其他还需注意一点:编写翻译驱动时的 “塑造” 意况应当选拔 Check Build,那样会一并生成同名称的符号文件,后缀为 “.pdb”,进而调节和测量检验器能够展现我们本身驱动中的函数与变量名称,升高调节和测验功效,如下图:

 

图片 6

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

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

 

图片 7

栈的顶层函数 “ReferenceDeviceAndHookIRPdispatchRoutine+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”:

图片 8

 

自个儿不想浪费时间在查看内核内部存款和储蓄器的分配细节上,所以本人按下 “p”,步过 ExAllocatePoolWithTag() 函数调用,接下去的 cmp/jne 汇编类别对应源码中反省是还是不是中标分配了内部存款和储蓄器并用于 openPacket 指针,实际的施行结果是跳转到地址 0x8f4a31c6 ,对应源码中开头化 OPEN_PACKET 结构前五个字段的逻辑:

图片 9

接下来直白单步推行到调用 ObReferenceObjectByName() 前夕,在这里间大家要 “步入” 它的里边,进行故障每种核查,所以按下 “t” 跟进,这里有三个小工夫,大家早已解析过 ObReferenceObjectByName() 的源码,知道它会调用比比较多函数,况兼大约通晓难点应际而生在 ObpLookupObjectName() 里面,所以指令 “tc”可以追踪到种种函数调用处截止,再由客商决定是否跟进该函数内部。

那是本身的光明期望,但现实总是狠毒的,在本身追踪到原子操作连串函数

nt!ExInterlockedPopEntrySList() 调用时,kd.exe 就卡住了,十分的小概继续追踪此后的调用链。从稍早的栈回溯信息来看,与源码如月大家估量的调用体系大约契合,只是不领悟为什么在 nt!ObpAllocateObjectNameBuffer() 中,为了给传入的驱动对象名称 “DeviceQQProtect” 分配内核内部存款和储蓄器,调用 nt!ExInterlockedPopEntrySList(),而前面一个却无力回天跟踪。。。。是设想机景况的来由,依然原子操作类函数的不可分割性质?

 

图片 10

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

讲一些废话,平时大家在栈回溯中看出的顶层表明行,有叁个 “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_ST福睿斯ING 结构的地点,对应源码定义中的一枚 _UNICODE_STOdysseyING 指针,该协会中存放的是我们驱动在注册表中的完整路线:

 

图片 11
——————————————————————————————————————————————————————————————————

简单来说,基于上述理由笔者敬敏不谢继续跟进到 ObpLookupObjectName() 里面查看它是或不是实施了 IopParseDevice() 回调,从而无法分明到底为何后者再次回到 C0000024。

自个儿想可能是因为根本源码版本的调换,导致相关例程的论断逻辑也区别等了,无法依附前一版源码的逻辑来编排推断运维在后一版内核上的驱动。

实质上施工方案可能有些,比较花时间而已,正是利用 “u” 指令反汇编 ObpLookupObjectName() 初阶处对应的机器指令,再反编译成类似的 C 伪码,与 NT 5.2 版内核源码相比,寻觅里面退换的地点,但那是一个费时费事的干活,且收入甚微,还比不上直接在互联互联网搜释出的 NT 6.1 版内核源码,或许临近的本子,再思考绕过的主意。

顺手说一下,依据 A 设备名获得 A 设备对象的指针,然后把 rootkit/自个儿驱动创设的黑心设备 attach 到 A 设备所在的设施栈,从而阻碍检查通过 A 设备的 IRP 内数据。。。。这种艺术已经相比较过时了,因为今天反病毒软件的基石方式组件也会检查这么些设施栈,找出别的相称特征码的黑心设备,再者,内核调节和测验器的 “!devstack” 命令很轻松遍历揭露出给定设备所在的设备栈内容,被遍布用于Computer考察取证中,从 rootkit 的首要目的——实现隐身——的角度来看, attach 到设备栈就不是贰个好标准。

反倒,通过 ObReferenceObjectByName() 总是能够猎取驱动对象的指针,进而能够 hook 该驱动的 IRP 分发例程,这种手法掩没性异常高,并且不便于被质量评定出来。

此起彼落的博文将研究哪边将这种手艺用在 rootkit 中,同时适应现阶段流行的相反相成多管理器(SMP)碰到。

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

本文由118kj开奖现场发布于品牌动态,转载请注明出处:调用源检测逻辑

关键词: