diff --git a/Cargo.lock b/Cargo.lock index 79591fc..f310864 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,12 +17,54 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -82,21 +124,32 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.1" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ + "anstream", "anstyle", "clap_lex", + "strsim", +] + +[[package]] +name = "clap_complete" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79504325bf38b10165b02e89b4347300f855f273c4cb30c4a3209e6583275e" +dependencies = [ + "clap", ] [[package]] @@ -105,6 +158,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "criterion" version = "0.5.1" @@ -176,6 +235,8 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" name = "cve-rs" version = "0.6.0" dependencies = [ + "clap", + "clap_complete", "criterion", "oorandom", "ureq", @@ -443,6 +504,12 @@ dependencies = [ "serde", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.50" @@ -523,6 +590,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "walkdir" version = "2.4.0" diff --git a/Cargo.toml b/Cargo.toml index f59d4fc..2637495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,8 @@ rust-version = "1.69.0" [dependencies] ureq = { version = "2.9.6", default-features = false, optional = true } oorandom = { version = "11.1.3", optional = true } +clap = { version = "4.5.4", features = ["cargo", "help"] } +clap_complete = "4.5.2" [dev-dependencies] criterion = "0.5.1" diff --git a/src/main.rs b/src/main.rs index 3e93ec9..5facfe2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,74 @@ #![deny(unsafe_code)] +use std::io; + +use clap::{ + builder::{styling::AnsiColor, Styles}, + crate_authors, crate_description, crate_name, crate_version, value_parser, Arg, ArgAction, + Command, +}; +use clap_complete::{generate, Generator, Shell}; +fn build_cli() -> Command { + Command::new(crate_name!()) + .arg_required_else_help(true) + .author(crate_authors!()) + .about(crate_description!()) + .version(crate_version!()) + .long_about(HELP) + .subcommand(Command::new("uaf").about("Run the use-after-free bug")) + .subcommand( + Command::new("bo").about("Run the buffer overflow exploit. Optionally take a shower"), + ) + .subcommand(Command::new("transition").about("Safely transmute a Boy to a Girl")) + .subcommand(Command::new("segfault").about("Segfault yourself")) + .subcommand( + Command::new("completions") + .about("Return shell completions") + .arg( + Arg::new("shell") + .action(ArgAction::Set) + .value_parser(value_parser!(Shell)) + .required(true), + ), + ) + .styles(STYLE) + .help_template(TEMPLATE) +} fn main() { - let mut args = std::env::args(); - let _program = args.next(); - let Some(subcommand) = args.next() else { - println!("{HELP}"); - return; - }; - - match subcommand.as_str() { + let mut command = build_cli(); + let matches = build_cli().clone().get_matches(); + let subcommand = matches.subcommand().unwrap(); + match subcommand.0 { "uaf" => cve_rs::use_after_free(), "segfault" => cve_rs::segfault(), "bo" => cve_rs::buffer_overflow().unwrap(), "transition" => transmute_demo().unwrap(), - "help" | "--help" | "h" | "-h" | "?" | "-?" => println!("{HELP}"), - other => println!("Error: Unknown command `{other}`.\n{HELP}"), + "completions" => print_completions( + subcommand.1.get_one::("shell").copied().unwrap(), + &mut command, + ), + _ => unreachable!(), } } +fn print_completions(gen: G, cmd: &mut Command) { + generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout()); +} + +const STYLE: Styles = Styles::styled() + .header(AnsiColor::Yellow.on_default()) + .usage(AnsiColor::Green.on_default()) + .literal(AnsiColor::Green.on_default()) + .placeholder(AnsiColor::Green.on_default()); + +const TEMPLATE: &str = "\ +{before-help}{name} {version} +{author-with-newline}{about-with-newline} +{usage-heading} {usage} + +{all-args}{after-help} +"; + const HELP: &str = r" cve-rs: Blazingly fast memory vulnerabilities, written in 100% safe rust. @@ -27,13 +78,6 @@ cve-rs exploits a soundness hole in lifetimes that lets us cast any lifetime to See: https://github.com/rust-lang/rust/issues/25860 This program is open-source! View the source for all these exploits here: https://github.com/Speykious/cve-rs - -Commands: - help Show this help message. - uaf Run the use-after-free bug. - bo Run the buffer overflow exploit. Optionally take a shower. - transition Safely transmute a Boy to a Girl. - segfault Segfault yourself. "; #[repr(C)] diff --git a/vhs/cassete.gif b/vhs/cassete.gif index e00650a..448d026 100644 Binary files a/vhs/cassete.gif and b/vhs/cassete.gif differ diff --git a/vhs/cassete.tape b/vhs/cassete.tape index da45fb2..5c73f45 100644 --- a/vhs/cassete.tape +++ b/vhs/cassete.tape @@ -9,11 +9,11 @@ Hide Type "source vhs/config.bash" Enter Show -Set TypingSpeed 0.1 +Set TypingSpeed 0.05 Type "bat examples/segfault.rs" Enter -Sleep 5s +Sleep 1s Type "cargo run --example segfault" -Sleep 5s -Enter Sleep 3s +Enter +Sleep 1s