diff --git a/Cargo.lock b/Cargo.lock index 1bb4bcb..cc3c260 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "anstream" version = "0.6.14" @@ -89,21 +74,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "backtrace" -version = "0.3.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.22.1" @@ -208,31 +178,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "data-encoding" version = "2.11.0" @@ -251,12 +196,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - [[package]] name = "encoding_rs" version = "0.8.34" @@ -331,10 +270,25 @@ dependencies = [ ] [[package]] -name = "futures-channel" -version = "0.3.30" +name = "futures" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -342,41 +296,64 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -391,12 +368,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - [[package]] name = "h2" version = "0.4.5" @@ -428,12 +399,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "http" version = "1.1.0" @@ -654,24 +619,15 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" -dependencies = [ - "adler", -] - [[package]] name = "mio" -version = "0.8.11" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -691,25 +647,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.19.0" @@ -815,12 +752,6 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.30" @@ -884,26 +815,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -968,18 +879,13 @@ version = "0.1.0" dependencies = [ "clap", "dns-lookup", - "rayon", + "futures", "reqwest", + "tokio", "trust-dns-resolver", "urlencoding", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustix" version = "0.38.34" @@ -1096,6 +1002,16 @@ dependencies = [ "serde", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -1224,18 +1140,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ - "backtrace", "bytes", "libc", "mio", - "num_cpus", + "parking_lot", "pin-project-lite", - "socket2 0.5.7", - "windows-sys 0.48.0", + "signal-hook-registry", + "socket2 0.6.3", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 12fc821..28d6218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,8 @@ edition = "2021" [dependencies] clap = { version = "4.5.4", features = ["derive"] } dns-lookup = "2.0.4" -rayon = "1.12.0" +futures = "0.3.32" reqwest = { version = "0.12.4", features = ["blocking"] } +tokio = { version = "1.52.3", features = ["full"] } trust-dns-resolver = "0.23.2" urlencoding = "2.1.3" diff --git a/src/main.rs b/src/main.rs index f4e77a9..cabe945 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,15 @@ use clap::Parser; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; -use rayon::ThreadPoolBuilder; +use futures::{stream, StreamExt}; use reqwest::{self, StatusCode}; use std::fs::File; use std::io::BufWriter; use std::io::Write; use std::path::PathBuf; use std::process::exit; -use std::sync::mpsc::{channel, Sender}; -use std::thread; +use std::sync::Arc; use std::{collections::HashMap, fs}; -use trust_dns_resolver::config::*; -use trust_dns_resolver::Resolver; +use tokio::sync::mpsc::{channel, Sender}; +use trust_dns_resolver::{config::*, TokioAsyncResolver}; use urlencoding::encode; enum OutputMessage { @@ -47,26 +45,20 @@ struct Args { ///input file full of domains formatted to one domain per line. #[arg(short, long)] domainfile: Option, - - ///number of threads to use by default it will use the rayon global pool default. - #[arg(long)] - threads: Option, } -fn try_sub( +async fn try_sub( domain: String, wildcard_reses: HashMap<&String, Vec>, tx: Sender, output: bool, + resolver: Arc, ) { - let mut opts = ResolverOpts::default(); - opts.edns0 = true; - let resolver = Resolver::new(ResolverConfig::default(), opts).unwrap(); let mut ips = Vec::new(); - if let Ok(ipv4s) = resolver.ipv4_lookup(&domain) { + if let Ok(ipv4s) = resolver.ipv4_lookup(&domain).await { ipv4s.iter().for_each(|ip| ips.push(ip.0.to_string())); } - if let Ok(ipv6s) = resolver.ipv6_lookup(&domain) { + if let Ok(ipv6s) = resolver.ipv6_lookup(&domain).await { ipv6s.iter().for_each(|ip| ips.push(ip.0.to_string())); } let mut wild_card = None; @@ -90,11 +82,14 @@ fn try_sub( } } if output { - if let Err(e) = tx.send(OutputMessage::SubDomainResult(format!( - "{}: {}", - &domain, - ips.join(", ") - ))) { + if let Err(e) = tx + .send(OutputMessage::SubDomainResult(format!( + "{}: {}", + &domain, + ips.join(", ") + ))) + .await + { eprintln!("error sending output! {}", e); } } @@ -102,14 +97,17 @@ fn try_sub( } } -fn try_dir(url: String, tx: Sender, output: bool) { - let resp_stat = reqwest::blocking::get(&encode(&url).to_string()); +async fn try_dir(url: String, tx: Sender, output: bool) { + let resp_stat = reqwest::get(&encode(&url).to_string()).await; if resp_stat.is_ok() { let resp = resp_stat.unwrap().status(); match resp { StatusCode::OK => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -117,7 +115,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::ACCEPTED => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -125,7 +126,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::CONTINUE => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -133,7 +137,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::CREATED => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -141,7 +148,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::FOUND => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -149,7 +159,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::IM_A_TEAPOT => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -157,7 +170,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::MOVED_PERMANENTLY => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -165,7 +181,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::PERMANENT_REDIRECT => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -173,7 +192,10 @@ fn try_dir(url: String, tx: Sender, output: bool) { } StatusCode::TEMPORARY_REDIRECT => { if output { - if let Err(e) = tx.send(OutputMessage::UrlResult(format!("{} {}", resp, url))) { + if let Err(e) = tx + .send(OutputMessage::UrlResult(format!("{} {}", resp, url))) + .await + { eprintln!("error sending output! {}", e); } } @@ -184,7 +206,8 @@ fn try_dir(url: String, tx: Sender, output: bool) { } } -fn main() { +#[tokio::main] +async fn main() { print!( " @@ -262,7 +285,7 @@ fn main() { let mut subs_to_try = Vec::new(); let args = Args::parse(); let mut targets = Vec::new(); - let (tx, rx) = channel(); + let (tx, mut rx) = channel(1024); if let Some(given_targets) = args.target { for target in given_targets.split(",").collect::>() { targets.push(target.to_owned()); @@ -286,32 +309,28 @@ fn main() { println!("no targets provided!"); exit(1); } - if let Some(thread) = args.threads { - ThreadPoolBuilder::new() - .num_threads(thread) - .build_global() - .unwrap(); - } - println!( - "INFO:::{} threads will be used:::", - rayon::current_num_threads() - ); println!("detecting if a wild card record exists..."); let mut opts = ResolverOpts::default(); opts.edns0 = true; - let resolver = Resolver::new(ResolverConfig::default(), opts).unwrap(); + let resolver = TokioAsyncResolver::tokio(ResolverConfig::default(), opts); let mut wild_card_results = HashMap::new(); for target in &targets { if !target.contains("http") { subs_to_try.push(target.clone()); let mut ips = Vec::new(); - if let Ok(ipv4s) = resolver.ipv4_lookup(&format!("burstpyrofoo.{}", target)) { + if let Ok(ipv4s) = resolver + .ipv4_lookup(&format!("burstpyrofoo.{}", target)) + .await + { ipv4s.iter().for_each(|ip| { ips.push(ip.0.to_string()); }); println!("INFO:::wildcard found: {} {}:::", target, ips.join(", ")); } - if let Ok(ipv6s) = resolver.ipv6_lookup(&format!("burstpyrofoo.{}", target)) { + if let Ok(ipv6s) = resolver + .ipv6_lookup(&format!("burstpyrofoo.{}", target)) + .await + { println!("wildcard found!"); ipv6s.iter().for_each(|ip| { ips.push(ip.0.to_string()); @@ -366,7 +385,7 @@ fn main() { path, path ); } - let write_handler = thread::spawn(move || { + let write_handler = tokio::spawn(async move { if output { let urlfile = File::create(urlpath).unwrap(); let subfile = File::create(subpath).unwrap(); @@ -376,7 +395,7 @@ fn main() { let mut url_counter = 0; let mut sub_counter = 0; loop { - let msg = rx.recv().unwrap(); + let msg = rx.recv().await.unwrap(); match msg { OutputMessage::UrlResult(res) => { if let Err(e) = writeln!(urlwrite, "{}", res) { @@ -413,32 +432,40 @@ fn main() { println!("INFO:::results will be printed to console and not saved...:::"); } }); - rayon::scope(|s| { - if !dirs_to_try.is_empty() { - s.spawn(|_| { - dirs_to_try.par_iter().for_each(|url| { - try_dir(url.to_string(), tx.clone(), output); - }); - }); + let resolver = TokioAsyncResolver::tokio(ResolverConfig::default(), opts); + let resolver = Arc::new(resolver); + let dir_stream = stream::iter(dirs_to_try.into_iter().map(|url| { + let tx = tx.clone(); + let output = output.clone(); + async move { + try_dir(url, tx, output).await; } - if !subs_to_try.is_empty() { - s.spawn(|_| { - subs_to_try.par_iter().for_each(|sub| { - try_sub( - sub.to_string(), - wild_card_results.clone(), - tx.clone(), - output, - ); - }); - }) + })); + let sub_stream = stream::iter(subs_to_try.into_iter().map(|sub| { + let tx = tx.clone(); + let output = output.clone(); + let wc = wild_card_results.clone(); + let resolver = resolver.clone(); + async move { + try_sub(sub, wc, tx, output, resolver.clone()).await; } - }); + })); + + let concurrency = 100; + dir_stream + .buffer_unordered(concurrency) + .collect::>() + .await; + + sub_stream + .buffer_unordered(concurrency) + .collect::>() + .await; println!("INFO:::enumeration finished!:::"); if output { println!("INFO:::waiting for output writer to finish...:::"); - tx.send(OutputMessage::Shutdown).unwrap(); + tx.send(OutputMessage::Shutdown).await.unwrap(); } - write_handler.join().unwrap(); + write_handler.await.unwrap(); println!("INFO:::done bruteforcing, happy hunting!:::"); }