驱动监控进程

0x00 前言

利用PsSetCreateProcessNotifyRoutine的回调函数进行监控进程的创建与销毁。

0x01 exe代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>
#define Main_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define Flag_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)
DWORD dwReturned;
char szDebugString[255]="";
DWORD dwErrorCode;
void ColseService(SC_HANDLE hSeriverMgr,SC_HANDLE hSeriverDDK)
{
        dwErrorCode = GetLastError();
        sprintf(szDebugString,"error code = %d",dwErrorCode);
        MessageBox(NULL,szDebugString,"failed!",NULL);
        if(hSeriverDDK)
        {
                CloseServiceHandle(hSeriverDDK);
        }
        if(hSeriverMgr)
        {
                CloseServiceHandle(hSeriverMgr);
        }
}
//服务的名字 sys的路径
void LoadDriver(char* szDriverName,char* szDriverImagePath)
{
        SC_HANDLE hSeriverMgr=NULL;
        SC_HANDLE hSeriverDDK=NULL;
        //打开SCM控制管理器
        hSeriverMgr = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
        if(hSeriverMgr==NULL)
        {
                ColseService(hSeriverMgr,hSeriverDDK);
        }
        //创建驱动对应的服务
        hSeriverDDK=CreateService(
                                  hSeriverMgr,//服务管理器句柄
                          szDriverName,//驱动文件的注册表名
                                  szDriverName,//注册表显示文件名
                                  SERVICE_ALL_ACCESS,//加载驱动程序的访问权限
                                  SERVICE_KERNEL_DRIVER,//表示加载的服务是驱动程序
                                  SERVICE_DEMAND_START,//注册表驱动程序的start值
                                  SERVICE_ERROR_IGNORE,//注册表驱动程序的ErrorControl的值
                                  szDriverImagePath,//注册表驱动程序的ImagePath的路径
                                  NULL,
                                  NULL,
                                  NULL,
                                  NULL,
                                  NULL
                                );
        if(hSeriverDDK==NULL)
        {
                dwErrorCode = GetLastError();
                if(dwErrorCode==ERROR_SERVICE_EXISTS)
                {
                        //服务已经创建,只需要打开就可以了
                        hSeriverDDK = OpenService(hSeriverMgr,szDriverName,SERVICE_ALL_ACCESS);
                        if(hSeriverDDK==NULL)
                        {
                                ColseService(hSeriverMgr,hSeriverDDK);
                        }
                }
                else
                {
                        //由于其他原因创建失败
                        ColseService(hSeriverMgr,hSeriverDDK);
                }
        }
        //开启此服务
        dwErrorCode = StartService(hSeriverDDK,NULL,NULL);
        if(!dwErrorCode)//若不成功
        {
                dwErrorCode = GetLastError();
                if(dwErrorCode=!ERROR_SERVICE_ALREADY_RUNNING)
                {
                        //原因不是别挂起或已经运行
                        ColseService(hSeriverMgr,hSeriverDDK);
                }
        }
}
//卸载驱动程序  
void UnloadDriver(char * szSvrName)  
{
        SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
        SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
        SERVICE_STATUS SvrSta;
        
        //打开SCM管理器
        hServiceMgr = OpenSCManager( NULLNULL, SC_MANAGER_ALL_ACCESS );  
        if( hServiceMgr == NULL )  
        {
                //带开SCM管理器失败
                ColseService(hServiceMgr,hServiceDDK);
        }  
        //打开驱动所对应的服务
        hServiceDDK = OpenService( hServiceMgr, szSvrName, SERVICE_ALL_ACCESS );  
        if( hServiceDDK == NULL )  
        {
                //打开驱动所对应的服务失败
                ColseService(hServiceMgr,hServiceDDK);
        }  
        
        //停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。  
        if(!ControlService( hServiceDDK, SERVICE_CONTROL_STOP , &SvrSta ) )  
        {  
                ColseService(hServiceMgr,hServiceDDK);
        }  
        
        //动态卸载驱动程序。  
        if(!DeleteService( hServiceDDK ))  
        {
                ColseService(hServiceMgr,hServiceDDK);
        }        
void show(HANDLE hDevice)
{
        char OutBuffer[255]="";
        DeviceIoControl(hDevice,     //已经打开的设备
                                        Main_CTL_CODE,////控制码
                                        NULL,  //输入缓冲区
                                        0,           //输入缓冲区大小
                                        &OutBuffer, //输出缓冲区
                                        255,           //输出缓冲区大小
                                        &dwReturned, //返回实际字节数
                                        NULL);
        printf(OutBuffer);
}
int main(int argc, char* argv[])
{
        LoadDriver("Notify","c:\\Notify.sys");
        //UnloadDriver("Notify");
        HANDLE hDevice=CreateFile(
                           "\\\\.\\NOTIFY_DeviceName",  //符号链接
                                    GENERIC_READ|GENERIC_WRITE,
                                        0,
                                        NULL,
                                        OPEN_EXISTING,
                                        FILE_ATTRIBUTE_NORMAL,
                                        NULL);
        //判断设备是否打开
        if(hDevice==INVALID_HANDLE_VALUE)
        {
                printf("获取驱动句柄失败: %s with Win32 error code: %d\n","MyDriver", GetLastError() );
                getchar();
                return -1;
        }
        HANDLE isWait;
    isWait = CreateEvent(NULL,false,false,NULL);
        DeviceIoControl(hDevice,     //已经打开的设备
                                        Flag_CTL_CODE,////控制码
                                        &isWait,  //输入缓冲区
                                        4,           //输入缓冲区大小
                                        NULL//输出缓冲区
                                        0,           //输出缓冲区大小
                                        &dwReturned, //返回实际字节数
                                        NULL);
        while(1)
        {
                WaitForSingleObject(isWait,INFINITE);
                show(hDevice);
        }
        
        getchar();
        //关闭设备句柄
        CloseHandle(hDevice);
        return 0;
}

0x02 驱动代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
///////////////////////////////////////////////////////////////////////////////
///
/// Copyright (c) 2017 - <company name here>
///
/// Original filename: Notify.cpp
/// Project          : Notify
/// Date of creation : 2017-01-25
/// Author(s)        : <author name(s)>
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2017-01-25] Initial revision.
///
///////////////////////////////////////////////////////////////////////////////
// $Id$
#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#include <stdio.h>
#ifdef __cplusplus
}; // extern "C"
#endif
#include "Notify.h"
#include <wdm.h>
#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif
/**********************************************************************************************************************************/
PVOID isWait = NULL;
PVOID inputBuffer;
char outString[255] = "";
char* processString;
/**********************************************************************************************************************************/
charGetProcessName(ULONG dwPid)  
{  
    HANDLE ProcessHandle;  
    NTSTATUS status;  
    OBJECT_ATTRIBUTES  ObjectAttributes;  
    CLIENT_ID myCid;  
    PEPROCESS EProcess;  
  
    InitializeObjectAttributes(&ObjectAttributes,0,0,0,0);   
  
    myCid.UniqueProcess = (HANDLE)dwPid;  
    myCid.UniqueThread = 0;  
  
    //打开进程,获取句柄  
    status = ZwOpenProcess (&ProcessHandle,PROCESS_ALL_ACCESS,&ObjectAttributes,&myCid);  
    if (!NT_SUCCESS(status))  
    {  
        DbgPrint("打开进程出错/n");  
        return 0;  
    }  
      
    //得到EPROCESS,结构中取进程名  
    status = ObReferenceObjectByHandle(ProcessHandle,FILE_READ_DATA,0,KernelMode,(PVOID *)&EProcess, 0);  
    if (status == STATUS_SUCCESS)  
    {  
        char *ProcessName = (char*)EProcess + 0x174;  
        //char *PsName = PsGetProcessImageFileName(EProcess);  
  
        DbgPrint("ProcessName is %s/n",ProcessName);  
        //DbgPrint("PsName is %s/n",PsName);  
  
        ZwClose(ProcessHandle);
                return ProcessName;
    }  
    else  
    {  
        DbgPrint("Get ProcessName error");  
    } 
        return 0;
}  
/**********************************************************************************************************************************/
VOID ProcessMonitorCallback(
                                                IN HANDLE hParentId,
                                                IN HANDLE hProcessId, 
                                                IN BOOLEAN bCreate)
{
        if(bCreate)
        {
                processString = GetProcessName((ULONG)hProcessId);
                sprintf(outString,"ParentId :%d process name: %s process ID: %d has beed started\n",hParentId, processString, hProcessId);
        }
        else
        {
                processString = GetProcessName((ULONG)hProcessId);
                sprintf(outString,"ParentId :%d process name: %s process ID: %d has beed killed\n",hParentId, processString, hProcessId);
        }
        
        if(isWait != NULL)
        {
                KeSetEvent((PRKEVENT)isWait, 0, FALSE);
        }
}
/**********************************************************************************************************************************/
NTSTATUS NOTIFY_DispatchCreateClose(
    IN PDEVICE_OBJECT                DeviceObject,
    IN PIRP                                        Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
NTSTATUS NOTIFY_DispatchDeviceControl(
    IN PDEVICE_OBJECT                DeviceObject,
    IN PIRP                                        Irp
    )
{
        DbgPrint("NOTIFY_DispatchDeviceControl");
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_NOTIFY_OPERATION:
                {
                        DbgPrint("IOCTL_NOTIFY_OPERATION");
                        RtlCopyMemory(Irp->UserBuffer, outString, sizeof(outString));
                        
                        DbgPrint("outString = %s",outString);
                        break;
                }
        case IOCTL_NOTIFY_FLAG:
                {
                        DbgPrint("IOCTL_NOTIFY_FLAG");
                        
                        inputBuffer = Irp->AssociatedIrp.SystemBuffer;
                        DbgPrint("inputBuffer:%08x\n", (HANDLE)inputBuffer);
                        status = ObReferenceObjectByHandle(*(HANDLE *)inputBuffer,
                                        GENERIC_ALL,
                                        NULL,
                                        KernelMode,
                                        &isWait,
                                        NULL);
                        if(isWait!=NULL)
                        {
                                KeSetEvent((PRKEVENT)isWait, 0, FALSE);
                        }
                        
                        break;
                }
    default:
        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Information = 0;
        break;
    }
    status = Irp->IoStatus.Status;
        Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
VOID NOTIFY_DriverUnload(
    IN PDRIVER_OBJECT                DriverObject
    )
{
        PsSetCreateProcessNotifyRoutine(ProcessMonitorCallback,TRUE);
        if(isWait!=NULL)
        {
                ZwClose(isWait);
        }
    PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
    IoDeleteSymbolicLink(&usSymlinkName);
    // Delete all the device objects
    while(pdoNextDeviceObj)
    {
        PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
        pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
        IoDeleteDevice(pdoThisDeviceObj);
    }
}
#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
    IN OUT PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING      RegistryPath
    )
{
    PDEVICE_OBJECT pdoDeviceObj = 0;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pdoGlobalDrvObj = DriverObject;
        PsSetCreateProcessNotifyRoutine(ProcessMonitorCallback,FALSE);
    // Create the device object.
    if(!NT_SUCCESS(status = IoCreateDevice(
        DriverObject,
        0,
        &usDeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pdoDeviceObj
        )))
    {
        // Bail out (implicitly forces the driver to unload).
        return status;
    };
    // Now create the respective symbolic link object
    if(!NT_SUCCESS(status = IoCreateSymbolicLink(
        &usSymlinkName,
        &usDeviceName
        )))
    {
        IoDeleteDevice(pdoDeviceObj);
        return status;
    }
    // NOTE: You need not provide your own implementation for any major function that
    //       you do not want to handle. I have seen code using DDKWizard that left the
    //       *empty* dispatch routines intact. This is not necessary at all!
    DriverObject->MajorFunction[IRP_MJ_CREATE] =
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = NOTIFY_DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NOTIFY_DispatchDeviceControl;
    DriverObject->DriverUnload = NOTIFY_DriverUnload;
    return STATUS_SUCCESS;
}
#ifdef __cplusplus
}; // extern "C"
#endif

效果图:
1.jpg