Merge branch 'master' into vverbose-output-scope-enhancement

This commit is contained in:
Michael Hunhoff
2020-06-25 13:23:00 -06:00
3 changed files with 122 additions and 67 deletions

View File

@@ -1,6 +1,36 @@
import logging
import idaapi
import idc
logger = logging.getLogger('capa')
# file type names as returned by idaapi.get_file_type_name()
SUPPORTED_FILE_TYPES = [
'Portable executable for 80386 (PE)',
'Portable executable for AMD64 (PE)',
'Binary file' # x86/AMD64 shellcode support
]
def inform_user_ida_ui(message):
idaapi.info('%s. Please refer to IDA Output window for more information.' % message)
def is_supported_file_type():
file_type = idaapi.get_file_type_name()
if file_type not in SUPPORTED_FILE_TYPES:
logger.error('-' * 80)
logger.error(' Input file does not appear to be a PE file.')
logger.error(' ')
logger.error(
' capa currently only supports analyzing PE files (or binary files containing x86/AMD64 shellcode) with IDA.')
logger.error(' If you don\'t know the input file type, you can try using the `file` utility to guess it.')
logger.error('-' * 80)
inform_user_ida_ui('capa does not support the format of this file')
return False
return True
def get_disasm_line(va):
''' '''

View File

@@ -26,16 +26,15 @@ import idaapi
import capa.main
import capa.rules
import capa.features.extractors.ida
import capa.ida.helpers
from capa.ida.explorer.view import CapaExplorerQtreeView
from capa.ida.explorer.model import CapaExplorerDataModel
from capa.ida.explorer.proxy import CapaExplorerSortFilterProxyModel
PLUGIN_NAME = 'capa explorer'
PLUGIN_NAME = 'capaex'
logger = logging.getLogger(PLUGIN_NAME)
logger = logging.getLogger('capa')
class CapaExplorerIdaHooks(idaapi.UI_Hooks):
@@ -326,12 +325,31 @@ class CapaExplorerForm(idaapi.PluginForm):
rules_path = os.path.join(os.path.dirname(self._file_loc), '../..', 'rules')
rules = capa.main.get_rules(rules_path)
rules = capa.rules.RuleSet(rules)
results = capa.main.find_capabilities(rules, capa.features.extractors.ida.IdaFeatureExtractor(), True)
capabilities = capa.main.find_capabilities(rules, capa.features.extractors.ida.IdaFeatureExtractor(), True)
# support binary files specifically for x86/AMD64 shellcode
# warn user binary file is loaded but still allow capa to process it
# TODO: check specific architecture of binary files based on how user configured IDA processors
if idaapi.get_file_type_name() == 'Binary file':
logger.warning('-' * 80)
logger.warning(' Input file appears to be a binary file.')
logger.warning(' ')
logger.warning(
' capa currently only supports analyzing binary files containing x86/AMD64 shellcode with IDA.')
logger.warning(
' This means the results may be misleading or incomplete if the binary file loaded in IDA is not x86/AMD64.')
logger.warning(' If you don\'t know the input file type, you can try using the `file` utility to guess it.')
logger.warning('-' * 80)
capa.ida.helpers.inform_user_ida_ui('capa encountered warnings during analysis')
if capa.main.is_file_limitation(rules, capabilities, is_standalone=False):
capa.ida.helpers.inform_user_ida_ui('capa encountered warnings during analysis')
logger.info('analysis completed.')
self._model_data.render_capa_results(rules, results)
self._render_capa_summary(rules, results)
self._model_data.render_capa_results(rules, capabilities)
self._render_capa_summary(rules, capabilities)
logger.info('render views completed.')
@@ -441,6 +459,9 @@ def main():
''' TODO: move to idaapi.plugin_t class '''
logging.basicConfig(level=logging.INFO)
if not capa.ida.helpers.is_supported_file_type():
return -1
global CAPA_EXPLORER_FORM
try:

View File

@@ -409,6 +409,60 @@ def appears_rule_cat(rules, capabilities, rule_cat):
return False
def is_file_limitation(rules, capabilities, is_standalone=True):
file_limitations = {
# capa will likely detect installer specific functionality.
# this is probably not what the user wants.
'other-features/installer/': [
' This sample appears to be an installer.',
' ',
' capa cannot handle installers well. This means the results may be misleading or incomplete.'
' You should try to understand the install mechanism and analyze created files with capa.'
],
# 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.
'other-features/compiled-to-dot-net': [
' This sample appears to be a .NET module.',
' ',
' .NET is a cross-platform framework for running managed applications.',
' capa cannot handle non-native files. This means that the results may be misleading or incomplete.',
' You may have to analyze the file manually, using a tool like the .NET decompiler dnSpy.'
],
# 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
'other-features/compiled-with-autoit': [
' This sample appears to be compiled with AutoIt.',
' ',
' AutoIt is a freeware BASIC-like scripting language designed for automating the Windows GUI.',
' capa cannot handle AutoIt scripts. This means that the results will be misleading or incomplete.',
' You may have to analyze the file manually, using a tool like the AutoIt decompiler MyAut2Exe.'
],
# capa won't detect much in packed samples
'anti-analysis/packing/': [
' This sample appears to be packed.',
' ',
' Packed samples have often been obfuscated to hide their logic.',
' capa cannot handle obfuscation well. This means the results may be misleading or incomplete.',
' If possible, you should try to unpack this input file before analyzing it with capa.'
]
}
for category, dialogue in file_limitations.items():
if not appears_rule_cat(rules, capabilities, category):
continue
logger.warning('-' * 80)
for line in dialogue:
logger.warning(line)
if is_standalone:
logger.warning(' ')
logger.warning(' Use -v or -vv if you really want to see the capabilities identified by capa.')
logger.warning('-' * 80)
return True
return False
def is_supported_file_type(sample):
'''
Return if this is a supported file based on magic header values
@@ -662,70 +716,12 @@ def main(argv=None):
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)
# capa will likely detect installer specific functionality.
# this is probably not what the user wants.
#
if is_file_limitation(rules, capabilities):
# bail if capa encountered file limitation e.g. a packed binary
# do show the output in verbose mode, though.
if not (args.verbose or args.vverbose):
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(
' 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.
#
# do show the output in verbose mode, though.
if not (args.verbose or args.vverbose):
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(
' 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
#
# do show the output in verbose mode, though.
if not (args.verbose or args.vverbose):
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)
if args.vverbose:
render_capabilities_vverbose(rules, capabilities)
elif args.verbose:
@@ -742,6 +738,10 @@ def ida_main():
logging.basicConfig(level=logging.INFO)
logging.getLogger().setLevel(logging.INFO)
import capa.ida.helpers
if not capa.ida.helpers.is_supported_file_type():
return -1
logger.info('-' * 80)
logger.info(' Using default embedded rules.')
logger.info(' ')
@@ -764,6 +764,10 @@ def ida_main():
import capa.features.extractors.ida
capabilities = find_capabilities(rules, capa.features.extractors.ida.IdaFeatureExtractor())
if is_file_limitation(rules, capabilities, is_standalone=False):
capa.ida.helpers.inform_user_ida_ui('capa encountered warnings during analysis')
render_capabilities_default(rules, capabilities)