diff --git a/src/main.rs b/src/main.rs index 033d664..f6bfbbd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,12 @@ use clap::Parser; -use std::io::prelude::*; use std::io::{self, Read}; -use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; -use std::time::{Duration, Instant}; -use std::thread; use atty::Stream; -use std::io::BufReader; +use std::time::{Duration}; + +mod tcp; + +use tcp::tcp_scan; +use tcp::tcp_stress; fn main() -> std::io::Result<()> { @@ -15,6 +16,8 @@ fn main() -> std::io::Result<()> { let sleep = Duration::from_millis(args.wait); let ports = handle_ports(args.ports.clone(), &args.range); let threads = args.cthreads; + + print_banner(); //Reading the payload from stdin (if applicable) let mut payload = String::new(); @@ -50,96 +53,18 @@ fn handle_ports(ports: Vec, range: &bool) -> Vec { } } +fn print_banner() { + let lines = [ + " ____ ____ ____ _______ ____ ________", + " / __ \\/ __ \\/ __ \\/_ __/ | / / / / /_ __/", + " / /_/ / / / / /_/ / / / / |/ / / / / / / ", + " / ____/ /_/ / _, _/ / / / /| / /_/ / / / ", + "/_/ \\____/_/ |_| /_/ /_/ |_/\\____/ /_/ ", + ]; - -///Scan the ports on address by attempting a tcp connection. -fn tcp_scan(address: String, timeout: Duration, sleep: Duration, ports: Vec) -> std::io::Result<()> { - println!("Scanning {}", address); - - for i in ports { - let socket = resolve_add(&address.as_str(), &i); - match TcpStream::connect_timeout(&socket, timeout) { - Ok(mut _s) => { - println!("TCP/{} => ACCEPT", i); - //s.write(b"Some padding")?; - } - Err(_) => { - println!("TCP/{} => REJECT", i); - } - } - - thread::sleep(sleep.clone()); - //stream.write(b"Some great padding")?; - //stream.read(&mut [0; 128])?; + for line in lines { + println!("{}", line); } - Ok(()) -} - -///Takes either an hostname or an IP address and port, and resolve to a socket address. -///DNS recordings can lead to multiple entries : we take the first one. -fn resolve_add(host: &str, port: &u32) -> SocketAddr { - let details = format!("{}:{}", host, port); - let server: Vec<_> = details - .to_socket_addrs() - .expect("Can't resolve your address") - .collect(); - return server[0]; -} - -///Try to stress the remote machine by attempting to every given port at once and sending payload -fn tcp_stress(payload: String, address: String, timeout: Duration, interval: Duration, ports: Vec, threads: u32) -> std::io::Result<()> { - let mut handles = vec![]; - - for port in ports { - tcp_scan(address.clone(), timeout, interval, vec![port])?; - let mut threads_left = threads; - - loop { - let add = address.clone(); - let pay = payload.clone(); - let int = interval * 1000; - let end_time = Instant::now() + int; - //pay.push_str("\r\n"); - - - handles.push(thread::spawn( move || { - let socket = resolve_add(&add.as_str(), &port); - loop { - //Check if it is time to stop - if Instant::now() >= end_time { break; } - match TcpStream::connect_timeout(&socket, timeout) { - Ok(mut s) => { - //Remote port answers - //Writing - s.write_all(pay.as_bytes()).unwrap(); - s.flush().unwrap(); - - //Reading - s.set_read_timeout(Some(Duration::from_millis(500))).unwrap(); - let mut reader = BufReader::new(s.try_clone().unwrap()); - let mut answer = String::new(); - let count = reader.read_line(&mut answer).unwrap_or(0); - if count > 0 { - println!("Read {} bytes for port {} -> {}", count, &port, answer); - } - - //Sleeping - thread::sleep(Duration::from_millis(10)); - - }, - Err(_) => (), - } - } - })); - *&mut threads_left -=1; - if threads_left == 0 { break; } - } - } - println!("\nStressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval * 1000); - for handle in handles { - let _ = handle.join(); - } - Ok(()) } ///A simple TCP port scanner / stresser. diff --git a/src/tcp.rs b/src/tcp.rs new file mode 100644 index 0000000..ac70157 --- /dev/null +++ b/src/tcp.rs @@ -0,0 +1,100 @@ +use std::io::prelude::*; +use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; +use std::time::{Duration, Instant}; +use std::thread; +use std::io::BufReader; + + +///Scan the ports on address by attempting a tcp connection. +pub fn tcp_scan(address: String, timeout: Duration, sleep: Duration, ports: Vec) -> std::io::Result<()> { + println!("Scanning {}", address); + + for i in ports { + let socket = resolve_add(&address.as_str(), &i); + match TcpStream::connect_timeout(&socket, timeout) { + Ok(_) => { + println!("TCP/{} => ACCEPT", i); + //s.write(b"Some padding")?; + } + Err(_) => { + println!("TCP/{} => REJECT", i); + } + } + + thread::sleep(sleep.clone()); + //stream.write(b"Some great padding")?; + //stream.read(&mut [0; 128])?; + } + Ok(()) +} + +///Takes either an hostname or an IP address and port, and resolve to a socket address. +///DNS recordings can lead to multiple entries : we take the first one. +fn resolve_add(host: &str, port: &u32) -> SocketAddr { + let details = format!("{}:{}", host, port); + let server: Vec<_> = details + .to_socket_addrs() + .expect("Can't resolve your address") + .collect(); + return server[0]; +} + + + +///Try to stress the remote machine by attempting to every given port at once and sending payload +pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval: Duration, ports: Vec, threads: u32) -> std::io::Result<()> { + let mut handles = vec![]; + + for port in ports { + tcp_scan(address.clone(), timeout, interval, vec![port])?; + let mut threads_left = threads; + + loop { + let add = address.clone(); + let pay = payload.clone(); + let int = interval * 1000; + let end_time = Instant::now() + int; + //pay.push_str("\r\n"); + + + handles.push(thread::spawn( move || { + let socket = resolve_add(&add.as_str(), &port); + loop { + //Check if it is time to stop + if Instant::now() >= end_time { break; } + match TcpStream::connect_timeout(&socket, timeout) { + Ok(mut s) => { + //Remote port answers + //Writing + s.write_all(pay.as_bytes()).unwrap(); + s.flush().unwrap(); + + //Reading + s.set_read_timeout(Some(Duration::from_millis(500))).unwrap(); + let mut reader = BufReader::new(s.try_clone().unwrap()); + let mut answer = String::new(); + let count = reader.read_line(&mut answer).unwrap_or(0); + if count > 0 { + println!("Read {} bytes for port {} -> {}", count, &port, answer); + } + + //Sleeping + thread::sleep(Duration::from_millis(10)); + + }, + Err(_) => (), + } + } + })); + *&mut threads_left -=1; + if threads_left == 0 { break; } + } + } + println!("\nStressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval * 1000); + for handle in handles { + let _ = handle.join(); + } + Ok(()) +} + +