实现关闭进程函数,杀掉pchunter

实现关闭进程函数,杀掉pchunter_第1张图片

前段时间包同学到一家公司去面试,面试官问他如果不用TerminateProcess如何实现关闭进程,作为一个快要毕业的人来说对这个问题很敏感,毕竟也要面对这关. 现在问题摆在面前,如何解决这个问题,想了想最好的方法就是直接看操作系统怎么实现 TerminateProcess 的自己实现个就好了,在一定程度上就可以阻止别人通过hook技术来拦截. 这段代码很早就写好了,但是帖子什么的一直没什么时间写(薛老师今天讲的壳还没有脱),写完这篇帖子去脱壳了

另外: 本人小菜,大神们轻点喷


开始吧!下面截图的代码都是win2000的代码,在看源码的同时有时候需要用ida打开win7的ntoskrnl.exe对比着看,所幸的是虽然经过很多版本更迭,但是这块的基本原理没啥变化,所以就尽量不贴ida反汇编的图了(可读性差)

NtTerminateProcess的函数实现,其中最关键的 如图:

实现关闭进程函数,杀掉pchunter_第2张图片
实现关闭进程函数,杀掉pchunter_第3张图片

这个函数主要干的事情就是遍历进程的线程,然后对每个线程执行PspTerminateThreadByPointer

再分析下 PspTerminateThreadByPointer 函数的实现

这个函数是分两种情况的:

情况一,是线程自己关闭自己:直接执行PspExitThread

实现关闭进程函数,杀掉pchunter_第4张图片

      PspExitThread这个函数太庞杂简单说下它的作用: 

      1. 执行了一大堆清理代码,主要清理当前线程Ethread的资源

      2. 从调度链表和等待链表中去掉它

      3. 如果是进程的最后一个线程,直接清理进程空间

      4. 执行KiSwapThread切换到一个新线程去

实现关闭进程函数,杀掉pchunter_第5张图片

  情况二,关闭掉别的线程:在对方线线程中插入一个内核apc,这个内核apc最后会调用PspExitThread函数

实现关闭进程函数,杀掉pchunter_第6张图片
实现关闭进程函数,杀掉pchunter_第7张图片

      PspTerminateThreadByPointer 和NtTerminateProcess分析总结:

      1. 所谓杀死进程,其实只要把每个线程杀死就好了,最后一个线程会负责收尸的

      2. 线程不能被杀死,只能自杀.所以如果想杀掉线程最好让它自己执行自杀代码,内核apc(后面会简单讲下内核apc,没法深入再讲就错题了)是个不错的选择

    内核Apc执行的时机(讲的不对请指正哈):

    1. 中断和异常返回,下面是ReatOs的代码(贴代码为证,避免别人说我瞎哔哔O(∩_∩)O哈哈~)

实现关闭进程函数,杀掉pchunter_第8张图片

  2. 高irql转到第irql,这块直接看win732逆向的代码:KfLowerIrql

实现关闭进程函数,杀掉pchunter_第9张图片

        主要关注: HalpCheckForSoftwareInterrrupt

实现关闭进程函数,杀掉pchunter_第10张图片

        执行apc的地方就是KiDeliverApc

实现关闭进程函数,杀掉pchunter_第11张图片

    3. 线程切换的时候,还是直接贴win2000的代码

实现关闭进程函数,杀掉pchunter_第12张图片
实现关闭进程函数,杀掉pchunter_第13张图片

      原理讲完了,现在直接贴效果图了:

      杀掉之前,写好进程id:

实现关闭进程函数,杀掉pchunter_第14张图片

  执行完杀掉的代码:

实现关闭进程函数,杀掉pchunter_第15张图片

另外直接附上代码:

Entry.c

#include

#include

//需要杀死的进程id

#define PCHUNTER_ID  3232

VOID DriverUnload(PDRIVER_OBJECT pDriver);

PEPROCESS LookupProcess(HANDLE hPid);

PETHREAD LookupThread(HANDLE hTid);

VOID KillProcess(PEPROCESS pEProcess);

ULONG GetPspTerminateThreadByPointer();

ULONG GetPspExitThread(ULONG PspTerminateThreadByPointer);

VOID SelfTerminateThread(

KAPC *Apc,

PKNORMAL_ROUTINE *NormalRoutine,

PVOID *NormalContext,

PVOID *SystemArgument1,

PVOID *SystemArgument2);

fpTypePspExitThread g_fpPspExitThreadAddr = NULL;

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pPath)

{

DbgBreakPoint();

pDriver->DriverUnload = DriverUnload;

//提前把函数查找出来

ULONG uPspTerminateThreadByPointerAddr =  GetPspTerminateThreadByPointer();

if (0 == uPspTerminateThreadByPointerAddr)

{

KdPrint(("查找PspTerminateThreadByPointerAddr地址出错\n"));

return STATUS_SUCCESS;

}

g_fpPspExitThreadAddr = (fpTypePspExitThread)GetPspExitThread(uPspTerminateThreadByPointerAddr);

if (NULL == g_fpPspExitThreadAddr)

{

KdPrint(("查找PspExitThread地址出错\n"));

return STATUS_SUCCESS;

}

//

PEPROCESS pProcess = LookupProcess((HANDLE)PCHUNTER_ID);

if (NULL == pProcess)

{

KdPrint((("没有在PsCidTable中找到进程,尼玛不会隐藏了吧\n")));

}

else

{

KillProcess(pProcess);

}

return STATUS_SUCCESS;

}

