Skip to content

Commit

Permalink
Updates, package improvements and bugfixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevoreilly committed Mar 8, 2017
1 parent ade2a11 commit d877b35
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 278 deletions.
Binary file modified analyzer/windows/bin/loader.exe
Binary file not shown.
Binary file modified analyzer/windows/bin/loader_x64.exe
Binary file not shown.
Binary file modified analyzer/windows/dll/CAPE_Extraction.dll
Binary file not shown.
Binary file modified analyzer/windows/dll/CAPE_UPX.dll
Binary file not shown.
Binary file modified analyzer/windows/dll/cuckoomon.dll
Binary file not shown.
Binary file modified analyzer/windows/dll/cuckoomon_x64.dll
Binary file not shown.
8 changes: 7 additions & 1 deletion analyzer/windows/lib/common/abstracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def debug(self, path, args, interest):
@return: process pid
"""
dll = self.options.get("dll")
dll_64 = self.options.get("dll_64")
gw = self.options.get("setgw", None)

u = Utils()
Expand All @@ -168,7 +169,12 @@ def debug(self, path, args, interest):
raise CuckooPackageError("Unable to execute the initial process, "
"analysis aborted.")

p.debug_inject(dll, interest, childprocess=False)
is_64bit = p.is_64bit()

if is_64bit:
p.debug_inject(dll_64, interest, childprocess=False)
else:
p.debug_inject(dll, interest, childprocess=False)
p.resume()
p.close()

Expand Down
4 changes: 1 addition & 3 deletions analyzer/windows/modules/packages/CAPE_Extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ def __init__(self, options={}, config=None):
self.options = options
self.pids = []
self.options["dll"] = "CAPE_Extraction.dll"
self.options["procmemdump"] = '0'
self.options["dll_64"] = "CAPE_Extraction_x64.dll"

def start(self, path):
self.options["dll"] = "CAPE_Extraction.dll"
self.options["procmemdump"] = '0'
arguments = self.options.get("arguments")

# If the file doesn't have an extension, add .exe
Expand Down
69 changes: 7 additions & 62 deletions modules/machinery/vmwareserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,6 @@ def _initialize_check(self):
raise CuckooMachineError("VMware vmrun path missing, "
"please add it to vmwareserver.conf")

# if not os.path.exists(self.options.vmwareserver.path):
# raise CuckooMachineError("VMware vmrun not found in "
# "specified path %s" %
# self.options.vmwareserver.path)
# Consistency checks.
# for machine in self.machines():
# vmx_path = machine.label

# snapshot = self._snapshot_from_vmx(vmx_path)
# self._check_vmx(vmx_path)
self._check_snapshot(vmx_path, snapshot)

# Base checks.
Expand All @@ -59,7 +49,7 @@ def _check_snapshot(self, vmx_path, snapshot):
@param snapshot: snapshot name
@raise CuckooMachineError: if snapshot not found
"""
#check_string = "strace " + \

check_string = self.options.vmwareserver.path + \
" -T ws-shared -h " + \
self.options.vmwareserver.vmware_url + \
Expand Down Expand Up @@ -88,9 +78,8 @@ def start(self, vmx_path):
"""
snapshot = self._snapshot_from_vmx(vmx_path)

# Preventive check
# Check if the machine is already running, stop if so.
if self._is_running(vmx_path):
#raise CuckooMachineError("Machine %s is already running" % vmx_path)
log.debug("Machine %s is already running, attempting to stop..." % vmx_path)
self.stop(vmx_path)
time.sleep(3)
Expand All @@ -99,7 +88,6 @@ def start(self, vmx_path):

time.sleep(3)

#start_string = "strace " + \
start_string = self.options.vmwareserver.path + \
" -T ws-shared -h " + \
self.options.vmwareserver.vmware_url + \
Expand All @@ -126,8 +114,7 @@ def stop(self, vmx_path):
@param vmx_path: path to vmx file
@raise CuckooMachineError: if unable to stop.
"""
#stop_string = "strace " + \
#self.options.vmwareserver.path + \

stop_string = self.options.vmwareserver.path + \
" -T ws-shared -h " + \
self.options.vmwareserver.vmware_url + \
Expand Down Expand Up @@ -159,15 +146,15 @@ def _revert(self, vmx_path, snapshot):
"""
log.debug("Revert snapshot for vm %s: %s" % (vmx_path, snapshot))

#revert_string = "strace " + \
#self.options.vmwareserver.path + \
revert_string = self.options.vmwareserver.path + \
" -T ws-shared -h " + \
self.options.vmwareserver.vmware_url + \
" -u " + self.options.vmwareserver.username + \
" -p " + self.options.vmwareserver.password + \
" revertToSnapshot " + "\"" + vmx_path + "\" " + snapshot

#log.debug("Revert string: %s" % revert_string)

try:
if subprocess.call(revert_string, shell=True):
raise CuckooMachineError("Unable to revert snapshot for "
Expand All @@ -183,21 +170,17 @@ def _is_running(self, vmx_path):
@param vmx_path: path to vmx file
@return: running status
"""
#list_string = "strace " + \
#self.options.vmwareserver.path + \
list_string = self.options.vmwareserver.path + \
" -T ws-shared -h " + \
self.options.vmwareserver.vmware_url + \
" -u " + self.options.vmwareserver.username + \
" -p " + self.options.vmwareserver.password + \
" list " + "\"" + vmx_path + "\""

