mirror of
https://github.com/edu4rdshl/fhc.git
synced 2026-07-17 23:24:50 +00:00
Add support for using wordlists.
Random user agent per request support. Bump dependencies. Performance improvement dropping the tasks once finished. Signed-off-by: Edu4rdSHL <edu4rdshl@protonmail.com>
This commit is contained in:
parent
a4220feeb2
commit
4439d45a10
5 changed files with 349 additions and 363 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
/hosts.txt
|
/hosts.txt
|
||||||
|
*.txt
|
||||||
|
|
|
||||||
609
Cargo.lock
generated
609
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -12,8 +12,9 @@ readme = "README.md"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "0.2.22", features = ["full"] }
|
tokio = { version = "1.5.0", features = ["full", "io-util"] }
|
||||||
futures = "0.3.5"
|
futures = "0.3.14"
|
||||||
clap = "2.33.3"
|
clap = "2.33.3"
|
||||||
reqwest = { version = "0.10.8", features = ["default-tls"] }
|
reqwest = { version = "0.11.3", features = ["default-tls"] }
|
||||||
openssl = { version = "0.10.30", features = ["vendored"] }
|
openssl = { version = "0.10.34", features = ["vendored"] }
|
||||||
|
rand = "0.8.3"
|
||||||
|
|
|
||||||
52
src/main.rs
52
src/main.rs
|
|
@ -1,7 +1,9 @@
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
clap::{value_t, App, Arg},
|
clap::{value_t, App, Arg},
|
||||||
futures::stream::StreamExt,
|
futures::stream::StreamExt,
|
||||||
reqwest,
|
reqwest::{self, header::USER_AGENT},
|
||||||
tokio::{
|
tokio::{
|
||||||
self,
|
self,
|
||||||
io::{self, AsyncReadExt},
|
io::{self, AsyncReadExt},
|
||||||
|
|
@ -28,13 +30,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Timeout in seconds. Default: 3"),
|
.help("Timeout in seconds. Default: 3"),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
Arg::with_name("user-agent")
|
|
||||||
.short("u")
|
|
||||||
.long("user-agent")
|
|
||||||
.takes_value(true)
|
|
||||||
.help("User agent string."),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("show-codes")
|
Arg::with_name("show-codes")
|
||||||
.short("s")
|
.short("s")
|
||||||
|
|
@ -42,6 +37,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Show status codes for discovered hosts."),
|
.help("Show status codes for discovered hosts."),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("domain")
|
||||||
|
.short("d")
|
||||||
|
.long("domain")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Target domain."),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("1xx")
|
Arg::with_name("1xx")
|
||||||
.short("1")
|
.short("1")
|
||||||
|
|
@ -94,41 +96,53 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let threads = value_t!(matches.value_of("threads"), usize).unwrap_or_else(|_| 100);
|
let threads = value_t!(matches.value_of("threads"), usize).unwrap_or_else(|_| 100);
|
||||||
let timeout = value_t!(matches.value_of("timeout"), u64).unwrap_or_else(|_| 3);
|
let timeout = value_t!(matches.value_of("timeout"), u64).unwrap_or_else(|_| 5);
|
||||||
let user_agent = value_t!(matches.value_of("user-agent"), String).unwrap_or_else(|_| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36".to_string());
|
let user_agents_list = utils::user_agents();
|
||||||
let show_status_codes = matches.is_present("show-codes");
|
let show_status_codes = matches.is_present("show-codes");
|
||||||
|
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::from_secs(timeout))
|
.timeout(std::time::Duration::from_secs(timeout))
|
||||||
.danger_accept_invalid_certs(true)
|
.danger_accept_invalid_certs(true)
|
||||||
.user_agent(user_agent)
|
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
// Read stdin
|
// Read stdin
|
||||||
let mut buffer = String::new();
|
|
||||||
let mut stdin = io::stdin();
|
let mut stdin = io::stdin();
|
||||||
|
let mut buffer = String::new();
|
||||||
stdin.read_to_string(&mut buffer).await?;
|
stdin.read_to_string(&mut buffer).await?;
|
||||||
let hosts: Vec<String> = buffer.lines().map(str::to_owned).collect();
|
|
||||||
|
let hosts: Vec<String> = if matches.is_present("domain") {
|
||||||
|
let domain = value_t!(matches, "domain", String).unwrap();
|
||||||
|
buffer
|
||||||
|
.lines()
|
||||||
|
.map(|word| format!("{}.{}", word, domain))
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
buffer.lines().map(str::to_owned).collect()
|
||||||
|
};
|
||||||
|
|
||||||
futures::stream::iter(hosts.into_iter().map(|host| {
|
futures::stream::iter(hosts.into_iter().map(|host| {
|
||||||
|
// Use a random user agent
|
||||||
|
let user_agent = utils::return_random_string(&user_agents_list);
|
||||||
// HTTP/HTTP URLs
|
// HTTP/HTTP URLs
|
||||||
let https_url = format!("https://{}", host);
|
let https_url = format!("https://{}", host);
|
||||||
let http_url = format!("http://{}", host);
|
let http_url = format!("http://{}", host);
|
||||||
// Create futures
|
// Create futures
|
||||||
let https_send_fut = client.get(&https_url).send();
|
let https_send_fut = client.get(&https_url).header(USER_AGENT, &user_agent);
|
||||||
let http_send_fut = client.get(&http_url).send();
|
let http_send_fut = client.get(&http_url).header(USER_AGENT, &user_agent);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let mut response_code = 0;
|
let mut response_code = 0;
|
||||||
let mut valid_url = String::new();
|
let mut valid_url = String::new();
|
||||||
if let Ok(resp) = https_send_fut.await {
|
if let Ok(resp) = https_send_fut.send().await {
|
||||||
valid_url = https_url;
|
valid_url = https_url;
|
||||||
response_code = resp.status().as_u16();
|
response_code = resp.status().as_u16();
|
||||||
} else if let Ok(resp) = http_send_fut.await {
|
drop(resp)
|
||||||
|
} else if let Ok(resp) = http_send_fut.send().await {
|
||||||
valid_url = http_url;
|
valid_url = http_url;
|
||||||
response_code = resp.status().as_u16()
|
response_code = resp.status().as_u16();
|
||||||
|
drop(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid_url.is_empty() && conditional_response_code == 0)
|
if (!valid_url.is_empty() && conditional_response_code == 0)
|
||||||
|| ((!valid_url.is_empty() && conditional_response_code != 0)
|
|| ((!valid_url.is_empty() && conditional_response_code != 0)
|
||||||
&& (response_code >= conditional_response_code
|
&& (response_code >= conditional_response_code
|
||||||
|
|
|
||||||
41
src/utils.rs
Normal file
41
src/utils.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
use rand::{seq::SliceRandom, thread_rng};
|
||||||
|
|
||||||
|
pub fn user_agents() -> Vec<String> {
|
||||||
|
vec!["Mozilla/5.0 (Windows NT 6.1; WOW64; rv:77.0) Gecko/20190101 Firefox/77.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:77.0) Gecko/20100101 Firefox/77.0".to_string(),
|
||||||
|
"Mozilla/5.0 (X11; Linux ppc64le; rv:75.0) Gecko/20100101 Firefox/75.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/75.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.10; rv:75.0) Gecko/20100101 Firefox/75.0".to_string(),
|
||||||
|
"Mozilla/5.0 (X11; Linux; rv:74.0) Gecko/20100101 Firefox/74.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/73.0".to_string(),
|
||||||
|
"Mozilla/5.0 (X11; OpenBSD i386; rv:72.0) Gecko/20100101 Firefox/72.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:71.0) Gecko/20100101 Firefox/71.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:70.0) Gecko/20191022 Firefox/70.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:70.0) Gecko/20190101 Firefox/70.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows; U; Windows NT 9.1; en-US; rv:12.9.1.11) Gecko/20100821 Firefox/70".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:69.2.1) Gecko/20100101 Firefox/69.2".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 6.1; rv:68.7) Gecko/20100101 Firefox/68.7".to_string(),
|
||||||
|
"Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19577".to_string(),
|
||||||
|
"Mozilla/5.0 (X11) AppleWebKit/62.41 (KHTML, like Gecko) Edge/17.10859 Safari/452.6".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14931".to_string(),
|
||||||
|
"Chrome (AppleWebKit/537.1; Chrome50.0; Windows NT 6.3) AppleWebKit/537.36 (KHTML like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.9200".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36".to_string(),
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36".to_string(),
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36".to_string(),
|
||||||
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36".to_string(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_random_string(strings: &[String]) -> String {
|
||||||
|
if strings.is_empty() {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
strings.choose(&mut thread_rng()).unwrap().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue