ProcessHacker驱动漏洞分析

介绍

ProcessHacker的2.8.0.0版本的驱动程序kprocesshacker.sys存在漏洞,该驱动是数字签名的,利用驱动漏洞可以在R0下结束进程、暂停进程,且可结束自我防护不严格的杀毒软件。


目的

以漏洞利用工具入手,分析漏洞点以增强知识理解和调试熟练度。


寻找漏洞点

先检验一下ProcessHacker能否杀火绒。

ProcessHacker驱动漏洞分析

火绒直接被杀了且没有重新启动。

ProcessHacker驱动漏洞分析

既然是结束进程,可能用到了ZwTerminateProcess
也有其他使用非公开内核函数的方法来结束进程,但一般正常的工具应该不会那样做,这种技术是非常稀有的。

为了证实使用的ZwTerminateProcess这一点,可以调试一下结束进程操作是否真的调用了ZwTerminateProcess.

我没有找到2.8.0.0版本驱动的ProcessHacker的文件,用的是其他版本进行调试。
先找到函数偏移量0x68f1

ProcessHacker驱动漏洞分析

当我尝试用其他版本的exe加载2.8.0.0的sys文件时,虽然exe可以正常使用,但是经过调试后发现sys文件似乎没有被调用,因为ProcessHacker.exe用的自己而不是驱动来调用ZwTerminateProcess,且驱动模块入口没有成功断下来,看来exe和sys版本是配对的。
如图,当我使用了其他版本的exe来使用2.8.0.0的驱动时,无法结束火绒。因为结束进程的操作没有从驱动层发起,而是从exe本身发起。

ProcessHacker驱动漏洞分析

言归正传。如图在驱动模块的ZwTerminateProcess下断点之后在ProcessHacker执行结束进程时断住了。说明确实是调用的ZwTerminateProcess来结束的进程

ProcessHacker驱动漏洞分析

来看看漏洞成因。

搜索ZwTerminateProcess可以看到被函数FUN_00017e78调用了,那么FUN_00017e78是不是造成漏洞的主要原因呢

ProcessHacker驱动漏洞分析


在看FUN_00017e78的反汇编之前先看看ZwTerminateProcess函数原型ZwTerminateProcess接受2个参数,第一个是进程的句柄,第二个是进程的退出状态。简单粗暴

NTSTATUS ZwTerminateProcess(
  _In_ HANDLE ProcessHandle,
  _In_ NTSTATUS ExitStatus
)
;

如果是结束进程可以被控制,那想必第一个参数ProcessHandle肯定可以被控制。

FUN_00017e78函数反汇编如下

ProcessHacker驱动漏洞分析
ulonglong FUN_00017e78(undefined8 param_1,undefined4 param_2,undefined param_3)

{
  longlong lVar1;
  uint uVar2;
  ulonglong uVar3;
  longlong lVar4;
  code *pcVar5;
  longlong local_res20;
  ulonglong uVar6;
  undefined8 local_18 [2];

  uVar6 = 0;
  uVar3 = ObReferenceObjectByHandle
                    (param_1,0,*(undefined8 *)PsProcessType_exref,param_3,&local_res20,0);
  if ((int)uVar3 < 0) {
    return uVar3;
  }
  lVar4 = IoGetCurrentProcess();
  lVar1 = local_res20;
  if (local_res20 == lVar4) {
    uVar3 = 0xc00000db;
  }
  else {
    if ((DAT_00014334 == 0) && (pcVar5 = (code *)FUN_00011bac(&DAT_000141c0), pcVar5 != (code *)0x0)
       ) {
      uVar2 = (*pcVar5)(lVar1,param_2);
      uVar3 = (ulonglong)uVar2;
      if (uVar2 != 0xc00000bbgoto LAB_00017f58;
    }
    uVar2 = ObOpenObjectByPointer
                      (local_res20,0x200,0,1,*(undefined8 *)PsProcessType_exref,
                       uVar6 & 0xffffffffffffff00,local_18);
    uVar3 = (ulonglong)uVar2;
    if (-1 < (int)uVar2) {
      uVar2 = ZwTerminateProcess(local_18[0],param_2);
      uVar3 = (ulonglong)uVar2;
      ZwClose(local_18[0]);
    }
  }
LAB_00017f58:
  ObfDereferenceObject(local_res20);
  return uVar3;
}

代码读得头昏脑胀?没关系,这种事情可以交给GPT。

简而言之,FUN_00017e78将第一个参数传入了ObReferenceObjectByHandle,该函数是打开进程对象,并返回一个句柄。ObReferenceObjectByHandle将返回的句柄存到了local_18数组的第一个元素。而ZwTerminateProcess接受local_18的第一个元素作为结束的进程句柄传入。

所以只需要控制FUN_00017e78函数的第一个参数或直接控制ZwTerminateProcess传入参数就可以利用驱动直接结束进程。

再来看看利用工具是怎么实现的。


利用工具分析

https://github.com/MrEmpy/Reaper
工具几个函数如图
主要功能函数包括加载驱动、卸载驱动、暂停进程、结束进程。

ProcessHacker驱动漏洞分析

来试一下工具的效果吧!
如下图杀了火绒2个进程,火绒已经被杀没了。

ProcessHacker驱动漏洞分析


这个工具每次结束一个进程都会停止驱动,火绒存在多个进程,若要实战需要改一下程序。
总而言之,这是可以正确地杀死火绒的。


来用windbg跟一下。
首先在2.8.0.0版本的sys找到函数偏移量

ProcessHacker驱动漏洞分析


根据偏移量在内存下断点

ProcessHacker驱动漏洞分析

执行reaper工具,成功在预期函数处断下,rcx是进程句柄,rdx是退出状态。

ProcessHacker驱动漏洞分析

这个工具首先使用DeployDriver加载sys驱动并设置对象路径\.KProcessHacker2, 然后通过指定的PID使用OpenProcess获取要结束的进程句柄。
而最核心的在于这两行相应功能的IOCTL编号,这也是漏洞存在的点

#define IOCTL_CODE_KILLPROCESS 0x999920df
#define IOCTL_CODE_SUSPENDPROC 0x999920d7

通过DeviceIoControl函数操作驱动对象,往相应的IOCTL编号发送了ioInput结构体,这个结构体包含进程句柄和退出状态,直接操控了ZwTerminateProcess函数的传参。


尾声

关于漏洞点,也就是IOCTL编号为什么是这个,还需要进一步研究。



原文始发于微信公众号(XINYU2428):ProcessHacker驱动漏洞分析

版权声明:admin 发表于 2023年12月15日 上午9:51。
转载请注明:ProcessHacker驱动漏洞分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...