{i cwe_checker} is implemented as a plugin for the {{: https://github.com/BinaryAnalysisPlatform/bap} Binary Analysis Platform} (BAP).
To use it, just run BAP with {i cwe_checker} as a pass:
{[bap [BINARY_FILE] --pass=cwe_checker]}
This runs all static analysis based checks.
You can find more documentation on these checks at their {{: ../cwe_checker_core/Cwe_checker_core/index.html} module documentation pages}.
The behaviour of these checks can be modified through an optional configuration file.
Just edit the [src/config.json] file and then add [--cwe-checker-config=src/config.json] as a command line option.
You can find more on the available command line options {{!section:CmdLineOptions} here}.
The symbolic execution based checks can be run with the emulation recipe in the recipes folder.
{[bap PATH_TO_BINARY --recipe=recipes/emulation]}
Note that these checks are rather slow at the moment and should only be applied to small binaries.
{2 How to use the docker image}
The docker image, which is based on the current master branch of the repository, can be installed with
{[docker pull fkiecad/cwe_checker]}
To use it, mount the target binary inside the docker container and call {i bap} with {i cwe_checker} as a pass as usual:
{[docker run --rm -v [BINARY]:/tmp/input fkiecad/cwe_checker bap /tmp/input --pass=cwe-checker]}
If you are using a customized [config.json] file, don't forget to mount it inside your container as well!
If you want to print the output to a file with [--cwe-checker-out], you also need to mount the output file to the docker container, or else the file will be lost once the container gets destroyed.
{1:CmdLineOptions Command line options}
All command line options have to be prefixed with [--cwe-checker] (so that BAP knows to forward them to the {i cwe_checker} plugin).
The available command line options are:
- [-config=[FILE]] Use [[FILE]] as the configuration file.
If you omit this option, {i cwe_checker} uses a standard configuration file located at [src/config.json].
- [-module-versions] Prints the version numbers of each check.
- [-json] Format the CWE-warnings as JSON.
If you print to {i stdout}, note that debug, info and error messages are not formatted as JSON and may pollute the output.
Use [-no-logging] to suppress these messages.
- [-no-logging] Suppress printing of debug, info and error messages.
This is useful if you want to print to {i stdout} with the [-json] flag to prevent these messages polluting the JSON output.
- [-out=[FILE]] Print the CWE-warnings to the file located at [[FILE]].
Note that debug, info and error messages are still printed to stdout and not to the file.
- [-partial=[MODULE_LIST]] Only run the checks given in [[MODULE_LIST]], where [[MODULE_LIST]] is a comma separated list of module names.
E.g. [-partial=CWE190,CWE476] would only run the checks for CWE-190 and CWE-476.
The names of all available modules can be printed with the [-module-versions] command line option.
{1:ToolIntegration Integration with IDA Pro}
To annotate CWE-hits in IDA Pro, first run {i cwe_checker} and save the JSON-formatted output to a file.
Now open the binary file in IDA Pro and execute the generated [cwe_hits.py] script from within IDA Pro (Alt+F7).
{1:HackingHowto How to write your own check}
{2 Step 1: Get acquainted with BAP}
{i cwe_checker} interfaces via OCaml with the {{: https://github.com/BinaryAnalysisPlatform/bap} Binary Analysis Platform} as a backend and you should read its documentation.
All information about a binary file is gathered through BAP.
{2 Step 2: Write the check}
You need a [your_check.ml] and a [your_check.mli] file that should be located in the [src/checkers] folder.
The [your_check.mli] file should look like this:
{[
(** This module implements your_check.
Some more documentation about your_check.
*)
val name : string (* The name of your check *)
val version : string (* The version of your check (e.g. "0.1"). *)
val check_cwe : Bap.Std.program Bap.Std.term -> Bap.Std.project -> Bap.Std.word Bap.Std.Tid.Map.t -> string list list -> string list -> unit
]}
A corresponding example [your_check.ml] file, which just prints a "hello world" message, would look like this:
{[
open Core_kernel
open Bap.Std (* To interface with BAP *)
let name = "your_check"
let version = "0.1"
let check_cwe program project tid_map symbol_pairs parameters =
Log_utils.info "Hello world!"
]}
In practice you would use the parameters of {i check_cwe}-function to gather the necessary information for the computation of your check.
These parameters are:
- [program: Bap.Std.program Bap.Std.term] The program term of the binary
- [project: Bap.Std.project] The BAP-project term of the binary
- [Tid_map: Bap.Std.word Bap.Std.Tid.Map.t] A map from the Tids of basic blocks to concrete addresses in the binary file
- [symbols_pairs: string list list] Symbols read from the {i config.json} file
- [parameters: string list] Parameters read from the config.json file
The results of your check should be reported back to the user via the functions in the {{: ../cwe_checker_core/Cwe_checker_core/Log_utils/index.html} Log_utils}-module.
See its module-level documentation for more details.
{2 Step 3: Add your check to the {i cwe_checker} plugin}
The main file of the {i cwe_checker} plugin is located at [plugins/cwe_checker/cwe_checker.ml].
In there you have to add your check to the list of {i known_modules}.
Here the {i requires_pairs} flag controls whether the symbols in the [config.json] file are a string list or a list of string lists.
The {i has_parameters} flag controls whether the [config.json] file contains parameters to control the behaviour of the check.
Now just recompile {i cwe_checker} via [make all] and your check will be available for use.