root/capture-mod/trunk/Analyzer.cpp

Revision 1776, 12.1 kB (checked in by xkovah, 3 months ago)

some example scripts, and I'm just cleaning some stuff up

Line 
1 #include "Analyzer.h"
2
3 Analyzer::Analyzer(Visitor* v, Server* s, RegistryMonitor * r, FileMonitor * f, ProcessMonitor * p)
4 {
5     processMonitor = p;
6     registryMonitor = r;
7     fileMonitor = f;
8     collectModifiedFiles = false;
9     captureNetworkPackets = false;
10     networkPacketDumper = NULL;
11
12     onOptionChangedConnection = OptionsManager::getInstance()->connect_onOptionChanged(boost::bind(&Analyzer::onOptionChanged, this, _1));
13
14     visitor = v;
15     visitor->onVisitEvent(boost::bind(&Analyzer::onVisitEvent, this, _1, _2, _3, _4));
16    
17     server = s;
18
19     processMonitor->start();
20     registryMonitor->start();
21     fileMonitor->start();
22 }
23
24 Analyzer::~Analyzer(void)
25 {
26     DebugPrint(L"Analyzer: Deconstructor");
27     /* Do not change the order of these */
28     /* The registry monitor must be deleted first ... as when the other monitors
29        kernel drivers are unloaded they cause a lot of registry events which, but
30        they are unloaded before these registry events are finished inside the
31        registry kernel driver. So ... when it comes to unloading the registry
32        kernel driver it will crash ... I guess. I'm not too sure on this as the
33        bug check has nothing to do with Capture instead it has something to do
34        with the PNP manager and deleting the unreferenced device */
35     delete registryMonitor;
36     delete processMonitor;
37     delete fileMonitor;
38     if(captureNetworkPackets)
39     {
40         delete networkPacketDumper;
41     }
42 }
43
44 void
45 Analyzer::onOptionChanged(wstring option)
46 {
47     wstring value = OptionsManager::getInstance()->getOption(option);
48     if(option == L"capture-network-packets") {
49         if(value == L"true")
50         {
51             if(captureNetworkPackets == false)
52             {
53                 printf("Creating network dumper\n");
54                 networkPacketDumper = new NetworkPacketDumper();
55                 captureNetworkPackets = true;
56             }
57         } else {
58             if(captureNetworkPackets == true)
59             {
60                 captureNetworkPackets = false;
61                 //if(networkPacketDumper != NULL)
62                 delete networkPacketDumper;         
63             }
64         }
65     } else if(option == L"collect-modified-files") {
66         if(value == L"true")
67         {
68             collectModifiedFiles = true;
69         } else {
70             collectModifiedFiles = false;
71         }
72         fileMonitor->setMonitorModifiedFiles(collectModifiedFiles);
73     } else if(option == L"send-exclusion-lists") {
74         if(value == L"true")
75         {
76             processMonitor->clearExclusionList();
77             registryMonitor->clearExclusionList();
78             fileMonitor->clearExclusionList();
79         }
80     }
81 }
82
83 void
84 Analyzer::start()
85 {
86     malicious = false;
87     DebugPrint(L"Analyzer: Start");
88     if(captureNetworkPackets)
89     {
90         networkPacketDumper->start();
91     }
92     onProcessEventConnection = processMonitor->connect_onProcessEvent(boost::bind(&Analyzer::onProcessEvent, this, _1, _2, _3, _4, _5, _6));
93     onRegistryEventConnection = registryMonitor->connect_onRegistryEvent(boost::bind(&Analyzer::onRegistryEvent, this, _1, _2, _3, _4, _5));
94     onFileEventConnection = fileMonitor->connect_onFileEvent(boost::bind(&Analyzer::onFileEvent, this, _1, _2, _3, _4, _5));
95     DebugPrint(L"Analyzer: Registered with callbacks");
96     if(collectModifiedFiles)
97     {
98         fileMonitor->setMonitorModifiedFiles(true);
99     }
100 }
101
102 void
103 Analyzer::stop()
104 {
105     DebugPrint(L"Analyzer: Stop");
106     onProcessEventConnection.disconnect();
107     onRegistryEventConnection.disconnect();
108     onFileEventConnection.disconnect();
109
110     if(captureNetworkPackets)
111     {
112         networkPacketDumper->stop();
113     }
114
115     if(collectModifiedFiles || captureNetworkPackets)
116     {
117         SYSTEMTIME st;
118         GetLocalTime(&st);
119         if(collectModifiedFiles)
120         {
121             fileMonitor->setMonitorModifiedFiles(false);
122             fileMonitor->copyCreatedFiles();
123         }
124
125         wchar_t* szLogFileName = new wchar_t[1024];
126
127         wstring log = L"capture_";
128         log += boost::lexical_cast<wstring>(st.wDay);
129         log += boost::lexical_cast<wstring>(st.wMonth);
130         log += boost::lexical_cast<wstring>(st.wYear);
131         log += L"_";
132         log += boost::lexical_cast<wstring>(st.wHour);
133         log += boost::lexical_cast<wstring>(st.wMinute);
134         log += L".zip";
135         GetFullPathName(log.c_str(), 1024, szLogFileName, NULL);
136
137         bool compressed = compressLogDirectory(szLogFileName);
138
139         if(malicious)
140         {
141             if(server->isConnected() && compressed)
142             {               
143                 FileUploader* uploader = new FileUploader(server);
144                 uploader->sendFile(szLogFileName);
145                 delete uploader;
146                 DeleteFile(szLogFileName);
147             }
148         }
149
150         delete [] szLogFileName;
151     }
152 }
153
154 wstring
155 Analyzer::errorCodeToString(DWORD errorCode)
156 {
157     wchar_t szTemp[16];
158     swprintf_s(szTemp, 16, L"%08x", errorCode);
159     wstring error = szTemp;
160     return error;
161 }
162
163
164 bool
165 Analyzer::compressLogDirectory(wstring logFileName)
166 {
167     BOOL created = FALSE;
168     STARTUPINFO siStartupInfo;
169     wchar_t szTempPath[1024];
170     PROCESS_INFORMATION piProcessInfo;
171
172     DeleteFile(logFileName.c_str());
173
174     memset(&siStartupInfo, 0, sizeof(siStartupInfo));
175     memset(&piProcessInfo, 0, sizeof(piProcessInfo));
176     ZeroMemory(&szTempPath, sizeof(szTempPath));
177
178     siStartupInfo.cb = sizeof(siStartupInfo);
179
180     _tcscat_s(szTempPath, 1024, L"\"");
181     _tcscat_s(szTempPath, 1024, L"7za.exe");
182     _tcscat_s(szTempPath, 1024, L"\" a -tzip -y \"");
183     _tcscat_s(szTempPath, 1024, logFileName.c_str());
184     _tcscat_s(szTempPath, 1024, L"\" logs");
185     LPTSTR szCmdline=_tcsdup(szTempPath);
186     created = CreateProcess(NULL,szCmdline, 0, 0, FALSE,
187         CREATE_DEFAULT_ERROR_MODE, 0, 0, &siStartupInfo,
188         &piProcessInfo);
189
190     DWORD err = WaitForSingleObject( piProcessInfo.hProcess, INFINITE );
191
192     //DebugPrint(L"Analyzer: compressLogDirectory - WaitForSingleObject = 0x%08x, CreateProcess=%i", err, created);
193     if(!created)
194     {
195         printf("Analyzer: Cannot open 7za.exe process - 0x%08x\n", GetLastError());
196         return false;
197     } else {
198         /* Delete the log directory */
199         wchar_t* szFullPath = new wchar_t[1024];
200         GetFullPathName(L"logs", 1024, szFullPath, NULL);
201         SHFILEOPSTRUCT deleteLogDirectory;
202         deleteLogDirectory.wFunc = FO_DELETE;
203         deleteLogDirectory.pFrom = szFullPath;
204         deleteLogDirectory.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
205         SHFileOperation(&deleteLogDirectory);
206         delete [] szFullPath;
207         return true;
208     }
209 }
210
211 void
212 Analyzer::sendVisitEvent(wstring* type, wstring* time,
213                          wstring* url, wstring* classification, wstring* application,
214                          wstring* majorErrorCode, wstring* minorErrorCode)
215 {
216     Attribute att;
217     queue<Attribute> vAttributes;
218     att.name = L"type";
219     att.value = *type;
220     vAttributes.push(att);
221     att.name = L"time";
222     att.value = *time;
223     vAttributes.push(att);
224     att.name = L"url";
225     att.value = CaptureGlobal::urlEncode(*url);
226     vAttributes.push(att);
227     att.name = L"application";
228     att.value = *application;
229     vAttributes.push(att);
230     att.name = L"malicious";
231     att.value = *classification;
232     vAttributes.push(att);
233     att.name = L"major-error-code";
234     att.value = *majorErrorCode;
235     vAttributes.push(att);
236     att.name = L"minor-error-code";
237     att.value = *minorErrorCode;
238     vAttributes.push(att);
239
240     server->sendXML(L"visit-event", &vAttributes);
241 }
242
243 void
244 Analyzer::onVisitEvent(DWORD majorErrorCode, DWORD minorErrorCode, std::wstring url, std::wstring applicationPath)
245 {
246     bool send = false;
247     wstring type = L"";
248     wstring classification = L"";
249     wstring majErrorCode = L"";
250     wstring minErrorCode = L"";
251
252     if(majorErrorCode == CAPTURE_VISITATION_START) {
253         type = L"start";
254         send = true;
255     } else if(majorErrorCode == CAPTURE_VISITATION_FINISH) {
256         this->stop();
257     } else if(majorErrorCode == CAPTURE_VISITATION_NETWORK_ERROR ||
258         majorErrorCode == CAPTURE_VISITATION_TIMEOUT_ERROR)
259     {
260         type = L"error";
261         classification = boost::lexical_cast<wstring>(malicious);
262         majErrorCode = boost::lexical_cast<wstring>(majorErrorCode);
263         minErrorCode = boost::lexical_cast<wstring>(minorErrorCode);
264         send = true;
265     } else if(majorErrorCode == CAPTURE_VISITATION_PRESTART) {
266         this->start();
267     } else if(majorErrorCode == CAPTURE_VISITATION_POSTFINISH) {   
268         type = L"finish";
269         classification = boost::lexical_cast<wstring>(malicious);
270         send = true;
271     } else if(majorErrorCode == CAPTURE_VISITATION_PROCESS_ERROR) {
272         malicious = true;
273         type = L"error";
274         classification = boost::lexical_cast<wstring>(malicious);
275         majErrorCode = boost::lexical_cast<wstring>(majorErrorCode);
276         minErrorCode = boost::lexical_cast<wstring>(minorErrorCode);
277         send = true;
278     }
279
280     if(send)
281     {
282         SYSTEMTIME st;
283
284         GetLocalTime(&st);             // gets current time
285         wstring time = L"";
286         time += boost::lexical_cast<wstring>(st.wDay);
287         time += L"/";
288         time += boost::lexical_cast<wstring>(st.wMonth);
289         time += L"/";
290         time += boost::lexical_cast<wstring>(st.wYear);
291         time += L" ";
292         time += boost::lexical_cast<wstring>(st.wHour);
293         time += L":";
294         time += boost::lexical_cast<wstring>(st.wMinute);
295         time += L".";
296         time += boost::lexical_cast<wstring>(st.wMilliseconds);
297         printf("%ls: %ls %ls %ls %ls\n", type.c_str(), url.c_str(), applicationPath.c_str(), majErrorCode.c_str(), minErrorCode.c_str());
298         sendVisitEvent(&type, &time, &url, &classification, &applicationPath, &majErrorCode, &minErrorCode);
299     }
300 }
301
302 void
303 Analyzer::sendSystemEvent(wstring* type, wstring* time,
304                     wstring* process, wstring* action,
305                     wstring* object, vector<wstring>* extra)
306 {
307
308     Attribute att;
309     queue<Attribute> vAttributes;
310     att.name = L"time";
311     att.value = *time;
312     vAttributes.push(att);
313     att.name = L"type";
314     att.value = *type;
315     vAttributes.push(att);
316     att.name = L"process";
317     att.value = *process;
318     vAttributes.push(att);
319     att.name = L"action";
320     att.value = *action;
321     vAttributes.push(att);
322     att.name = L"object";
323     att.value = *object;
324     vAttributes.push(att);
325     if(type->compare(L"registry") == 0){
326         att.name = L"reg_type";
327         att.value = extra->at(0);
328         vAttributes.push(att);
329         att.name = L"reg_value";
330         att.value = extra->at(1);
331         vAttributes.push(att);
332     }
333     else{
334         att.name = L"extra";
335         att.value = extra->front();
336         vAttributes.push(att);
337     }
338
339     if(OptionsManager::getInstance()->getOption(L"log-system-events-file") == L"")
340     {
341         // Output the event to stdout
342         if(type->compare(L"process") == 0){
343             printf("%ls %ls PID:%ls %ls PID:%ls %ls", type->c_str(), action->c_str(),
344                 extra->at(0).c_str(), process->c_str(), extra->at(1).c_str(), object->c_str());
345         }
346         else if (type->compare(L"registry") == 0){
347             printf("%ls %ls PID:%ls %ls %ls", type->c_str(), action->c_str(), extra->at(0).c_str(), process->c_str(), object->c_str());
348             vector<wstring>::const_iterator itr = extra->begin();
349             itr++;
350             for(itr; itr != extra->end(); itr++ ) {
351                 printf(" %ls", itr->c_str());
352             }
353         }
354         else if (type->compare(L"file") == 0) {
355             printf("%ls %ls PID:%ls %ls %ls", type->c_str(), action->c_str(), extra->at(0).c_str(), process->c_str(), object->c_str());
356         }
357
358         printf("\n");
359     } else {
360         // Send the event to the logger
361         Logger::getInstance()->writeSystemEventToLog(type, time, process, action, object, extra);
362     }
363     server->sendXML(L"system-event", &vAttributes);
364 }
365
366 void
367 Analyzer::onProcessEvent(BOOLEAN created, wstring time,
368                          DWORD parentProcessId, wstring parentProcess,
369                          DWORD processId, wstring process)
370 {
371     malicious = true;
372     wstring processEvent = L"process";
373     wstring processType = L"";
374     if(created == TRUE)
375     {
376         processType = L"created";
377     } else {
378         processType = L"terminated";
379     }
380     //TODO: cleanup a little
381     vector<wstring> extra;
382     wchar_t parentProcessIdString[11];
383     swprintf(parentProcessIdString, 11, L"%ld", parentProcessId);
384     extra.push_back(parentProcessIdString);
385     wchar_t processIdString[11];
386     swprintf(processIdString, 11, L"%ld", processId);
387     extra.push_back(processIdString);
388
389     sendSystemEvent(&processEvent, &time,
390                     &parentProcess, &processType,
391                     &process, &extra);
392 }
393
394 void 
395 Analyzer::onRegistryEvent(wstring registryEventType, wstring time,
396                           wstring processPath, wstring registryEventPath, vector<wstring> extra)
397 {
398     malicious = true;
399     wstring registryEvent = L"registry";
400     sendSystemEvent(&registryEvent, &time,
401                     &processPath, &registryEventType,
402                     &registryEventPath, &extra);
403 }
404
405 void
406 Analyzer::onFileEvent(wstring fileEventType, wstring time,
407                          wstring processPath, wstring fileEventPath, vector<wstring> extra)
408 {
409     malicious = true;
410     wstring fileEvent = L"file";
411     sendSystemEvent(&fileEvent, &time,
412                     &processPath, &fileEventType,
413                     &fileEventPath, &extra);
414 }
Note: See TracBrowser for help on using the browser.