mirror of
https://github.com/mandiant/capa.git
synced 2025-12-22 07:10:29 -08:00
double to single quotes
This commit is contained in:
@@ -10,7 +10,7 @@ try:
|
||||
except (ImportError, SyntaxError):
|
||||
pass
|
||||
|
||||
__all__ = ["ida", "viv"]
|
||||
__all__ = ['ida', 'viv']
|
||||
|
||||
|
||||
class FeatureExtractor(object):
|
||||
|
||||
@@ -7,13 +7,13 @@ import re
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
ASCII_BYTE = r" !\"#\$%&\'\(\)\*\+,-\./0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\}\\\~\t".encode('ascii')
|
||||
ASCII_RE_4 = re.compile(b"([%s]{%d,})" % (ASCII_BYTE, 4))
|
||||
UNICODE_RE_4 = re.compile(b"((?:[%s]\x00){%d,})" % (ASCII_BYTE, 4))
|
||||
REPEATS = [b"A", b"\x00", b"\xfe", b"\xff"]
|
||||
ASCII_BYTE = r' !\"#\$%&\'\(\)\*\+,-\./0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\}\\\~\t'.encode('ascii')
|
||||
ASCII_RE_4 = re.compile(b'([%s]{%d,})' % (ASCII_BYTE, 4))
|
||||
UNICODE_RE_4 = re.compile(b'((?:[%s]\x00){%d,})' % (ASCII_BYTE, 4))
|
||||
REPEATS = [b'A', b'\x00', b'\xfe', b'\xff']
|
||||
SLICE_SIZE = 4096
|
||||
|
||||
String = namedtuple("String", ["s", "offset"])
|
||||
String = namedtuple('String', ['s', 'offset'])
|
||||
|
||||
|
||||
def buf_filled_with(buf, character):
|
||||
@@ -46,10 +46,10 @@ def extract_ascii_strings(buf, n=4):
|
||||
if n == 4:
|
||||
r = ASCII_RE_4
|
||||
else:
|
||||
reg = b"([%s]{%d,})" % (ASCII_BYTE, n)
|
||||
reg = b'([%s]{%d,})' % (ASCII_BYTE, n)
|
||||
r = re.compile(reg)
|
||||
for match in r.finditer(buf):
|
||||
yield String(match.group().decode("ascii"), match.start())
|
||||
yield String(match.group().decode('ascii'), match.start())
|
||||
|
||||
|
||||
def extract_unicode_strings(buf, n=4):
|
||||
@@ -72,11 +72,11 @@ def extract_unicode_strings(buf, n=4):
|
||||
if n == 4:
|
||||
r = UNICODE_RE_4
|
||||
else:
|
||||
reg = b"((?:[%s]\x00){%d,})" % (ASCII_BYTE, n)
|
||||
reg = b'((?:[%s]\x00){%d,})' % (ASCII_BYTE, n)
|
||||
r = re.compile(reg)
|
||||
for match in r.finditer(buf):
|
||||
try:
|
||||
yield String(match.group().decode("utf-16"), match.start())
|
||||
yield String(match.group().decode('utf-16'), match.start())
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import file
|
||||
import function
|
||||
import basicblock
|
||||
import insn
|
||||
__all__ = ["file", "function", "basicblock", "insn"]
|
||||
__all__ = ['file', 'function', 'basicblock', 'insn']
|
||||
|
||||
|
||||
def get_va(self):
|
||||
|
||||
@@ -237,17 +237,17 @@ def main(argv=None):
|
||||
]
|
||||
format_help = ', '.join(['%s: %s' % (f[0], f[1]) for f in formats])
|
||||
|
||||
parser = argparse.ArgumentParser(description="save capa features to a file")
|
||||
parser.add_argument("sample", type=str,
|
||||
help="Path to sample to analyze")
|
||||
parser.add_argument("output", type=str,
|
||||
help="Path to output file")
|
||||
parser.add_argument("-v", "--verbose", action="store_true",
|
||||
help="Enable verbose output")
|
||||
parser.add_argument("-q", "--quiet", action="store_true",
|
||||
help="Disable all output but errors")
|
||||
parser.add_argument("-f", "--format", choices=[f[0] for f in formats], default="auto",
|
||||
help="Select sample format, %s" % format_help)
|
||||
parser = argparse.ArgumentParser(description='save capa features to a file')
|
||||
parser.add_argument('sample', type=str,
|
||||
help='Path to sample to analyze')
|
||||
parser.add_argument('output', type=str,
|
||||
help='Path to output file')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Enable verbose output')
|
||||
parser.add_argument('-q', '--quiet', action='store_true',
|
||||
help='Disable all output but errors')
|
||||
parser.add_argument('-f', '--format', choices=[f[0] for f in formats], default='auto',
|
||||
help='Select sample format, %s' % format_help)
|
||||
args = parser.parse_args(args=argv)
|
||||
|
||||
if args.quiet:
|
||||
@@ -271,6 +271,6 @@ def main(argv=None):
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(main())
|
||||
|
||||
@@ -362,7 +362,7 @@ class CapaExplorerForm(idaapi.PluginForm):
|
||||
technique = parts[2].replace('-', ' ')
|
||||
techniques.add(technique)
|
||||
if len(parts) > 3:
|
||||
raise capa.rules.InvalidRule(capa.main.RULE_CATEGORY + " tag must have at most three components")
|
||||
raise capa.rules.InvalidRule(capa.main.RULE_CATEGORY + ' tag must have at most three components')
|
||||
|
||||
# set row count to max set size
|
||||
self._view_summary.setRowCount(max(map(len, (rules, objectives, behaviors, techniques))))
|
||||
|
||||
102
capa/main.py
102
capa/main.py
@@ -221,7 +221,7 @@ def render_capabilities_default(ruleset, results):
|
||||
technique = parts[2].replace('-', ' ')
|
||||
techniques.add(technique)
|
||||
if len(parts) > 3:
|
||||
raise capa.rules.InvalidRule(RULE_CATEGORY + " tag must have at most three components")
|
||||
raise capa.rules.InvalidRule(RULE_CATEGORY + ' tag must have at most three components')
|
||||
|
||||
if technique:
|
||||
o[objective][behavior][technique][rule.name] = rule
|
||||
@@ -349,7 +349,7 @@ def render_result(res, indent=''):
|
||||
if sum(map(lambda c: c.success, res.children)) > 0:
|
||||
print('%soptional:' % indent)
|
||||
else:
|
||||
print("%s%d or more" % (indent, res.statement.count))
|
||||
print('%s%d or more' % (indent, res.statement.count))
|
||||
elif not isinstance(res.statement, (capa.features.Feature, capa.engine.Element, capa.engine.Range, capa.engine.Regex)):
|
||||
# when rending a structural node (and/or/not),
|
||||
# then we only care about the node name.
|
||||
@@ -517,7 +517,7 @@ def get_rules(rule_path):
|
||||
with open(rule_path, 'rb') as f:
|
||||
rule = capa.rules.Rule.from_yaml(f.read().decode('utf-8'))
|
||||
|
||||
if is_nursery_rule_path(root):
|
||||
if is_nursery_rule_path(rule_path):
|
||||
rule.meta['nursery'] = True
|
||||
|
||||
rules.append(rule)
|
||||
@@ -637,35 +637,35 @@ def main(argv=None):
|
||||
try:
|
||||
extractor = get_extractor(args.sample, args.format)
|
||||
except UnsupportedFormatError:
|
||||
logger.error("-" * 80)
|
||||
logger.error(" Input file does not appear to be a PE file.")
|
||||
logger.error(" ")
|
||||
logger.error(" Today, capa currently only supports analyzing PE files (or shellcode, when using --format sc32|sc64).")
|
||||
logger.error(" If you don't know the input file type, you can try using the `file` utility to guess it.")
|
||||
logger.error("-" * 80)
|
||||
logger.error('-' * 80)
|
||||
logger.error(' Input file does not appear to be a PE file.')
|
||||
logger.error(' ')
|
||||
logger.error(' Today, capa currently only supports analyzing PE files (or shellcode, when using --format sc32|sc64).')
|
||||
logger.error(' If you don\'t know the input file type, you can try using the `file` utility to guess it.')
|
||||
logger.error('-' * 80)
|
||||
return -1
|
||||
except UnsupportedRuntimeError:
|
||||
logger.error("-" * 80)
|
||||
logger.error(" Unsupported runtime or Python interpreter.")
|
||||
logger.error(" ")
|
||||
logger.error(" Today, capa supports running under Python 2.7 using Vivisect for binary analysis.")
|
||||
logger.error(" It can also run within IDA Pro, using either Python 2.7 or 3.5+.")
|
||||
logger.error(" ")
|
||||
logger.error(" If you're seeing this message on the command line, please ensure you're running Python 2.7.")
|
||||
logger.error("-" * 80)
|
||||
logger.error('-' * 80)
|
||||
logger.error(' Unsupported runtime or Python interpreter.')
|
||||
logger.error(' ')
|
||||
logger.error(' Today, capa supports running under Python 2.7 using Vivisect for binary analysis.')
|
||||
logger.error(' It can also run within IDA Pro, using either Python 2.7 or 3.5+.')
|
||||
logger.error(' ')
|
||||
logger.error(' If you\'re seeing this message on the command line, please ensure you\'re running Python 2.7.')
|
||||
logger.error('-' * 80)
|
||||
return -1
|
||||
|
||||
capabilities = find_capabilities(rules, extractor)
|
||||
|
||||
if appears_rule_cat(rules, capabilities, 'other-features/installer/'):
|
||||
logger.warning("-" * 80)
|
||||
logger.warning(" This sample appears to be an installer.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" capa cannot handle installers well. This means the results may be misleading or incomplete.")
|
||||
logger.warning(" You should try to understand the install mechanism and analyze created files with capa.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" Use -v or -vv if you really want to see the capabilities identified by capa.")
|
||||
logger.warning("-" * 80)
|
||||
logger.warning('-' * 80)
|
||||
logger.warning(' This sample appears to be an installer.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' capa cannot handle installers well. This means the results may be misleading or incomplete.')
|
||||
logger.warning(' You should try to understand the install mechanism and analyze created files with capa.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' Use -v or -vv if you really want to see the capabilities identified by capa.')
|
||||
logger.warning('-' * 80)
|
||||
# capa will likely detect installer specific functionality.
|
||||
# this is probably not what the user wants.
|
||||
#
|
||||
@@ -674,16 +674,16 @@ def main(argv=None):
|
||||
return -1
|
||||
|
||||
if appears_rule_cat(rules, capabilities, 'other-features/compiled-to-dot-net'):
|
||||
logger.warning("-" * 80)
|
||||
logger.warning(" This sample appears to be a .NET module.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" .NET is a cross-platform framework for running managed applications.")
|
||||
logger.warning('-' * 80)
|
||||
logger.warning(' This sample appears to be a .NET module.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' .NET is a cross-platform framework for running managed applications.')
|
||||
logger.warning(
|
||||
" Today, capa cannot handle non-native files. This means that the results may be misleading or incomplete.")
|
||||
logger.warning(" You may have to analyze the file manually, using a tool like the .NET decompiler dnSpy.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" Use -v or -vv if you really want to see the capabilities identified by capa.")
|
||||
logger.warning("-" * 80)
|
||||
' Today, capa cannot handle non-native files. This means that the results may be misleading or incomplete.')
|
||||
logger.warning(' You may have to analyze the file manually, using a tool like the .NET decompiler dnSpy.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' Use -v or -vv if you really want to see the capabilities identified by capa.')
|
||||
logger.warning('-' * 80)
|
||||
# capa won't detect much in .NET samples.
|
||||
# it might match some file-level things.
|
||||
# for consistency, bail on things that we don't support.
|
||||
@@ -693,16 +693,16 @@ def main(argv=None):
|
||||
return -1
|
||||
|
||||
if appears_rule_cat(rules, capabilities, 'other-features/compiled-with-autoit'):
|
||||
logger.warning("-" * 80)
|
||||
logger.warning(" This sample appears to be compiled with AutoIt.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" AutoIt is a freeware BASIC-like scripting language designed for automating the Windows GUI.")
|
||||
logger.warning('-' * 80)
|
||||
logger.warning(' This sample appears to be compiled with AutoIt.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' AutoIt is a freeware BASIC-like scripting language designed for automating the Windows GUI.')
|
||||
logger.warning(
|
||||
" Today, capa cannot handle AutoIt scripts. This means that the results will be misleading or incomplete.")
|
||||
logger.warning(" You may have to analyze the file manually, using a tool like the AutoIt decompiler MyAut2Exe.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" Use -v or -vv if you really want to see the capabilities identified by capa.")
|
||||
logger.warning("-" * 80)
|
||||
' Today, capa cannot handle AutoIt scripts. This means that the results will be misleading or incomplete.')
|
||||
logger.warning(' You may have to analyze the file manually, using a tool like the AutoIt decompiler MyAut2Exe.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' Use -v or -vv if you really want to see the capabilities identified by capa.')
|
||||
logger.warning('-' * 80)
|
||||
# capa will detect dozens of capabilities for AutoIt samples,
|
||||
# but these are due to the AutoIt runtime, not the payload script.
|
||||
# so, don't confuse the user with FP matches - bail instead
|
||||
@@ -712,13 +712,13 @@ def main(argv=None):
|
||||
return -1
|
||||
|
||||
if appears_rule_cat(rules, capabilities, 'anti-analysis/packing/'):
|
||||
logger.warning("-" * 80)
|
||||
logger.warning(" This sample appears packed.")
|
||||
logger.warning(" ")
|
||||
logger.warning(" Packed samples have often been obfuscated to hide their logic.")
|
||||
logger.warning(" capa cannot handle obfuscation well. This means the results may be misleading or incomplete.")
|
||||
logger.warning(" If possible, you should try to unpack this input file before analyzing it with capa.")
|
||||
logger.warning("-" * 80)
|
||||
logger.warning('-' * 80)
|
||||
logger.warning(' This sample appears packed.')
|
||||
logger.warning(' ')
|
||||
logger.warning(' Packed samples have often been obfuscated to hide their logic.')
|
||||
logger.warning(' capa cannot handle obfuscation well. This means the results may be misleading or incomplete.')
|
||||
logger.warning(' If possible, you should try to unpack this input file before analyzing it with capa.')
|
||||
logger.warning('-' * 80)
|
||||
|
||||
if args.vverbose:
|
||||
render_capabilities_vverbose(capabilities)
|
||||
@@ -770,7 +770,7 @@ def is_runtime_ida():
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
if is_runtime_ida():
|
||||
ida_main()
|
||||
else:
|
||||
|
||||
@@ -28,13 +28,13 @@ def main(argv=None):
|
||||
]
|
||||
format_help = ', '.join(['%s: %s' % (f[0], f[1]) for f in formats])
|
||||
|
||||
parser = argparse.ArgumentParser(description="detect capabilities in programs.")
|
||||
parser.add_argument("sample", type=str,
|
||||
help="Path to sample to analyze")
|
||||
parser.add_argument("-f", "--format", choices=[f[0] for f in formats], default="auto",
|
||||
help="Select sample format, %s" % format_help)
|
||||
parser.add_argument("-F", "--function", type=lambda x: int(x, 0),
|
||||
help="Show features for specific function")
|
||||
parser = argparse.ArgumentParser(description='detect capabilities in programs.')
|
||||
parser.add_argument('sample', type=str,
|
||||
help='Path to sample to analyze')
|
||||
parser.add_argument('-f', '--format', choices=[f[0] for f in formats], default='auto',
|
||||
help='Select sample format, %s' % format_help)
|
||||
parser.add_argument('-F', '--function', type=lambda x: int(x, 0),
|
||||
help='Show features for specific function')
|
||||
args = parser.parse_args(args=argv)
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
@@ -77,5 +77,5 @@ def main(argv=None):
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -26,7 +26,7 @@ def main():
|
||||
fnames = {}
|
||||
for f in idautils.Functions():
|
||||
fname = idc.get_name(f)
|
||||
if fname.startswith("sub_"):
|
||||
if fname.startswith('sub_'):
|
||||
continue
|
||||
|
||||
name_demangled = idc.demangle_name(fname, INF_SHORT_DN_ATTR)
|
||||
@@ -35,12 +35,12 @@ def main():
|
||||
|
||||
fnames[f] = fname
|
||||
|
||||
with open(idc.ARGV[1], "w") as f:
|
||||
with open(idc.ARGV[1], 'w') as f:
|
||||
json.dump(fnames, f)
|
||||
|
||||
# exit IDA
|
||||
idc.qexit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -40,5 +40,5 @@ def main():
|
||||
idc.qexit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -66,15 +66,15 @@ def main(argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
parser = argparse.ArgumentParser(description="Freeze capa features of a file or of files in a directory")
|
||||
parser.add_argument("file_path", type=str,
|
||||
help="Path to file or directory to analyze")
|
||||
parser.add_argument("-r", "--reprocess", action="store_true", default=False,
|
||||
help="Overwrite existing analysis")
|
||||
parser.add_argument("-v", "--verbose", action="store_true",
|
||||
help="Enable verbose output")
|
||||
parser.add_argument("-q", "--quiet", action="store_true",
|
||||
help="Disable all output but errors")
|
||||
parser = argparse.ArgumentParser(description='Freeze capa features of a file or of files in a directory')
|
||||
parser.add_argument('file_path', type=str,
|
||||
help='Path to file or directory to analyze')
|
||||
parser.add_argument('-r', '--reprocess', action='store_true', default=False,
|
||||
help='Overwrite existing analysis')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Enable verbose output')
|
||||
parser.add_argument('-q', '--quiet', action='store_true',
|
||||
help='Disable all output but errors')
|
||||
args = parser.parse_args(args=argv)
|
||||
|
||||
if args.quiet:
|
||||
@@ -98,5 +98,5 @@ def main(argv=None):
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -217,23 +217,23 @@ def main(argv=None):
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
parser = argparse.ArgumentParser(description="Run capa rule file against frozen features in a directory")
|
||||
parser.add_argument("rules", type=str,
|
||||
help="Path to directory containing rules")
|
||||
parser.add_argument("rule_name", type=str,
|
||||
help="Name of rule to test")
|
||||
parser.add_argument("frozen_path", type=str,
|
||||
help="Path to frozen feature file or directory")
|
||||
parser.add_argument("-f", "--fast", action="store_true",
|
||||
help="Don't test slow files")
|
||||
parser.add_argument("-o", "--only_matching", action="store_true",
|
||||
help="Print only if rule matches")
|
||||
parser.add_argument("-s", "--save_image", action="store",
|
||||
help="Directory to save exported images of function graphs")
|
||||
parser.add_argument("-v", "--verbose", action="count", default=0,
|
||||
help="Increase output verbosity")
|
||||
parser.add_argument("-q", "--quiet", action="store_true",
|
||||
help="Disable all output but errors")
|
||||
parser = argparse.ArgumentParser(description='Run capa rule file against frozen features in a directory')
|
||||
parser.add_argument('rules', type=str,
|
||||
help='Path to directory containing rules')
|
||||
parser.add_argument('rule_name', type=str,
|
||||
help='Name of rule to test')
|
||||
parser.add_argument('frozen_path', type=str,
|
||||
help='Path to frozen feature file or directory')
|
||||
parser.add_argument('-f', '--fast', action='store_true',
|
||||
help='Don't test slow files')
|
||||
parser.add_argument('-o', '--only_matching', action='store_true',
|
||||
help='Print only if rule matches')
|
||||
parser.add_argument('-s', '--save_image', action='store',
|
||||
help='Directory to save exported images of function graphs')
|
||||
parser.add_argument('-v', '--verbose', action='count', default=0,
|
||||
help='Increase output verbosity')
|
||||
parser.add_argument('-q', '--quiet', action='store_true',
|
||||
help='Disable all output but errors')
|
||||
args = parser.parse_args(args=argv)
|
||||
|
||||
if args.quiet:
|
||||
@@ -293,5 +293,5 @@ def main(argv=None):
|
||||
print_summary(args.verbose, time0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -85,13 +85,13 @@ def get_function_names(fnames_file):
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Launch IDA Pro in autonomous mode to dump function names of a file or of files in a directory")
|
||||
parser.add_argument("file_path", type=str,
|
||||
help="File or directory path to analyze")
|
||||
parser.add_argument("-r", "--reprocess", action="store_true", default=False,
|
||||
help="Overwrite existing analysis")
|
||||
parser.add_argument("-v", "--verbose", action="store_true",
|
||||
help="Enable verbose output")
|
||||
description='Launch IDA Pro in autonomous mode to dump function names of a file or of files in a directory')
|
||||
parser.add_argument('file_path', type=str,
|
||||
help='File or directory path to analyze')
|
||||
parser.add_argument('-r', '--reprocess', action='store_true', default=False,
|
||||
help='Overwrite existing analysis')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Enable verbose output')
|
||||
args = parser.parse_args(args=sys.argv[1:])
|
||||
|
||||
if args.verbose:
|
||||
@@ -127,5 +127,5 @@ def main():
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -101,17 +101,17 @@ def get_md5_hexdigest(sample_path):
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Launch IDA Pro in autonomous mode to export images of function graphs")
|
||||
parser.add_argument("file_path", type=str,
|
||||
help="File to export from")
|
||||
parser.add_argument("out_dir", type=str,
|
||||
help="Export target directory")
|
||||
parser.add_argument("-f", "--functions", action="store",
|
||||
help="Comma separated list of functions to export")
|
||||
parser.add_argument("-m", "--manual", action="store_true",
|
||||
help="Manual mode: show IDA dialog boxes")
|
||||
parser.add_argument("-v", "--verbose", action="store_true",
|
||||
help="Enable verbose output")
|
||||
description='Launch IDA Pro in autonomous mode to export images of function graphs')
|
||||
parser.add_argument('file_path', type=str,
|
||||
help='File to export from')
|
||||
parser.add_argument('out_dir', type=str,
|
||||
help='Export target directory')
|
||||
parser.add_argument('-f', '--functions', action='store',
|
||||
help='Comma separated list of functions to export')
|
||||
parser.add_argument('-m', '--manual', action='store_true',
|
||||
help='Manual mode: show IDA dialog boxes')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Enable verbose output')
|
||||
args = parser.parse_args(args=sys.argv[1:])
|
||||
|
||||
if args.verbose:
|
||||
@@ -131,5 +131,5 @@ def main():
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
34
setup.py
34
setup.py
@@ -5,26 +5,26 @@ import setuptools
|
||||
|
||||
|
||||
requirements = [
|
||||
"six",
|
||||
"tqdm",
|
||||
"pyyaml",
|
||||
"tabulate",
|
||||
'six',
|
||||
'tqdm',
|
||||
'pyyaml',
|
||||
'tabulate',
|
||||
]
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
# py3
|
||||
requirements.append("networkx")
|
||||
requirements.append('networkx')
|
||||
else:
|
||||
# py2
|
||||
requirements.append("enum34")
|
||||
requirements.append("vivisect")
|
||||
requirements.append("viv-utils")
|
||||
requirements.append("networkx==2.2") # v2.2 is last version supported by Python 2.7
|
||||
requirements.append('enum34')
|
||||
requirements.append('vivisect')
|
||||
requirements.append('viv-utils')
|
||||
requirements.append('networkx==2.2') # v2.2 is last version supported by Python 2.7
|
||||
|
||||
# this sets __version__
|
||||
# via: http://stackoverflow.com/a/7071358/87207
|
||||
# and: http://stackoverflow.com/a/2073599/87207
|
||||
with open(os.path.join("capa", "version.py"), "rb") as f:
|
||||
with open(os.path.join('capa', 'version.py'), 'rb') as f:
|
||||
exec(f.read())
|
||||
|
||||
|
||||
@@ -35,17 +35,17 @@ def get_rule_paths():
|
||||
setuptools.setup(
|
||||
name='capa',
|
||||
version=__version__,
|
||||
description="",
|
||||
long_description="",
|
||||
author="Willi Ballenthin, Moritz Raabe",
|
||||
description='',
|
||||
long_description='',
|
||||
author='Willi Ballenthin, Moritz Raabe',
|
||||
author_email='william.ballenthin@mandiant.com, moritz.raabe@mandiant.com',
|
||||
url='https://www.github.com/fireeye/capa',
|
||||
packages=setuptools.find_packages(exclude=['tests', 'testbed']),
|
||||
package_dir={'capa': 'capa'},
|
||||
package_data={'capa': get_rule_paths()},
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"capa=capa.main:main",
|
||||
'console_scripts': [
|
||||
'capa=capa.main:main',
|
||||
]
|
||||
},
|
||||
include_package_data=True,
|
||||
@@ -56,7 +56,7 @@ setuptools.setup(
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Intended Audience :: Developers',
|
||||
'Natural Language :: English',
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 3",
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 3',
|
||||
],
|
||||
)
|
||||
|
||||
@@ -159,12 +159,12 @@ def test_serialize_features():
|
||||
|
||||
def test_freeze_sample(tmpdir, sample_9324d1a8ae37a36ae560c37448c9705a):
|
||||
# tmpdir fixture handles cleanup
|
||||
o = tmpdir.mkdir("capa").join("test.frz").strpath
|
||||
o = tmpdir.mkdir('capa').join('test.frz').strpath
|
||||
assert capa.features.freeze.main([sample_9324d1a8ae37a36ae560c37448c9705a.path, o, '-v']) == 0
|
||||
|
||||
|
||||
def test_freeze_load_sample(tmpdir, sample_9324d1a8ae37a36ae560c37448c9705a):
|
||||
o = tmpdir.mkdir("capa").join("test.frz")
|
||||
o = tmpdir.mkdir('capa').join('test.frz')
|
||||
viv_extractor = capa.features.extractors.viv.VivisectFeatureExtractor(sample_9324d1a8ae37a36ae560c37448c9705a.vw,
|
||||
sample_9324d1a8ae37a36ae560c37448c9705a.path)
|
||||
with open(o.strpath, 'wb') as f:
|
||||
|
||||
@@ -15,6 +15,21 @@ def test_main(sample_9324d1a8ae37a36ae560c37448c9705a):
|
||||
assert capa.main.main([sample_9324d1a8ae37a36ae560c37448c9705a.path, '-v']) == 0
|
||||
|
||||
|
||||
def test_main_single_rule(sample_9324d1a8ae37a36ae560c37448c9705a, tmpdir):
|
||||
# tests a single rule can be loaded successfully
|
||||
RULE_CONTENT = textwrap.dedent('''
|
||||
rule:
|
||||
meta:
|
||||
name: test rule
|
||||
scope: file
|
||||
features:
|
||||
- string: test
|
||||
''')
|
||||
rule_file = tmpdir.mkdir('capa').join('rule.yml')
|
||||
rule_file.write(RULE_CONTENT)
|
||||
assert capa.main.main([sample_9324d1a8ae37a36ae560c37448c9705a.path, '-v', '-r', rule_file.strpath]) == 0
|
||||
|
||||
|
||||
def test_main_shellcode(sample_499c2a85f6e8142c3f48d4251c9c7cd6_raw32):
|
||||
assert capa.main.main([sample_499c2a85f6e8142c3f48d4251c9c7cd6_raw32.path, '-v', '-f', 'sc32']) == 0
|
||||
|
||||
|
||||
@@ -82,14 +82,14 @@ def test_string_features(mimikatz):
|
||||
|
||||
def test_byte_features(sample_9324d1a8ae37a36ae560c37448c9705a):
|
||||
features = extract_function_features(viv_utils.Function(sample_9324d1a8ae37a36ae560c37448c9705a.vw, 0x406F60))
|
||||
wanted = capa.features.Bytes(b"\xED\x24\x9E\xF4\x52\xA9\x07\x47\x55\x8E\xE1\xAB\x30\x8E\x23\x61")
|
||||
wanted = capa.features.Bytes(b'\xED\x24\x9E\xF4\x52\xA9\x07\x47\x55\x8E\xE1\xAB\x30\x8E\x23\x61')
|
||||
# use `==` rather than `is` because the result is not `True` but a truthy value.
|
||||
assert wanted.evaluate(features) == True
|
||||
|
||||
|
||||
def test_byte_features64(sample_lab21_01):
|
||||
features = extract_function_features(viv_utils.Function(sample_lab21_01.vw, 0x1400010C0))
|
||||
wanted = capa.features.Bytes(b"\x32\xA2\xDF\x2D\x99\x2B\x00\x00")
|
||||
wanted = capa.features.Bytes(b'\x32\xA2\xDF\x2D\x99\x2B\x00\x00')
|
||||
# use `==` rather than `is` because the result is not `True` but a truthy value.
|
||||
assert wanted.evaluate(features) == True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user