#log.debug("List string: %s" % list_string)

try:
p = subprocess.Popen(list_string, stdout=subprocess.PIPE, shell=True)
#p = subprocess.Popen(list_string,
#p = subprocess.Popen([self.options.vmware.path, "list"],
#stdout=subprocess.PIPE,
#stderr=subprocess.PIPE)
output, error = p.communicate()
except OSError as e:
raise CuckooMachineError("Unable to check running status for %s. "
Expand All @@ -216,41 +199,3 @@ def _snapshot_from_vmx(self, vmx_path):
"""
vm_info = self.db.view_machine_by_label(vmx_path)
return vm_info.snapshot

def dump_memory(self, vmx_path, path):
"""Take a memory dump of the machine."""
if not os.path.exists(vmx_path):
raise CuckooMachineError("Can't find .vmx file {0}. Ensure to configure a fully qualified path in vmwareserver.conf (key = vmx_path)".format(vmx_path))

try:
subprocess.call([self.options.vmwareserver.path,
"-T ws-shared -h", self.options.vmwareserver.vmware_url,
"-u", self.options.vmwareserver.username, "-p", self.options.vmwareserver.password,
"snapshot",
vmx_path, "memdump"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError as e:
raise CuckooMachineError("vmrun failed to take a memory dump of the machine with label %s: %s" % (vmx_path, e))

vmwarepath, _ = os.path.split(vmx_path)
latestvmem = max(glob.iglob(os.path.join(vmwarepath, "*.vmem")),
key=os.path.getctime)

# We need to move the snapshot to the current analysis directory as
# vmware doesn't support an option for the destination path :-/
shutil.move(latestvmem, path)

# Old snapshot can be deleted, as it isn't needed any longer.
try:
subprocess.call([self.options.vmwareserver.path,
"-T ws-shared -h", vmware_url,
"-u", self.options.vmwareserver.username, "-p", self.options.vmwareserver.password,
"deleteSnapshot",
vmx_path, "memdump"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError as e:
raise CuckooMachineError("vmrun failed to delete the temporary snapshot in %s: %s" % (vmx_path, e))

log.info("Successfully generated memory dump for virtual machine with label %s ", vmx_path)
97 changes: 55 additions & 42 deletions modules/processing/parsers/mwcp/malwareconfigreporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class malwareconfigreporter(object):
metadata: Dictionary containing the metadata extracted from the malware by the parser
pe: a pefile object, assuming pefile is installed and succesful parsing of file
outputfiles: dictionary of entries for each ouput file. The key is the filename specified. Each entry
is a dictionary with keys of data and description. If the path key is set, the file was written
is a dictionary with keys of data, description, and md5. If the path key is set, the file was written
to that path on the filesystem.
fields: dictionary containing the standardized fields with each field comprising an embedded
dictionary. The 1st level keys are the field names. Under that, the keys are "description",
Expand Down Expand Up @@ -168,7 +168,7 @@ def filename(self):
else:
#we were passed data buffer. Lazy initialize a temp file for this
if not self.__tempfilename:
with tempfile.NamedTemporaryFile(delete=False,dir=self.tempdir,prefix="mwcp-inputfile-") as tfile:
with tempfile.NamedTemporaryFile(delete=False,dir=self.managed_tempdir(),prefix="mwcp-inputfile-") as tfile:
tfile.write(self.data)
self.__tempfilename = tfile.name

Expand Down Expand Up @@ -349,12 +349,12 @@ def __add_metadata_listofstringtuples(self, keyu, value):
if len(values) >= 2:
if values[1] not in ["tcp", "udp", "icmp"]:
self.debug("Expected port type to be tcp or udp (or icmp)")
elif keyu == "registrykeyvalue":
self.add_metadata("registrykey", values[0])
elif keyu == "registrypathdata":
self.add_metadata("registrypath", values[0])
if len(values) >= 2:
self.add_metadata("registryvalue", values[1])
self.add_metadata("registrydata", values[1])
if len(values) != 2:
self.debug("Expected two values in type registrykeyvalue, received %i" % len(values))
self.debug("Expected two values in type registrypathdata, received %i" % len(values))
elif keyu == "service":
if values[0]:
self.add_metadata("servicename", values[0])
Expand Down Expand Up @@ -463,9 +463,8 @@ def list_parsers(self):
if modulename[-len(self.__parsernamepostfix):] == self.__parsernamepostfix and len(modulename) > len(self.__parsernamepostfix):
parsers.append(modulename[:-len(self.__parsernamepostfix)])

return parsers


return sorted(parsers, key=lambda s: s.lower())

def load_parser_instance(self, name):
'''
Load parser instance by parser name
Expand Down Expand Up @@ -502,6 +501,8 @@ def get_parser_descriptions(self):
parserobj = self.load_parser_instance(parsername)
if parserobj:
descriptions.append((parsername, parserobj.author, parserobj.description))
else:
descriptions.append((parsername, "Parser exists but failed to load.", "Parser exists but failed to load."))
self.__return_stdout()
return descriptions
except (Exception, SystemExit) as e:
Expand Down Expand Up @@ -584,13 +585,14 @@ def output_file(self, data, filename, description=''):
filename: filename (basename) of file
description: description of the file
'''
self.outputfiles[filename] = {'data': data, 'description': description}
basename = os.path.basename(filename)
md5 = hashlib.md5(data).hexdigest()
self.outputfiles[filename] = {'data': data, 'description': description, 'md5': md5}

if self.__base64outputfiles:
self.add_metadata("outputfile", [basename, description, base64.b64encode(data)])
self.add_metadata("outputfile", [basename, description, md5, base64.b64encode(data)])
else:
self.add_metadata("outputfile", [basename, description])
self.add_metadata("outputfile", [basename, description, md5])

if self.__disableoutputfiles:
return
Expand Down Expand Up @@ -627,8 +629,8 @@ def format_list(self, values, key=None):

if key == "credential" and len(values) == 2:
return "%s:%s" % (values[0],values[1])
elif key == "outputfile" and len(values) >= 2:
return "%s %s" % (values[0],values[1])
elif key == "outputfile" and len(values) >= 3:
return "%s %s" % (values[0],values[1],values[2])
elif key == "port" and len(values) == 2:
return "%s/%s" % (values[0],values[1])
elif key == "listenport" and len(values) == 2:
Expand All @@ -645,67 +647,78 @@ def format_list(self, values, key=None):
return ' '.join(values)

def print_keyvalue(self, key, value):
printkey = key
print self.get_printable_key_value(key, value)

def output_text(self):
'''
Output in human readable report format
'''

if sys.stdout.encoding:
encoding = sys.stdout.encoding
else:
encoding = "utf8"
print self.get_output_text().encode("utf8")

def get_printable_key_value(self, key, value):
output = u""
printkey = key

if isinstance(value, basestring):
print((u'%-20s %s' % (printkey, value)).encode(encoding, 'backslashreplace'))
output += u"{:20} {}\n".format(printkey, value)
else:
for item in value:
if isinstance(item, basestring):
print((u'%-20s %s' % (printkey, item)).encode(encoding, 'backslashreplace'))
output += u"{:20} {}\n".format(printkey, item)
else:
print((u'%-20s %s' % (printkey, self.format_list(item, key=key))).encode(encoding, 'backslashreplace'))
printkey = ""

def output_text(self):
output += u"{:20} {}\n".format(printkey, self.format_list(item, key=key))
printkey = u""

return output

def get_output_text(self):
'''
Output in human readable report format
Get data in human readable report format.
'''


output = u""
infoorderlist = INFO_FIELD_ORDER
fieldorderlist = STANDARD_FIELD_ORDER

if 'inputfilename' in self.metadata:
print("\n----File Information----\n")
output += u"\n----File Information----\n\n"
for key in infoorderlist:
if key in self.metadata:
self.print_keyvalue(key,self.metadata[key])
output += self.get_printable_key_value(key, self.metadata[key])

print("\n----Standard Metadata----\n")
output += u"\n----Standard Metadata----\n\n"

for key in fieldorderlist:
if key in self.metadata:
self.print_keyvalue(key,self.metadata[key])
output += self.get_printable_key_value(key, self.metadata[key])

#in case we have additional fields in fields.json but the order is not updated
for key in self.metadata:
if key not in fieldorderlist and key not in ["other", "debug", "outputfile"] and key in self.fields:
self.print_keyvalue(key,self.metadata[key])
output += self.get_printable_key_value(key, self.metadata[key])

if "other" in self.metadata:
print("\n----Other Metadata----\n")
output += u"\n----Other Metadata----\n\n"
for key in sorted(list(self.metadata["other"])):
self.print_keyvalue(key,self.metadata["other"][key])
output += self.get_printable_key_value(key, self.metadata["other"][key])

if "debug" in self.metadata:
print("\n----Debug----\n")
#self.print_keyvalue("debug",self.metadata["debug"])
output += u"\n----Debug----\n\n"
for item in self.metadata["debug"]:
print(item)
output += u"{}\n".format(item)

if "outputfile" in self.metadata:
print("\n----Output Files----\n")
for key, value in self.metadata["outputfile"]:
self.print_keyvalue(key,value)
output += u"\n----Output Files----\n\n"
for value in self.metadata["outputfile"]:
output += self.get_printable_key_value(value[0], (value[1], value[2]))

if self.errors:
print("\n----Errors----\n")
output += u"\n----Errors----\n\n"
for item in self.errors:
print(item)
output += u"{}\n".format(item)

return output

def __redirect_stdout(self):
#we redirect stdout during execution of parser to trap the output
Expand Down
Loading

0 comments on commit d877b35

Please sign in to comment.