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
use std::process::Command;
use structopt::StructOpt;
// TODO: Add validation function for `--partial=???` parameter.
// TODO: `--partial` option needs better documentation on how to specify the list of checks to run.
// TODO: Add module version printing function
#[derive(Debug, StructOpt)]
/// Find vulnerable patterns in binary executables
struct CmdlineArgs {
/// The path to the binary.
#[structopt(required_unless("module-versions"), validator(check_file_existence))]
binary: Option<String>,
/// Path to a custom configuration file to use instead of the standard one.
#[structopt(long, short, validator(check_file_existence))]
config: Option<String>,
/// Write the results to a file.
#[structopt(long, short)]
out: Option<String>,
/// Specify a specific set of checks to be run.
#[structopt(long, short)]
partial: Option<String>,
/// Generate JSON output.
#[structopt(long, short)]
json: bool,
/// Do not print log messages. This prevents polluting STDOUT for json output.
#[structopt(long, short)]
quiet: bool,
/// Checks if there is a path from an input function to a CWE hit.
#[structopt(long)]
check_path: bool,
/// Prints out the version numbers of all known modules.
#[structopt(long)]
module_versions: bool,
}
fn main() {
let cmdline_args = CmdlineArgs::from_args();
if cmdline_args.module_versions {
println!("printing module versions");
todo!(); // TODO: implement!
} else if let Some(exit_code) = build_bap_command(&cmdline_args).status().unwrap().code() {
std::process::exit(exit_code);
}
}
/// Build the BAP command corresponding to the given command line arguments.
fn build_bap_command(args: &CmdlineArgs) -> Command {
let mut command = Command::new("bap");
command.arg(args.binary.as_ref().unwrap());
command.arg("--pass=cwe-checker");
if let Some(ref string) = args.config {
command.arg("--cwe-checker-config=".to_string() + string);
}
if let Some(ref string) = args.out {
command.arg("--cwe-checker-out=".to_string() + string);
}
if let Some(ref string) = args.partial {
command.arg("--cwe-checker-partial=".to_string() + string);
}
if args.json {
command.arg("--cwe-checker-json");
}
if args.quiet {
command.arg("--cwe-checker-no-logging");
}
if args.check_path {
command.arg("--cwe-checker-check-path");
}
if args.module_versions {
command.arg("--cwe-checker-module-versions");
}
command
}
/// Check the existence of a file
fn check_file_existence(file_path: String) -> Result<(), String> {
if std::fs::metadata(&file_path)
.map_err(|err| format!("{}", err))?
.is_file()
{
Ok(())
} else {
Err(format!("{} is not a file.", file_path))
}
}