1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{0 cwe_checker}
{1 Contents}
- {!section:Basics}
- {!section:CmdLineOptions}
- {!section:ToolIntegration}
- {!section:HackingHowto}
{1:Basics Basic usage}
{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}.
Alternatively, you can run the {i cwe_checker} through the command
{[cwe_checker [BINARY_FILE] ]}
Internally, this also calls BAP as above, but enables shorter {{!section:CmdLineOptions} command line options}.
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 and should only be applied to small binaries.
{e Deprecation warning:} We recently decided to deprecate support for the symbolic execution based checks and they will be removed in a future version.
Users of these checks should take a look at the {{: https://github.com/BinaryAnalysisPlatform/bap-toolkit} BAP toolkit},
which provides better-maintained versions of these checks.
{2 How to use the docker images}
There are two docker images containing preinstalled versions of the {i cwe_checker}:
- [docker pull fkiecad/cwe_checker:latest] pulls the image based on the current master branch.
- [docker pull fkiecad/cwe_checker:stable] pulls the image based on the current stable release version.
To use them, 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}
If you run the {i cwe_checker} as a BAP plugin, all command line options have to be prefixed with [--cwe-checker] (so that BAP knows to forward them to the {i cwe_checker} plugin).
If you run the {i cwe_checker} directly, do not prefix the command line options.
The available command line options are:
- [-version] Print the version number of the {i cwe_checker} and exit.
- [-check-path] Find paths between input functions (configurable in the configuration file) and CWE hits.
Should be used together with the [-partial] command line option if you are only interested in paths to specific CWEs.
- [-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 and Ghidra}
To annotate CWE-hits in IDA Pro or Ghidra, first run {i cwe_checker} and save the JSON-formatted output to a file.
{[bap [BINARY] --pass=cwe-checker --cwe-checker-json --cwe-checker-out=cwe_hits.json]}
After that execute the tool-specific script to import the results:
- For IDA Pro run the [cwe_checker_to_ida.py] script located in the [cwe_checker_to_ida] folder.
{[python3 cwe_checker_to_ida.py -i cwe_hits.json -o cwe_hits.py]}
Now open the binary file in IDA Pro and execute the generated [cwe_hits.py] script from within IDA Pro (Alt+F7).
- For Ghidra copy the [cwe_checker_ghidra_plugin.py] script located in the [ghidra_plugin] folder into the script folder of Ghidra.
Now open the binary in Ghidra and run the [cwe_checker_ghidra_plugin.py] script through the script manager and select the generated [cwe_hits.json] file when prompted.
{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.