root/honeyclient/branches/rel/1.0/Capture2/capture-client-xeno-mod/FileMonitor.cpp

Revision 881, 13.8 kB (checked in by xkovah, 1 year ago)

adding all the changes for the new DB schema (revert to the prev if there are problems)

Line 
1 #include "FileMonitor.h"
2
3 FileMonitor::FileMonitor(void)
4 {
5     HRESULT hResult;
6     monitorRunning = false;
7     driverInstalled = false;
8     int turn = 0;
9     communicationPort = INVALID_HANDLE_VALUE;
10     monitorModifiedFiles = false;
11
12     hMonitorStoppedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
13    
14     FilterUnload(L"CaptureFileMonitor");
15     hResult = FilterLoad(L"CaptureFileMonitor");
16     // Keep trying to load the filter - On some VM's this can take a few seconds
17     while((turn < 5) && IS_ERROR( hResult ))
18     {
19         turn++;
20         printf("FileMonitor: WARNING - Filter driver not loaded (error: %x) waiting 3 seconds to try again ... (try %i of 5)\n", hResult, turn);
21         Sleep(3000);
22         hResult = FilterLoad(L"CaptureFileMonitor");
23     }
24    
25     if (!IS_ERROR( hResult )) {
26        
27         hResult = FilterConnectCommunicationPort( CAPTURE_FILEMON_PORT_NAME,
28                                                 0,
29                                                 NULL,
30                                                 0,
31                                                 NULL,
32                                                 &communicationPort );
33         if (IS_ERROR( hResult )) {
34
35             printf( "FileMonitor: ERROR - Could not connect to filter: 0x%08x\n", hResult );
36         } else {
37             printf("Loaded filter driver: CaptureFileMonitor\n");
38             driverInstalled = true;
39             //this.setMonitorModifiedFiles(false);
40         }
41        
42         wchar_t exListDriverPath[1024];
43         GetFullPathName(L"FileMonitor.exl", 1024, exListDriverPath, NULL);
44         Monitor::loadExclusionList(exListDriverPath);
45
46         /* Create a log directory exclusion which allows all writes in
47            Captures log directory */
48         wchar_t logDirectory[1024];
49         GetFullPathName(L"logs", 1024, logDirectory, NULL);
50         wstring captureLogDirectory = logDirectory;
51         Monitor::prepareStringForExclusion(&captureLogDirectory);
52         captureLogDirectory += L"\\\\.*";
53
54         wstring captureExecutablePath = ProcessManager::getInstance()->getProcessPath(GetCurrentProcessId());
55         Monitor::prepareStringForExclusion(&captureExecutablePath);
56        
57         /* Exclude file events in the log directory */
58         /* NOTE we exclude all processes because files are copied/delete/openend
59            etc in the context of the calling process not Capture */
60         Monitor::addExclusion(L"+", L"write", L".*", captureLogDirectory, true);
61         Monitor::addExclusion(L"+", L"create", L".*", captureLogDirectory, true);
62         Monitor::addExclusion(L"+", L"delete", L".*", captureLogDirectory, true);
63         Monitor::addExclusion(L"+", L"open", L".*", captureLogDirectory, true);
64         Monitor::addExclusion(L"+", L"read", L".*", captureLogDirectory, true);
65
66         /* Exclude Captures temp directory */
67         wchar_t tempDirectory[1024];
68         GetFullPathName(L"temp", 1024, tempDirectory, NULL);
69         wstring captureTempDirectory = tempDirectory;
70         Monitor::prepareStringForExclusion(&captureTempDirectory);
71         captureTempDirectory += L"\\\\.*";
72
73         //wstring captureExecutablePath = ProcessManager::getInstance()->getProcessPath(GetCurrentProcessId());
74         //Monitor::prepareStringForExclusion(&captureExecutablePath);
75         
76         /* Exclude file events in the log directory */
77         /* NOTE we exclude all processes because files are copied/delete/openend
78            etc in the context of the calling process not Capture */
79         Monitor::addExclusion(L"+", L"write", L".*", captureTempDirectory, true);
80         Monitor::addExclusion(L"+", L"create", L".*", captureTempDirectory, true);
81         Monitor::addExclusion(L"+", L"delete", L".*", captureTempDirectory, true);
82         Monitor::addExclusion(L"+", L"open", L".*", captureTempDirectory, true);
83         Monitor::addExclusion(L"+", L"read", L".*", captureTempDirectory, true);
84        
85         if(OptionsManager::getInstance()->getOption(L"log-system-events-file") != L"")
86         {
87             wstring loggerFile = Logger::getInstance()->getLogFullPath();
88             Monitor::prepareStringForExclusion(&loggerFile);
89             Monitor::addExclusion(L"+", L"create", captureExecutablePath, loggerFile, true);
90             Monitor::addExclusion(L"+", L"write", captureExecutablePath, loggerFile, true);
91         }
92         onFileExclusionReceivedConnection = EventController::getInstance()->connect_onServerEvent(L"file-exclusion", boost::bind(&FileMonitor::onFileExclusionReceived, this, _1));
93
94         initialiseDosNameMap();
95     }
96 }
97
98 void
99 FileMonitor::setMonitorModifiedFiles(bool monitor)
100 {
101     FILEMONITOR_MESSAGE command;
102     FILEMONITOR_SETUP setupFileMonitor;
103     HRESULT hResult;
104     DWORD bytesReturned;
105
106     monitorModifiedFiles = monitor;
107
108     if(monitor == true)
109     {
110         setupFileMonitor.bCollectDeletedFiles = TRUE;
111     } else {
112         setupFileMonitor.bCollectDeletedFiles = FALSE;
113     }
114     GetFullPathName(L"logs\\deleted_files", 1024, setupFileMonitor.wszLogDirectory, NULL);
115     CreateDirectory(setupFileMonitor.wszLogDirectory,NULL);
116     setupFileMonitor.nLogDirectorySize = (UINT)wcslen(setupFileMonitor.wszLogDirectory)*sizeof(wchar_t);
117    
118     DebugPrint(L"Deleted file directory: %i -> %ls\n", setupFileMonitor.nLogDirectorySize, setupFileMonitor.wszLogDirectory);
119
120     command.Command = SetupMonitor;
121
122     hResult = FilterSendMessage( communicationPort,
123                              &command,
124                              sizeof( FILEMONITOR_COMMAND ),
125                              &setupFileMonitor,
126                              sizeof(FILEMONITOR_SETUP),
127                              &bytesReturned );
128 }
129
130 FileMonitor::~FileMonitor(void)
131 {
132     stop();
133     if(isDriverInstalled())
134     {
135         driverInstalled = false;
136         CloseHandle(communicationPort);
137         FilterUnload(L"CaptureFileMonitor");
138     }
139     CloseHandle(hMonitorStoppedEvent);
140 }
141
142 void 
143 FileMonitor::initialiseDosNameMap()
144 {
145     UCHAR buffer[1024];
146     PFILTER_VOLUME_BASIC_INFORMATION volumeBuffer = (PFILTER_VOLUME_BASIC_INFORMATION)buffer;
147     HANDLE volumeIterator = INVALID_HANDLE_VALUE;
148     ULONG volumeBytesReturned;
149     WCHAR driveLetter[15];
150
151     HRESULT hResult = FilterVolumeFindFirst( FilterVolumeBasicInformation,
152                                          volumeBuffer,
153                                          sizeof(buffer)-sizeof(WCHAR),   //save space to null terminate name
154                                          &volumeBytesReturned,
155                                          &volumeIterator );
156     if (volumeIterator != INVALID_HANDLE_VALUE) {
157         do {
158             assert((FIELD_OFFSET(FILTER_VOLUME_BASIC_INFORMATION,FilterVolumeName) + volumeBuffer->FilterVolumeNameLength) <= (sizeof(buffer)-sizeof(WCHAR)));
159             __analysis_assume((FIELD_OFFSET(FILTER_VOLUME_BASIC_INFORMATION,FilterVolumeName) + volumeBuffer->FilterVolumeNameLength) <= (sizeof(buffer)-sizeof(WCHAR)));
160             volumeBuffer->FilterVolumeName[volumeBuffer->FilterVolumeNameLength/sizeof( WCHAR )] = UNICODE_NULL;
161                
162             if(SUCCEEDED( FilterGetDosName(volumeBuffer->FilterVolumeName,
163                 driveLetter,
164                 sizeof(driveLetter)/sizeof(WCHAR) )
165                 ))
166             {
167                 wstring dLetter = driveLetter;
168                 dosNameMap.insert(DosPair(volumeBuffer->FilterVolumeName, dLetter));
169             }
170         } while (SUCCEEDED( hResult = FilterVolumeFindNext( volumeIterator,
171                                                             FilterVolumeBasicInformation,
172                                                             volumeBuffer,
173                                                             sizeof(buffer)-sizeof(WCHAR),    //save space to null terminate name
174                                                             &volumeBytesReturned ) ));
175     }
176
177     if (INVALID_HANDLE_VALUE != volumeIterator) {
178         FilterVolumeFindClose( volumeIterator );
179     }
180 }
181
182 boost::signals::connection
183 FileMonitor::connect_onFileEvent(const signal_fileEvent::slot_type& s)
184 {
185     return signal_onFileEvent.connect(s);
186 }
187
188 bool
189 FileMonitor::isDirectory(wstring filePath)
190 {
191     DWORD code = GetFileAttributes(filePath.c_str());
192     if (code==INVALID_FILE_ATTRIBUTES)
193         return false;
194     if ((code&FILE_ATTRIBUTE_DIRECTORY)==FILE_ATTRIBUTE_DIRECTORY)
195         return true;
196     return false;
197 }
198
199 void
200 FileMonitor::onFileExclusionReceived(Element* pElement)
201 {
202     wstring excluded = L"";
203     wstring fileEventType = L"";
204     wstring processPath = L"";
205     wstring filePath = L"";
206
207     vector<Attribute>::iterator it;
208     for(it = pElement->attributes.begin(); it != pElement->attributes.end(); it++)
209     {
210         if(it->name == L"action") {
211             fileEventType = it->value;
212         } else if(it->name == L"object") {
213             filePath = it->value;
214         } else if(it->name == L"subject") {
215             processPath = it->value;
216         } else if(it->name == L"excluded") {
217             excluded = it->value;
218         }
219     }
220     Monitor::addExclusion(excluded, fileEventType, processPath, filePath);
221 }
222
223 void
224 FileMonitor::start()
225 {
226     if(!isMonitorRunning() && isDriverInstalled())
227     {
228         fileEvents = (BYTE*)malloc(FILE_EVENTS_BUFFER_SIZE);
229         fileMonitorThread = new Thread(this);
230         fileMonitorThread->start("FileMonitor");
231     }
232 }
233
234 void
235 FileMonitor::stop()
236 {   
237     if(isMonitorRunning() && isDriverInstalled())
238     {
239         monitorRunning = false;
240         WaitForSingleObject(hMonitorStoppedEvent, 1000);
241         fileMonitorThread->stop();
242         delete fileMonitorThread;
243         free(fileEvents);
244     }   
245 }
246
247 bool
248 FileMonitor::getFileEventName(PFILE_EVENT pFileEvent, wstring *fileEventName)
249 {
250     bool found = true;
251     *fileEventName = L"UNKNOWN";
252     if(pFileEvent->majorFileEventType == IRP_MJ_CREATE) {
253         /* Defined at http://msdn2.microsoft.com/en-us/library/ms804358.aspx */
254         //if(!FlagOn(pFileEvent->flags, FO_STREAM_FILE) && pFileEvent->flags > 0)
255         //{
256             if( pFileEvent->information == FILE_CREATED ||
257                 pFileEvent->information == FILE_OVERWRITTEN ||
258                 pFileEvent->information == FILE_SUPERSEDED ) {
259                 *fileEventName = L"Create";
260             } else if(pFileEvent->information == FILE_OPENED) {
261                 *fileEventName = L"Open";
262             } else {
263                 found = false;
264             }
265         //} else {
266         //  found = false;
267         //}
268             /* Ignore stream accesses */
269             wstring eventPath = pFileEvent->filePath;
270             if(eventPath.find(L":", 0) != wstring::npos)
271             {
272                 found = false;
273             }
274     } else if(pFileEvent->majorFileEventType == IRP_MJ_READ) {
275         *fileEventName = L"Read";
276     } else if(pFileEvent->majorFileEventType == IRP_MJ_WRITE) {
277         *fileEventName = L"Write";
278     } else if(pFileEvent->majorFileEventType == IRP_MJ_DELETE) {
279         *fileEventName = L"Delete";
280     //} else if(pFileEvent->majorFileEventType == IRP_MJ_CLOSE) {
281     //  *fileEventName = L"Close";
282     } else {
283         found = false;
284     }
285     return found;
286 }
287
288 wstring
289 FileMonitor::convertFileObjectNameToDosName(wstring fileObjectName)
290 {
291     stdext::hash_map<wstring, wstring>::iterator it;
292     for(it = dosNameMap.begin(); it != dosNameMap.end(); it++)
293     {
294         size_t position = fileObjectName.rfind(it->first,0);
295         if(position != wstring::npos)
296         {
297             fileObjectName.replace(position, it->first.length(), it->second, 0, it->second.length());
298             break;
299         }
300     }
301     //transform(fileObjectName.begin(), fileObjectName.end(), fileObjectName.begin(), tolower);
302     return fileObjectName;
303 }
304
305 void
306 FileMonitor::createFilePathAndCopy(wstring* logPath, wstring* filePath)
307 {
308     printf("Copying file: %ls\n", filePath->c_str());
309     wstring drive = filePath->substr(0,filePath->find_first_of(L":"));
310     wstring fileName = filePath->substr(filePath->find_last_of(L"\\")+1);
311     wstring intermediateDirectory = *logPath;
312     intermediateDirectory += drive;
313     intermediateDirectory += L"\\";
314     intermediateDirectory += filePath->substr(filePath->find_first_of(L"\\")+1,filePath->find_last_of(L"\\")-filePath->find_first_of(L"\\")-1);
315     SHCreateDirectoryEx(NULL,
316                             intermediateDirectory.c_str(),
317                             NULL
318                             );
319     wstring filePathAndName = intermediateDirectory;
320     filePathAndName += L"\\";
321     filePathAndName += fileName;
322     if(!CopyFile(
323         filePath->c_str(),
324         filePathAndName.c_str(),
325         FALSE
326         ))
327     {
328         printf("\t... failed: 0x%08x\n", GetLastError());
329     } else {
330         printf("\t... done\n");
331     }
332 }
333
334 void
335 FileMonitor::copyCreatedFiles()
336 {
337     stdext::hash_set<wstring>::iterator it;
338     wchar_t currentDirectory[1024];
339     GetFullPathName(L"logs\\modified_files\\", 1024, currentDirectory, NULL);
340     wstring logPath = currentDirectory;
341     DebugPrint(L"Modified file directory: %ls\n", logPath.c_str());
342     for(it = modifiedFiles.begin(); it != modifiedFiles.end(); it++)
343     {
344         wstring filePath = *it;
345         createFilePathAndCopy(&logPath, &filePath );
346     }
347     modifiedFiles.clear();
348 }
349
350 void
351 FileMonitor::run()
352 {
353     HRESULT hResult;
354     DWORD bytesReturned = 0;
355     monitorRunning = true;
356     while(isMonitorRunning())
357     {
358         FILEMONITOR_MESSAGE command;
359         command.Command = GetFileEvents;
360
361         ZeroMemory(fileEvents, FILE_EVENTS_BUFFER_SIZE);
362
363         hResult = FilterSendMessage( communicationPort,
364                                      &command,
365                                      sizeof( FILEMONITOR_COMMAND ),
366                                      fileEvents,
367                                      FILE_EVENTS_BUFFER_SIZE,
368                                      &bytesReturned );
369         if(bytesReturned >= sizeof(FILE_EVENT))
370         {
371             UINT offset = 0;
372             do {
373                 PFILE_EVENT e = (PFILE_EVENT)(fileEvents + offset);
374
375                 wstring fileEventName;
376                 wstring fileEventPath;
377                 wstring processModuleName;
378                 wstring processPath;
379                 vector<wstring> extraData;
380                 wchar_t processIdString[11];
381                 swprintf(processIdString, 11, L"%ld", e->processId);
382                 extraData.push_back(processIdString);
383
384                 if(getFileEventName(e, &fileEventName))
385                 {
386                     processPath = ProcessManager::getInstance()->getProcessPath(e->processId);
387                     processModuleName = ProcessManager::getInstance()->getProcessModuleName(e->processId);
388                    
389                     fileEventPath = e->filePath;
390                     fileEventPath = convertFileObjectNameToDosName(fileEventPath);
391
392                     if((fileEventPath != L"UNKNOWN"))
393                     {
394                         if(!Monitor::isEventAllowed(fileEventName, processPath, fileEventPath))
395                         {
396                             if(monitorModifiedFiles)
397                             {
398        
399                                 if(!isDirectory(fileEventPath))
400                                 {
401                                     if(e->majorFileEventType == IRP_MJ_CREATE ||
402                                         e->majorFileEventType == IRP_MJ_WRITE )
403                                     {   
404                                         modifiedFiles.insert(fileEventPath);
405                                     } else if(e->majorFileEventType == IRP_MJ_DELETE)
406                                     {
407                                         modifiedFiles.erase(fileEventPath);
408                                     }   
409                                 }
410                             }
411
412                             wchar_t szTempTime[256];
413                             convertTimefieldsToString(e->time, szTempTime, 256);
414                             wstring time = szTempTime;
415
416                             signal_onFileEvent(fileEventName, time, processPath, fileEventPath, extraData);
417                         }
418                     }
419                 }
420                
421                 offset += sizeof(FILE_EVENT) + e->filePathLength;
422             } while(offset < bytesReturned);   
423         }
424        
425         if(bytesReturned == FILE_EVENTS_BUFFER_SIZE)
426         {
427             Sleep(FILE_EVENT_BUFFER_FULL_WAIT_TIME);
428         } else {
429             Sleep(FILE_EVENT_WAIT_TIME);
430         }
431     }
432     SetEvent(hMonitorStoppedEvent);
433 }
Note: See TracBrowser for help on using the browser.