ring0下使用ZwTerminateProcess函数结束指定进程

DemonGan

发布日期: 2019-02-10 20:10:18 浏览量: 503
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

背景

在用户层上,Windows 给我们提供了一个 WIN32 API 函数 TerminateProcess 来结束指定进程。那么,在内核层下,也给我们提供了一个相应的内核函数来实现相应的功能,这个内核函数就是 ZwTerminateProcess。

本文就是介绍在内核下使用 ZwTerminateProcess 函数来结束指定进程,现在,我就把实现的思路和原理整理成文档,分享给大家。

函数介绍

ZwOpenProcess 函数

打开进程对象的句柄,并设置该对象的访问权限。

函数声明

  1. NTSTATUS ZwOpenProcess(
  2. _Out_ PHANDLE ProcessHandle,
  3. _In_ ACCESS_MASK DesiredAccess,
  4. _In_ POBJECT_ATTRIBUTES ObjectAttributes,
  5. _In_opt_ PCLIENT_ID ClientId
  6. );

参数

  • ProcessHandle [out]
    指向类型为HANDLE的变量的指针。 ZwOpenProcess例程将进程句柄写入该参数指向的变量。
  • DesiredAccess [in]
    一个ACCESS_MASK值,其中包含调用者对进程对象请求的访问权限。
  • ObjectAttributes [in]
    指向OBJECT_ATTRIBUTES结构的指针,该结构指定要应用于进程对象句柄的属性。在Windows Vista和更高版本的Windows中,此结构的ObjectName字段必须设置为NULL。在Windows Server 2003,Windows XP和Windows 2000中,此字段可以作为选项指向对象名称。有关详细信息,请参阅以下备注部分。
  • ClientId [in]
    指向客户端ID的指针,用于标识要打开其进程的线程。在Windows Vista和更高版本的Windows中,此参数必须是指向有效客户端ID的非NULL指针。在Windows Server 2003,Windows XP和Windows 2000中,此参数是可选的,如果ObjectAttributes指向的OBJECT_ATTRIBUTES结构指定对象名称,则可以将其设置为NULL。有关详细信息,请参阅以下备注部分。

返回值

  • 成功,则返回 STATUS_SUCCESS;否则,返回错误码。

ZwTerminateProcess 函数

终止进程及其所有线程。

函数声明

  1. NTSTATUS ZwTerminateProcess(
  2. _In_opt_ HANDLE ProcessHandle,
  3. _In_ NTSTATUS ExitStatus
  4. );

参数

  • ProcessHandle [in]
    表示要终止的进程的进程对象的句柄。
  • ExitStatus [in]
    操作系统用作进程及其每个线程的最终状态的NTSTATUS值。

返回值

  • 成功,则返回 STATUS_SUCCESS;否则,返回错误码。

实现原理

这个程序的实现和用户层实现很类似,但也有些区别。实现的具体过程如下:

  • 首先,先试用 ZwOpenProcess 函数根据进程的 PID 打开指定进程。要注意的就是,进程的 PID 并不是像用户层那样直接传参,而是初始化到 CLIENT_ID 结构体当中。那么,成员 UniqueProcess 就是表示进程 PID。

  • 然后,我们就可以根据进程句柄,调用 ZwTerminateProcess 函数结束进程。终止状态可以任意指定。

  • 最后,我们也要调用 ZwClose 函数来关闭打开的进程句柄,释放资源。

经过上面 3 步,就可以实现了内核层结束进程的常规方法。

编码实现

  1. // 结束进程
  2. BOOLEAN TerminateProcess(HANDLE hProcessId)
  3. {
  4. HANDLE hProcess = NULL;
  5. CLIENT_ID stClientId = { 0 };
  6. OBJECT_ATTRIBUTES objectAttributs = { 0 };
  7. stClientId.UniqueProcess = hProcessId;
  8. stClientId.UniqueThread = 0;
  9. InitializeObjectAttributes(&objectAttributs, 0, 0, 0, 0);
  10. // 打开进程,获取进程句柄
  11. NTSTATUS status = ZwOpenProcess(&hProcess, 1, &objectAttributs, &stClientId);
  12. if (!NT_SUCCESS(status))
  13. {
  14. ShowError("ZwOpenProcess", status);
  15. return FALSE;
  16. }
  17. // 结束进程
  18. if (NULL != hProcess)
  19. {
  20. ZwTerminateProcess(hProcess, 0);
  21. }
  22. // 关闭进程句柄
  23. ZwClose(hProcess);
  24. return TRUE;
  25. }

程序测试

在 Win7 32 位系统下,驱动程序结束进程成功;在 Win10 64 位系统下,驱动程序结束进程成功;

总结

和用户层进行类比,大体上是一样的流程和操作原理。要今后学习内核编程的时候,很多时候都可以通过类比用户层的方式来学习记忆,这样可以达到事半功倍的效果。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download ZwTerminateProcess_Test.7z ( 8.04kb, 3次下载 )

发送私信

这一切都不是我的,但总有一天,会是我的

73
文章数
67
评论数
最近文章
eject