ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

进程强杀初探

2022-02-16 15:34:12  阅读:269  来源: 互联网

标签:TABLE pLdrDataTableEntry DllBase 强杀 初探 进程 ENTRY DATA UINT32


前言

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

测试

 

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

 

 

 

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

 

 

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

 

 

ZwTerminateProcess

 

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

 

NTSYSAPI NTSTATUS ZwTerminateProcess(
[in, optional] HANDLE   ProcessHandle,
[in]           NTSTATUS ExitStatus
);

 

 

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

 

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

 

PspTerminateProcess

 

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

 

 

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

 

 

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

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

 

  1. 暴力搜索,提取该函数的特征码,全盘搜索。

  2. 如果有已文档化的函数调用了PspTerminateProcess,那我们就可以通过指针加偏移的方式获取到他的地址,同样可以调用。

 

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

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

 

 

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

 

#include <ntddk.h>


VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("Driver unload successfully!\r\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
DbgPrint("注册表路径:%wZ 地址:%x Hello world!", reg_path, driver);

DbgPrint("%x", driver);

driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}

 

部署一下得到地址为85e17030

 

 

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

kd> dt _DRIVER_OBJECT 85e17030

 

 

 

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

 

看一下_LDR_DATA_TABLE_ENTRY的结构

 

kd> dt _LDR_DATA_TABLE_ENTRY

 

 

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

 

 

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

 

 

 

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

 

 

从中挑选如下代码

 

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

 

提取出的相应特征码如下

 

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

 

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

 

#include <ntifs.h>

