最近在论坛上看到很多人都在问这个问题,花了一些时间写了这个程序,原理很简单,主要功能通过一个内核驱动中使用PsSetCreateProcessNotifyRoutine 函数来实现。效果也不错
首先新建一个驱动程序工程,在DriverEntry例程中调用PsSetCreateProcessNotifyRoutine函数向系统添加一个回调函数,并创建一个系统事件对象,当系统中有进程新建或者进程终止,回调函数将会被调用,而在进程回调函数中,保存信息并出发系统事件,通知用户态的应用程序。
PsSetCreateProcessNotifyRoutine函数的原型声明如下:
NTSTATUS
PsSetCreateProcessNotifyRoutine(
IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
IN BOOLEAN Remove
);
回调函数的函数定义如下:
VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE) (
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
);
创建系统事件的函数:IoCreateNotificationEvent
下面是具体的代码:
#define CPN_DRIVER_H
#include <ntddk.h>
#include <devioctl.h>
//自定义函数声明
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS CPNDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID CPNUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS CPNDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID ProcessCallback(IN HANDLE hParentId, IN HANDLE hProcessId, IN BOOLEAN bCreate);
#define DEVICE_NAME L"\Device\CPNDriver"
#define LINK_NAME L"\DosDevices\CPNDriverLink"
#define EVENT_NAME L"\BaseNamedObjects\CPNDriverEvent"
typedef struct _DEVICE_EXTENSION
{
HANDLE hProcessHandle;
PKEVENT pProcessEvent;
HANDLE hParentID;
HANDLE hProcessID;
BOOLEAN bCreate;
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;
typedef struct _CALLBACK_INFO
{
HANDLE hParentId;
HANDLE hProcessId;
BOOLEAN bCreate;
}CALLBACK_INFO, *PCALLBACK_INFO;
#define IOCTL_CPNDRIVER_GET_PROCESSINFO CTL_CODE(FILE_DEVICE_UNKNOWN,0x0800,METHOD_BUFFERED,
FILE_READ_ACCESS|FILE_WRITE_ACCESS)
#endif
下面是C文件实现:
#include <ntddk.h>
#include <devioctl.h>
#include "CPNDriver.h"
PDEVICE_OBJECT g_pDeviceObject; //声明全局变量
DriverEntry例程:
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING usDevName;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
UNICODE_STRING usLinkName;
UNICODE_STRING usEventName;
//
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = CPNDispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CPNDispatchIoctl;
DriverObject->DriverUnload = CPNUnload;
//
RtlInitUnicodeString(&usDevName,DEVICE_NAME);
//
status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
&usDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDevObj);
if(!NT_SUCCESS(status))
{
return status;
}
//
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
//
RtlInitUnicodeString(&usLinkName,LINK_NAME);
status = IoCreateSymbolicLink(&usLinkName,&usDevName); //创建关联
if(!NT_SUCCESS(status))
{
IoDeleteDevice(pDevObj);
return status;
}
//
g_pDeviceObject = pDevObj;
//
RtlInitUnicodeString(&usEventName,EVENT_NAME);
pDevExt->pProcessEvent = IoCreateNotificationEvent(&usEventName,&pDevExt->hProcessHandle);
KeClearEvent(pDevExt->pProcessEvent);
//
status = PsSetCreateProcessNotifyRoutine(ProcessCallback,FALSE);
return status;
}
其他派遣例程:
{
UNICODE_STRING usLink;
PsSetCreateProcessNotifyRoutine(ProcessCallback,TRUE); //移除
RtlInitUnicodeString(&usLink,LINK_NAME);
IoDeleteSymbolicLink(&usLink);
IoDeleteDevice(DriverObject->DeviceObject);
}
NTSTATUS CPNDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS CPNDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
PCALLBACK_INFO pCallbackInfo = (PCALLBACK_INFO)Irp->AssociatedIrp.SystemBuffer;
ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch(uIoControlCode)
{
case IOCTL_CPNDRIVER_GET_PROCESSINFO:
{
if(uOutSize >= sizeof(CALLBACK_INFO))
{
pCallbackInfo->hParentId = pDevExt->hParentID;
pCallbackInfo->hProcessId = pDevExt->hProcessID;
pCallbackInfo->bCreate = pDevExt->bCreate;
status = STATUS_SUCCESS;
}
}
break;
}
if(status == STATUS_SUCCESS)
{
Irp->IoStatus.Information = uOutSize;
}
else
{
Irp->IoStatus.Information = 0;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
回调函数如下:
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension;
pDevExt->hParentID = hParentId;
pDevExt->hProcessID = hProcessId;
pDevExt->bCreate = bCreate;
//触发事件
KeSetEvent(pDevExt->pProcessEvent,0,FALSE);
KeClearEvent(pDevExt->pProcessEvent);
}
编译成sys后,创建一个Windows程序,下面用BCB来实现:
使用一个线程类来从驱动程序等待并获得信息,使用DeviceIoControl。
下面是线程类的具体实现以及声明:
class GetInformationThread : public TThread
{
public:
__fastcall GetInformationThread(bool CreateSuspended, TListView* tv);
protected:
void __fastcall Execute();
void __fastcall ReflashListView();
AnsiString __fastcall GetProcessNameFromID(DWORD dwProcessID);
private:
HANDLE hhParentId;
HANDLE hhProcessId;
BOOLEAN bbCreate;
TListView *lv;
};
//cpp实现
__fastcall GetInformationThread::GetInformationThread(bool CreateSuspended, TListView* tv)
:TThread(CreateSuspended)
{
lv = tv;
}
void __fastcall GetInformationThread::Execute()
{
CALLBACK_INFO CallbackInfo = { 0 };
CALLBACK_INFO CallbackTemp = { 0 };
while(!this->Terminated)
{
while(WaitForSingleObject(hProcessEvent,INFINITE)==WAIT_OBJECT_0)
{
DWORD BytesReturn;
BOOL bRet = DeviceIoControl(hDriver,IOCTL_CPNDRIVER_GET_PROCESSINFO,NULL,0,&CallbackInfo,
sizeof(CallbackInfo),&BytesReturn,NULL);
if(bRet)
{
if(CallbackInfo.hParentId != CallbackTemp.hParentId
|| CallbackInfo.hProcessId != CallbackTemp.hProcessId
|| CallbackInfo.bCreate != CallbackTemp.bCreate)
{
hhParentId = CallbackInfo.hParentId;
hhProcessId = CallbackInfo.hProcessId;
bbCreate = CallbackInfo.bCreate;
CallbackTemp = CallbackInfo;
Synchronize(ReflashListView);
}
}
else
{
ShowMessage("获取进程信息失败.");
break;
}
}
}
}
AnsiString __fastcall GetInformationThread::GetProcessNameFromID(DWORD dwProcessID)
{
//HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 pe;
ZeroMemory(&pe,sizeof(pe));
pe.dwSize = sizeof(pe);
AnsiString temp = "Unknown";
BOOL bMore = Process32First(hSnapshot,&pe);
while(bMore)
{
if(pe.th32ProcessID == dwProcessID)
{
temp = AnsiString(pe.szExeFile);
break;
}
else
{
bMore = Process32Next(hSnapshot,&pe);
}
}
return temp;
}
void __fastcall GetInformationThread::ReflashListView()
{
AnsiString parentProcessName;
AnsiString ProcessName;
parentProcessName = this->GetProcessNameFromID((DWORD)this->hhParentId);
ProcessName = this->GetProcessNameFromID((DWORD)this->hhProcessId);
if(this->bbCreate)
{
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
parentProcessName = this->GetProcessNameFromID((DWORD)this->hhParentId);
ProcessName = this->GetProcessNameFromID((DWORD)this->hhProcessId);
}
else
{
parentProcessName = this->GetProcessNameFromID((DWORD)this->hhParentId);
ProcessName = this->GetProcessNameFromID((DWORD)this->hhProcessId);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
}
TListItem *temp = lv->Items->Add();
temp->Caption = AnsiString((int)this->hhProcessId);
temp->SubItems->Add(AnsiString((int)this->hhParentId));
if(this->bbCreate)
{
temp->SubItems->Add("Create");
temp->SubItems->Add(parentProcessName);
temp->SubItems->Add(ProcessName);
}
else
{
temp->SubItems->Add("Close");
temp->SubItems->Add(parentProcessName);
temp->SubItems->Add(ProcessName);
}
}
引入一个头文件,声明驱动程序中使用的的信息返回结构(回调函数传出来的信息),以及设备控制代码的声明。
#define DRIVERINFOSTRUCT_H
#include <windows.h>
#include <winioctl.h>
#define IOCTL_CPNDRIVER_GET_PROCESSINFO CTL_CODE(FILE_DEVICE_UNKNOWN,
0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//用户与内核交互的缓冲区格式,这个结构向用户程序返回进程信息
typedef struct _CALLBACK_INFO
{
HANDLE hParentId;
HANDLE hProcessId;
BOOLEAN bCreate;
}CALLBACK_INFO, *PCALLBACK_INFO;
#endif
下面就是使用SCM服务管理函数,创建服务,打开服务,然后在打开驱动程序的句柄,启动线程访问。
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TButton *Button3;
TListView *ListView1;
TGroupBox *GroupBox1;
TLabel *Label1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
private: // User declarations
bool notifying;
char szDriverPath[256];
GetInformationThread *th;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//cpp文件实现
//---------------------------------------------------------------------------
#include <windows.h>
#include <tlhelp32.h>
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "DriverInfoStruct.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
SC_HANDLE hSCM;
SC_HANDLE hService;
HANDLE hDriver;
HANDLE hProcessEvent;
char szLinkName[] = "CPNDriverLink";
HANDLE hSnapshot;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
notifying = false;
Button1->Enabled = true;
Button2->Enabled = false;
Button3->Enabled = true;
this->szDriverPath[0] = '\0';
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char *p;
::GetFullPathName("CPNDriver.sys",256,szDriverPath,&p);
if(notifying==false)
{
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCM==NULL)
{
ShowMessage("打开服务控制管理器失败.");
notifying = false;
Button1->Enabled = true;
Button2->Enabled = false;
Button3->Enabled = true;
return;
}
hService = CreateService(hSCM,szLinkName,szLinkName,SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,szDriverPath,
NULL,0,NULL,NULL,NULL);
if(hService==NULL)
{
int nError = GetLastError();
if(nError==ERROR_SERVICE_EXISTS || nError==ERROR_SERVICE_MARKED_FOR_DELETE)
{
hService = OpenService(hSCM,szLinkName,SERVICE_ALL_ACCESS);
}
}
if(hService==NULL)
{
ShowMessage("创建服务出错.");
CloseServiceHandle(hSCM);
notifying = false;
Button1->Enabled = true;
Button2->Enabled = false;
Button3->Enabled = true;
return;
}
if(!StartService(hService,0,NULL))
{
int nError = GetLastError();
if(nError != ERROR_SERVICE_ALREADY_RUNNING)
{
ShowMessage("启动服务出错.");
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
notifying = false;
Button1->Enabled = true;
Button2->Enabled = false;
Button3->Enabled = true;
return;
}
}
char szDriverFile[256] = "";
wsprintf(szDriverFile,"\\\\.\\%s",szLinkName);
hDriver = CreateFile(szDriverFile,GENERIC_READ|GENERIC_WRITE,
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hDriver==INVALID_HANDLE_VALUE)
{
ShowMessage("打开设备失败.");
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
notifying = false;
Button1->Enabled = true;
Button2->Enabled = false;
Button3->Enabled = true;
return;
}
hProcessEvent = OpenEvent(SYNCHRONIZE,FALSE,"CPNDriverEvent");
th = new GetInformationThread(true,ListView1);
th->Resume();
notifying = true;
Button1->Enabled = false;
Button2->Enabled = true;
Button3->Enabled = false;
}
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
th->Terminate();
CloseHandle(hDriver);
SERVICE_STATUS ss;
ControlService(hService,SERVICE_CONTROL_STOP,&ss);
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
notifying = false;
Button1->Enabled = true;
Button2->Enabled = false;
Button3->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
this->Close();
}