模拟PspTerminateProcess结束进程-学习笔记

11 篇文章 0 订阅
7 篇文章 0 订阅

此文是阅读黑防上胡文亮大牛《模拟实现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;
}
这个自己实现的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;	
}

其主要实现为,用KeInitializeApc初始化APC,再用KeInsertQueueApc插入线程。APC的回调过程为:

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;
}

{  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

附上本人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.



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值