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

Revision 841, 15.0 kB (checked in by xkovah, 1 year ago)

added a sleep so that the loop will not take up too many resources

Line 
1 #include <iostream>
2 #include <boost/signal.hpp>
3 #include <boost/bind.hpp>
4 #include "Server.h"
5 #include "Visitor.h"
6 #include "Analyzer.h"
7 #include "ProcessManager.h"
8 #include "shellapi.h"
9 using namespace std;
10
11 /* Initialise static variables. These are all singletons */
12 /* Process manager which keeps track of opened processes and their paths */
13 bool ProcessManager::instanceCreated = false;
14 ProcessManager* ProcessManager::processManager = NULL;
15
16 /* Objects listen for internal events from this controller */
17 bool EventController::instanceCreated = false;
18 EventController* EventController::pEventController = NULL;
19
20 /* Logging capabilities that either writes to a file or console */
21 bool Logger::instanceCreated = false;
22 Logger* Logger::logger = NULL;
23
24 /* Global options available to all objects */
25 bool OptionsManager::instanceCreated = false;
26 OptionsManager* OptionsManager::optionsManager = NULL;
27
28 class CaptureClient : public Runnable
29 {
30 public:
31     CaptureClient()
32     {
33         /* Capture needs the SeDriverLoadPrivilege and SeDebugPrivilege to correctly run.
34            If it doesn't acquire these privileges it exits. DebugPrivilege is used in the
35            ProcessManager to open handles to existing process. DriverLoadPrivilege allows
36            Capture to load the kernel drivers. */
37         if(!obtainDebugPrivilege() || !obtainDriverLoadPrivilege())
38         {   
39             printf("\n\nCould not acquire privileges. Make sure you are running Capture with Administrator rights\n");
40             exit(1);
41         }
42
43         /* Create the log directories */
44         CreateDirectory(L"logs",NULL);
45
46         /* If logging to a file has been specified open the file for write access */
47         if(OptionsManager::getInstance()->getOption(L"log-system-events-file") != L"")
48             Logger::getInstance()->openLogFile(OptionsManager::getInstance()->getOption(L"log-system-events-file"));
49
50         hStopRunning = CreateEvent(NULL, FALSE, FALSE, NULL);
51         wstring serverIp = OptionsManager::getInstance()->getOption(L"server");
52         server = new Server(serverIp, 7070);
53         server->onConnectionStatusChanged(boost::bind(&CaptureClient::onConnectionStatusChanged, this, _1));
54
55         /* Listen for events from the EventController. These are messages passed from the server */
56         onServerConnectEventConnection = EventController::getInstance()->connect_onServerEvent(L"connect", boost::bind(&CaptureClient::onServerConnectEvent, this, _1));
57         onServerPingEventConnection = EventController::getInstance()->connect_onServerEvent(L"ping", boost::bind(&CaptureClient::onServerPingEvent, this, _1));
58
59         /* Start running the Capture Client */
60         visitor = new Visitor();
61         analyzer =  new Analyzer(visitor, server);
62         Thread* captureClientThread = new Thread(this);
63         captureClientThread->start("CaptureClient");
64     }
65    
66     ~CaptureClient()
67     {
68         onServerConnectEventConnection.disconnect();
69         onServerPingEventConnection.disconnect();
70         CloseHandle(hStopRunning);
71         delete analyzer;
72         delete visitor;
73         delete server;
74        
75        
76         Logger::getInstance()->closeLogFile();
77         delete Logger::getInstance();
78         delete ProcessManager::getInstance();
79         delete OptionsManager::getInstance();
80         delete EventController::getInstance();
81     }
82
83     void run()
84     {       
85         if((OptionsManager::getInstance()->getOption(L"server") == L"") ||
86             server->connectToServer())
87         {
88             /* If Capture is being run in standalone mode start the analyzer now */
89             /* Send file test */
90             printf("---------------------------------------------------------\n");
91             if((OptionsManager::getInstance()->getOption(L"server") == L""))
92             {
93                 analyzer->start();
94             }
95             /* Wait till a user presses a key then exit */
96             /*Xeno - changed to make it only quit with a q*/
97             DWORD c;
98             while(1){
99                 c = getchar();
100                 if(c == 'q'){
101                     break;
102                 }
103                 else{
104                     Sleep(99999999);
105                 }
106             }
107             if((OptionsManager::getInstance()->getOption(L"server") == L""))
108             {
109                 analyzer->stop();
110             }
111         }
112         SetEvent(hStopRunning);
113     }
114
115     /* Event passed when the state of the connection between the server is changed.
116        When capture becomes disconnected from the server the client exits */
117     void onConnectionStatusChanged(bool connectionStatus)
118     {
119         printf("Got connect status changed\n");
120         if(!connectionStatus)
121         {
122             if(OptionsManager::getInstance()->getOption(L"server") != L"")
123                 printf("Disconnected from server: Exiting client\n");
124             SetEvent(hStopRunning);
125         }
126     }
127
128     /* Responds to a connect event from the server. It sends the virtual machine
129        server id and virtual machine id this client is hosted on back to the server */
130     void onServerConnectEvent(Element* pElement)
131     {
132         printf("Got connect event\n");
133         if(pElement->name == L"connect")
134         {
135             Attribute att;
136             queue<Attribute> vAttributes;
137             att.name = L"vm-server-id";
138             att.value = OptionsManager::getInstance()->getOption(L"vm-server-id");
139             vAttributes.push(att);
140             att.name = L"vm-id";
141             att.value = OptionsManager::getInstance()->getOption(L"vm-id");
142             vAttributes.push(att);
143             server->sendXML(L"connect", &vAttributes);
144         }
145     }
146
147     /* Sends a pong message back to the server when a ping is received */
148     void onServerPingEvent(Element* pElement)
149     {
150         if(pElement->name == L"ping")
151         {
152             queue<Attribute> vAttributes;
153             server->sendXML(L"pong", &vAttributes);
154         }
155     }
156
157     /* Get the driver load privilege so that the kernel drivers can be loaded */
158     bool obtainDriverLoadPrivilege()
159     {
160         HANDLE hToken;
161         if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))
162         {
163             TOKEN_PRIVILEGES tp;
164             LUID luid;
165             LPCTSTR lpszPrivilege = L"SeLoadDriverPrivilege";
166
167             if ( !LookupPrivilegeValue(
168                     NULL,            // lookup privilege on local system
169                     lpszPrivilege,   // privilege to lookup
170                     &luid ) )        // receives LUID of privilege
171             {
172                 printf("LookupPrivilegeValue error: %u\n", GetLastError() );
173                 return false;
174             }
175
176             tp.PrivilegeCount = 1;
177             tp.Privileges[0].Luid = luid;
178             tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
179
180             // Enable the privilege or disable all privileges.
181             if ( !AdjustTokenPrivileges(
182                 hToken,
183                 FALSE,
184                 &tp,
185                 sizeof(TOKEN_PRIVILEGES),
186                 (PTOKEN_PRIVILEGES) NULL,
187                 (PDWORD) NULL) )
188             {
189               printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
190               return false;
191             }
192
193             if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
194             {   
195                 printf("The token does not have the specified privilege. \n");
196                 return false;
197             }
198         }
199         CloseHandle(hToken);
200         return true;
201
202     }
203
204     /* Get the debug privilege so that we can get process information for all process
205        except for the system process */
206     bool obtainDebugPrivilege()
207     {
208         HANDLE hToken;
209         if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))
210         {
211             TOKEN_PRIVILEGES tp;
212             LUID luid;
213             LPCTSTR lpszPrivilege = L"SeDebugPrivilege";
214
215             if ( !LookupPrivilegeValue(
216                     NULL,            // lookup privilege on local system
217                     lpszPrivilege,   // privilege to lookup
218                     &luid ) )        // receives LUID of privilege
219             {
220                 printf("LookupPrivilegeValue error: %u\n", GetLastError() );
221                 return false;
222             }
223
224             tp.PrivilegeCount = 1;
225             tp.Privileges[0].Luid = luid;
226             tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
227
228             // Enable the privilege or disable all privileges.
229             if ( !AdjustTokenPrivileges(
230                 hToken,
231                 FALSE,
232                 &tp,
233                 sizeof(TOKEN_PRIVILEGES),
234                 (PTOKEN_PRIVILEGES) NULL,
235                 (PDWORD) NULL) )
236             {
237               printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
238               return false;
239             }
240
241             if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
242             {   
243                 printf("The token does not have the specified privilege. \n");
244                 return false;
245             }
246         }
247         CloseHandle(hToken);
248         return true;
249     }
250
251     HANDLE hStopRunning;
252 private:
253     Server* server;
254     Visitor* visitor;
255     Analyzer* analyzer;
256
257     boost::signals::connection onServerConnectEventConnection;
258     boost::signals::connection onServerPingEventConnection;
259    
260 };
261
262 int _tmain(int argc, WCHAR* argv[])
263 {
264     /* Set the current directory to the where the CaptureClient.exe is found */
265     /* This is a bug fix for the VIX library as the runProgramInGuest function
266        opens the client from within c:\windows\system32 so nothing will load
267        properly during execution */
268     wchar_t* szFullPath = new wchar_t[4096];
269     GetFullPathName(argv[0], 4096, szFullPath, NULL);
270     DebugPrint(L"Capture: Argv[0] -> %s\n", argv[0]);
271     DebugPrint(L"Capture: GetFullPathName -> %ls\n", szFullPath);
272     wstring dir = szFullPath;
273     dir = dir.substr(0, dir.find_last_of(L"\\")+1);
274     SetCurrentDirectory(dir.c_str());
275     DebugPrint(L"Capture: Dir -> %ls\n", dir.c_str());
276     GetCurrentDirectory(4096, szFullPath);
277
278     DebugPrint(L"Capture: Current directory set -> %ls\n", szFullPath);
279    
280     /* Delete the log directory */
281     /*
282     GetFullPathName(L"logs", 4096, szFullPath, NULL);
283     SHFILEOPSTRUCT deleteLogDirectory;
284     deleteLogDirectory.wFunc = FO_DELETE;
285     deleteLogDirectory.pFrom = szFullPath;
286     deleteLogDirectory.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
287     SHFileOperation(&deleteLogDirectory);
288 */
289     delete [] szFullPath;
290    
291     wstring serverIp = L"";
292     wstring vmServerId = L"";
293     wstring vmId = L"";
294     wstring logSystemEventsFile = L"";
295     wstring collectModifiedFiles = L"false";
296     wstring captureNetworkPackets = L"false";
297
298     for(int i = 1; i < argc; i++)
299     {
300         wstring option = argv[i];
301         if(option == L"--help" || option == L"-h") {
302             printf("\nCapture client is a high interaction client honeypot which using event monitoring can monitor the state of the system it is being run on. ");
303             printf("Capture can monitor processes, files, and the registry at the moment and classifies an event as being malicious by checking exclusion lists. ");
304             printf("\nThese exclusion lists are regular expressions which can either allow or deny a particular event from a process in the system. Because of the fact ");
305             printf("that it uses regular expressions, creating these list can be very simple but can also provide very fine grained exclusion if needed.\nThe client ");
306             printf("can also copy all modified and deleted files to a temporary directory as well as capture all incoming and outgoing packets on the network adapters ");
307             printf("on the system.\nThe client can be run in the following two modes:\n");
308             printf("\n\nClient<->Server\n\n");
309             printf("The client connects to a central Capture server where the client can be sent urls to visit. These urls can contain other information which tell ");
310             printf("the client which program to use, for example www.google.com could be visited with either Internet Explorer or Mozilla Firefox and how long to visit the ");
311             printf("url. While the url is being visited the state of the system is monitored and if anything malicious occurs during the visitation period the event ");
312             printf("is passed back to the server. In this mode the client is run inside of a virtual machine so that when a malicious event occurs the server can revert ");
313             printf("the virtual machine to a clean state\n\n");
314             printf("To use this mode the options -s, -a, -b must be set so the client knows how to connect and authenticate with the server. To configure the ");
315             printf("programs that are available to visit a url edit the clients.conf file. If -cn are set then the log directory will be sent to the server once ");
316             printf("a malicious url is visited. For this to work tar.exe and gzip.exe must be included in the Capture Client folder.\n");
317             printf("\n\nStandalone\n\n");
318             printf("In this mode the client runs in the background of a system and monitors the state of it. Rather than being controlled by a remote server, in standalone mode ");
319             printf("the user has control over the system. Malicious events can either be stored in a file or outputted to stdout.");
320             printf("\n\nUsage: CaptureClient.exe [-chn] [-s server address -a vm server id -b vm id] [-l file]\n");
321             printf("\n  -h\t\tPrint this help message");
322             printf("\n  -s address\tAddress of the server the client connects up to. NOTE -a & -b\n\t\tmust be defined when using this option");
323             printf("\n  -a server id\tUnique id of the virtual machine server that hosts the client");
324             printf("\n  -b vm id\tUnique id of the virtual machine that this client is run on");
325             printf("\n  -l file\tOutput system events to a file rather than stdout\n");
326             printf("\n  -c\t\tCopy files into the log directory when they are modified or\n\t\tdeleted");
327             printf("\n  -n\t\tCapture all incoming and outgoing network packets from the\n\t\tnetwork adapters on the system and store them in .pcap files in\n\t\tthe log directory");
328             printf("\n\nIf -s is not set the client will operate in standalone mode");
329             exit(1);
330         } else if(option == L"-s") {
331             if((i+1 < argc) && (argv[i+1][0] != '-')) {
332                 serverIp = argv[++i];
333                 printf("Option: Connect to server: %ls\n", serverIp.c_str());
334             }
335         } else if(option == L"-a") {
336             if((i+1 < argc) && (argv[i+1][0] != '-')) {
337                 vmServerId = argv[++i];
338             }
339         } else if(option == L"-b") {
340             if((i+1 < argc) && (argv[i+1][0] != '-')) {
341                 vmId = argv[++i];
342             }
343         } else if(option == L"-l") {
344             if((i+1 < argc) && (argv[i+1][0] != '-')) {         
345                 logSystemEventsFile = argv[++i];
346                 printf("Option: Logging system events to %ls\n", logSystemEventsFile.c_str());
347             }
348         } else {
349             if(argv[i][0] == '-')
350             {
351                 for(UINT k = 1; k < option.length(); k++)
352                 {
353                     if(argv[i][k] == 'c') {
354                         printf("Option: Collecting modified files\n");
355                         collectModifiedFiles = L"true";
356                     } else if(argv[i][k] == 'n') {
357                         HMODULE hModWinPcap = LoadLibrary(L"wpcap.dll");
358                         if(hModWinPcap == NULL)
359                         {
360                             printf("NetworkPacketDumper: ERROR - wpcap.dll not found. Check that winpcap is installed on this system\n");
361                             printf("Cannot use -n option if winpcap is not installed ... exiting\n");
362                             exit(1);
363                         } else {
364                             printf("Option: Capturing network packets\n");
365                             captureNetworkPackets = L"true";
366                             FreeLibrary(hModWinPcap);
367                         }
368                     }
369                 }
370             }
371         }
372     }
373
374     OptionsManager::getInstance()->addOption(L"server", serverIp);
375     OptionsManager::getInstance()->addOption(L"vm-server-id", vmServerId);
376     OptionsManager::getInstance()->addOption(L"vm-id", vmId);
377     OptionsManager::getInstance()->addOption(L"log-system-events-file", logSystemEventsFile);
378     OptionsManager::getInstance()->addOption(L"collect-modified-files", collectModifiedFiles);
379     OptionsManager::getInstance()->addOption(L"capture-network-packets", captureNetworkPackets);
380
381     if(collectModifiedFiles == L"true")
382     {
383         if(serverIp != L"")
384         {
385             WIN32_FIND_DATA FindFileData;
386             HANDLE hFind;
387
388             hFind = FindFirstFile(L"7za.exe",&FindFileData);
389             if(hFind == INVALID_HANDLE_VALUE)
390             {
391                 printf("Analyzer: ERROR - Could not find 7za.exe (http://www.7-zip.org/) - Not collecting modified files\n");
392                 printf("Cannot use -c option if 7za.exe is not in the current directory ... exiting\n");
393                 exit(1);
394             }
395         }
396     }
397
398     CaptureClient* cp = new CaptureClient();
399     WaitForSingleObject(cp->hStopRunning, INFINITE);
400     delete cp;
401     return 0;
402 }
Note: See TracBrowser for help on using the browser.