驱动 -- 强制结束进程 -- 整理

有一阵子没 写博客,正好这几天 写了个 内核级强制结束进程 的小例子。写这个例子之前都没去查什么资料,主要是想试试自己能不能写出来吧。写完后才发现 看雪论坛 曾经发表过一篇很相似的文章,实现的细节可能有点不一样,不过原理基本是相同的了。

都是通过 这个  PspTerminateThreadByPointer 函数,我是通过查 ReactOs 来理解的  NtTeriminateProcess 的内部实现过程,

然后 通过 在 SI 里面查找引用,找到的一个 导出函数中调用了 PspTerminateThreadByPointer . 这个函数就是  PsTerminateSystemThread,然后通过 windbg 确认,发现 在Win7 和Xp 下 这个函数 均调用了 PspTerminateThreadByPointer,之后 查到调用的地方,具体的可以去windbg里面看一下,这个函数里面很短,具体我没看,因为这里我只需要用到这个 PspTerminateThreadByPointer 函数。 

PspTerminateThreadByPointer() 这个函数的内部我只简单的看了一下,通过向线程插入APC让线程自己结束的办法。

在Win7 和 XP 的32位下这个函数的 参数又一点点 区别,可以看到 在 Win7 下 他有 3个 参数 ,一个是指向线程对象的指针,一个是退出码,还有一个 始终为 1 的参数,XP 下没有 第三个, (当然 由于我并没有完成 Win7 下的代码,这里的分析可能有问题),需要说明的一点是以下代码仅仅兼容 XP 32位版本。

typedef
NTSTATUS
(*PSPTERMINATETHREADBYPOINTER)(
IN PETHREAD Thread,
IN NTSTATUS ExitStatus
);
NTSTATUS PsLookupProcessByProcessId(
_In_   HANDLE ProcessId,
_Out_  PEPROCESS *Process
);
/*
特征码
winxp e8 28fcffff


win7  e8 d9570400
*/
BOOLEAN PspTerminateProcessById(ULONG uPid)
{
UNICODE_STRING usNtTerminateProcess;
ULONG uNtTerminateProcessAddr;
ULONG   uConditionCode;
ULONG uError;
BOOLEAN bFind = FALSE;
PEPROCESS KillProcess;
PSPTERMINATETHREADBYPOINTER PspTerminateThreadByPointer;
RtlInitUnicodeString(&usNtTerminateProcess, L"PsTerminateSystemThread");

uNtTerminateProcessAddr = (ULONG)MmGetSystemRoutineAddress(&usNtTerminateProcess);


if (0 == uNtTerminateProcessAddr)
{
KdPrint(("Error Not Fined A"));
return FALSE;
}
uConditionCode = 0xfffffc28;
uError = 0;
KdPrint(("Addr Is :0x%X", uNtTerminateProcessAddr));

//搜索特征码,不知道我这种写法是不是有点笨
do
{
if (uError > 100)
{
bFind = FALSE;
KdPrint(("Error Not Fined B"));
break;
}
bFind = TRUE;
uNtTerminateProcessAddr++;
uError++;
} while (uConditionCode != *((ULONG*)uNtTerminateProcessAddr));


if (bFind)
{
KdPrint(("Addr Is :0x%X", uNtTerminateProcessAddr));
}
PspTerminateThreadByPointer = (PSPTERMINATETHREADBYPOINTER)(*((ULONG*)uNtTerminateProcessAddr) + (ULONG)(uNtTerminateProcessAddr + 4));


NTSTATUS Status = PsLookupProcessByProcessId((HANDLE)uPid, &KillProcess);
if (!NT_SUCCESS(Status))
{
KdPrint(("Error Coide is 0x%X", Status));
return FALSE;
}
//KdPrint(("EPROCESS Is :0x%X", ));
// ==> 取出 ThreadListHead 找出一个线程的头
//-0x22c 就是 PETHREAD 的地址
//KdBreakPoint();
LIST_ENTRY* pList;
pList = (LIST_ENTRY*)(ULONG)*(ULONG*)((ULONG)KillProcess + 0x190);
LIST_ENTRY* pListNext;
pListNext = pList->Flink;
if (pListNext->Flink != pList)//如果只有一条线程就直接结束 否则 BSOD
{
LIST_ENTRY* pListCurNext;
do
{
LIST_ENTRY* pList_Cur = pListNext;
pListNext = pListNext->Flink;
pListCurNext = pListNext->Flink;
PspTerminateThreadByPointer((PETHREAD)((ULONG)(pList_Cur)-0x22C), 0);


} while (pListCurNext != pList);
}
PspTerminateThreadByPointer((PETHREAD)((ULONG)(pList)-0x22C), 0);//到这里就清理成功了
//ObDereferenceObject(KillProcess);//解引用,不过貌似这个对象都没有了,不确定需不需要解除引用
return bFind;
}

2018/5/10 修改

注,这里的代码太凌乱,风格太差,整体来说并没有什么意义,留下来也仅仅是做个纪念。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值