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

Revision 881, 12.3 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 "Analyzer.h"
2
3 Analyzer::Analyzer(Visitor* v, Server* s)
4 {
5     processMonitor = new ProcessMonitor();
6     registryMonitor = new RegistryMonitor();
7     fileMonitor = new FileMonitor();
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     /* FIXME: for now HC doesn't care about attributes...fix these if and when we use the C code
308         for sending stuff to the server.
309     */
310     Attribute att;
311     queue<Attribute> vAttributes;
312     att.name = L"time";
313     att.value = *time;
314     vAttributes.push(att);
315     att.name = L"type";
316     att.value = *type;
317     vAttributes.push(att);
318     att.name = L"process";
319     att.value = *process;
320     vAttributes.push(att);
321     att.name = L"action";
322     att.value = *action;
323     vAttributes.push(att);
324     att.name = L"object";
325     att.value = *object;
326     vAttributes.push(att);
327     if(type->compare(L"registry") == 0){
328         att.name = L"reg_type";
329         att.value = extra->at(0);
330         vAttributes.push(att);
331         att.name = L"reg_value";
332         att.value = extra->at(1);
333         vAttributes.push(att);
334     }
335     else{
336         att.name = L"extra";
337         att.value = extra->front();
338         vAttributes.push(att);
339     }
340
341     if(OptionsManager::getInstance()->getOption(L"log-system-events-file") == L"")
342     {
343         // Output the event to stdout
344         if(type->compare(L"process") == 0){
345             printf("%ls %ls PID:%ls %ls PID:%ls %ls", type->c_str(), action->c_str(),
346                 extra->at(0).c_str(), process->c_str(), extra->at(1).c_str(), object->c_str());
347         }
348         else if (type->compare(L"registry") == 0){
349             printf("%ls %ls PID:%ls %ls %ls", type->c_str(), action->c_str(), extra->at(0).c_str(), process->c_str(), object->c_str());
350             vector<wstring>::const_iterator itr = extra->begin();
351             itr++;
352             for(itr; itr != extra->end(); itr++ ) {
353                 printf(" %ls", itr->c_str());
354             }
355         }
356         else if (type->compare(L"file") == 0) {
357             printf("%ls %ls PID:%ls %ls %ls", type->c_str(), action->c_str(), extra->at(0).c_str(), process->c_str(), object->c_str());
358         }
359
360         printf("\n");
361     } else {
362         // Send the event to the logger
363         Logger::getInstance()->writeSystemEventToLog(type, time, process, action, object, extra);
364     }
365     server->sendXML(L"system-event", &vAttributes);
366 }
367
368 void
369 Analyzer::onProcessEvent(BOOLEAN created, wstring time,
370                          DWORD parentProcessId, wstring parentProcess,
371                          DWORD processId, wstring process)
372 {
373     malicious = true;
374     wstring processEvent = L"process";
375     wstring processType = L"";
376     if(created == TRUE)
377     {
378         processType = L"created";
379     } else {
380         processType = L"terminated";
381     }
382     //Xeno sez ? Is this comment still valid
383     //FIXME: use the right constructor instead
384     vector<wstring> extra;
385     wchar_t parentProcessIdString[11];
386     swprintf(parentProcessIdString, 11, L"%ld", parentProcessId);
387     extra.push_back(parentProcessIdString);
388     wchar_t processIdString[11];
389     swprintf(processIdString, 11, L"%ld", processId);
390     extra.push_back(processIdString);
391
392     sendSystemEvent(&processEvent, &time,
393                     &parentProcess, &processType,
394                     &process, &extra);
395 }
396
397 void 
398 Analyzer::onRegistryEvent(wstring registryEventType, wstring time,
399                           wstring processPath, wstring registryEventPath, vector<wstring> extra)
400 {
401     malicious = true;
402     wstring registryEvent = L"registry";
403     sendSystemEvent(&registryEvent, &time,
404                     &processPath, &registryEventType,
405                     &registryEventPath, &extra);
406 }
407
408 void
409 Analyzer::onFileEvent(wstring fileEventType, wstring time,
410                          wstring processPath, wstring fileEventPath, vector<wstring> extra)
411 {
412     malicious = true;
413     wstring fileEvent = L"file";
414     sendSystemEvent(&fileEvent, &time,
415                     &processPath, &fileEventType,
416                     &fileEventPath, &extra);
417 }
Note: See TracBrowser for help on using the browser.