今年终于是完整的都做出来了,想到去年连让驱动成功运行的任务都做不到,真是感慨,但是还是有点遗憾,花了很多时间去复现题目的ddma方案写检测,导致没时间去写其他类型的检测。
然后昨晚看到另一个大神发的WP,真是震撼,我的文章就是相形见拙了哈哈,不过也公布出来给大伙参考参考一些思路。
部署失败会输出Code...之类的错误信息,搜索字符串找到该处,是通过一个间接Call返回数据来输出Code的。

dbg动调发现会调用到如下Call,可以比较容易看出这是在检测系统是否启用了Hyper-V功能。

禁用物理机的Hyper-V,然后给虚拟机启用虚拟化功能,再在虚拟机Powershell运行Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All -All安装Hyper-V,即可通过phase 0。


通过上面函数里用到的全局状态值,这边可以找到共四个。

找交叉调用可以找到以下函数,是写出了一个驱动文件,然后启动服务,最后判断是否写出&启动成功。

可以看到这边使用cpuid通信,根据上文大概就能知道加载的驱动是hypervisor之类的,是判断是否通信成功。


通过上文有看到写出一个sys,在此处可以断点拿到隐藏的驱动文件。

断点在CloseHandle后,在C:\Windows\System32\drivers底下可以找到随机名称的sys。

存在大量ollvm平坦化,不考虑全部分析。
这边发现许多地方都有这种计算间接跳转Call地方,可以看到内存中存在大量的这种数据,猜测是程序内函数地址或API地址。


借助AI帮忙一键计算分析所有的Call地址。

同时AI帮忙命名了几个全局变量和函数指针具体的意义,有助于后续的代码分析。



以上AI记录截图见AI记录\记录1.png和AI记录\记录2.png
注释函数地址idapython脚本见annotate_apis.py
sub_140018260,该函数可以看到是根据系统版本,选择不同的特征字节返回。

我系统使用的特征字节转汇编如下,是hvix64.exe的VMExit handler特征字节。
sub_140009530这边看到是和设备通信的函数。

断点开头,看第一个参数,也就是设备的handle,windbg查到的设备是\Driver\disk

查看交叉调用一共有两个函数调用了(sub_140003E10/sub_140004FB0),从第一个函数分析,其中有一个PreparePageAccess(sub_140003EB0)函数调用,对a2地址做了什么。


sub_140003EB0分析,总体功能就是获取传入的虚拟地址的物理地址,然后设置权限位允许设备访问。


回到上一层,根据上面搜到的handle设备等线索,可以知道就是vhdmp虚拟磁盘设备,通过SCSI通信直接读写,可以绕过EPT保护。
下面是将a2物理页内容写入磁盘,然后再将磁盘里的内容页读入到a1,这样达到了copy a2地址内存到a1的效果,然后最后再恢复磁盘。


翻到一个ManualMapPE(sub_14000E630)函数,也就是手动映射加载PE文件,比较普通的映射加载,这里多了将内存映射到0x327fffE00000,也就是重定位的时候将基址设置为了0x327fffE00000。

找CopyPage函数的交叉调用,有且只有一个sub_14000BEB0。
这边是先遍历物理页,必须内存全都为0xff才符合条件,其实就是在搜hypervisor的保护页。

然后映射保护页,用Disk读取出被保护的内存,这样能够读取到hv相关的代码。

判断了一下CPU厂商

这边可以看到调用了上面分析到的BuildSigPattern,然后在刚刚读取的hv代码页里面去扫VmExit Handler的特征。

扫到后通过加上BuildSigPattern提供的一个固定偏移量,得到了目标Hook地址。

在ManualMapPE函数下方会找到一个函数,sub_14000FC40,被ollvm混淆了,但是可以看到代码量很大,而且存在下图类似Hook一样的代码块,可以直接使用D810去除控制流平坦化。


开头先在目标地址后面找连续的0xCC内存段,用来放shellcode。

申请了内存,将shellcode模板复制到内存中。


然后搜索shellcode中的两个占位符,替换成映射加载驱动的payload地址,以及a5参数。


再把shellcode复制到目标padding地址。

然后这边是在shellcode结尾写入执行原代码以及jmp回原始代码下一条,也就是标准inline hook的处理方式,然后调用CopyPage,写入hv物理页,然后再写一个jmp到shellcode的字节。

最后底下又写了一个跳板,然后在目标Hook点写入Jmp,jmp到跳板处执行,可以看到0x327FFFE00000,就是上面ManualMapPE驱动映射的内存地址。

[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。