1
2
3
4
5
6 import os
7 import logging
8 import time
9
10 from lib.cuckoo.common.abstracts import Processing
11 from lib.cuckoo.common.config import Config
12 from lib.cuckoo.common.constants import CUCKOO_ROOT
13
14 log = logging.getLogger(__name__)
15
16 try:
17 import volatility.conf as conf
18 import volatility.registry as registry
19 import volatility.commands as commands
20 import volatility.utils as utils
21 import volatility.plugins.malware.devicetree as devicetree
22 import volatility.plugins.malware.apihooks as apihooks
23 import volatility.plugins.getsids as sidm
24 import volatility.plugins.privileges as privm
25 import volatility.plugins.taskmods as taskmods
26 import volatility.win32.tasks as tasks
27 import volatility.obj as obj
28 import volatility.exceptions as exc
29 import volatility.plugins.filescan as filescan
30 import volatility.protos as protos
31
32 HAVE_VOLATILITY = True
33
34
35 rootlogger = logging.getLogger()
36 logging.getLogger("volatility.obj").setLevel(rootlogger.level)
37 logging.getLogger("volatility.utils").setLevel(rootlogger.level)
38 except ImportError as e:
39 if e.message == "No module named Crypto.Hash":
40 log.error(
41 "The PyCrypto package is missing (install with "
42 "`pip install pycrypto`)"
43 )
44
45 HAVE_VOLATILITY = False
46
48 """ Volatility API interface."""
49
50 - def __init__(self, memdump, osprofile=None):
51 """@param memdump: the memdump file path
52 @param osprofile: the profile (OS type)
53 """
54 registry.PluginImporter()
55 self.memdump = memdump
56 self.osprofile = osprofile
57 self.config = None
58 self.addr_space = None
59 self.init_config()
60
62 """Use psscan to get system dtb and apply it."""
63 ps = filescan.PSScan(self.config)
64
65 for ep in ps.calculate():
66 if str(ep.ImageFileName) == "System":
67 self.config.update("dtb", ep.Pcb.DirectoryTableBase)
68 return True
69
70 return False
71
73 """Creates a volatility configuration."""
74 if self.config is not None and self.addr_space is not None:
75 return self.config
76
77 self.config = conf.ConfObject()
78 self.config.optparser.set_conflict_handler("resolve")
79 registry.register_global_options(self.config, commands.Command)
80 base_conf = {
81 "profile": "WinXPSP2x86",
82 "use_old_as": None,
83 "kdbg": None,
84 "help": False,
85 "kpcr": None,
86 "tz": None,
87 "pid": None,
88 "output_file": None,
89 "physical_offset": None,
90 "conf_file": None,
91 "dtb": None,
92 "output": None,
93 "info": None,
94 "location": "file://" + self.memdump,
95 "plugins": None,
96 "debug": None,
97 "cache_dtb": True,
98 "filename": None,
99 "cache_directory": None,
100 "verbose": None,
101 "write": False
102 }
103
104 if self.osprofile:
105 base_conf["profile"] = self.osprofile
106
107 for key, value in base_conf.items():
108 self.config.update(key, value)
109
110
111
112 try:
113 self.addr_space = utils.load_as(self.config)
114 except exc.AddrSpaceError:
115 if self.get_dtb():
116 self.addr_space = utils.load_as(self.config)
117 else:
118 raise
119
120 self.plugins = \
121 registry.get_plugin_classes(commands.Command, lower=True)
122 return self.config
123
125 """Volatility pslist plugin.
126 @see volatility/plugins/taskmods.py
127 """
128 results = []
129
130 command = taskmods.PSList(self.config)
131 for process in command.calculate():
132 new = {
133 "process_name": str(process.ImageFileName),
134 "process_id": int(process.UniqueProcessId),
135 "parent_id": int(process.InheritedFromUniqueProcessId),
136 "num_threads": str(process.ActiveThreads),
137 "num_handles": str(process.ObjectTable.HandleCount),
138 "session_id": str(process.SessionId),
139 "create_time": str(process.CreateTime or ""),
140 "exit_time": str(process.ExitTime or ""),
141 }
142
143 results.append(new)
144
145 return dict(config={}, data=results)
146
148 """Volatility psxview plugin.
149 @see volatility/plugins/malware/psxview.py
150 """
151 results = []
152
153 command = self.plugins["psxview"](self.config)
154 for offset, process, ps_sources in command.calculate():
155 new = {
156 "process_name": str(process.ImageFileName),
157 "process_id": int(process.UniqueProcessId),
158 "pslist": str(offset in ps_sources["pslist"]),
159 "psscan": str(offset in ps_sources["psscan"]),
160 "thrdproc": str(offset in ps_sources["thrdproc"]),
161 "pspcid": str(offset in ps_sources["pspcid"]),
162 "csrss": str(offset in ps_sources["csrss"]),
163 "session": str(offset in ps_sources["session"]),
164 "deskthrd": str(offset in ps_sources["deskthrd"]),
165 }
166
167 results.append(new)
168
169 return dict(config={}, data=results)
170
172 """Volatility callbacks plugin.
173 @see volatility/plugins/malware/callbacks.py
174 """
175 results = []
176
177 command = self.plugins["callbacks"](self.config)
178 for (sym, cb, detail), mods, mod_addrs in command.calculate():
179 module = tasks.find_module(mods, mod_addrs, self.addr_space.address_mask(cb))
180
181 if module:
182 module_name = module.BaseDllName or module.FullDllName
183 else:
184 module_name = "UNKNOWN"
185
186 new = {
187 "type": str(sym),
188 "callback": hex(int(cb)),
189 "module": str(module_name),
190 "details": str(detail or "-"),
191 }
192
193 results.append(new)
194
195 return dict(config={}, data=results)
196
198 """Volatility idt plugin.
199 @see volatility/plugins/malware/idt.py
200 """
201 results = []
202
203 command = self.plugins["idt"](self.config)
204 for n, entry, addr, module in command.calculate():
205 if module:
206 module_name = str(module.BaseDllName or "")
207 sect_name = command.get_section_name(module, addr)
208 else:
209 module_name = "UNKNOWN"
210 sect_name = ''
211
212
213 cpu_number = entry.obj_parent.obj_parent.ProcessorBlock.Number
214 new = {
215 "cpu_number": int(cpu_number),
216 "index": int(n),
217 "selector": hex(int(entry.Selector)),
218 "address": hex(int(addr)),
219 "module": module_name,
220 "section": sect_name,
221 }
222 results.append(new)
223
224 return dict(config={}, data=results)
225
227 """Volatility gdt plugin.
228 @see volatility/plugins/malware/idt.py
229 """
230 results = []
231
232 command = self.plugins["gdt"](self.config)
233
234 for n, entry in command.calculate():
235 selector = n * 8
236
237
238 if entry.Present:
239 present = "P"
240 else:
241 present = "Np"
242
243
244
245 if entry.Type == "CallGate32":
246 base = entry.CallGate
247 limit = 0
248 granularity = "-"
249 else:
250 base = entry.Base
251 limit = entry.Limit
252 if entry.Granularity:
253 granularity = "Pg"
254 else:
255 granularity = "By"
256
257
258 cpu_number = entry.obj_parent.obj_parent.ProcessorBlock.Number
259
260 new = {
261 "cpu_number": int(cpu_number),
262 "selector": hex(selector),
263 "base": hex(int(base)),
264 "limit": hex(int(limit)),
265 "type": str(entry.Type),
266 "dpl": str(entry.Dpl),
267 "granularity": granularity,
268 "present": present,
269 }
270 results.append(new)
271
272 return dict(config={}, data=results)
273
275 """Volatility ssdt plugin.
276 @see volatility/plugins/ssdt.py
277 """
278 results = []
279
280 command = self.plugins["ssdt"](self.config)
281
282
283 addr_space = self.addr_space
284 syscalls = addr_space.profile.syscalls
285 bits32 = addr_space.profile.metadata.get("memory_model", "32bit") == "32bit"
286
287 for idx, table, n, vm, mods, mod_addrs in command.calculate():
288 for i in range(n):
289 if bits32:
290
291 syscall_addr = obj.Object("address", table + (i * 4), vm).v()
292 else:
293
294
295 offset = obj.Object("long", table + (i * 4), vm).v()
296
297 syscall_addr = table + (offset >> 4)
298
299 try:
300 syscall_name = syscalls[idx][i]
301 except IndexError:
302 syscall_name = "UNKNOWN"
303
304 syscall_mod = tasks.find_module(mods, mod_addrs, addr_space.address_mask(syscall_addr))
305 if syscall_mod:
306 syscall_modname = "{0}".format(syscall_mod.BaseDllName)
307 else:
308 syscall_modname = "UNKNOWN"
309
310 new = {
311 "index": int(idx),
312 "table": "0x%x" % int(table),
313 "entry": "{0:#06x}".format(idx * 0x1000 + i),
314 "syscall_name": syscall_name,
315 "syscall_addr": "0x%x" % int(syscall_addr),
316 "syscall_modname": syscall_modname,
317 }
318
319 if bits32 and syscall_mod is not None:
320 ret = apihooks.ApiHooks.check_inline(
321 va=syscall_addr, addr_space=vm,
322 mem_start=syscall_mod.DllBase,
323 mem_end=syscall_mod.DllBase + syscall_mod.SizeOfImage)
324
325
326 if ret is not None:
327 hooked, data, dest_addr = ret
328 if hooked:
329
330
331
332 hook_mod = tasks.find_module(mods, mod_addrs,
333 dest_addr)
334 if hook_mod:
335 hook_name = "{0}".format(hook_mod.BaseDllName)
336 else:
337 hook_name = "UNKNOWN"
338
339
340 new.update({
341 "hook_dest_addr": "{0:#x}".format(dest_addr),
342 "hook_name": hook_name,
343 })
344
345 results.append(new)
346
347 return dict(config={}, data=results)
348
350 """Volatility timers plugin.
351 @see volatility/plugins/malware/timers.py
352 """
353 results = []
354
355 command = self.plugins["timers"](self.config)
356 for timer, module in command.calculate():
357 if timer.Header.SignalState.v():
358 signaled = "Yes"
359 else:
360 signaled = "-"
361
362 if module:
363 module_name = str(module.BaseDllName or "")
364 else:
365 module_name = "UNKNOWN"
366
367 due_time = "{0:#010x}:{1:#010x}".format(timer.DueTime.HighPart, timer.DueTime.LowPart)
368
369 new = {
370 "offset": hex(timer.obj_offset),
371 "due_time": due_time,
372 "period": int(timer.Period),
373 "signaled": signaled,
374 "routine": hex(int(timer.Dpc.DeferredRoutine)),
375 "module": module_name,
376 }
377 results.append(new)
378
379 return dict(config={}, data=results)
380
382 """Volatility messagehooks plugin.
383 @see volatility/plugins/malware/messagehooks.py
384 """
385 results = []
386
387 command = self.plugins["messagehooks"](self.config)
388 for winsta, atom_tables in command.calculate():
389 for desk in winsta.desktops():
390 for name, hook in desk.hooks():
391 module = command.translate_hmod(winsta, atom_tables, hook.ihmod)
392 new = {
393 "offset": hex(int(hook.obj_offset)),
394 "session": int(winsta.dwSessionId),
395 "desktop": "{0}\\{1}".format(winsta.Name, desk.Name),
396 "thread": "<any>",
397 "filter": str(name),
398 "flags": str(hook.flags),
399 "function": hex(int(hook.offPfn)),
400 "module": str(module),
401 }
402 results.append(new)
403
404 for thrd in desk.threads():
405 info = "{0} ({1} {2})".format(
406 thrd.pEThread.Cid.UniqueThread,
407 thrd.ppi.Process.ImageFileName,
408 thrd.ppi.Process.UniqueProcessId)
409
410 for name, hook in thrd.hooks():
411 module = command.translate_hmod(winsta, atom_tables, hook.ihmod)
412
413 new = {
414 "offset": hex(int(hook.obj_offset)),
415 "session": int(winsta.dwSessionId),
416 "desktop": "{0}\\{1}".format(winsta.Name, desk.Name),
417 "thread": str(info),
418 "filter": str(name),
419 "flags": str(hook.flags),
420 "function": hex(int(hook.offPfn)),
421 "module": str(module),
422 }
423 results.append(new)
424
425 return dict(config={}, data=results)
426
428 """Volatility getsids plugin.
429 @see volatility/plugins/malware/getsids.py
430 """
431 results = []
432
433 command = self.plugins["getsids"](self.config)
434 for task in command.calculate():
435 token = task.get_token()
436
437 if not token:
438 continue
439
440 for sid_string in token.get_sids():
441 if sid_string in sidm.well_known_sids:
442 sid_name = " {0}".format(sidm.well_known_sids[sid_string])
443 else:
444 sid_name_re = sidm.find_sid_re(sid_string, sidm.well_known_sid_re)
445 if sid_name_re:
446 sid_name = " {0}".format(sid_name_re)
447 else:
448 sid_name = ""
449
450 new = {
451 "filename": str(task.ImageFileName),
452 "process_id": int(task.UniqueProcessId),
453 "sid_string": str(sid_string),
454 "sid_name": str(sid_name),
455 }
456 results.append(new)
457
458 return dict(config={}, data=results)
459
461 """Volatility privs plugin.
462 @see volatility/plugins/malware/privs.py
463 """
464 results = []
465
466 command = self.plugins["privs"](self.config)
467
468 for task in command.calculate():
469 for value, present, enabled, default in task.get_token().privileges():
470 try:
471 name, desc = privm.PRIVILEGE_INFO[int(value)]
472 except KeyError:
473 continue
474
475 attributes = []
476 if present:
477 attributes.append("Present")
478 if enabled:
479 attributes.append("Enabled")
480 if default:
481 attributes.append("Default")
482
483 new = {
484 "process_id": int(task.UniqueProcessId),
485 "filename": str(task.ImageFileName),
486 "value": int(value),
487 "privilege": str(name),
488 "attributes": ",".join(attributes),
489 "description": str(desc),
490 }
491 results.append(new)
492
493 return dict(config={}, data=results)
494
496 """Volatility malfind plugin.
497 @param dump_dir: optional directory for dumps
498 @see volatility/plugins/malware/malfind.py
499 """
500 results = []
501
502 command = self.plugins["malfind"](self.config)
503 for task in command.calculate():
504 for vad, address_space in task.get_vads(vad_filter=task._injection_filter):
505 if command._is_vad_empty(vad, address_space):
506 continue
507
508 new = {
509 "process_name": str(task.ImageFileName),
510 "process_id": int(task.UniqueProcessId),
511 "vad_start": "{0:#x}".format(vad.Start),
512 "vad_tag": str(vad.Tag),
513 }
514 results.append(new)
515
516 if dump_dir:
517 filename = os.path.join(dump_dir, "process.{0:#x}.{1:#x}.dmp".format(task.obj_offset, vad.Start))
518 command.dump_vad(filename, vad, address_space)
519
520 return dict(config={}, data=results)
521
523 """Volatility yarascan plugin.
524 @see volatility/plugins/malware/yarascan.py
525 """
526 results = []
527
528 ypath = os.path.join(CUCKOO_ROOT, "data", "yara", "index_memory.yar")
529 if not os.path.exists(ypath):
530 return dict(config={}, data=[])
531
532 self.config.update("YARA_FILE", ypath)
533
534 command = self.plugins["yarascan"](self.config)
535 for o, addr, hit, content in command.calculate():
536
537
538 if o is None:
539 owner = "Unknown Kernel Memory"
540 elif o.obj_name == "_EPROCESS":
541 owner = "Process {0} Pid {1}".format(o.ImageFileName, o.UniqueProcessId)
542 else:
543 owner = "{0}".format(o.BaseDllName)
544
545 hexdump = "".join(
546 "{0:#010x} {1:<48} {2}\n".format(addr + o, h, ''.join(c))
547 for o, h, c in utils.Hexdump(content[0:64]))
548
549 new = {
550 "rule": hit.rule,
551 "owner": owner,
552 "hexdump": hexdump,
553 }
554 results.append(new)
555
556 return dict(config={}, data=results)
557
559 """Volatility apihooks plugin.
560 @see volatility/plugins/malware/apihooks.py
561 """
562 results = []
563
564 command = self.plugins["apihooks"](self.config)
565 for process, module, hook in command.calculate():
566 proc_name = str(process.ImageFileName) if process else ''
567 if command.whitelist(hook.hook_mode | hook.hook_type,
568 proc_name, hook.VictimModule,
569 hook.HookModule, hook.Function):
570 continue
571
572 new = {
573 "hook_mode": str(hook.Mode),
574 "hook_type": str(hook.Type),
575 "victim_module": str(module.BaseDllName or ""),
576 "victim_function": str(hook.Detail),
577 "hook_address": "{0:#x}".format(hook.hook_address),
578 "hooking_module": str(hook.HookModule)
579 }
580
581 if process:
582 new["process_id"] = int(process.UniqueProcessId)
583 new["process_name"] = str(process.ImageFileName)
584
585 results.append(new)
586
587 return dict(config={}, data=results)
588
590 """Volatility dlllist plugin.
591 @see volatility/plugins/taskmods.py
592 """
593 results = []
594
595 command = self.plugins["dlllist"](self.config)
596 for task in command.calculate():
597 new = {
598 "process_id": int(task.UniqueProcessId),
599 "process_name": str(task.ImageFileName),
600 "commandline": str(task.Peb.ProcessParameters.CommandLine or ""),
601 "loaded_modules": []
602 }
603
604 for module in task.get_load_modules():
605 new["loaded_modules"].append({
606 "dll_base": str(module.DllBase),
607 "dll_size": str(module.SizeOfImage),
608 "dll_full_name": str(module.FullDllName or ""),
609 "dll_load_count": int(module.LoadCount),
610 })
611
612 results.append(new)
613
614 return dict(config={}, data=results)
615
617 """Volatility handles plugin.
618 @see volatility/plugins/handles.py
619 """
620 results = []
621
622 command = self.plugins["handles"](self.config)
623 for pid, handle, object_type, name in command.calculate():
624 new = {
625 "process_id": int(pid),
626 "handle_value": str(handle.HandleValue),
627 "handle_granted_access": str(handle.GrantedAccess),
628 "handle_type": str(object_type),
629 "handle_name": str(name)
630 }
631
632 results.append(new)
633
634 return dict(config={}, data=results)
635
637 """Volatility ldrmodules plugin.
638 @see volatility/plugins/malware/malfind.py
639 """
640 results = []
641
642 command = self.plugins["ldrmodules"](self.config)
643 for task in command.calculate():
644
645
646 inloadorder = dict((mod.DllBase.v(), mod) for mod in task.get_load_modules())
647 ininitorder = dict((mod.DllBase.v(), mod) for mod in task.get_init_modules())
648 inmemorder = dict((mod.DllBase.v(), mod) for mod in task.get_mem_modules())
649
650
651 mapped_files = {}
652 for vad, address_space in task.get_vads(vad_filter=task._mapped_file_filter):
653
654
655 if obj.Object("_IMAGE_DOS_HEADER", offset=vad.Start, vm=address_space).e_magic != 0x5A4D:
656 continue
657
658 mapped_files[int(vad.Start)] = str(vad.FileObject.FileName or "")
659
660
661
662 for base in mapped_files.keys():
663
664 load_mod = inloadorder.get(base, None)
665 init_mod = ininitorder.get(base, None)
666 mem_mod = inmemorder.get(base, None)
667
668 new = {
669 "process_id": int(task.UniqueProcessId),
670 "process_name": str(task.ImageFileName),
671 "dll_base": "{0:#x}".format(base),
672 "dll_in_load": load_mod is not None,
673 "dll_in_init": init_mod is not None,
674 "dll_in_mem": mem_mod is not None,
675 "dll_mapped_path": str(mapped_files[base]),
676 "load_full_dll_name": "",
677 "init_full_dll_name": "",
678 "mem_full_dll_name": ""
679 }
680
681 if load_mod:
682 new["load_full_dll_name"] = str(load_mod.FullDllName)
683
684 if init_mod:
685 new["init_full_dll_name"] = str(init_mod.FullDllName)
686
687 if mem_mod:
688 new["mem_full_dll_name"] = str(mem_mod.FullDllName)
689
690 results.append(new)
691
692 return dict(config={}, data=results)
693
695 """Volatility mutantscan plugin.
696 @see volatility/plugins/filescan.py
697 """
698 results = []
699
700 command = self.plugins["mutantscan"](self.config)
701 for mutant in command.calculate():
702 header = mutant.get_object_header()
703 tid = 0
704 pid = 0
705 if mutant.OwnerThread > 0x80000000:
706 thread = mutant.OwnerThread.dereference_as("_ETHREAD")
707 tid = thread.Cid.UniqueThread
708 pid = thread.Cid.UniqueProcess
709
710 new = {
711 "mutant_offset": "{0:#x}".format(mutant.obj_offset),
712 "num_pointer": int(header.PointerCount),
713 "num_handles": int(header.HandleCount),
714 "mutant_signal_state": str(mutant.Header.SignalState),
715 "mutant_name": str(header.NameInfo.Name or ""),
716 "process_id": int(pid),
717 "thread_id": int(tid)
718 }
719
720 results.append(new)
721
722 return dict(config={}, data=results)
723
725 """Volatility devicetree plugin.
726 @see volatility/plugins/malware/devicetree.py
727 """
728 results = []
729
730 command = self.plugins["devicetree"](self.config)
731 for driver_obj in command.calculate():
732 new = {
733 "driver_offset": "0x{0:08x}".format(driver_obj.obj_offset),
734 "driver_name": str(driver_obj.DriverName or ""),
735 "devices": []
736 }
737
738 for device in driver_obj.devices():
739 device_header = obj.Object(
740 "_OBJECT_HEADER",
741 offset=device.obj_offset - device.obj_vm.profile.get_obj_offset("_OBJECT_HEADER", "Body"),
742 vm=device.obj_vm,
743 native_vm=device.obj_native_vm
744 )
745
746 device_name = str(device_header.NameInfo.Name or "")
747
748 new_device = {
749 "device_offset": "0x{0:08x}".format(device.obj_offset),
750 "device_name": device_name,
751 "device_type": devicetree.DEVICE_CODES.get(device.DeviceType.v(), "UNKNOWN"),
752 "devices_attached": []
753 }
754
755 new["devices"].append(new_device)
756
757 level = 0
758
759 for att_device in device.attached_devices():
760 device_header = obj.Object(
761 "_OBJECT_HEADER",
762 offset=att_device.obj_offset - att_device.obj_vm.profile.get_obj_offset("_OBJECT_HEADER", "Body"),
763 vm=att_device.obj_vm,
764 native_vm=att_device.obj_native_vm
765 )
766
767 device_name = str(device_header.NameInfo.Name or "")
768 name = (device_name + " - " + str(att_device.DriverObject.DriverName or ""))
769
770 new_device["devices_attached"].append({
771 "level": level,
772 "attached_device_offset": "0x{0:08x}".format(att_device.obj_offset),
773 "attached_device_name": name,
774 "attached_device_type": devicetree.DEVICE_CODES.get(att_device.DeviceType.v(), "UNKNOWN")
775 })
776
777 level += 1
778
779 results.append(new)
780
781 return dict(config={}, data=results)
782
784 """Volatility svcscan plugin - scans for services.
785 @see volatility/plugins/malware/svcscan.py
786 """
787 results = []
788
789 command = self.plugins["svcscan"](self.config)
790 for rec in command.calculate():
791 new = {
792 "service_offset": "{0:#x}".format(rec.obj_offset),
793 "service_order": int(rec.Order),
794 "process_id": int(rec.Pid),
795 "service_name": str(rec.ServiceName.dereference()),
796 "service_display_name": str(rec.DisplayName.dereference()),
797 "service_type": str(rec.Type),
798 "service_binary_path": str(rec.Binary),
799 "service_state": str(rec.State)
800 }
801
802 results.append(new)
803
804 return dict(config={}, data=results)
805
807 """Volatility modscan plugin.
808 @see volatility/plugins/modscan.py
809 """
810 results = []
811
812 command = self.plugins["modscan"](self.config)
813 for ldr_entry in command.calculate():
814 new = {
815 "kernel_module_offset": "{0:#x}".format(ldr_entry.obj_offset),
816 "kernel_module_name": str(ldr_entry.BaseDllName or ""),
817 "kernel_module_file": str(ldr_entry.FullDllName or ""),
818 "kernel_module_base": "{0:#x}".format(ldr_entry.DllBase),
819 "kernel_module_size": int(ldr_entry.SizeOfImage),
820 }
821
822 results.append(new)
823
824 return dict(config={}, data=results)
825
827 """Volatility imageinfo plugin.
828 @see volatility/plugins/imageinfo.py
829 """
830 results = []
831
832 command = self.plugins["imageinfo"](self.config)
833 new = {}
834 for key, value in command.calculate():
835 new[key] = value
836
837 osp = new["Suggested Profile(s)"].split(",")[0]
838 new["osprofile"] = osp
839
840 results.append(new)
841
842 return dict(config={}, data=results)
843
845 """Volatility sockscan plugin.
846 @see volatility/plugins/sockscan.py
847 """
848 results = []
849
850 command = self.plugins["sockscan"](self.config)
851 for sock in command.calculate():
852 new = {
853 "offset": "{0:#010x}".format(sock.obj_offset),
854 "process_id": str(sock.Pid),
855 "address": str(sock.LocalIpAddress),
856 "port": str(sock.LocalPort),
857 "protocol": "{0} ({1})".format(sock.Protocol, protos.protos.get(sock.Protocol.v(), "-")),
858 "create_time": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(sock.CreateTime))),
859 }
860 results.append(new)
861
862 return dict(config={}, data=results)
863
865 """Volatility sockscan plugin.
866 @see volatility/plugins/netscan.py
867 """
868 results = []
869
870 command = self.plugins["netscan"](self.config)
871 for net_obj, proto, laddr, lport, raddr, rport, state in command.calculate():
872 new = {
873 "offset": "{0:#010x}".format(net_obj.obj_offset),
874 "process_id": str(net_obj.Owner.UniqueProcessId),
875 "local_address": str(laddr),
876 "local_port": str(lport),
877 "remote_address": str(raddr),
878 "remote_port": str(rport),
879 "protocol": str(proto),
880 }
881 results.append(new)
882
883 return dict(config={}, data=results)
884
885
887 """Handle several volatility results."""
888 PLUGINS = [
889 "pslist",
890 "psxview",
891 "callbacks",
892 ["idt", "x86"],
893 "ssdt",
894 ["gdt", "x86"],
895 "timers",
896 "messagehooks",
897 "getsids",
898 "privs",
899 "malfind",
900 "apihooks",
901 "dlllist",
902 "handles",
903 "ldrmodules",
904 "mutantscan",
905 "devicetree",
906 "svcscan",
907 "modscan",
908 "yarascan",
909 ["sockscan", "winxp"],
910 ["netscan", "vista", "win7"],
911 ]
912
913 - def __init__(self, memfile, osprofile=None):
914 self.mask_pid = []
915 self.taint_pid = set()
916 self.memfile = memfile
917
918 conf_path = os.path.join(CUCKOO_ROOT, "conf", "memory.conf")
919 if not os.path.exists(conf_path):
920 log.error("Configuration file {0} not found".format(conf_path))
921 self.voptions = False
922 return
923
924 self.voptions = Config("memory")
925
926 for pid in self.voptions.mask.pid_generic.split(","):
927 pid = pid.strip()
928 if pid:
929 self.mask_pid.append(int(pid))
930
931 self.no_filter = not self.voptions.mask.enabled
932 if self.voptions.basic.guest_profile:
933 self.osprofile = self.voptions.basic.guest_profile
934 else:
935 self.osprofile = osprofile or self.get_osprofile()
936
940
942 results = {}
943
944
945 if not self.voptions:
946 return
947
948 vol = VolatilityAPI(self.memfile, self.osprofile)
949
950 for plugin_name in self.PLUGINS:
951 if isinstance(plugin_name, list):
952 plugin_name, profiles = plugin_name[0], plugin_name[1:]
953 else:
954 profiles = []
955
956
957
958 osp = self.osprofile.lower()
959 for profile in profiles:
960 if osp.startswith(profile) or osp.endswith(profile):
961 break
962 else:
963 if profiles:
964 continue
965
966 plugin = self.voptions.get(plugin_name)
967 if not plugin or not plugin.enabled:
968 log.debug("Skipping '%s' volatility module", plugin_name)
969 continue
970
971 if plugin_name in vol.plugins:
972 log.debug("Executing volatility '%s' module.", plugin_name)
973 results[plugin_name] = getattr(vol, plugin_name)()
974
975 self.find_taint(results)
976 self.cleanup()
977
978 return self.mask_filter(results)
979
981 """Filter out masked stuff. Keep tainted stuff."""
982 new = {}
983
984 for akey in old.keys():
985 new[akey] = {"config": old[akey]["config"], "data": []}
986 conf = getattr(self.voptions, akey, None)
987 new[akey]["config"]["filter"] = conf.filter
988 for item in old[akey]["data"]:
989
990 if not conf.filter:
991 new[akey]["data"].append(item)
992 elif "process_id" in item and \
993 item["process_id"] in self.mask_pid and \
994 item["process_id"] not in self.taint_pid:
995 pass
996 else:
997 new[akey]["data"].append(item)
998 return new
999
1001 """Find tainted items."""
1002 if "malfind" in res:
1003 for item in res["malfind"]["data"]:
1004 self.taint_pid.add(item["process_id"])
1005
1007 """Delete the memory dump (if configured to do so)."""
1008
1009 if self.voptions.basic.delete_memdump:
1010 try:
1011 os.remove(self.memfile)
1012 except OSError:
1013 log.error("Unable to delete memory dump file at path \"%s\" ", self.memfile)
1014
1016 """Volatility Analyzer."""
1017
1019 """Run analysis.
1020 @return: volatility results dict.
1021 """
1022 self.key = "memory"
1023
1024 results = {}
1025 if HAVE_VOLATILITY:
1026 if self.memory_path and os.path.exists(self.memory_path):
1027 try:
1028 results = VolatilityManager(self.memory_path).run()
1029 except Exception:
1030 log.exception("Generic error executing volatility")
1031 else:
1032 log.error("Memory dump not found: to run volatility you have to enable memory_dump")
1033 else:
1034 log.error("Cannot run volatility module: volatility library not available")
1035
1036 return results
1037