1
2
3
4
5 import os
6 import sys
7 import time
8 import socket
9 import string
10 import random
11 import platform
12 import subprocess
13 import ConfigParser
14 from StringIO import StringIO
15 from zipfile import ZipFile
16 from SimpleXMLRPCServer import SimpleXMLRPCServer
17
18 BIND_IP = "0.0.0.0"
19 BIND_PORT = 8000
20
21 STATUS_INIT = 0x0001
22 STATUS_RUNNING = 0x0002
23 STATUS_COMPLETED = 0x0003
24 STATUS_FAILED = 0x0004
25 CURRENT_STATUS = STATUS_INIT
26
27 ERROR_MESSAGE = ""
28 ANALYZER_FOLDER = ""
29 RESULTS_FOLDER = ""
30
32 """Cuckoo agent, it runs inside guest."""
33
35 self.system = platform.system().lower()
36 self.analyzer_path = ""
37 self.analyzer_pid = 0
38
40 global ERROR_MESSAGE
41 global ANALYZER_FOLDER
42
43 if not ANALYZER_FOLDER:
44 random.seed(time.time())
45 container = "".join(random.choice(string.ascii_lowercase) for x in range(random.randint(5, 10)))
46
47 if self.system == "windows":
48 system_drive = os.environ["SYSTEMDRIVE"] + os.sep
49 ANALYZER_FOLDER = os.path.join(system_drive, container)
50 elif self.system == "linux" or self.system == "darwin":
51 ANALYZER_FOLDER = os.path.join(os.environ["HOME"], container)
52 else:
53 ERROR_MESSAGE = "Unable to identify operating system"
54 return False
55
56 try:
57 os.makedirs(ANALYZER_FOLDER)
58 except OSError as e:
59 ERROR_MESSAGE = e
60 return False
61
62 return True
63
65 """Get current status.
66 @return: status.
67 """
68 return CURRENT_STATUS
69
71 """Get error message.
72 @return: error message.
73 """
74 return str(ERROR_MESSAGE)
75
77 """Get analysis data.
78 @param data: analysis data.
79 @param name: file name.
80 @return: operation status.
81 """
82 global ERROR_MESSAGE
83 data = data.data
84
85 if self.system == "windows":
86 root = os.environ["TEMP"]
87 elif self.system == "linux" or self.system == "darwin":
88 root = "/tmp"
89 else:
90 ERROR_MESSAGE = "Unable to write malware to disk because of " \
91 "failed identification of the operating system"
92 return False
93
94 file_path = os.path.join(root, name)
95
96 try:
97 with open(file_path, "wb") as malware:
98 malware.write(data)
99 except IOError as e:
100 ERROR_MESSAGE = "Unable to write malware to disk: {0}".format(e)
101 return False
102
103 return True
104
106 """Creates analysis.conf file from current analysis options.
107 @param options: current configuration options, dict format.
108 @return: operation status.
109 """
110 global ERROR_MESSAGE
111
112 if type(options) != dict:
113 return False
114
115 config = ConfigParser.RawConfigParser()
116 config.add_section("analysis")
117
118 try:
119 for key, value in options.items():
120
121 if isinstance(value, basestring):
122 try:
123 value = value.encode("utf-8")
124 except UnicodeEncodeError:
125 pass
126
127 config.set("analysis", key, value)
128
129 config_path = os.path.join(ANALYZER_FOLDER, "analysis.conf")
130
131 with open(config_path, "wb") as config_file:
132 config.write(config_file)
133 except Exception as e:
134 ERROR_MESSAGE = str(e)
135 return False
136
137 return True
138
140 """Add analyzer.
141 @param data: analyzer data.
142 @return: operation status.
143 """
144 data = data.data
145
146 if not self._initialize():
147 return False
148
149 try:
150 zip_data = StringIO()
151 zip_data.write(data)
152
153 with ZipFile(zip_data, "r") as archive:
154 archive.extractall(ANALYZER_FOLDER)
155 finally:
156 zip_data.close()
157
158 self.analyzer_path = os.path.join(ANALYZER_FOLDER, "analyzer.py")
159
160 return True
161
163 """Execute analysis.
164 @return: analyzer PID.
165 """
166 global ERROR_MESSAGE
167 global CURRENT_STATUS
168
169 if not self.analyzer_path or not os.path.exists(self.analyzer_path):
170 return False
171
172 try:
173 proc = subprocess.Popen([sys.executable, self.analyzer_path],
174 cwd=os.path.dirname(self.analyzer_path))
175 self.analyzer_pid = proc.pid
176 except OSError as e:
177 ERROR_MESSAGE = str(e)
178 return False
179
180 CURRENT_STATUS = STATUS_RUNNING
181
182 return self.analyzer_pid
183
184 - def complete(self, success=True, error="", results=""):
204
205 if __name__ == "__main__":
206 try:
207 if not BIND_IP:
208 BIND_IP = socket.gethostbyname(socket.gethostname())
209
210 print("[+] Starting agent on %s:%s ..." % (BIND_IP, BIND_PORT))
211
212
215 socket.getfqdn = FakeGetFQDN
216
217 server = SimpleXMLRPCServer((BIND_IP, BIND_PORT), allow_none=True)
218 server.register_instance(Agent())
219 server.serve_forever()
220 except KeyboardInterrupt:
221 server.shutdown()
222