監視系統中進程的創建和終止

//write by jingzhongrong

最近在論壇上看到很多人都在問這個問題,花了一些時間寫了這個程序,原理很簡單,主要功能通過一個內核驅動中使用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

下面是具體的代碼:

 

#ifndef CPN_DRIVER_H
#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 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    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;
}

其他派遣例程:

 

VOID CPNUnload(IN PDRIVER_OBJECT DriverObject)
{
    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;
}

回調函數如下:

 

VOID ProcessCallback(IN HANDLE hParentId, IN HANDLE hProcessId, IN BOOLEAN bCreate)
{
    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);
  }
}

引入一個頭文件,聲明驅動程序中使用的的信息返回結構(回調函數傳出來的信息),以及設備控制代碼的聲明。

#ifndef DRIVERINFOSTRUCT_H
#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服務管理函數,創建服務,打開服務,然後在打開驅動程序的句柄,啓動線程訪問。

//h頭文件實現
#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(); 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章