diff --git a/.gitignore b/.gitignore index c19feef..0668415 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ Cargo.lock *.log *.spec build/ -__pycache__/ \ No newline at end of file +__MACOSX/ +__pycache__/ +.DS_Store \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 249bbdb..c68e074 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "catherine" -description = "Catherine is a blue team security framework with an extensible module collection, various types of cryptographic processes, hexadecimal dumping and aggregation, malicious domain detection, and real-time database analysis." -version = "0.4.1" +description = "The Catherine Framework is a general-purpose cybersecurity framework built to aggregate, validate, decode, decrypt, and maintain data." +version = "0.5.0" authors = ["azazelm3dj3d"] license = "BSD-2-Clause" categories = ["cryptography", "command-line-utilities", "encoding"] @@ -9,16 +9,24 @@ keywords = ["cybersecurity", "blueteam", "framework", "security", "defense"] edition = "2021" repository = "https://github.com/azazelm3dj3d/catherine" +[build-dependencies] +tauri-build = { version = "1.2.1", features = [] } + [dependencies] -os_type = { git = "https://github.com/azazelm3dj3d/os_type", branch = "main", version = "2.6.1" } +os_type = "2.6.0" chrono = "0.4" colored = "2" serde = "1.0" serde_json = "1.0" libloading = "0.7" -prettytable-rs = "0.9.0" -mercy = "1.2.17" +prettytable-rs = "0.10.0" +mercy = "1.2.22" rand = "0.7.2" +tauri = { version = "1.2.4", features = [] } [target.'cfg(target_os = "windows")'.dependencies] -ipconfig = "0.3.0" \ No newline at end of file +ipconfig = "0.3.0" + +[features] +default = [ "custom-protocol" ] +custom-protocol = [ "tauri/custom-protocol" ] \ No newline at end of file diff --git a/README.md b/README.md index dac4a19..cbfbc3e 100644 --- a/README.md +++ b/README.md @@ -6,37 +6,59 @@ Catherine - +The Catherine Framework is a general-purpose cybersecurity framework built to aggregate, validate, decode, decrypt, and maintain data. Catherine currently collects information from dumping hexadecimal content from files, validates malicious domains & IP addresses, attempts to crack unknown hashes, handles real-time database analysis, various types of decoding, and much more. Thanks to Catherine being built in an easily packaged executable, you can quickly download the tool by running `cargo install catherine` via the `Cargo` ecosystem. Catherine can also be quickly compiled by pulling down the source code from `git` and simply running `cargo build`. -Catherine is a blue team security framework with an extensible module collection, various types of cryptographic processes, hexadecimal dumping and aggregation, malicious domain detection, and real-time database analysis. Catherine is as simple as installing via Cargo or using `git` to pull down the source code and immediately start using the framework with `cargo run`. The modules for Catherine can be installed by using the `catherine_install` script or running the `install` command within the Catherine prompt. This requires sudo privileges. +Catherine provides a Command Line Interface (CLI) and Graphical User Interface (GUI) built into the executable. This means whether you install from source or `Cargo`, you can choose your method of use. -One thing to note before installing, while Catherine should work on most operating systems, the modules are only built for Linux-based distributions. +## Installation + +You can easily install via the `Cargo` CLI: -### Installation -Install via Cargo (without modules): ```bash cargo install catherine ``` -Install via Cargo (with modules): +If you'd prefer to install from source, you can also do this fairly easily, but it will still require the `Cargo` CLI. + +First, clone the repository using `git`: + ```bash -curl https://raw.githubusercontent.com/azazelm3dj3d/catherine/main/catherine_install > catherine_install && chmod +x catherine_install +git clone https://github.com/azazelm3dj3d/catherine.git ``` + +Once you've cloned the repository and you're in the correct directory, simply run the following command: + ```bash -./catherine_install +cargo build ``` -### Uninstall -If you need to uninstall Catherine on your system for any reason or would like to remove the external modules, you can do so with these commands: +Now you'll have a local debug build available for testing under `target/debug/catherine`. + +Catherine also offers custom modules for Linux operating systems. You can access these modules by installing Catherine via the `catherine_install` script. + +You can review the script [here](https://github.com/azazelm3dj3d/catherine/blob/main/catherine_install). -Remove Catherine: ```bash -cargo uninstall catherine +# The script requires sudo privileges to build a directory under `/opt/catherine/` +sudo ./catherine_install ``` -Remove all Catherine files: +NOTE: I am working on converting all external [modules](https://github.com/azazelm3dj3d/catherine-modules) (Python, C, Go) into native modules (Rust) to offer everything in a built-in executable via `Cargo` without any extra steps, but for now, I've made sure to keep them accessible (excluding the GUI) for extended functionality. + +## Usage + +If you've already installed the application from `Cargo`, all you have to do now is run the following command to initialize the Catherine shell: + ```bash -rm -r /opt/catherine +catherine ``` +If a GUI is more your style, there is a simple version available with the majority of the available CLI commands. All you have to do to launch the interface is initialize the Catherine shell and run the following command within the shell: + +```bash +🦀 Catherine [v0.x.x] (None) ☀️ 〉launch +``` + +NOTE: I am still working on making the GUI a little nicer looking, but a basic version is currently available for testing. + If a bug or issue is found, please report it [here](https://github.com/azazelm3dj3d/catherine/issues). \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3b92901 --- /dev/null +++ b/build.rs @@ -0,0 +1,9 @@ +/* + Project: Catherine Framework (https://github.com/azazelm3dj3d/catherine) + Author: azazelm3dj3d (https://github.com/azazelm3dj3d) + License: BSD 2-Clause +*/ + +fn main() { + tauri_build::build() +} \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..823a879 --- /dev/null +++ b/public/index.html @@ -0,0 +1,289 @@ + + + + + + + + + + Catherine Framework + + + + +
+
+
+
+
+
+
+ +
+
+

