此文是阅读黑防上胡文亮大牛《模拟实现NT系统通用PspTerminateProcess》后作为学习笔记记录下来的,仅作学习记录,理解错的请勿拍砖。和通过特征暴力搜索定位PspTerminateProcess的地址的方法相比,亮点就是模拟了实现PspTerminateProcess,PspTerminateThreadByPointer等函数。
此前先看PJF大牛的一篇《进程终止的内幕》
“
有来信询问进程结束的有关问题,下面就这个问题简单讨论一下(下面的讨论基于2000,其他NT系统也类似)。
首先看看一个应用程序想要强制结束另一个进程所要做的事:首先获得目标的进程ID,接着利用OpenProcess获取进程句柄(确保足够权限),最后将句柄传给TerminateProcess了结那个进程。
1、OpenProcess通过本机系统服务接口进入核心态,随后调用ntoskrnl的NtOpenProcess。在服务函数里,系统使用 SeSinglePrivilegeCheck检查调用者是否有DEBUG权限(SeDebugPrivilege),若有,则修改 AccessState使得在后面的操作中获取允许任意进程访问操作的句柄。最后通过ObOpenObjectByName或 PsLookupProcess*** + ObOpenObjectByPointer来打开进程(创建并返回进程句柄)。
2、TerminateProcess通过本机系统服务接口进入核心态,随后调用ntoskrnl的NtTerminateProcess。系统首先调用 ObReferenceObjectByHandle获取进程执行体块,执行体块的DebugPort指出进程是否处于调试状态,若处于调试状态且传入的 ExitStatus为DBG_TERMINATE_PROCESS则返回失败禁止结束进程。随后服务函数转入正题:
系统利用ThreadListHead枚举进程的每一个线程,使用PspTerminateThreadByPointer来结束它们。注意并不是对每个 线程系统都会忠实地执行你的命令:若枚举到的线程是系统线程则不会继续执行而是返回STATUS_INVALID_PARAMETER。判断的方法是线程 的Teb为零或者Teb的值在内核地址空间。有人问2000下为何csrss.exe进程杀不死,很简单,打开IceSword,在进程栏利用右键菜单的 “线程信息”看一下,看到那几个Teb为零的线程没有?(注意是针对windows2000,XP下不同。另外一点就是csrss中其它非系统线程的线程 是很容易被杀死的,试图结束csrss时也可以看到在Teb为零的线程前面的线程已被杀掉,只是操作停在了Teb为零的线程这里)再看看system进 程,呵呵。IceSword也并未提供杀除这种进程的功能,因为觉得没有需求。在最后一个线程结束时,进程的生命也结束了,随着 PspExitProcess/ObKillProcess灰飞烟灭。
另一方面,线程是怎样结束的呢。PspTerminateThreadByPointer并不是直接“杀掉”指定线程,实质上线程是“自杀”的,呵呵。系 统简单的使用KeInitializeApc/KeInsertQueueApc插入了一个核心态的APC调用,若是用户线程,会再插入用户态的APC调 用,最终线程在自己的执行环境中使用PspExitThread(...=>KeTerminateThread=> KiSwapThread)悲壮的自行了断。
有人问起为什么IceSword有时杀不死除那三个有系统线程的进程(两个是csrss、system,而idle是个非常奇特的存在,与众不同,这里不 多废话了)外的其它进程。从上面的讨论可以找到答案。这种情况往往是目标进程的某用户态线程进入核心态后,系统出了某些问题挂死在核心态,无法返回执行 Apc例程的缘故。IceSword未强制除去它们是考虑此刻系统可能已经有某些问题,强制删除操作更有可能使系统崩溃,不过有了不少用户要求有这项功 能,所以以后有空可能会加上(已经有一大堆杂七杂八的要求了,很难有时间升级一下版本,~_~)。
一般来说,要干掉一个进程,有了Debug权限就可以了,若别人有了保护,那就要发挥你的能力了。
我想上面的讨论对于想要杀除进程、保护进程的人有一些启发了吧。
”
有了上面的了解,就可以隐约得出一个实现PspTerminateProcess的流程,就好比要干掉一个组织,你得先从茫茫人海根据该组织人员的特征去找该组织成员,然后找到一个杀一个,直到杀光后这个组织也就完了。就是枚举出目标进程的线程,然后通过PspTerminateThreadByPointer 去结束线程。 代码如下:
PS:
模拟PspTerminateProcess 一下命名为ForceTerminateProcess
ForceTerminateThread 是模拟PspTerminateThreadByPointer 阅读时注意
- NTSTATUS ForceTerminateProcess(PEPROCESS Process)
- {
- ULONG i;
- PETHREAD txtd;
- PEPROCESS txps;
- NTSTATUS st = STATUS_UNSUCCESSFUL;
- for (i=8;i<=65536;i=i+4)
- {
- st = PsLookupThreadByThreadId(i,&txtd);
- if ( NT_SUCCESS(st) )
- {
- txps=IoThreadToProcess(txtd);
- if ( txps == Process )
- {
- ForceTerminateThread(txtd);
- }
- }
- }
- return STATUS_SUCCESS;
- }
NTSTATUS ForceTerminateProcess(PEPROCESS Process)
{
ULONG i;
PETHREAD txtd;
PEPROCESS txps;
NTSTATUS st = STATUS_UNSUCCESSFUL;
for (i=8;i<=65536;i=i+4)
{
st = PsLookupThreadByThreadId(i,&txtd);
if ( NT_SUCCESS(st) )
{
txps=IoThreadToProcess(txtd);
if ( txps == Process )
{
ForceTerminateThread(txtd);
}
}
}
return STATUS_SUCCESS;
}
这个自己实现的PspTerminateProcess和原来的PspTerminateProcess有点区别。原来的PspTerminateProcess是通过PEPROCESS的hreadListHead链表来获取所有线程。这里是作者用来一个认为足够大的数字(65536)来枚举出目标进程的所有线程。理论上线程ID上限为2的32次方-1,因此在不考虑极端现象,使用足够大的数字来枚举。
其过程为:循环用{ PsLookupThreadByThreadId传入线程ID获取线程结构指针,再通过IoThreadToProcess传入线程指针结构,返回线程所属的进程指针,然后对比确定该线程属于目标进程后,调用PspTerminateThreadBypointer传入该线程结构指针,日掉它}。
如果打个比喻说上面的模拟PspTerminateProcess的作用是从茫茫人海找出组织成员的话,那么杀手就是PspTerminateThreadBypointer了(这里是ForceTerminateThread)。那么这个杀手PspTerminateThreadBypointer是怎么杀死线程的呢?再回头拜读PJF的《进程终止的内幕》可知,具体模拟代码如下:
- NTSTATUS ForceTerminateThread(PETHREAD Thread)
- {
- ULONG SYS_THREAD = 0x10;
- NTSTATUS st = STATUS_UNSUCCESSFUL;
- ULONG Size = 0;
- ULONG i = 0;
- PKAPC pApc = 0;
- if ( MmIsAddressValid((PVOID)Thread) == TRUE)//判断是否有效地址
- {
- pApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));//分配内存
- //Fix Thread Type To SYSTEM THREAD
- *(PULONG)((ULONG)Thread+EToffSET)=SYS_THREAD; //XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280 //给CrossThreadFlags赋值
- //If APC is OK
- if (pApc)
- {
- KeInitializeApc(pApc, Thread, OriginalApcEnvironment, ApcCallBack, 0, 0, KernelMode, 0);//初始化APC
- KeInsertQueueApc(pApc, pApc, 0, 2);//插入APC队列
- }
- st = STATUS_SUCCESS;
- }
- return st;
- }
NTSTATUS ForceTerminateThread(PETHREAD Thread)
{
ULONG SYS_THREAD = 0x10;
NTSTATUS st = STATUS_UNSUCCESSFUL;
ULONG Size = 0;
ULONG i = 0;
PKAPC pApc = 0;
if ( MmIsAddressValid((PVOID)Thread) == TRUE)//判断是否有效地址
{
pApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));//分配内存
//Fix Thread Type To SYSTEM THREAD
*(PULONG)((ULONG)Thread+EToffSET)=SYS_THREAD; //XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280 //给CrossThreadFlags赋值
//If APC is OK
if (pApc)
{
KeInitializeApc(pApc, Thread, OriginalApcEnvironment, ApcCallBack, 0, 0, KernelMode, 0);//初始化APC
KeInsertQueueApc(pApc, pApc, 0, 2);//插入APC队列
}
st = STATUS_SUCCESS;
}
return st;
}
其主要实现为,用KeInitializeApc初始化APC,再用KeInsertQueueApc插入线程。APC的回调过程为:
- VOID ApcCallBack(PKAPC Apc,PKNORMAL_ROUTINE *NormalRoutine,PVOID *NormalContext,PVOID *SystemArgument1,PVOID *SystemArgument2)
- {
- ExFreePool(Apc);
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
VOID ApcCallBack(PKAPC Apc,PKNORMAL_ROUTINE *NormalRoutine,PVOID *NormalContext,PVOID *SystemArgument1,PVOID *SystemArgument2)
{
ExFreePool(Apc);
PsTerminateSystemThread(STATUS_SUCCESS);
}
这样线程是在自己的执行环境调用PsTerminateSystemThread进行自杀了。因为PsTerminateSystemThread只能结束系统线程,而且只对当前线程有效。 因此,在初始化APC之前,我们得对线程结构的CrossThreadFlags动下手脚,这个是用来判断是否为系统线程的标志。我们将其赋值为0x10(系统线程标志常量PS_CROSS_THREAD_FLAGS_SYSTEM),这样就能让PsTerminateSystemThread以为是系统线程了。
其实现为:使用线程指针+CrossThreadFlags偏移来定位CrossThreadFlags,然后赋值。
( *(PULONG)((ULONG)Thread+EToffSET)=SYS_THREAD; //XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280)
这里也是唯一使用硬编码的地方。不同版本的windows系统,ETHREAD结构的CrossThreadFlags偏移不同XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280这样根据不同版本的系统选择不同的偏移量就能实现通用的PspTerminateProcess了。
作者文中的附带的驱动还实现了其它的功能,为了防止他人阅读混淆,我特地精简了一下,以及对分发函数的Control Code做了一点小改变。源码属于作者。我WInXP+WinDDK
MyKiller.c
- //#define WINVER 0x0500 //VC6.0默认编译环境为WINVER=0x0400
- #include "ntddk.h"
- #include <windef.h>
- #include <stdlib.h>
- #include "MyKiller.h"
- //#include "dbghelp.h"
- //===========================================
- /*
- typedef struct _KAPC_STATE
- {
- LIST_ENTRY ApcListHead[2];
- PVOID Process;
- BOOLEAN KernelApcInProgress;
- BOOLEAN KernelApcPending;
- BOOLEAN UserApcPending;
- }KAPC_STATE, *PKAPC_STATE;
- */
- typedef enum _KAPC_ENVIRONMENT
- {
- OriginalApcEnvironment,
- AttachedApcEnvironment,
- CurrentApcEnvironment,
- InsertApcEnvironment
- }KAPC_ENVIRONMENT;
- NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);
- NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
- NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
- VOID DriverUnload(PDRIVER_OBJECT pDriverObj);
- NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
- /*
- NTKERNELAPI VOID KeAttachProcess (PEPROCESS Process);
- NTKERNELAPI VOID KeDetachProcess (VOID);
- */
- NTKERNELAPI NTSTATUS PsLookupProcessByProcessId (IN ULONG ProcessId,OUT PEPROCESS *Process);
- NTKERNELAPI NTSTATUS PsLookupThreadByThreadId (IN ULONG ThreadId,OUT PETHREAD *Thread);
- NTKERNELAPI PEPROCESS IoThreadToProcess(IN PETHREAD Thread);
- NTKERNELAPI BOOLEAN MmIsAddressValid(IN PVOID VirtualAddress);
- NTKERNELAPI NTSTATUS PsTerminateSystemThread(IN NTSTATUS ExitStatus);
- NTKERNELAPI VOID KeInitializeApc(PKAPC Apc,PETHREAD Thread,KAPC_ENVIRONMENT Environment,PKKERNEL_ROUTINE KernelRoutine,PKRUNDOWN_ROUTINE RundownRoutine,PKNORMAL_ROUTINE NormalRoutine,KPROCESSOR_MODE ProcessorMode,PVOID NormalContext);
- NTKERNELAPI BOOLEAN KeInsertQueueApc(PKAPC Apc,PVOID SystemArgument1,PVOID SystemArgument2,KPRIORITY Increment);
- //====================
- PEPROCESS eProcess;
- ULONG processID;
- ULONG EToffSET=0x248; //default is XP
- //====================
- VOID ApcCallBack(PKAPC Apc,PKNORMAL_ROUTINE *NormalRoutine,PVOID *NormalContext,PVOID *SystemArgument1,PVOID *SystemArgument2)
- {
- ExFreePool(Apc);
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
- NTSTATUS ForceTerminateThread(PETHREAD Thread)
- {
- ULONG SYS_THREAD = 0x10;
- NTSTATUS st = STATUS_UNSUCCESSFUL;
- ULONG Size = 0;
- ULONG i = 0;
- PKAPC pApc = 0;
- if ( MmIsAddressValid((PVOID)Thread) == TRUE)
- {
- pApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
- //Fix Thread Type To SYSTEM THREAD
- *(PULONG)((ULONG)Thread+EToffSET)=SYS_THREAD; //XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280
- //If APC is OK
- if (pApc)
- {
- KeInitializeApc(pApc, Thread, OriginalApcEnvironment, ApcCallBack, 0, 0, KernelMode, 0);
- KeInsertQueueApc(pApc, pApc, 0, 2);
- }
- st = STATUS_SUCCESS;
- }
- return st;
- }
- NTSTATUS ForceTerminateProcess(PEPROCESS Process)
- {
- ULONG i;
- PETHREAD txtd;
- PEPROCESS txps;
- NTSTATUS st = STATUS_UNSUCCESSFUL;
- for (i=8;i<=65536;i=i+4)
- {
- st = PsLookupThreadByThreadId(i,&txtd);
- if ( NT_SUCCESS(st) )
- {
- txps=IoThreadToProcess(txtd);
- if ( txps == Process )
- {
- ForceTerminateThread(txtd);
- }
- }
- }
- return STATUS_SUCCESS;
- }
- NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
- {
- NTSTATUS status = STATUS_SUCCESS;
- UNICODE_STRING ustrLinkName;
- UNICODE_STRING ustrDevName;
- PDEVICE_OBJECT pDevObj;
- //dprintf("[MyKiller] DriverEntry: %S\n",pRegistryString->Buffer);
- // Create dispatch points for device control, create, close.
- pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
- pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
- pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
- pDriverObj->DriverUnload = DriverUnload;
- RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
- status = IoCreateDevice(pDriverObj,
- 0,
- &ustrDevName,
- FILE_DEVICE_UNKNOWN,
- 0,
- FALSE,
- &pDevObj);
- //dprintf("[MyKiller] Device Name %S",ustrDevName.Buffer);
- if(!NT_SUCCESS(status))
- {
- //dprintf("[MyKiller] IoCreateDevice = 0x%x\n", status);
- return status;
- }
- RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
- status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
- if(!NT_SUCCESS(status))
- {
- //dprintf("[MyKiller] IoCreateSymbolicLink = 0x%x\n", status);
- IoDeleteDevice(pDevObj);
- return status;
- }
- //dprintf("[MyKiller] SymbolicLink:%S",ustrLinkName.Buffer);
- return STATUS_SUCCESS;
- }
- VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
- {
- UNICODE_STRING strLink;
- RtlInitUnicodeString(&strLink, LINK_NAME);
- //
- // Delete the symbolic link
- //
- IoDeleteSymbolicLink(&strLink);
- //
- // Delete the device object
- //
- IoDeleteDevice(pDriverObj->DeviceObject);
- //dprintf("[MyKiller] Unloaded\n");
- }
- NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
- {
- pIrp->IoStatus.Status = STATUS_SUCCESS;
- pIrp->IoStatus.Information = 0;
- //dprintf("[MyKiller] IRP_MJ_CREATE\n");
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
- {
- pIrp->IoStatus.Status = STATUS_SUCCESS;
- pIrp->IoStatus.Information = 0;
- //dprintf("[MyKiller] IRP_MJ_CLOSE\n");
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
- {
- NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
- PIO_STACK_LOCATION pIrpStack;
- ULONG uIoControlCode;
- PVOID pIoBuffer;
- ULONG uInSize;
- ULONG uOutSize;
- pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
- uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
- pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
- uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
- uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
- switch(uIoControlCode)
- {
- case IOCTL_ApcKps:
- {
- __try
- {
- memcpy(&processID,pIoBuffer,sizeof(processID));
- PsLookupProcessByProcessId(processID,&eProcess);
- ForceTerminateProcess(eProcess);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- ;
- }
- break;
- }
- case IOCTL_OffSet:
- {
- __try
- {
- memcpy(&EToffSET,pIoBuffer,sizeof(EToffSET));
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
- ;
- }
- break;
- }
- //OVER
- }
- if(status == STATUS_SUCCESS)
- pIrp->IoStatus.Information = uOutSize;
- else
- pIrp->IoStatus.Information = 0;
- pIrp->IoStatus.Status = status;
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);
- return status;
- }
//#define WINVER 0x0500 //VC6.0默认编译环境为WINVER=0x0400
#include "ntddk.h"
#include <windef.h>
#include <stdlib.h>
#include "MyKiller.h"
//#include "dbghelp.h"
//===========================================
/*
typedef struct _KAPC_STATE
{
LIST_ENTRY ApcListHead[2];
PVOID Process;
BOOLEAN KernelApcInProgress;
BOOLEAN KernelApcPending;
BOOLEAN UserApcPending;
}KAPC_STATE, *PKAPC_STATE;
*/
typedef enum _KAPC_ENVIRONMENT
{
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment,
InsertApcEnvironment
}KAPC_ENVIRONMENT;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
VOID DriverUnload(PDRIVER_OBJECT pDriverObj);
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
/*
NTKERNELAPI VOID KeAttachProcess (PEPROCESS Process);
NTKERNELAPI VOID KeDetachProcess (VOID);
*/
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId (IN ULONG ProcessId,OUT PEPROCESS *Process);
NTKERNELAPI NTSTATUS PsLookupThreadByThreadId (IN ULONG ThreadId,OUT PETHREAD *Thread);
NTKERNELAPI PEPROCESS IoThreadToProcess(IN PETHREAD Thread);
NTKERNELAPI BOOLEAN MmIsAddressValid(IN PVOID VirtualAddress);
NTKERNELAPI NTSTATUS PsTerminateSystemThread(IN NTSTATUS ExitStatus);
NTKERNELAPI VOID KeInitializeApc(PKAPC Apc,PETHREAD Thread,KAPC_ENVIRONMENT Environment,PKKERNEL_ROUTINE KernelRoutine,PKRUNDOWN_ROUTINE RundownRoutine,PKNORMAL_ROUTINE NormalRoutine,KPROCESSOR_MODE ProcessorMode,PVOID NormalContext);
NTKERNELAPI BOOLEAN KeInsertQueueApc(PKAPC Apc,PVOID SystemArgument1,PVOID SystemArgument2,KPRIORITY Increment);
//====================
PEPROCESS eProcess;
ULONG processID;
ULONG EToffSET=0x248; //default is XP
//====================
VOID ApcCallBack(PKAPC Apc,PKNORMAL_ROUTINE *NormalRoutine,PVOID *NormalContext,PVOID *SystemArgument1,PVOID *SystemArgument2)
{
ExFreePool(Apc);
PsTerminateSystemThread(STATUS_SUCCESS);
}
NTSTATUS ForceTerminateThread(PETHREAD Thread)
{
ULONG SYS_THREAD = 0x10;
NTSTATUS st = STATUS_UNSUCCESSFUL;
ULONG Size = 0;
ULONG i = 0;
PKAPC pApc = 0;
if ( MmIsAddressValid((PVOID)Thread) == TRUE)
{
pApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
//Fix Thread Type To SYSTEM THREAD
*(PULONG)((ULONG)Thread+EToffSET)=SYS_THREAD; //XP=0x248, 2K3=0x240, VISTA+2k8=0x260, Win7=0x280
//If APC is OK
if (pApc)
{
KeInitializeApc(pApc, Thread, OriginalApcEnvironment, ApcCallBack, 0, 0, KernelMode, 0);
KeInsertQueueApc(pApc, pApc, 0, 2);
}
st = STATUS_SUCCESS;
}
return st;
}
NTSTATUS ForceTerminateProcess(PEPROCESS Process)
{
ULONG i;
PETHREAD txtd;
PEPROCESS txps;
NTSTATUS st = STATUS_UNSUCCESSFUL;
for (i=8;i<=65536;i=i+4)
{
st = PsLookupThreadByThreadId(i,&txtd);
if ( NT_SUCCESS(st) )
{
txps=IoThreadToProcess(txtd);
if ( txps == Process )
{
ForceTerminateThread(txtd);
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING ustrLinkName;
UNICODE_STRING ustrDevName;
PDEVICE_OBJECT pDevObj;
//dprintf("[MyKiller] DriverEntry: %S\n",pRegistryString->Buffer);
// Create dispatch points for device control, create, close.
pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
pDriverObj->DriverUnload = DriverUnload;
RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
status = IoCreateDevice(pDriverObj,
0,
&ustrDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDevObj);
//dprintf("[MyKiller] Device Name %S",ustrDevName.Buffer);
if(!NT_SUCCESS(status))
{
//dprintf("[MyKiller] IoCreateDevice = 0x%x\n", status);
return status;
}
RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
if(!NT_SUCCESS(status))
{
//dprintf("[MyKiller] IoCreateSymbolicLink = 0x%x\n", status);
IoDeleteDevice(pDevObj);
return status;
}
//dprintf("[MyKiller] SymbolicLink:%S",ustrLinkName.Buffer);
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
UNICODE_STRING strLink;
RtlInitUnicodeString(&strLink, LINK_NAME);
//
// Delete the symbolic link
//
IoDeleteSymbolicLink(&strLink);
//
// Delete the device object
//
IoDeleteDevice(pDriverObj->DeviceObject);
//dprintf("[MyKiller] Unloaded\n");
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
//dprintf("[MyKiller] IRP_MJ_CREATE\n");
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
//dprintf("[MyKiller] IRP_MJ_CLOSE\n");
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATION pIrpStack;
ULONG uIoControlCode;
PVOID pIoBuffer;
ULONG uInSize;
ULONG uOutSize;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch(uIoControlCode)
{
case IOCTL_ApcKps:
{
__try
{
memcpy(&processID,pIoBuffer,sizeof(processID));
PsLookupProcessByProcessId(processID,&eProcess);
ForceTerminateProcess(eProcess);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
;
}
break;
}
case IOCTL_OffSet:
{
__try
{
memcpy(&EToffSET,pIoBuffer,sizeof(EToffSET));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
;
}
break;
}
//OVER
}
if(status == STATUS_SUCCESS)
pIrp->IoStatus.Information = uOutSize;
else
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}
{ MyKiller.h 头文件 }
- #include <devioctl.h>
- #ifndef _MYKILLER_H
- #define _MYKILLER_H 1
- //============================================
- #define DEVICE_NAME L"\\Device\\devMyKiller" //Driver Name
- #define LINK_NAME L"\\DosDevices\\MyKiller" //Link Name
- //============================================
- #define IOCTL_BASE 0x800
- #define MY_CTL_CODE(i) \
- CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define IOCTL_ApcKps MY_CTL_CODE(1)
- #define IOCTL_OffSet MY_CTL_CODE(2)
- //============================================
- #endif
#include <devioctl.h>
#ifndef _MYKILLER_H
#define _MYKILLER_H 1
//============================================
#define DEVICE_NAME L"\\Device\\devMyKiller" //Driver Name
#define LINK_NAME L"\\DosDevices\\MyKiller" //Link Name
//============================================
#define IOCTL_BASE 0x800
#define MY_CTL_CODE(i) \
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_ApcKps MY_CTL_CODE(1)
#define IOCTL_OffSet MY_CTL_CODE(2)
//============================================
#endif
附上本人driver通讯部分Delphi源码。
- unit uMain;
- {
- MichaelJScofield
- }
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls, ComCtrls, ExtCtrls;
- type
- TfrmKiller = class(TForm)
- lblInfo: TLabel;
- edtOSVersion: TEdit;
- lblPid: TLabel;
- edtPID: TEdit;
- btnKill: TButton;
- btnLoad: TButton;
- btnUnload: TButton;
- lvProcessList: TListView;
- tmrRefresh: TTimer;
- procedure btnKillClick(Sender: TObject);
- procedure btnLoadClick(Sender: TObject);
- procedure btnUnloadClick(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure lvProcessListSelectItem(Sender: TObject; Item: TListItem;
- Selected: Boolean);
- procedure tmrRefreshTimer(Sender: TObject);
- private
- procedure GetProcessList;
- public
- { Public declarations }
- end;
- const
- Windows_2000 = 0;
- Windows_XP = 1;
- Windows_2003 = 2;
- Windows_Vista = 3;
- Windows_7 = 4;
- var
- frmKiller: TfrmKiller;
- function GetSystemVersion:string;
- implementation
- uses
- PsAPI,
- TlHelp32,
- WinSvc,
- PsClass,
- IoCtrl;
- var
- // svrsta: SERVICE_STATUS;
- PsDrvCtrl: TDriverControl;
- {$R *.dfm}
- { Get Windows OS Version }
- {
- else if Win32Platform=VER_PLATFORM_WIN32_WINDOWS then
- begin
- if AWin32Version=4.0 then
- Result := os + '95'
- else if AWin32Version=4.1 then
- Result := os + '98'
- else if AWin32Version=4.9 then
- Result := os + 'Me'
- else
- Result := os + '9x'
- end
- else if Win32Platform = VER_PLATFORM_WIN32_NT then
- begin
- if AWin32Version=3.51 then
- Result := os + 'NT 3.51'
- else if AWin32Version=4.0 then
- Result := os + 'NT 4.0'
- else if AWin32Version=5.0 then
- Result := os + '2000'
- else if AWin32Version=5.1 then
- ShowMessage('xp系统')
- else if AWin32Version=5.2 then
- Result := os + '2003'
- else if AWin32Version=6.0 then
- begin
- ShowMessage('vista系统')
- end
- else if AWin32Version=6.1 then
- Result := os + '7'
- else
- Result := os ;
- end
- else
- Result := os + '??';
- Result:=Result + ' '+GetWIndowsVersionString;
- }
- { 获取系统版本 }
- function GetSystemVersion:string;
- var
- OSVerStatus: OSVERSIONINFO;
- begin
- OSVerStatus.dwOSVersionInfoSize := SizeOf(OSVerStatus);
- if GetVersionEx(OSVerStatus) then
- begin
- if OSVerStatus.dwPlatformId=VER_PLATFORM_WIN32_NT then
- begin
- if OSVerStatus.dwMajorVersion=5 then // 写死了 5.0 200 5.1 XP 5.2 2003 其它版本的就放过吧
- begin
- case OSVerStatus.dwMinorVersion of
- 0:Result := 'Microsoft Windows 2000';
- 1:Result := 'Microsoft Windows XP';
- 2:Result := 'Microsoft Windows 2003';
- end;
- end else Result := 'Other Windows Version.';
- end;
- end else Result := 'Unknow System Version.';
- end;
- { 获取windows版本 }
- function GetSystemVersionID:Integer;
- var
- OSVerStatus: OSVERSIONINFO;
- begin
- OSVerStatus.dwOSVersionInfoSize := SizeOf(OSVerStatus);
- if GetVersionEx(OSVerStatus) then
- begin
- if OSVerStatus.dwPlatformId=VER_PLATFORM_WIN32_NT then
- begin
- if OSVerStatus.dwMajorVersion=5 then // 写死了 5.0 200 5.1 XP 5.2 2003
- begin
- Result := OSVerStatus.dwMinorVersion;
- end;
- if OSVerStatus.dwMajorVersion=6 then //6.0 Vista 6.1 Win7
- begin
- if OSVerStatus.dwMinorVersion=0 then Result := 3;
- if OSVerStatus.dwMinorVersion=1 then Result := 4;
- end;
- end;
- end;
- end;
- { 传输偏移地址 Control Code }
- function IOCTL_Offset: DWORD;
- begin
- Result := CTL_CODE(FILE_DEVICE_UNKNOWN,$802,METHOD_BUFFERED,FILE_ANY_ACCESS);
- end;
- { 传输进程PID Control Code }
- function IOCTL_PID: DWORD;
- begin
- Result := CTL_CODE(FILE_DEVICE_UNKNOWN,$801,METHOD_BUFFERED,FILE_ANY_ACCESS);
- end;
- { 获取进程列表 }
- procedure TfrmKiller.GetProcessList;
- var
- hSnapshot,hProcess,hModule: THandle;
- ProcessList: PROCESSENTRY32;
- cbNeeded: DWORD;
- PsPathBuf: array[0..MAX_PATH] of Char;
- begin
- hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
- ProcessList.dwSize := SizeOf(PROCESSENTRY32);
- if Process32First(hSnapshot,ProcessList) then
- begin
- while Process32Next(hSnapshot,ProcessList) do
- begin
- hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
- False,
- ProcessList.th32ProcessID);
- if hProcess<>0 then
- begin
- if EnumProcessModules(hProcess,@hModule,SizeOf(hModule),cbNeeded) then
- begin
- ZeroMemory(@PsPathBuf,MAX_PATH+1);
- GetModuleFileNameEx(hProcess,hModule,PsPathBuf,SizeOf(PsPathBuf));
- with lvProcessList.Items.Add do
- begin
- Caption := PsPathBuf;
- SubItems.Add(IntToStr(ProcessList.th32ProcessID));
- end;
- end;
- end;
- end;
- end;
- CloseHandle(hSnapshot);
- CloseHandle(hProcess);
- // CloseHandle(hModule);
- end;
- { 驱动通讯 }
- procedure TfrmKiller.btnKillClick(Sender: TObject);
- var
- dwProcessId,dwReturn,dwOffset: DWORD;
- begin
- dwProcessId := StrToInt(Trim(edtPID.Text));
- case GetSystemVersionID of
- Windows_2000 : dwOffset := $240; //CrossThreadFlags 硬编码
- Windows_XP : dwOffset := $248;
- Windows_2003 : dwOffset := $240;
- Windows_Vista : dwOffset := $260;
- Windows_7 : dwOffset := $280;
- end;
- PsDrvCtrl.IoControl(IOCTL_Offset,
- @dwOffset,
- 4,
- @dwReturn,
- SizeOf(DWORD));
- PsDrvCtrl.IoControl(IOCTL_PID,
- @dwProcessId,
- 4,
- @dwReturn,
- SizeOf(DWORD));
- lvProcessList.Clear;
- Sleep(1500);
- Application.ProcessMessages;
- lvProcessList.Clear;
- GetProcessList;
- end;
- procedure TfrmKiller.btnLoadClick(Sender: TObject);
- var
- lpFilePart: PAnsiChar;
- lpDrvPath: Array [0..255] of Char;
- begin
- edtOSVersion.Text := GetSystemVersion;
- GetFullPathName('MyKiller.sys', 256, lpDrvPath, lpFilePart);
- PsDrvCtrl := TDriverControl.Create(lpDrvPath, 'mykiller');
- if not PsDrvCtrl.IsVaild then
- begin
- PsDrvCtrl.Free;
- ShowMessage('无法加载驱动');
- Exit;
- end;
- if not PsDrvCtrl.StartDriver then
- begin
- PsDrvCtrl.Free;
- ShowMessage('无法启动驱动');
- Exit;
- end;
- if not PsDrvCtrl.OpenDevice then
- begin
- PsDrvCtrl.StopDriver;
- PsDrvCtrl.Free;
- ShowMessage('无法打开驱动。');
- Exit;
- end;
- ShowMessage('驱动已经成功启动。');
- btnUnload.Enabled := True;
- btnKill.Enabled := True;
- btnLoad.Enabled := False;
- end;
- procedure TfrmKiller.btnUnloadClick(Sender: TObject);
- begin
- PsDrvCtrl.StopDriver;
- PsDrvCtrl.Free;
- ShowMessage('驱动已经卸载成功。');
- btnUnload.Enabled := False;
- btnKill.Enabled := False;
- btnLoad.Enabled := True;
- end;
- procedure TfrmKiller.FormCreate(Sender: TObject);
- begin
- GetProcessList;
- end;
- procedure TfrmKiller.lvProcessListSelectItem(Sender: TObject;
- Item: TListItem; Selected: Boolean);
- begin
- edtPID.Text := Item.SubItems.Text;
- end;
- procedure TfrmKiller.tmrRefreshTimer(Sender: TObject);
- begin
- lvProcessList.Clear;
- GetProcessList;
- end;
- end.
unit uMain;
{
MichaelJScofield
}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TfrmKiller = class(TForm)
lblInfo: TLabel;
edtOSVersion: TEdit;
lblPid: TLabel;
edtPID: TEdit;
btnKill: TButton;
btnLoad: TButton;
btnUnload: TButton;
lvProcessList: TListView;
tmrRefresh: TTimer;
procedure btnKillClick(Sender: TObject);
procedure btnLoadClick(Sender: TObject);
procedure btnUnloadClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure lvProcessListSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
procedure tmrRefreshTimer(Sender: TObject);
private
procedure GetProcessList;
public
{ Public declarations }
end;
const
Windows_2000 = 0;
Windows_XP = 1;
Windows_2003 = 2;
Windows_Vista = 3;
Windows_7 = 4;
var
frmKiller: TfrmKiller;
function GetSystemVersion:string;
implementation
uses
PsAPI,
TlHelp32,
WinSvc,
PsClass,
IoCtrl;
var
// svrsta: SERVICE_STATUS;
PsDrvCtrl: TDriverControl;
{$R *.dfm}
{ Get Windows OS Version }
{
else if Win32Platform=VER_PLATFORM_WIN32_WINDOWS then
begin
if AWin32Version=4.0 then
Result := os + '95'
else if AWin32Version=4.1 then
Result := os + '98'
else if AWin32Version=4.9 then
Result := os + 'Me'
else
Result := os + '9x'
end
else if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
if AWin32Version=3.51 then
Result := os + 'NT 3.51'
else if AWin32Version=4.0 then
Result := os + 'NT 4.0'
else if AWin32Version=5.0 then
Result := os + '2000'
else if AWin32Version=5.1 then
ShowMessage('xp系统')
else if AWin32Version=5.2 then
Result := os + '2003'
else if AWin32Version=6.0 then
begin
ShowMessage('vista系统')
end
else if AWin32Version=6.1 then
Result := os + '7'
else
Result := os ;
end
else
Result := os + '??';
Result:=Result + ' '+GetWIndowsVersionString;
}
{ 获取系统版本 }
function GetSystemVersion:string;
var
OSVerStatus: OSVERSIONINFO;
begin
OSVerStatus.dwOSVersionInfoSize := SizeOf(OSVerStatus);
if GetVersionEx(OSVerStatus) then
begin
if OSVerStatus.dwPlatformId=VER_PLATFORM_WIN32_NT then
begin
if OSVerStatus.dwMajorVersion=5 then // 写死了 5.0 200 5.1 XP 5.2 2003 其它版本的就放过吧
begin
case OSVerStatus.dwMinorVersion of
0:Result := 'Microsoft Windows 2000';
1:Result := 'Microsoft Windows XP';
2:Result := 'Microsoft Windows 2003';
end;
end else Result := 'Other Windows Version.';
end;
end else Result := 'Unknow System Version.';
end;
{ 获取windows版本 }
function GetSystemVersionID:Integer;
var
OSVerStatus: OSVERSIONINFO;
begin
OSVerStatus.dwOSVersionInfoSize := SizeOf(OSVerStatus);
if GetVersionEx(OSVerStatus) then
begin
if OSVerStatus.dwPlatformId=VER_PLATFORM_WIN32_NT then
begin
if OSVerStatus.dwMajorVersion=5 then // 写死了 5.0 200 5.1 XP 5.2 2003
begin
Result := OSVerStatus.dwMinorVersion;
end;
if OSVerStatus.dwMajorVersion=6 then //6.0 Vista 6.1 Win7
begin
if OSVerStatus.dwMinorVersion=0 then Result := 3;
if OSVerStatus.dwMinorVersion=1 then Result := 4;
end;
end;
end;
end;
{ 传输偏移地址 Control Code }
function IOCTL_Offset: DWORD;
begin
Result := CTL_CODE(FILE_DEVICE_UNKNOWN,$802,METHOD_BUFFERED,FILE_ANY_ACCESS);
end;
{ 传输进程PID Control Code }
function IOCTL_PID: DWORD;
begin
Result := CTL_CODE(FILE_DEVICE_UNKNOWN,$801,METHOD_BUFFERED,FILE_ANY_ACCESS);
end;
{ 获取进程列表 }
procedure TfrmKiller.GetProcessList;
var
hSnapshot,hProcess,hModule: THandle;
ProcessList: PROCESSENTRY32;
cbNeeded: DWORD;
PsPathBuf: array[0..MAX_PATH] of Char;
begin
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
ProcessList.dwSize := SizeOf(PROCESSENTRY32);
if Process32First(hSnapshot,ProcessList) then
begin
while Process32Next(hSnapshot,ProcessList) do
begin
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
False,
ProcessList.th32ProcessID);
if hProcess<>0 then
begin
if EnumProcessModules(hProcess,@hModule,SizeOf(hModule),cbNeeded) then
begin
ZeroMemory(@PsPathBuf,MAX_PATH+1);
GetModuleFileNameEx(hProcess,hModule,PsPathBuf,SizeOf(PsPathBuf));
with lvProcessList.Items.Add do
begin
Caption := PsPathBuf;
SubItems.Add(IntToStr(ProcessList.th32ProcessID));
end;
end;
end;
end;
end;
CloseHandle(hSnapshot);
CloseHandle(hProcess);
// CloseHandle(hModule);
end;
{ 驱动通讯 }
procedure TfrmKiller.btnKillClick(Sender: TObject);
var
dwProcessId,dwReturn,dwOffset: DWORD;
begin
dwProcessId := StrToInt(Trim(edtPID.Text));
case GetSystemVersionID of
Windows_2000 : dwOffset := $240; //CrossThreadFlags 硬编码
Windows_XP : dwOffset := $248;
Windows_2003 : dwOffset := $240;
Windows_Vista : dwOffset := $260;
Windows_7 : dwOffset := $280;
end;
PsDrvCtrl.IoControl(IOCTL_Offset,
@dwOffset,
4,
@dwReturn,
SizeOf(DWORD));
PsDrvCtrl.IoControl(IOCTL_PID,
@dwProcessId,
4,
@dwReturn,
SizeOf(DWORD));
lvProcessList.Clear;
Sleep(1500);
Application.ProcessMessages;
lvProcessList.Clear;
GetProcessList;
end;
procedure TfrmKiller.btnLoadClick(Sender: TObject);
var
lpFilePart: PAnsiChar;
lpDrvPath: Array [0..255] of Char;
begin
edtOSVersion.Text := GetSystemVersion;
GetFullPathName('MyKiller.sys', 256, lpDrvPath, lpFilePart);
PsDrvCtrl := TDriverControl.Create(lpDrvPath, 'mykiller');
if not PsDrvCtrl.IsVaild then
begin
PsDrvCtrl.Free;
ShowMessage('无法加载驱动');
Exit;
end;
if not PsDrvCtrl.StartDriver then
begin
PsDrvCtrl.Free;
ShowMessage('无法启动驱动');
Exit;
end;
if not PsDrvCtrl.OpenDevice then
begin
PsDrvCtrl.StopDriver;
PsDrvCtrl.Free;
ShowMessage('无法打开驱动。');
Exit;
end;
ShowMessage('驱动已经成功启动。');
btnUnload.Enabled := True;
btnKill.Enabled := True;
btnLoad.Enabled := False;
end;
procedure TfrmKiller.btnUnloadClick(Sender: TObject);
begin
PsDrvCtrl.StopDriver;
PsDrvCtrl.Free;
ShowMessage('驱动已经卸载成功。');
btnUnload.Enabled := False;
btnKill.Enabled := False;
btnLoad.Enabled := True;
end;
procedure TfrmKiller.FormCreate(Sender: TObject);
begin
GetProcessList;
end;
procedure TfrmKiller.lvProcessListSelectItem(Sender: TObject;
Item: TListItem; Selected: Boolean);
begin
edtPID.Text := Item.SubItems.Text;
end;
procedure TfrmKiller.tmrRefreshTimer(Sender: TObject);
begin
lvProcessList.Clear;
GetProcessList;
end;
end.