typedef struct _LDR_DATA_TABLE_ENTRY
{
   LIST_ENTRY InLoadOrderLinks;
   LIST_ENTRY InMemoryOrderLinks;
   LIST_ENTRY InInitializationOrderLinks;
   PVOID DllBase;
   PVOID EntryPoint;
   UINT32 SizeOfImage;
   UNICODE_STRING FullDllName;
   UNICODE_STRING BaseDllName;
   UINT32 Flags;
   UINT16 LoadCount;
   UINT16 TlsIndex;
   LIST_ENTRY HashLinks;
   PVOID SectionPointer;
   UINT32 CheckSum;
   UINT32 TimeDateStamp;
   PVOID LoadedImports;
   PVOID EntryPointActivationContext;
   PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

typedef NTSTATUS(*pfnPspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode);

VOID DriverUnload(IN PDRIVER_OBJECT driverObject);  //卸载驱动
PVOID SearchFunction(PUCHAR DllBase, UINT32 SizeOfImage);   // 查找模块中匹配特征码

ULONG g_uPID = 1492; // 要关闭的进程PID

// 特征码
UCHAR g_szSpecialCode[] = {
   0x56, 0x64, 0xA1, 0x24, 0x01, 0x00, 0x00, 0x8B,
   0x75, 0x08, 0x3B, 0x70, 0x44, 0x75, 0x07, 0xB8,
   0x0D, 0x00, 0x00, 0xC0, 0xEB, 0x5A, 0x57 };
// 特征码长度
UINT32 g_uSpecialCodeLen = sizeof(g_szSpecialCode);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath)
{
   NTSTATUS status = STATUS_SUCCESS;
   PLDR_DATA_TABLE_ENTRY pLdrDataTableEntry = NULL;
   pfnPspTerminateProcess pPspTerminateProcess = NULL;
   PEPROCESS pEprocess = NULL;

   DbgPrint("驱动加载完成\r\n");

   pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)driverObject->DriverSection;
   pLdrDataTableEntry = CONTAINING_RECORD(pLdrDataTableEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
   pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pLdrDataTableEntry->InLoadOrderLinks.Flink;

   do
  {
       pLdrDataTableEntry = CONTAINING_RECORD(pLdrDataTableEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

       // 如果存在则搜索特征码
       if (pLdrDataTableEntry->DllBase)
      {
           pPspTerminateProcess = (pfnPspTerminateProcess)
               SearchFunction((PUCHAR)pLdrDataTableEntry->DllBase, pLdrDataTableEntry->SizeOfImage);
      }

       if (pPspTerminateProcess)
           break;
       
       // 遍历
       pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pLdrDataTableEntry->InLoadOrderLinks.Flink;

  } while ((UINT32)pLdrDataTableEntry != (UINT32)driverObject->DriverSection);

   if (pPspTerminateProcess)
  {
       status = PsLookupProcessByProcessId((HANDLE)g_uPID, &pEprocess);
       if (NT_SUCCESS(status))
      {
           status = pPspTerminateProcess(pEprocess, 0);

           if (NT_SUCCESS(status))
          {
               DbgPrint("使用 PspTerminateProcess 关闭进程成功, PID = %d\r\n", g_uPID);
          }
      }
       else
      {
           DbgPrint("PsLookupProcessByProcessId Error 0x%X\r\n", status);
      }
  }

   driverObject->DriverUnload = DriverUnload;
   return STATUS_SUCCESS;
}

VOID DriverUnload(IN PDRIVER_OBJECT driverObject)
{
   DbgPrint("驱动卸载完成\r\n");
}

PVOID SearchFunction(PUCHAR DllBase, UINT32 SizeOfImage)
{
   DbgPrint("Here is MemorySearch , length is : %d\r\n", SizeOfImage);

   PVOID pFuncAddr = NULL;
   UINT32 uEnd = (UINT32)DllBase + SizeOfImage - g_uSpecialCodeLen;    // 减去特征码后的长度
   UINT32 i = 0;
   BOOLEAN bOk = TRUE;

   while ((UINT32)DllBase <= uEnd)
  {
       bOk = TRUE;
       for (i = 0; i < g_uSpecialCodeLen; i++)
      {
           if (!MmIsAddressValid(&DllBase[i]) || DllBase[i] != g_szSpecialCode[i])
          {
               bOk = FALSE;
               break;
          }
      }

       if (bOk)
      {
           pFuncAddr = (PVOID)(DllBase - 5);
           DbgPrint("找到特征码,内存地址为%p\r\n", pFuncAddr);
           break;
      }
       DllBase++;
  }

   return pFuncAddr;
}

 

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

 

 

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

 

 

演示效果如下

 

 

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

 

// r3tor0killer.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <winioctl.h>


#define SYMBOLICLINK_NAME L"\\\\.\\HbgDevLnk"
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IN_BUFFER_MAXLENGTH 4
#define OUT_BUFFER_MAXLENGTH 4

int main()
{
   // 获取设备句柄
   HANDLE hDevice =CreateFileW(SYMBOLICLINK_NAME, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
   DWORD dwError = GetLastError();
   if (hDevice == INVALID_HANDLE_VALUE)
  {
       printf("获取设备句柄失败 %d\n", dwError);  // 如果返回1,在驱动中指定 IRP_MJ_CREATE 处理函数
       getchar();
       return 1;
  }
   else
  {
       printf("获取设备句柄成功 \n");
  }
   // 测试通信
   DWORD dwInBuffer = 0x850;
   DWORD dwOutBuffer = 0;
   DWORD dwOut;
   DeviceIoControl(hDevice, OPER2, &dwInBuffer,
IN_BUFFER_MAXLENGTH,
                   &dwOutBuffer,
OUT_BUFFER_MAXLENGTH, &dwOut, NULL);
   printf("dwOutBuffer: %08X dwOut: %08X\n", dwOutBuffer, dwOut);
   // 关闭设备
   CloseHandle(hDevice);
   return 0;
}

 

实现效果如下

 

 

后记

 

因为时间原因一些自己整理的笔记没有及时发文章,一些平时学习的笔记都放在了公众号 红队蓝军 上,感兴趣的小伙伴们可以关注一下

 

标签:TABLE,pLdrDataTableEntry,DllBase,强杀,初探,进程,ENTRY,DATA,UINT32
来源: https://www.cnblogs.com/Drunkmars/p/15900773.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有