Compare commits

...
Author SHA1 Message Date
Brandon fa072bac12 For Kaeros 2020-09-17 19:12:24 +01:00
Brandon ff5a4b44f8 Added debug statements 2020-09-16 18:46:52 +01:00
Brandon 3763c384ca made macro TUI accessible 2020-09-15 21:56:31 +01:00
Brandon 7b85b9756b Changed quiet mode to greppable 2020-09-15 18:34:47 +01:00
Brandon d23b4f1ccf removed unused code 2020-09-15 18:22:10 +01:00
Brandon a185d0fb26 Merge branch 'master' into bee-add-top-ports 2020-09-15 02:46:31 +01:00
Brandon 64624e90b3 merging 2020-09-15 02:46:29 +01:00
Brandon 774213cc15 Fixed tests 2020-09-10 01:48:49 +01:00
Brandon 58906b7f7e added top ports 2020-09-10 01:36:40 +01:00
4 changed files with 103 additions and 82 deletions

No files matched your search

+47 -24
View File
@@ -2,6 +2,7 @@ use serde_derive::Deserialize;
use std::fs;
use structopt::{clap::arg_enum, StructOpt};
const LOWEST_PORT_NUMBER: u16 = 1;
const TOP_PORT_NUMBER: u16 = 65535;
@@ -70,9 +71,9 @@ pub struct Opts {
#[structopt(short, long)]
pub no_config: bool,
/// Quiet mode. Only output the ports. No Nmap. Useful for grep or outputting to a file.
/// greppable mode. Only output the ports. No Nmap. Useful for grep or outputting to a file.
#[structopt(short, long)]
pub quiet: bool,
pub greppable: bool,
/// Accessible mode. Turns off features which negatively affect screen readers.
#[structopt(long)]
@@ -110,6 +111,10 @@ pub struct Opts {
/// For things like --script '(safe and vuln)' enclose it in quotations marks \"'(safe and vuln)'\"")
#[structopt(last = true)]
pub command: Vec<String>,
/// Use the top 1000 ports.
#[structopt(long)]
pub top: bool,
}
impl Opts {
@@ -146,7 +151,7 @@ impl Opts {
}
}
merge_required!(addresses, quiet, accessible, batch_size, timeout, scan_order, command);
merge_required!(addresses, greppable, accessible, batch_size, timeout, scan_order, command);
}
fn merge_optional(&mut self, config: &Config) {
@@ -160,7 +165,12 @@ impl Opts {
}
}
merge_optional!(ports, range, ulimit);
// Only use top ports when the user asks for them
if self.top {
// self.ports = config.ports.clone().values().cloned().collect();
}
merge_optional!(range, ulimit);
}
}
@@ -172,7 +182,7 @@ pub struct Config {
addresses: Option<Vec<String>>,
ports: Option<Vec<u16>>,
range: Option<PortRange>,
quiet: Option<bool>,
greppable: Option<bool>,
accessible: Option<bool>,
batch_size: Option<u16>,
timeout: Option<u32>,
@@ -182,6 +192,7 @@ pub struct Config {
command: Option<Vec<String>>,
}
impl Config {
/// Reads the configuration file with TOML format and parses it into a
/// Config struct.
@@ -190,12 +201,23 @@ impl Config {
///
/// addresses = ["127.0.0.1", "127.0.0.1"]
/// ports = [80, 443, 8080]
/// quiet = true
/// greppable = true
/// scan_order: "Serial"
///
pub fn read() -> Self {
let config_dir = dirs::home_dir();
// TODO make opt.accessible use opts
// right now its greppable=False, accessible=True
// I want it to use opts.accessible instead of accessible=True
crate::detail!(format!(
"{} {:?}",
"The config file is expected to be at", config_dir
), false, true);
let mut paths = Vec::new();
paths.push(match dirs::home_dir() {
paths.push(match config_dir {
Some(mut path) => {
path.push(".rustscan.toml");
path
@@ -203,30 +225,26 @@ impl Config {
None => panic!("Could not infer config file path."),
});
paths.push(match dirs::config_dir() {
Some(mut path) => {
path.push("rustscan");
path.push("config.toml");
path
}
None => panic!("Could not infer config file path."),
});
let mut contents: Option<String> = None;
for path in paths.iter().rev() {
println!{"path is {:?}", path};
contents = match fs::read_to_string(path) {
Ok(content) => {
contents = Some(content);
println!("contents is {:?}", contents);
break;
}
Err(_) => None,
};
println!("contents is {:?}", contents);
}
// println!("{:?}", contents);
if contents.is_none() {
contents = Some(String::new());
}
let config: Config = match toml::from_str(&contents.unwrap()) {
Ok(config) => config,
Err(e) => {
@@ -235,6 +253,8 @@ impl Config {
}
};
println!("\nconfig is {:?}", config);
config
}
}
@@ -249,7 +269,7 @@ mod tests {
addresses: vec![],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 0,
timeout: 0,
ulimit: None,
@@ -258,13 +278,14 @@ mod tests {
no_nmap: false,
scan_order: ScanOrder::Serial,
no_config: true,
top: false,
};
let config = Config {
addresses: Some(vec!["127.0.0.1".to_owned()]),
ports: None,
range: None,
quiet: Some(true),
greppable: Some(true),
batch_size: Some(25_000),
timeout: Some(1_000),
ulimit: None,
@@ -277,7 +298,7 @@ mod tests {
opts.merge(&config);
assert_eq!(opts.addresses, vec![] as Vec<String>);
assert_eq!(opts.quiet, false);
assert_eq!(opts.greppable, false);
assert_eq!(opts.accessible, false);
assert_eq!(opts.timeout, 0);
assert_eq!(opts.command, vec![] as Vec<String>);
@@ -290,7 +311,7 @@ mod tests {
addresses: vec![],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 0,
timeout: 0,
ulimit: None,
@@ -299,6 +320,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_nmap: false,
no_config: false,
top: false,
};
let config = Config {
@@ -306,7 +328,7 @@ mod tests {
ports: None,
no_nmap: Some(false),
range: None,
quiet: Some(true),
greppable: Some(true),
batch_size: Some(25_000),
timeout: Some(1_000),
ulimit: None,
@@ -318,7 +340,7 @@ mod tests {
opts.merge_required(&config);
assert_eq!(opts.addresses, config.addresses.unwrap());
assert_eq!(opts.quiet, config.quiet.unwrap());
assert_eq!(opts.greppable, config.greppable.unwrap());
assert_eq!(opts.timeout, config.timeout.unwrap());
assert_eq!(opts.command, config.command.unwrap());
assert_eq!(opts.accessible, config.accessible.unwrap());
@@ -331,7 +353,7 @@ mod tests {
addresses: vec![],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 0,
timeout: 0,
ulimit: None,
@@ -340,6 +362,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_nmap: false,
no_config: false,
top: false,
};
let config = Config {
@@ -349,7 +372,7 @@ mod tests {
start: 1,
end: 1_000,
}),
quiet: None,
greppable: None,
batch_size: None,
timeout: None,
no_nmap: Some(false),
+33 -36
View File
@@ -1,6 +1,6 @@
extern crate shell_words;
mod tui;
pub mod tui;
mod input;
use input::{Config, Opts, PortRange, ScanOrder};
@@ -45,14 +45,14 @@ fn main() {
info!("Main() `opts` arguments are {:?}", opts);
if !opts.quiet && !opts.accessible {
if !opts.greppable && !opts.accessible {
print_opening();
}
let ips: Vec<IpAddr> = parse_addresses(&opts);
if ips.is_empty() {
warning!("No IPs could be resolved, aborting scan.", false);
warning!("No IPs could be resolved, aborting scan.", false, opts.accessible);
std::process::exit(1);
}
@@ -63,7 +63,7 @@ fn main() {
&ips,
batch_size,
Duration::from_millis(opts.timeout.into()),
opts.quiet,
opts.greppable,
PortStrategy::pick(opts.range, opts.ports, opts.scan_order),
);
@@ -93,19 +93,19 @@ fn main() {
opts.batch_size,
(opts.batch_size / 2).to_string(),
"'rustscan -b <batch_size> <ip address>'");
warning!(x, opts.quiet);
warning!(x, opts.greppable, opts.accessible);
}
for (ip, ports) in ports_per_ip.iter_mut() {
let nmap_str_ports: Vec<String> = ports.into_iter().map(|port| port.to_string()).collect();
detail!("Starting Nmap", opts.quiet);
detail!("Starting Nmap", opts.greppable, opts.accessible);
// nmap port style is 80,443. Comma separated with no spaces.
let ports_str = nmap_str_ports.join(",");
// if quiet mode is on nmap should not be spawned
if opts.quiet {
// if greppable mode is on nmap should not be spawned
if opts.greppable {
println!("{}", ports_str);
continue;
}
@@ -118,7 +118,7 @@ fn main() {
output!(format!(
"The Nmap command to be run is nmap {}\n",
&nmap_args.join(" ")
));
), false, opts.accessible);
// Runs the nmap command and spawns it as a process.
let mut child = Command::new("nmap")
@@ -146,19 +146,7 @@ Faster Nmap scanning with Rust."#;
println!("{}", info.gradient(Color::Yellow).bold());
funny_opening!();
let config_path = match dirs::config_dir() {
Some(mut path) => {
path.push("rustscan");
path.push("config.toml");
path
}
None => panic!("Couldn't find config dir."),
};
detail!(format!(
"{} {:?}",
"The config file is expected to be at", config_path
));
}
#[cfg(not(tarpaulin_include))]
fn build_nmap_arguments<'a>(
@@ -191,7 +179,7 @@ fn parse_addresses(opts: &Opts) -> Vec<IpAddr> {
Ok(mut iter) => ips.push(iter.nth(0).unwrap().ip()),
_ => {
let failed_to_resolve = format!("Host {:?} could not be resolved.", ip_or_host);
warning!(failed_to_resolve, opts.quiet);
warning!(failed_to_resolve, opts.greppable, opts.accessible);
}
},
}
@@ -208,7 +196,7 @@ fn adjust_ulimit_size(opts: &Opts) -> rlimit::rlim {
Ok(_) => {
detail!(
format!("Automatically increasing ulimit value to {}.", limit),
opts.quiet
opts.greppable, opts.accessible
);
}
Err(_) => println!("{}", "ERROR. Failed to set ulimit value."),
@@ -226,7 +214,7 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
// Adjust the batch size when the ulimit value is lower than the desired batch size
if ulimit < batch_size {
warning!("File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers",
opts.quiet
opts.greppable, opts.accessible
);
// When the OS supports high file limits like 8000, but the user
@@ -236,7 +224,7 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
// ulimit is smaller than aveage batch size
// user must have very small ulimit
// decrease batch size to half of ulimit
warning!("Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. ");
warning!("Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. ", false, opts.accessible);
info!("Halving batch_size because ulimit is smaller than average batch size");
batch_size = ulimit / 2
} else if ulimit > DEFAULT_FILE_DESCRIPTORS_LIMIT {
@@ -252,7 +240,7 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
detail!(format!(
"File limit higher than batch size. Can increase speed by increasing batch size '-b {}'.",
ulimit - 100
), opts.quiet);
), opts.greppable, opts.accessible);
}
batch_size as u16
@@ -271,7 +259,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -280,6 +268,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = infer_batch_size(&opts, 120);
@@ -292,7 +281,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -301,6 +290,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = infer_batch_size(&opts, 9_000);
@@ -314,7 +304,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -323,6 +313,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = infer_batch_size(&opts, 5_000);
@@ -335,7 +326,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -344,6 +335,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = adjust_ulimit_size(&opts);
@@ -356,12 +348,12 @@ mod tests {
assert!(1 == 1);
}
#[test]
fn test_high_ulimit_no_quiet_mode() {
fn test_high_ulimit_no_greppable_mode() {
let opts = Opts {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 10,
timeout: 1_000,
ulimit: None,
@@ -370,6 +362,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
infer_batch_size(&opts, 1_000_000);
@@ -383,7 +376,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned(), "192.168.0.0/30".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -392,6 +385,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
@@ -413,7 +407,7 @@ mod tests {
addresses: vec!["google.com".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -422,6 +416,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
@@ -434,7 +429,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned(), "im_wrong".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -443,6 +438,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
@@ -455,7 +451,7 @@ mod tests {
addresses: vec!["im_wrong".to_owned(), "300.10.1.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -464,6 +460,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
-1
View File
@@ -92,7 +92,6 @@ impl Scanner {
async fn scan_socket(&self, socket: SocketAddr) -> io::Result<SocketAddr> {
match self.connect(socket).await {
Ok(x) => {
// match stream_result.shutdown(Shutdown::Both)
info!("Shutting down stream");
match x.shutdown(Shutdown::Both) {
_ => {}
+23 -21
View File
@@ -3,44 +3,46 @@
#[macro_export]
macro_rules! warning {
($name:expr) => {
($name:expr, $greppable:expr, $accessible:expr) => {
use ansi_term::Colour::Red;
println!("{} {}", Red.bold().paint("[!]"), $name);
};
// quiet mode
($name:expr, $quiet:expr) => {
use ansi_term::Colour::Red;
if !$quiet {
// if greppable, no else statement so do not print.
if !$greppable {
println!("{} {}", Red.bold().paint("[!]"), $name);
}
else if !$accessible{
// Don't print the ascii art
println!("{}", $name);
}
};
}
#[macro_export]
macro_rules! detail {
($name:expr) => {
($name:expr, $greppable:expr, $accessible:expr) => {
use ansi_term::Colour::Blue;
println!("{} {}", Blue.bold().paint("[~]"), $name);
};
($name:expr, $quiet:expr) => {
use ansi_term::Colour::Blue;
if !$quiet {
// if greppable, no else statement so do not print.
if !$greppable {
println!("{} {}", Blue.bold().paint("[~]"), $name);
}
else if !$accessible{
// Don't print the ascii art
println!("{}", $name);
}
};
}
#[macro_export]
macro_rules! output {
($name:expr, $quiet:expr) => {
($name:expr, $greppable:expr, $accessible:expr) => {
use ansi_term::Colour::RGB;
if !$quiet {
// if greppable, no else statement so do not print.
if !$greppable {
println!("{} {}", RGB(0, 255, 9).bold().paint("[>]"), $name);
}
};
($name:expr) => {
use ansi_term::Colour::RGB;
println!("{} {}", RGB(0, 255, 9).bold().paint("[>]"), $name);
else if !$accessible{
// Don't print the ascii art
println!("{}", $name);
}
};
}
@@ -50,15 +52,15 @@ macro_rules! funny_opening {
() => {
use rand::seq::SliceRandom;
let quotes = vec![
"Nmap? More like slowmap.🐢",
"Hello, Elliot.",
"🌍HACK THE PLANET🌍",
"Real hackers hack time ⌛",
"Please contribute more quotes to our GitHub https://github.com/rustscan/rustscan",
"😵 https://admin.tryhackme.com",
"Mess with the best, die like the rest",
];
let random_quote = quotes.choose(&mut rand::thread_rng()).unwrap();
println!("{}\n", random_quote);
// println!("{} {}", RGB(0, 255, 9).bold().paint("[>]"), $name);
};
}