diff --git a/README.md b/README.md index 94c9c71f..3da7582a 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,11 @@ For this to match, the function must: If only one of these features is found in a function, the rule will not match. +## limitations +### circular rule dependencies +While capa supports [matching on prior rule matches](#matching-prior-rule-matches) users should ensure that their rules do not introduce circular dependencies between rules. + + # extracted features ## function features @@ -248,10 +253,14 @@ though possibly a local function (like `malloc`) extracted via FLIRT. The parameter is a string describing the function name, specified like `module.functionname` or `functionname`. +Windows API functions that take string arguments come in two API versions. For example `CreateProcessA` takes ANSI strings and `CreateProcessW` takes Unicode strings. capa extracts these API features both with and without the suffix character `A` or `W`. That means you can write a rule to match on both APIs using the base name. If you want to match a specific API version, you can include the suffix. + Example: - api: kernel32.CreateFileA - api: CreateFileA + api: kernel32.CreateFile # matches both Ansi (CreateFileA) and Unicode (CreateFileW) versions + api: CreateFile + api: GetEnvironmentVariableW # only matches on Unicode version + ### number A number used by the logic of the program. diff --git a/capa/main.py b/capa/main.py index bacb2741..840425a0 100644 --- a/capa/main.py +++ b/capa/main.py @@ -640,7 +640,7 @@ def main(argv=None): 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(' 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 @@ -648,7 +648,7 @@ def main(argv=None): 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(' 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.') @@ -679,11 +679,12 @@ def main(argv=None): 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.') + ' 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. @@ -698,7 +699,7 @@ def main(argv=None): 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.') + ' 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.') diff --git a/doc/usage.md b/doc/usage.md index cd187865..e48295d5 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -1,5 +1,7 @@ -# Usage -## Command line +# capa usage + + +# command line After you have downloaded the standalone version of capa or installed it via `pip` (see the [installation](installation.md) documentation) you can run capa directly from your terminal shell. - `$ capa -h` @@ -7,14 +9,21 @@ After you have downloaded the standalone version of capa or installed it via `pi In this mode capa relies on vivisect which only runs under Python 2. -## IDA Pro +## only run selected rules +Use the `-t` option to only run selected rules. This is the preferred method over specifying a rule path which fails if dependent rules reside in other directories. + +``` +$ capa -t communication malware.exe +``` + +# IDA Pro capa runs from within IDA Pro. Run `capa/main.py` via File - Script file... (ALT + F7). When running in IDA, capa uses IDA's disassembly and file analysis as its backend. These results may vary from the standalone version that uses vivisect. In IDA, capa supports Python 2 and Python 3. If you encounter issues with your specific setup please open a new [Issue](https://github.com/fireeye/capa/issues). -## IDA plugins +## IDA Pro plugins capa comes with two IDA Pro plugins located in the `capa/ida` directory. ### capa explorer @@ -22,5 +31,5 @@ The capa explorer allows you to interactively display and browse capabilities ca ![capa explorer](capa_explorer.png) -### Rule generator +### rule generator The rule generator helps you to easily write new rules based on the function you are currently analyzing in your IDA disassembly view. diff --git a/rules b/rules index eaae0e89..d34acf7b 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit eaae0e89a75eae6d564873287ae55afb30f8970b +Subproject commit d34acf7bbd5a2132740bcce00703f657a39dfcdd diff --git a/tests/test_viv_features.py b/tests/test_viv_features.py index c773a7d2..ac0bac9d 100644 --- a/tests/test_viv_features.py +++ b/tests/test_viv_features.py @@ -62,6 +62,7 @@ def test_api_features(mimikatz): def test_api_features_64_bit(sample_a198216798ca38f280dc413f8c57f2c2): features = extract_function_features(viv_utils.Function(sample_a198216798ca38f280dc413f8c57f2c2.vw, 0x4011B0)) assert capa.features.insn.API('kernel32.GetStringTypeA') in features + assert capa.features.insn.API('kernel32.GetStringTypeW') not in features assert capa.features.insn.API('kernel32.GetStringType') in features assert capa.features.insn.API('GetStringTypeA') in features assert capa.features.insn.API('GetStringType') in features