首页
社区
课程
招聘
[分享]使用为导出函数PspTerminateProcess关闭进程
发表于: 6天前 225

[分享]使用为导出函数PspTerminateProcess关闭进程

6天前
225

环境:winXP


`PspTerminateProcess`是为导出函数,所以无法直接通过dll进行调用,**函数只是没有导出,而不是不存在**,对于未导出的函数,我们有两种解决办法,1.特征码匹配,2.解析内核PDB文件,我打算采取特征码匹配的方式得到为导出的函数地址。


思路

1. 确定`PspTerminateProcess`所在的模块

通过`Driver_OBJECT`的成员`DriverSection

`指向的`LDR_DATA_TABLE_ENTRY`结构,得到内核空间中的各个模块,确定模块之后,即可查找的基地址


2. 在windbg中查看函数`PspTerminateProcess`,选取特征码

特征码需要避开硬编码地址(全局变量、间接Call(FF)),硬编码地址可能会因为系统重启而导致模块装载位置变化,从而影响硬编码地址,避开公共代码部分,选择该函数特有的部分


关于特征码我使用的如下区域

3. 从基地址开始进行特征码匹配,如果匹配成功会得到我们获取特征码的位置,根据特征码相当于函数开始处的偏移,即可得到该函数的地址

4. 定义函数指针

在定义函数指针之前,我们需要搞清楚`PspTerminateProcess`的参数,在10-10-12分页下IDA去分页一下函数`PspTerminateProcess`,使用交叉引用就可以知道有谁调用了这个函数,最终我们确定了函数`PsTerminateProcess`

我们去查阅关于`PsTerminateProcess`的资料,会发现该函数是个导出函数

NTSTATUS NTAPI PsTerminateProcess(IN PEPROCESS Process,
                   IN NTSTATUS ExitStatus)
{
    /* Call the internal API */
    return PspTerminateProcess(Process, ExitStatus);
}

所以我们就可以确定`PspTerminateProcess`的函数指针


typedef NTSTATUS(*funcPspTerminateProcess)(PEPROCESS process, NTSTATUS ExitStatus);
funcPspTerminateProcess PspTerminateProcess;


代码示例

#include <ntifs.h>

NTSTATUS UnloadDriver(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("Driver Uninstall!!\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Driver Loading!!\n");
	DriverObject->DriverUnload = UnloadDriver;

	//1.获取PspTerminateProcess所在模块的基址
	PDRIVER_OBJECT Driver = DriverObject;
	LIST_ENTRY* pListHead = Driver->DriverSection;
	LIST_ENTRY* pCurrent = pListHead->Flink;
	UINT32 DllBase = 0;
	UINT32 SizeOfImage = 0;

	UNICODE_STRING targetName;
	RtlInitUnicodeString(&targetName, L"ntoskrnl.exe");
	while (pCurrent != pListHead)
	{
		PUNICODE_STRING pDllName = (PUNICODE_STRING)((UINT32)pCurrent + 0x2c);

		DbgPrint("DllName: %wZ", pDllName);
		UINT32 BaseAddr = *(UINT32*)((UINT32)pCurrent + 0x18);



		if (!RtlCompareUnicodeString(pDllName, &targetName, FALSE))
		{
			DllBase = BaseAddr;
			SizeOfImage = *(UINT32*)((UINT32)pCurrent + 0x20);
			DbgPrint("ntoskrnl GET! Base: %X, Size: %X\n", DllBase, SizeOfImage);
			break;
		}
		pCurrent = pCurrent->Flink;
	}

	//2.获取特征码,进行特征码匹配
	UCHAR Buffer1[12] = { 0xf6, 0x47, 0x01, 0x20, 0x74, 0x12, 0x8d, 0x86, 0x74, 0x01, 0x00, 0x00 };
	PUCHAR pBase = (PUCHAR)DllBase;
	
	//特征码匹配
	UINT32 signature_offset; //特征码相对于函数开始处的偏移
	for (UINT32 i = 0; i < SizeOfImage - sizeof(Buffer1); i++)
	{
		__try
		{
			if (RtlCompareMemory(Buffer1, pBase + i, sizeof(Buffer1)) == sizeof(Buffer1))
			{

				DbgPrint("PspTerminateProcess GET!!!!!\n");
				DbgPrint("PspTerminateProcess signature found at offset: 0x%X\n", i);
				signature_offset = i;
				break;
			}
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			continue;
		}
	}

	//3.定义PspTerminateProcess的函数指针
	typedef NTSTATUS(*funcPspTerminateProcess)(PEPROCESS process, NTSTATUS ExitStatus);
	funcPspTerminateProcess PspTerminateProcess;

	//4.获取PspTerminateProcess函数地址
	PspTerminateProcess = (funcPspTerminateProcess)((UINT32)pBase + signature_offset - 0x22);//特征码相对于函数开始处的偏移,计算出PspTerminateProcess函数地址
	DbgPrint("PspTerminateProcess: %x\n", PspTerminateProcess);
	
	//5.定义PspTerminateProcess函数的参数
	PEPROCESS pEProc;//每个进程都有一个 EPROCESS 结构,里面保存着进程的各种信息,和相关结构的指针。
	HANDLE pid = 1796;//输入要结束的进程PID
	NTSTATUS status = PsLookupProcessByProcessId(pid, &pEProc);//PsLookupProcessByProcessId 函数用于根据进程ID查找对应的EPROCESS结构指针。

	//6.调用PspTerminateProcess的函数指针 杀死指定pid的进程
	__try
	{
		PspTerminateProcess(pEProc, 0);

	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{

	}

	return STATUS_SUCCESS;
}


测试

使用PspTerminateProcess函数杀死`notepad.exe`

此处的`pid = 1664`,修改驱动程序中定义的`pid`,生成驱动程序

HANDLE pid = 1664;//要结束的进程PID

注册并运行驱动

成功杀死了`notepad.exe`



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

最后于 6天前 被mb_ldqerboa编辑 ,原因:
收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回