Author: sinister
Email: sinister@whitecell.org
Homepage: http://www.whitecell.org
(Describe it first. Many may ask how some process/thread monitoring tools are implemented.
I wrote it to give those friends a better understanding and save my mails. If you
If you are familiar with the NT driver, you may have mastered the method mentioned in this article and can skip it .)
Sometimes we want to dynamically monitor the creation and destruction of any process/thread in the system. To achieve
For this purpose, I have read the DDK manual and found the pssetcreateprocesspolicyroutine () provided by it (),
Pssetcreatethreadpolicyroutine (), and other functions can implement this function. These two functions can
Register a callbalck function with the system to monitor processes, threads, and other operations. The original function is as follows:
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 ); NTSTATUS PsSetCreateThreadNotifyRoutine( IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine ); VOID (*PCREATE_THREAD_NOTIFY_ROUTINE) ( IN HANDLE ProcessId, IN HANDLE ThreadId, IN BOOLEAN Create );
The original form shows that the callback function only provides the process ID/thread ID. Not provided
Process name. Then we need to further obtain the process name through the process ID. This requires an undisclosed
Function pslookupprocessbyprocessid (). The original function is as follows:
NTSTATUS PsLookupProcessByProcessId( IN ULONG ulProcId, OUT PEPROCESS * pEProcess );
The eprocess structure of function output is also an undisclosed kernel process structure. Many people call it kpeb.
The offset 0x1fc in the eprocess structure points to the offset of the current process name. (Although this structure can be found in
Directly used in the driver. However, its structure has not been published. Many experts on the Internet have already provided its structure. Yes
If you are interested, you can search by yourself or get it from ifs DDK. The structure is too long, so you will not post it here)
With this structure, we can get the process name. The NT System also provides a function for dynamic monitoring.
Load the image according to the process. This function can obtain the DLL name and full path called when the process is planted.
Some image information. It provides us with more detailed process loading information and better help.
The original function is as follows:
NTSTATUS PsSetLoadImageNotifyRoutine( IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine ); VOID (*PLOAD_IMAGE_NOTIFY_ROUTINE) ( IN PUNICODE_STRING FullImageName, IN HANDLE ProcessId, // where image is mapped IN PIMAGE_INFO ImageInfo ); typedef struct _IMAGE_INFO { union { ULONG Properties; struct { ULONG ImageAddressingMode : 8; //code addressing mode ULONG SystemModeImage : 1; //system mode image ULONG ImageMappedToAllPids : 1; //mapped in all processes ULONG Reserved : 22; }; }; PVOID ImageBase; ULONG ImageSelector; ULONG ImageSize; ULONG ImageSectionNumber; } IMAGE_INFO, *PIMAGE_INFO;
With the functions and structures provided above, we can implement a process/thread monitor. The following section
The Code demonstrates how to implement this function.
/*************************************** * ************************* File Name: wssprocmon. c Description: Process/thread monitor Author: sinister last modification date: *************************************** * *************************/# include "ntddk. H "# include" string. H "# define processnameoffset 0x1fc static ntstatus mydrvdispatch (in pdevice_object deviceobject, in pirirp IRP); ntstatus pslookupprocessbyprocessid (in ulong ulproci D, out peprocess * peprocess); void processcreatemon (in handle hparentid, in handle PID, in Boolean bcreate); void threadcreatemon (in handle PID, in handle tid, in Boolean bcreate ); void imagecreatemon (in punicode_string fullimagename, in handle processid, in pimage_info imageinfo); // driver entry ntstatus DriverEntry (in pdriver_object driverobject, in punicode_string registrypath) {unicode_string Namestring, linkstring; pdevice_object deviceobject; ntstatus status; int I; // create a device rtlinitunicodestring (& namestring, l "\ device \ wssprocmon"); status = iocreatedevice (driverobject, 0, & namestring, file_device_unknown, 0, true, & deviceobject); If (! Nt_success (Status) return status; rtlinitunicodestring (& linkstring, l "\ dosdevices \ wssprocmon"); status = iocreatesymboliclink (& linkstring, & namestring); If (! Nt_success (Status) {iodeletedevice (driverobject-> deviceobject); Return status;} status = pssetloadimagenotifyroutine (imagecreatemon); If (! Nt_success (Status) {dbuplint ("pssetloadimagenotifyroutine () \ n"); Return status;} status = pssetcreatethreadpolicyroutine (threadcreatemon); If (! Nt_success (Status) {dbuplint ("pssetcreatethreadpolicyroutine () \ n"); Return status ;}status = pssetcreateprocesspolicyroutine (processcreatemon, false); If (! Nt_success (Status) {dbuplint ("pssetcreateprocesspolicyroutine () \ n"); Return status ;}for (I = 0; I <irp_mj_maximum_function; I ++) {driverobject-> majorfunction [I] = mydrvdispatch;} return STATUS_SUCCESS;} // process static ntstatus mydrvdispatch (in pdevice_object deviceobject, in pirp) {IRP-> iostatus. status = STATUS_SUCCESS; IRP-> iostatus. information = 0l; iocompleterequest (IRP, 0); Return IRP-> iostatus. status;} void processcreatemon (in handle hparentid, in handle PID, in Boolean bcreate) {peprocess eprocess; ulong ulcurrentprocessid; lptstr lpcurproc; ntstatus; status = running (ulong) PID, & eprocess); If (! Nt_success (Status) {dbuplint ("pslookupprocessbyprocessid () \ n"); Return ;}if (bcreate) {lpcurproc = (lptstr) eprocess; lpcurproc = lpcurproc + processnameoffset; dbuplint ("create process = process name: % s, process parentid: % d, process ID: % d, process address % x: \ n", lpcurproc, hparentid, PID, eprocess);} else {dbuplint ("terminated = process ID: % d \ n", pid) ;}} void threadcreatemon (In handle PID, in handle tid, in Boolean bcreate) {peprocess eprocess; ulong ulcurrentprocessid; lptstr lpcurproc; ntstatus status; status = pslookupprocessbyprocessid (ulong) PID, & eprocess ); if (! Nt_success (Status) {dbuplint ("pslookupprocessbyprocessid () \ n"); Return ;}if (bcreate) {lpcurproc = (lptstr) eprocess; lpcurproc = lpcurproc + processnameoffset; dbuplint ("create thread = process name: % s process ID: % d, thread ID: % d \ n", lpcurproc, PID, tid );} else {dbuplint ("terminated = thread ID: % d \ n", tid) ;}} void imagecreatemon (in punicode_string fullimagename, in handle processid, in pimage_info imageinfo) {dbuplint ("fullimagename: % s, process ID: % d \ n", fullimagename-> buffer, processid); dbuplint ("imagebase: % x, imagesize: % d \ n ", imageinfo-> imagebase, imageinfo-> imagesize );}