Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add casr-csharp #207

Merged
merged 38 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
e04e640
Casr-csharp init
headshog Feb 21, 2024
22e5f9d
casr-csharp fix
headshog Mar 6, 2024
f25a742
casr-csharp fix x2
headshog Mar 6, 2024
a693fb3
casr-afl fix
headshog Mar 6, 2024
a0eb1ed
casr-afl fix x2
headshog Mar 6, 2024
b11f652
casr-afl fix dotnet/mono run
headshog Mar 6, 2024
fdf7d4f
fix regex
headshog Mar 7, 2024
325827e
fix style
headshog Mar 7, 2024
395a046
fix test afl
headshog Mar 7, 2024
48dcc0c
casr-afl fix done
headshog Mar 7, 2024
e07e474
tests init
headshog Mar 10, 2024
3852f5c
tests and casr-afl done
headshog Mar 12, 2024
58a62cb
tests and casr-afl done x2
headshog Mar 12, 2024
8e22058
remove artifact
headshog Mar 12, 2024
2f0a243
fix casr-afl anc docs
headshog Mar 13, 2024
4275d45
fix ARGS in code and docs
headshog Mar 13, 2024
b498319
fix style
headshog Mar 13, 2024
cc7d464
fix style x2
headshog Mar 13, 2024
3817017
fix style x3
headshog Mar 13, 2024
9fea237
fix docs
headshog Mar 13, 2024
a15354e
add whet to aarch64 workflow
headshog Mar 18, 2024
f570c1b
fix afl csharp test
headshog Mar 19, 2024
14078af
refactored casr-afl
headshog Mar 19, 2024
0ac0078
add casr-afl_csharp ignore_cmdline test
headshog Mar 19, 2024
ebdc91d
Fix usage
headshog Mar 19, 2024
9a22947
Fix by review
headshog Mar 20, 2024
d28447b
Fixes
headshog Mar 21, 2024
9c869cf
Fixes again
headshog Mar 21, 2024
8b2d680
Rebase
headshog Mar 26, 2024
615f0e4
Fix cargo.toml
headshog Mar 26, 2024
494463c
Handle copy_dir and remove range from .value_parser
headshog Mar 27, 2024
4101879
Fix casr-afl and clippy
headshog Apr 2, 2024
0a6f36d
fix docs and csharp tests
headshog Apr 2, 2024
defe5f7
add gitignore to csharp artifacts
headshog Apr 2, 2024
b3cafbb
fix csharp report
headshog Apr 3, 2024
dee63ce
fix csharp test and readme use cases
headshog Apr 3, 2024
d85041d
fix usage usecases and add strip-path for casr-csharp
headshog Apr 3, 2024
402e540
Fix casr-core append
SweetVishnya Apr 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/amd64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
sudo apt update && sudo apt install -y nodejs
sudo npm install -g jsfuzz
sudo npm install --save-dev @jazzer.js/core
wget -q https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb && rm packages-microsoft-prod.deb
sudo apt update && sudo apt install -y --no-install-recommends dotnet-sdk-8.0
curl https://sh.rustup.rs -o rustup.sh && chmod +x rustup.sh && \
./rustup.sh -y && rm rustup.sh
rustup install nightly
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
sudo apt update && sudo apt install -y nodejs
sudo npm install -g jsfuzz
sudo npm install --save-dev @jazzer.js/core
wget -q https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb && rm packages-microsoft-prod.deb
sudo apt update && sudo apt install -y --no-install-recommends dotnet-sdk-8.0
curl https://sh.rustup.rs -o rustup.sh && chmod +x rustup.sh && \
./rustup.sh -y && rm rustup.sh
rustup install nightly
Expand Down
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ java reports and get report from
to analyze JavaScript reports and get report from
[Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js) or
[jsfuzz](https://github.com/fuzzitdev/jsfuzz).
Use `casr-csharp` to analyze C# reports and get report from
[Sharpfuzz](https://github.com/Metalnem/sharpfuzz).

Crash report contains many useful information: severity (like [exploitable](https://github.com/jfoote/exploitable))
for x86, x86\_64, arm32, aarch64, rv32g, rv64g architectures,
Expand All @@ -44,7 +46,8 @@ stored in JSON format. `casr-cli` is meant to provide TUI for viewing reports
and converting them into SARIF report.
Reports triage (deduplication, clustering) is done by `casr-cluster`.
Triage is based on stack trace comparison from [gdb-command](https://github.com/anfedotoff/gdb-command).
`casr-afl` is used to triage crashes found by [AFL++](https://github.com/AFLplusplus/AFLplusplus).
`casr-afl` is used to triage crashes found by [AFL++](https://github.com/AFLplusplus/AFLplusplus)
and AFL-based fuzzer [Sharpfuzz](https://github.com/Metalnem/sharpfuzz).
`casr-libfuzzer` can triage crashes found by
[libFuzzer](https://www.llvm.org/docs/LibFuzzer.html) based fuzzer
(C/C++/[go-fuzz](https://github.com/dvyukov/go-fuzz)/[Atheris](https://github.com/google/atheris)
Expand Down Expand Up @@ -81,6 +84,7 @@ and program languages:
* Python
* Java
* JavaScript
* C#
SweetVishnya marked this conversation as resolved.
Show resolved Hide resolved

It could be built with `exploitable` feature for severity estimation crashes
collected from gdb. To save crash reports as json use `serde` feature.
Expand Down Expand Up @@ -161,6 +165,10 @@ Create report from JavaScript:

$ casr-js -o js.casrep -- node casr/tests/casr_tests/js/test_casr_js.js

Create report from C#:

$ casr-csharp -o csharp.casrep -- dotnet run --project casr/tests/casr_tests/csharp/test_casr_csharp.csproj

View report:

$ casr-cli casr/tests/casr_tests/casrep/test_clustering_san/load_fuzzer_crash-120697a7f5b87c03020f321c8526adf0f4bcc2dc.casrep
Expand Down Expand Up @@ -193,6 +201,15 @@ Triage crashes after AFL++ fuzzing with casr-afl:
$ # You may also additionally generate crash reports for uninstrumented binary with casr-gdb
$ casr-afl -i casr/tests/casr_tests/casrep/afl-out-xlnt -o casr/tests/tmp_tests_casr/casr_afl_out -- /tmp/load_sydr @@

Triage crashes after Sharpfuzz fuzzing with casr-afl:

$ cp -r casr/tests/casr_tests/csharp/test_casr_afl_csharp /tmp/test_casr_afl_csharp
$ cp -r casr/tests/casr_tests/csharp/test_casr_afl_csharp_module /tmp/test_casr_afl_csharp_module
$ dotnet publish -o /tmp/test_casr_afl_csharp/bin
$ casr-afl -i casr/tests/casr_tests/casrep/afl-out-sharpfuzz -o casr/tests/tmp_tests_casr/casr_afl_csharp_out
$ # You may force your own run arguments using --ignore-cmdline
$ casr-afl --ignore-cmdline -i casr/tests/casr_tests/casrep/afl-out-sharpfuzz -o casr/tests/tmp_tests_casr/casr_afl_csharp_out -- dotnet run --no-build --project /tmp/test_casr_afl_csharp/test_casr_afl_csharp.csproj @@

Triage libFuzzer crashes with casr-libfuzzer:

$ casr-libfuzzer -t 30 -i casr/tests/casr_tests/casrep/libfuzzer_crashes_xlnt -o casr/tests/tmp_tests_casr/casr_libfuzzer_out -- casr/tests/casr_tests/bin/load_fuzzer
Expand Down Expand Up @@ -227,23 +244,23 @@ Upload new and unique CASR reports to
When you have crashes from fuzzing you may do the following steps:

1. Create reports for all crashes via `casr-san`, `casr-gdb` (if no sanitizers
are present), `casr-python`, `casr-java`, or `casr-js`.
are present), `casr-python`, `casr-java`, `casr-js`, or `casr-csharp`.
2. Deduplicate collected crash reports via `casr-cluster -d`.
3. Cluster deduplicated crash reports via `casr-cluster -c`.
4. Create reports and deduplicate them for all UBSAN errors via `casr-ubsan`.
5. View reports from clusters using `casr-cli` or upload them to
[DefectDojo](https://github.com/DefectDojo/django-DefectDojo) with
`casr-dojo`.

If you use [AFL++](https://github.com/AFLplusplus/AFLplusplus), the pipeline
If you use [AFL++](https://github.com/AFLplusplus/AFLplusplus) or AFL-based
fuzzer [Sharpfuzz](https://www.llvm.org/docs/LibFuzzer.html), the pipeline
(without `casr-ubsan` and `casr-dojo`) could be done automatically by
`casr-afl`.

If you use [libFuzzer](https://www.llvm.org/docs/LibFuzzer.html) based fuzzer
(C/C++/[go-fuzz](https://github.com/dvyukov/go-fuzz)/[Atheris](https://github.com/google/atheris)
/[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer)/[Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js)/
[jsfuzz](https://github.com/fuzzitdev/jsfuzz)),
the pipeline (without `casr-ubsan` and `casr-dojo`) could be done automatically
[jsfuzz](https://github.com/fuzzitdev/jsfuzz)), the pipeline (without `casr-ubsan` and `casr-dojo`) could be done automatically
by `casr-libfuzzer`.

## Contributing
Expand Down
1 change: 1 addition & 0 deletions casr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ required-features = ["dojo"]

[dev-dependencies]
lazy_static = "1.4"
copy_dir = "0.1.3"
78 changes: 50 additions & 28 deletions casr/src/bin/casr-afl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
fn main() -> Result<()> {
let matches = clap::Command::new("casr-afl")
.version(clap::crate_version!())
.about("Triage crashes found by AFL++")
.about("Triage crashes found by AFL++/Sharpfuzz")
.term_width(90)
.arg(
Arg::new("log-level")
Expand All @@ -40,7 +40,7 @@
.default_value("0")
.value_name("SECONDS")
.help("Timeout (in seconds) for target execution, 0 value means that timeout is disabled")
.value_parser(clap::value_parser!(u64).range(0..))
.value_parser(clap::value_parser!(u64))
)
.arg(
Arg::new("input")
Expand Down Expand Up @@ -100,26 +100,35 @@
.required(false)
.num_args(1..)
.last(true)
.help("Add \"-- ./gdb_fuzz_target <arguments>\" to generate additional crash reports with casr-gdb (e.g., test whether program crashes without sanitizers)"),
.help("Add \"-- ./gdb_fuzz_target <arguments>\" to generate additional crash reports with casr-gdb \
(for compiled binaries, e.g., test whether program crashes without sanitizers), \"-- dotnet <arguments>\" \
or \"-- mono <arguments>\" to triage C# crashes with additional options")
)
.get_matches();

// Init log.
util::initialize_logging(&matches);

let casr_san = util::get_path("casr-san")?;
let casr_gdb = util::get_path("casr-gdb")?;

let mut gdb_args = if let Some(argv) = matches.get_many::<String>("ARGS") {
let mut args = if let Some(argv) = matches.get_many::<String>("ARGS") {
argv.cloned().collect()
} else {
Vec::new()
};

if gdb_args.is_empty() && matches.get_flag("ignore-cmdline") {
if args.is_empty() && matches.get_flag("ignore-cmdline") {
bail!("ARGS is empty, but \"ignore-cmdline\" option is provided.");
}

// Get tool.
let mut tool = if matches.get_flag("ignore-cmdline")
&& (args[0].ends_with("dotnet") || args[0].ends_with("mono"))
SweetVishnya marked this conversation as resolved.
Show resolved Hide resolved
{
"casr-csharp"
} else {
"casr-gdb"
};
let tool_path = util::get_path(tool)?;

// Get all crashes.
let mut crashes: HashMap<String, CrashInfo> = HashMap::new();
for node_dir in fs::read_dir(matches.get_one::<PathBuf>("input").unwrap())? {
Expand All @@ -130,15 +139,24 @@

// Get crashes from one node.
let mut crash_info = casr::triage::CrashInfo {
casr_tool: casr_gdb.clone(),
..Default::default()
};
crash_info.target_args = if matches.get_flag("ignore-cmdline") {
gdb_args.clone()
if matches.get_flag("ignore-cmdline") {
crash_info.casr_tool = tool_path.clone();
crash_info.target_args = args.clone()
} else {
let cmdline_path = path.join("cmdline");
if let Ok(cmdline) = fs::read_to_string(&cmdline_path) {
cmdline.split_whitespace().map(|s| s.to_string()).collect()
let cmd_args: Vec<String> =
cmdline.split_whitespace().map(|s| s.to_string()).collect();
if cmd_args[0].ends_with("dotnet") || cmd_args[0].ends_with("mono") {
SweetVishnya marked this conversation as resolved.
Show resolved Hide resolved
tool = "casr-csharp";
crash_info.casr_tool = util::get_path("casr-csharp")?;
} else {
tool = "casr-gdb";
crash_info.casr_tool = util::get_path("casr-gdb")?;
}
crash_info.target_args = cmd_args;
} else {
error!("Couldn't read {}.", cmdline_path.display());
continue;
Expand All @@ -151,22 +169,26 @@
.position(|s| s.contains("@@"))
.map(|x| x + 1);

if let Some(target) = crash_info.target_args.first() {
match util::symbols_list(Path::new(target)) {
Ok(list) => {
if list.contains("__asan") {
crash_info.casr_tool = casr_san.clone()
// When we triage crashes for binaries, use casr-san.
if tool == "casr-gdb" {
if let Some(target) = crash_info.target_args.first() {
match util::symbols_list(Path::new(target)) {
Ok(list) => {
if list.contains("__asan") {
crash_info.casr_tool = util::get_path("casr-san")?.clone()
}
}
Err(e) => {
error!("{e}");

Check warning on line 182 in casr/src/bin/casr-afl.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-afl.rs#L181-L182

Added lines #L181 - L182 were not covered by tests
continue;
}
}
Err(e) => {
error!("{e}");
continue;
}
} else {
error!("Cmdline is empty. Path: {:?}", path.join("cmdline"));
continue;

Check warning on line 188 in casr/src/bin/casr-afl.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-afl.rs#L188

Added line #L188 was not covered by tests
}
} else {
error!("Cmdline is empty. Path: {:?}", path.join("cmdline"));
continue;
}

// Push crash paths.
for crash in path
.read_dir()?
Expand All @@ -183,10 +205,10 @@
}
}

if matches.get_flag("ignore-cmdline") {
gdb_args = Vec::new();
if matches.get_flag("ignore-cmdline") || tool != "casr-gdb" {
args = Vec::new();
}

// Generate reports
fuzzing_crash_triage_pipeline(&matches, &crashes, &gdb_args)
// Generate reports.
fuzzing_crash_triage_pipeline(&matches, &crashes, &args)
}
2 changes: 1 addition & 1 deletion casr/src/bin/casr-cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ fn main() -> Result<()> {
.value_parser(clap::value_parser!(u32).range(1..))
)
.get_matches();
init_ignored_frames!("cpp", "rust", "python", "go", "java", "js");
init_ignored_frames!("cpp", "rust", "python", "go", "java", "js", "csharp");

// Get number of threads
let jobs = if let Some(jobs) = matches.get_one::<u32>("jobs") {
Expand Down
Loading
Loading