+ Catherine Framework +

+
+ + + +
+
+
+
+
+
+ Decode +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+
+ +
+
+
+
+
+ Dump System Information (Linux only) +
+ +
+ +
+ +

+
+
+
+
+ +
+
+
+
+
+ Defang +
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+ +
+
+
+
+
+ WHOIS Lookup +
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+ +
+
+
+
+
+ Identify String +
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+ +
+
+
+
+
+ Crack Hash +
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+ +
+
+
+
+
+ Generate a Domain +
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+ +
+
+
+
+
+ Extract Zip File(s) +
+ +
+
+ +
+
+
+ +
+ +
+ +

+
+
+
+ +
+
+
+
+
+ Exit Catherine +
+
+ +
+
+
+
+ +
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/public/js/index.js b/public/js/index.js new file mode 100644 index 0000000..4f954eb --- /dev/null +++ b/public/js/index.js @@ -0,0 +1,97 @@ +/* + Project: Catherine Framework (https://github.com/azazelm3dj3d/catherine) + Author: azazelm3dj3d (https://github.com/azazelm3dj3d) + License: BSD 2-Clause +*/ + +const { invoke } = window.__TAURI__.tauri + +// Decode a string +const decodeString = () => { + invoke('decode_string', { + methodName: document.getElementById("methodName").value, + encodedData: document.getElementById("encodedData").value + }).then((response) => { + document.getElementById("res_0").innerHTML = response; + }) +} + +// Dump host system information +const sysInfo = () => { + invoke('sys_info').then((response) => { + document.getElementById("res_1").innerHTML = response; + }) +} + +// Defang a string +const defangString = () => { + invoke('defang_string', { + defangValue: document.getElementById("defangValue").value + }).then((response) => { + document.getElementById("res_2").innerHTML = response; + }) +} + +// WHOIS url lookup +const whoisLookup = () => { + invoke('whois_search', { + whoisUrl: document.getElementById("whoisUrl").value + }).then((response) => { + document.getElementById("res_3").innerHTML = response; + }) +} + +// Clears the WHOIS results to cleanup the UI +const clearWhoIs = () => { + document.getElementById("res_3").innerHTML = ""; +} + +// Malicious domain search +// const malSearch = () => { +// invoke('malicious_search', { +// malUrl: document.getElementById("malUrl").value +// }).then((response) => { +// document.getElementById("res_4").innerHTML = response; +// }) +// } + +// Identify an unknown string +const idString = () => { + invoke('id_string', { + idStr: document.getElementById("idStr").value + }).then((response) => { + document.getElementById("res_5").innerHTML = response; + }) +} + +// Attempt to crack an unknown hash +const crackHash = () => { + invoke('crack_hash', { + hashCracker: document.getElementById("hashCracker").value + }).then((response) => { + document.getElementById("res_6").innerHTML = response; + }) +} + +// Generate a domain for DNS squatting +const domainGen = () => { + invoke('domain_gen', { + domainStr: document.getElementById("domainStr").value + }).then(() => { + document.getElementById("res_7").innerHTML = "Check terminal"; + }) +} + +// Extract a zip file contents +const zipExtract = () => { + invoke('extract_zip', { + extractZipFile: document.getElementById("extractZipFile").value + }).then(() => { + document.getElementById("res_8").innerHTML = "Check terminal"; + }) +} + +// Exit application +const exitCatherine = () => { + invoke("exit_catherine") +} \ No newline at end of file diff --git a/src/catherine.rs b/src/catherine.rs index 6c0599f..42a4d8f 100644 --- a/src/catherine.rs +++ b/src/catherine.rs @@ -44,14 +44,16 @@ use crate::core::{ use mercy::{ mercy_decode, mercy_extra, - mercy_malicious, // status, url + mercy_malicious, mercy_experimental // status, url }; +use crate::ui::controller::launch_gui; + #[cfg(target_os = "windows")] extern crate ipconfig; pub(crate) static NAME: &str = "Catherine"; -pub(crate) static VERSION: &str = "0.4.1"; +pub(crate) static VERSION: &str = "0.5.0"; pub(crate) static NETSCAN_PATH: &str = "/opt/catherine/modules/net/netscan/dist/netscan"; pub(crate) static LINK_PARSER_PATH: &str = "/opt/catherine/modules/web/parsers/dist/links"; @@ -161,6 +163,7 @@ pub fn init(boot_msg: &str) { win_adapter_dump(); }, + // NOTE: Doesn't work on macOS "sys_info" => { println!("{}Internal IP Address: {}\n", mercy_extra("system_info", "all"), mercy_extra("internal_ip", "")); }, @@ -187,9 +190,42 @@ pub fn init(boot_msg: &str) { println!("Status: {}", mercy_malicious("status", set_url)); }, + "id" => { + let id: String = catherine_shell(NAME, VERSION, "identify/string".blue()); + let id_str: &str = &id; + + println!("{}", mercy_extra("identify", id_str)); + }, + + "crack_hash" => { + let hash: String = catherine_shell(NAME, VERSION, "crack_hash/hash".blue()); + let hash_str: &str = &hash; + + println!("{}", mercy_extra("crack", hash_str)); + }, + + "domain_gen" => { + let domain_name: String = catherine_shell(NAME, VERSION, "domain_gen/domain".blue()); + let domain_str: &str = &domain_name; + + mercy_experimental("domain_gen", domain_str); + }, + + "extract_zip" => { + let zip_name: String = catherine_shell(NAME, VERSION, "extract/zip".blue()); + let zip_str: &str = &zip_name; + + mercy_experimental("zip", zip_str); + }, + + // Launches the GUI + "launch" => { + launch_gui(); + }, + "version" => { println!("\nCatherine Framework v{}", VERSION); - println!("Author: azazelm3dj3d (https://github.com/azazelm3dj3d)"); + println!("Author: azazelm3dj3d (https://github.com/azazelm3dj3d)\n"); }, // Installs custom modules @@ -223,7 +259,7 @@ pub fn init(boot_msg: &str) { } }, - "help" => { + "help" | "h" => { help_menu(); }, diff --git a/src/core/commands.rs b/src/core/commands.rs index 2115e9f..85f00a6 100644 --- a/src/core/commands.rs +++ b/src/core/commands.rs @@ -332,7 +332,7 @@ pub fn win_adapter_dump() { pub fn help_menu() { println!("\n=== General ==="); - pretty_output("start_server\nscan_ports\nsearch_exploit\nset_decode\nsys_info\ndefang\nwhois\nmal_query\n", "Start a Rust server\nScan for open local ports\nSearch ExploitDB for an available exploit to review\nDecode an encoded message using one of our provided methods\nPrint local system information to stdout\nDefang a URL or IP address (prints to stdout)\nRun a domain registrar search against the WHOIS API\nRun a domain name search to validate if it's malicious (InQuest API)", "Command", "Description"); + pretty_output("start_server\nscan_ports\nsearch_exploit\nset_decode\nsys_info\ndefang\nwhois\nmal_query\nid\ncrack_hash\ndomain_gen\nextract_zip\nlaunch\n", "Start a Rust server\nScan for open local ports\nSearch ExploitDB for an available exploit to review\nDecode an encoded message using one of our provided methods\nPrint local system information to stdout\nDefang a URL or IP address (prints to stdout)\nRun a domain registrar search against the WHOIS API\nRun a domain name search to validate if it's malicious (InQuest API)\nAttempt to identify a string's origins\nAttempt to crack an unknown hash in real-time\nGenerate a string for domain squatting or phishing assessments\nExtract zip contents that are not password protected\nLaunch a GUI built with Tauri", "Command", "Description"); println!("\n=== Module ==="); pretty_output("set_module\nview_modules", "Set one of Catherine's modules\nCurrently installed modules", "Command", "Description"); diff --git a/src/main.rs b/src/main.rs index 34bd72e..ad0a121 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use rand::Rng; mod core; mod modules; +mod ui; mod catherine; mod meta; diff --git a/src/ui/controller.rs b/src/ui/controller.rs new file mode 100644 index 0000000..acb6c5c --- /dev/null +++ b/src/ui/controller.rs @@ -0,0 +1,111 @@ +/* + Project: Catherine Framework (https://github.com/azazelm3dj3d/catherine) + Author: azazelm3dj3d (https://github.com/azazelm3dj3d) + License: BSD 2-Clause +*/ + +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use std::{ + process::exit, + env +}; + +use chrono::{ + Timelike, + Local +}; + +use mercy::{ + mercy_decode, + mercy_extra, + mercy_experimental +}; + +#[tauri::command] +fn decode_string(method_name: &str, encoded_data: &str) -> String { + format!("Decoded String: {}", mercy_decode(method_name, encoded_data)) +} + +#[tauri::command] +fn sys_info() -> String { + if env::consts::OS == "linux" { + format!("{}Internal IP Address: {}\n", mercy_extra("system_info", "all"), mercy_extra("internal_ip", "")) + } else { + format!("Command not available on your operating system yet!") + } +} + +#[tauri::command] +fn defang_string(defang_value: &str) -> String { + format!("Defanged: {}", mercy_extra("defang", defang_value)) +} + +#[tauri::command] +fn whois_search(whois_url: &str) -> String { + format!("WHOIS Data: \n{}", mercy_extra("whois", whois_url)) +} + +// Causes extreme lag. Needs to be reviewed. +// #[tauri::command] +// fn malicious_search(mal_url: &str) -> String { +// format!("URL Status: {}!", mercy_malicious("status", mal_url)) +// } + +#[tauri::command] +fn id_string(id_str: &str) -> String { + format!("Guess: {}", mercy_extra("identify", id_str)) +} + +#[tauri::command] +fn crack_hash(hash_cracker: &str) -> String { + format!("{}", mercy_extra("crack", hash_cracker)) +} + +#[tauri::command] +fn domain_gen(domain_str: &str) -> String { + format!("{:?}", mercy_experimental("domain_gen", domain_str)) +} + +#[tauri::command] +fn extract_zip(extract_zip_file: &str) { + mercy_experimental("zip", extract_zip_file) +} + +#[tauri::command] +fn exit_catherine() -> String { + print!("\nThanks for checking out the Catherine Framework!"); + + let shutdown_time = Local::now(); + let (is_pm, hour) = shutdown_time.hour12(); + + println!( + "\nCatherine Framework shutdown at {:02}:{:02}:{:02} {}\n", + hour, + shutdown_time.minute(), + shutdown_time.second(), + if is_pm { "PM" } else { "AM" } + ); + + exit(0x0100); +} + +pub fn launch_gui() { + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![ + decode_string, + sys_info, + defang_string, + whois_search, + id_string, + crack_hash, + domain_gen, + extract_zip, + exit_catherine + ]) + .run(tauri::generate_context!()) + .expect("Unable to launch Catherine GUI"); +} \ No newline at end of file diff --git a/src/ui/mod.rs b/src/ui/mod.rs new file mode 100644 index 0000000..22f67fa --- /dev/null +++ b/src/ui/mod.rs @@ -0,0 +1,7 @@ +/* + Project: Catherine Framework (https://github.com/azazelm3dj3d/catherine) + Author: azazelm3dj3d (https://github.com/azazelm3dj3d) + License: BSD 2-Clause +*/ + +pub mod controller; \ No newline at end of file diff --git a/tauri.conf.json b/tauri.conf.json new file mode 100644 index 0000000..c4bf66d --- /dev/null +++ b/tauri.conf.json @@ -0,0 +1,67 @@ +{ + "build": { + "beforeBuildCommand": "", + "beforeDevCommand": "", + "devPath": "public", + "distDir": "public", + "withGlobalTauri": true + }, + "package": { + "productName": "catherine", + "version": "0.5.0" + }, + "tauri": { + "allowlist": { + "all": false + }, + "bundle": { + "active": true, + "category": "DeveloperTool", + "copyright": "", + "deb": { + "depends": [] + }, + "externalBin": [], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "identifier": "com.tauri.dev", + "longDescription": "", + "macOS": { + "entitlements": null, + "exceptionDomain": "", + "frameworks": [], + "providerShortName": null, + "signingIdentity": null + }, + "resources": [], + "shortDescription": "", + "targets": "all", + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "security": { + "csp": null + }, + "updater": { + "active": false + }, + "windows": [ + { + "fullscreen": false, + "height": 720, + "resizable": true, + "title": "Catherine Framework | v0.5.0", + "width": 1280 + } + ] + } + } + \ No newline at end of file