VOID DriverUnload(PDRIVER_OBJECT pDriver)

{

KdPrint(("驱动退出\n"));

}

PEPROCESS LookupProcess(HANDLE hPid)

{

PEPROCESS pEProcess = NULL;

if (NT_SUCCESS(PsLookupProcessByProcessId(hPid, &pEProcess)))

return pEProcess;

return NULL;

}

VOID KillProcess(PEPROCESS pEProcess)

{

PEPROCESS pEProc = NULL;

PETHREAD  pEThrd = NULL;

ULONG i = 0;

for (i = 4; i < 0x25600; i += 4)

{

pEThrd = LookupThread((HANDLE)i);

if (!pEThrd)  continue;

pEProc = IoThreadToProcess(pEThrd);

if (pEProc == pEProcess)

{

PKAPC pApc = NULL;

pApc = (PKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));

if (NULL == pApc) return;

//插入内核apc

KeInitializeApc(pApc, (PKTHREAD)pEThrd, OriginalApcEnvironment, (PKKERNEL_ROUTINE)&SelfTerminateThread, NULL, NULL, 0, NULL);

KeInsertQueueApc(pApc, NULL, 0, 2);

}

ObDereferenceObject(pEThrd);

}

}

PETHREAD LookupThread(HANDLE hTid)

{

PETHREAD pEThread = NULL;

if (NT_SUCCESS(PsLookupThreadByThreadId(hTid, &pEThread)))

return pEThread;

return NULL;

}

VOID SelfTerminateThread(

KAPC *Apc,

PKNORMAL_ROUTINE *NormalRoutine,

PVOID *NormalContext,

PVOID *SystemArgument1,

PVOID *SystemArgument2)

{

ExFreePool(Apc);

g_fpPspExitThreadAddr(STATUS_SUCCESS);

}

ULONG GetPspTerminateThreadByPointer()

{

UNICODE_STRING funcName;

RtlInitUnicodeString(&funcName, L"PsTerminateSystemThread");

ULONG step = 0;

ULONG targetFunAddr = 0;

ULONG baseFunAddr = (ULONG)MmGetSystemRoutineAddress(&funcName);

for (step = baseFunAddr; step < (baseFunAddr + 1024); step++)

{

//searching for 0x50,0xe8

if (((*(PUCHAR)(UCHAR*)(step - 1)) == 0x50) && ((*(PUCHAR)(UCHAR*)(step)) == 0xe8))

{

ULONG offset = *(PULONG)(step + 1);

targetFunAddr = step + 5 + offset;

break;

}

}

return targetFunAddr;

} //PspExitThread stamp code:0x0c 0xe8

ULONG GetPspExitThread(ULONG PspTerminateThreadByPointer)

{

ULONG step = 0;

ULONG targetFunAddr = 0;

ULONG baseFunc = PspTerminateThreadByPointer;

for (step = baseFunc; step < (baseFunc + 1024); step++)

{

//searching for 0x0c,0xe8

if (((*(PUCHAR)(UCHAR*)(step - 1)) == 0x0c) && ((*(PUCHAR)(UCHAR*)(step)) == 0xe8))

{

ULONG m_offset = *(PULONG)(step + 1);

targetFunAddr = step + 5 + m_offset;

break;

}

}

return targetFunAddr;

}

KrTypeDef.h#pragma  once

#include

#include

#pragma warning(disable:4189 4100)

typedef enum _KAPC_ENVIRONMENT

{

OriginalApcEnvironment,

AttachedApcEnvironment,

CurrentApcEnvironment,

InsertApcEnvironment

} KAPC_ENVIRONMENT;

typedef VOID (*PKNORMAL_ROUTINE) (

IN PVOID NormalContext,

IN PVOID SystemArgument1,

IN PVOID SystemArgument2

);

typedef VOID(*PKKERNEL_ROUTINE) (

IN struct _KAPC *Apc,

IN OUT PKNORMAL_ROUTINE *NormalRoutine,

IN OUT PVOID *NormalContext,

IN OUT PVOID *SystemArgument1,

IN OUT PVOID *SystemArgument2

);

typedef VOID(*PKRUNDOWN_ROUTINE) (

IN struct _KAPC *Apc

);

VOID NTAPI KeInitializeApc(__in PKAPC Apc,

__in PKTHREAD Thread,

__in KAPC_ENVIRONMENT TargetEnvironment,

__in PKKERNEL_ROUTINE KernelRoutine,

__in_opt PKRUNDOWN_ROUTINE RundownRoutine,

__in PKNORMAL_ROUTINE NormalRoutine,

__in KPROCESSOR_MODE Mode,

__in PVOID Context

);

BOOLEAN  NTAPI KeInsertQueueApc(IN PKAPC Apc,

IN PVOID SystemArgument1,

IN PVOID SystemArgument2,

IN KPRIORITY PriorityBoost);

typedef VOID(NTAPI *fpTypePspExitThread)(

IN NTSTATUS ExitStatus

);

#define OFFSET(type, f) ((SIZE_T) \

((char *)&((type *)0)->f - (char *)(type *)0))

ps:代码有处bug,就是假设在杀线程的同时创建线程怎么办?

实现关闭进程函数,杀掉pchunter_第16张图片

最后谢谢大家!

更多干货文章,关注看雪学院公众号 ikanxue

本文由看雪论坛 又出bug了 原创 转载请注明来自看雪社区

你可能感兴趣的:(实现关闭进程函数,杀掉pchunter)