1
2
3
4
5 import os
6 import shutil
7 import sys
8 import copy
9 import json
10 import urllib
11 import urllib2
12 import logging
13 import logging.handlers
14
15 import modules.auxiliary
16 import modules.processing
17 import modules.signatures
18 import modules.reporting
19
20 from lib.cuckoo.common.colors import red, green, yellow, cyan
21 from lib.cuckoo.common.config import Config
22 from lib.cuckoo.common.constants import CUCKOO_ROOT, CUCKOO_VERSION
23 from lib.cuckoo.common.exceptions import CuckooStartupError
24 from lib.cuckoo.common.exceptions import CuckooOperationalError
25 from lib.cuckoo.common.utils import create_folders
26 from lib.cuckoo.core.database import Database, TASK_RUNNING, TASK_FAILED_ANALYSIS
27 from lib.cuckoo.core.plugins import import_plugin, import_package, list_plugins
28
29 log = logging.getLogger()
30
32 """Checks if Python version is supported by Cuckoo.
33 @raise CuckooStartupError: if version is not supported.
34 """
35 if sys.version_info[:2] != (2, 7):
36 raise CuckooStartupError("You are running an incompatible version "
37 "of Python, please use 2.7")
38
39
41 """Checks if working directories are ready.
42 @raise CuckooStartupError: if directories are not properly configured.
43 """
44 if not os.path.exists(CUCKOO_ROOT):
45 raise CuckooStartupError("You specified a non-existing root "
46 "directory: {0}".format(CUCKOO_ROOT))
47
48 cwd = os.path.join(os.getcwd(), "cuckoo.py")
49 if not os.path.exists(cwd):
50 raise CuckooStartupError("You are not running Cuckoo from it's "
51 "root directory")
52
53
55 """Checks if config files exist.
56 @raise CuckooStartupError: if config files do not exist.
57 """
58 configs = [os.path.join(CUCKOO_ROOT, "conf", "cuckoo.conf"),
59 os.path.join(CUCKOO_ROOT, "conf", "reporting.conf"),
60 os.path.join(CUCKOO_ROOT, "conf", "auxiliary.conf")]
61
62 for config in configs:
63 if not os.path.exists(config):
64 raise CuckooStartupError("Config file does not exist at "
65 "path: {0}".format(config))
66
67 return True
68
82
84 """Checks version of Cuckoo."""
85 cfg = Config()
86
87 if not cfg.cuckoo.version_check:
88 return
89
90 print(" Checking for updates...")
91
92 url = "http://api.cuckoosandbox.org/checkversion.php"
93 data = urllib.urlencode({"version": CUCKOO_VERSION})
94
95 try:
96 request = urllib2.Request(url, data)
97 response = urllib2.urlopen(request)
98 except (urllib2.URLError, urllib2.HTTPError):
99 print(red(" Failed! ") + "Unable to establish connection.\n")
100 return
101
102 try:
103 response_data = json.loads(response.read())
104 except ValueError:
105 print(red(" Failed! ") + "Invalid response.\n")
106 return
107
108 if not response_data["error"]:
109 if response_data["response"] == "NEW_VERSION":
110 msg = "Cuckoo Sandbox version {0} is available " \
111 "now.\n".format(response_data["current"])
112 print(red(" Outdated! ") + msg)
113 else:
114 print(green(" Good! ") + "You have the latest version "
115 "available.\n")
116
117
119 """Logging to database handler.
120 Used to log errors related to tasks in database.
121 """
122
123 - def emit(self, record):
127
129 """Logging to console handler."""
130
131 - def emit(self, record):
132 colored = copy.copy(record)
133
134 if record.levelname == "WARNING":
135 colored.msg = yellow(record.msg)
136 elif record.levelname == "ERROR" or record.levelname == "CRITICAL":
137 colored.msg = red(record.msg)
138 else:
139 if "analysis procedure completed" in record.msg:
140 colored.msg = cyan(record.msg)
141 else:
142 colored.msg = record.msg
143
144 logging.StreamHandler.emit(self, colored)
145
147 """Initializes logging."""
148 formatter = logging.Formatter("%(asctime)s [%(name)s] %(levelname)s: %(message)s")
149
150 fh = logging.handlers.WatchedFileHandler(os.path.join(CUCKOO_ROOT, "log", "cuckoo.log"))
151 fh.setFormatter(formatter)
152 log.addHandler(fh)
153
154 ch = ConsoleHandler()
155 ch.setFormatter(formatter)
156 log.addHandler(ch)
157
158 dh = DatabaseHandler()
159 dh.setLevel(logging.ERROR)
160 log.addHandler(dh)
161
162 log.setLevel(logging.INFO)
163
165 """Initializes logging only to console."""
166 formatter = logging.Formatter("%(asctime)s [%(name)s] %(levelname)s: %(message)s")
167
168 ch = ConsoleHandler()
169 ch.setFormatter(formatter)
170 log.addHandler(ch)
171
172 log.setLevel(logging.INFO)
173
190
215
217 """Generates index for yara signatures."""
218
219 def find_signatures(root):
220 signatures = []
221 for entry in os.listdir(root):
222 if entry.endswith(".yara") or entry.endswith(".yar"):
223 signatures.append(os.path.join(root, entry))
224
225 return signatures
226
227 log.debug("Initializing Yara...")
228
229
230 yara_root = os.path.join(CUCKOO_ROOT, "data", "yara")
231
232
233 categories = ["binaries", "urls", "memory"]
234 generated = []
235
236 for category in categories:
237
238 category_root = os.path.join(yara_root, category)
239 if not os.path.exists(category_root):
240 continue
241
242
243 signatures = []
244 for entry in os.listdir(category_root):
245 if entry.endswith(".yara") or entry.endswith(".yar"):
246 signatures.append(os.path.join(category_root, entry))
247
248 if not signatures:
249 continue
250
251
252 index_name = "index_{0}.yar".format(category)
253 index_path = os.path.join(yara_root, index_name)
254
255
256 with open(index_path, "w") as index_handle:
257 for signature in signatures:
258 index_handle.write("include \"{0}\"\n".format(signature))
259
260 generated.append(index_name)
261
262 for entry in generated:
263 if entry == generated[-1]:
264 log.debug("\t `-- %s", entry)
265 else:
266 log.debug("\t |-- %s", entry)
267
268
270 """Clean up cuckoo setup.
271 It deletes logs, all stored data from file system and configured databases (SQL
272 and MongoDB.
273 """
274
275
276
277 create_structure()
278 init_console_logging()
279
280
281 db = Database()
282
283
284 db.drop()
285
286
287 cfg = Config("reporting")
288 if cfg.mongodb and cfg.mongodb.enabled:
289 from pymongo import MongoClient
290 host = cfg.mongodb.get("host", "127.0.0.1")
291 port = cfg.mongodb.get("port", 27017)
292 mdb = cfg.mongodb.get("db", "cuckoo")
293 try:
294 conn = MongoClient(host, port)
295 conn.drop_database(mdb)
296 conn.disconnect()
297 except:
298 log.warning("Unable to drop MongoDB database: %s", mdb)
299
300
301 paths = [
302 os.path.join(CUCKOO_ROOT, "db"),
303 os.path.join(CUCKOO_ROOT, "log"),
304 os.path.join(CUCKOO_ROOT, "storage"),
305 ]
306
307
308 for path in paths:
309 if os.path.isdir(path):
310 try:
311 shutil.rmtree(path)
312 except (IOError, OSError) as e:
313 log.warning("Error removing directory %s: %s", path, e)
314
315
316 for dirpath, dirnames, filenames in os.walk(CUCKOO_ROOT):
317 for fname in filenames:
318 if not fname.endswith(".pyc"):
319 continue
320
321 path = os.path.join(CUCKOO_ROOT, dirpath, fname)
322
323 try:
324 os.unlink(path)
325 except (IOError, OSError) as e:
326 log.warning("Error removing file %s: %s", path, e)
327