Added a cthreads argument

This commit is contained in:
Justine Pelletreau 2023-07-13 19:38:04 +02:00
parent 2cad1b4ef3
commit 06821e3087
2 changed files with 47 additions and 35 deletions

View File

@ -1,7 +1,8 @@
# Portnut # Portnut
TODO TODO
* Allow multiple threads hitting on the same port * Read the answer and count the number of answers received.
* Make a distributed version that allows stressing from multiple computers at the same time
Portnut is a tcp port scanner / stresser. Portnut is a tcp port scanner / stresser.
@ -15,13 +16,11 @@ TCP/8080 => REJECT
TCP/22 => REJECT TCP/22 => REJECT
#First scan the ports, and stress the available ones. #First scan the ports, and stress the available ones.
justine@portnut > echo "My payload" | target/release/portnut -a 127.0.0.1 -p 22,8080 -w 3 -s 1738 justine@portnut > echo "GET / HTTP/1.1" | target/release/portnut -a 127.0.0.1 -p 8080 -w 30 -s -c 100
Scanning 127.0.0.1
TCP/22 => REJECT
Scanning 127.0.0.1 Scanning 127.0.0.1
TCP/8080 => ACCEPT TCP/8080 => ACCEPT
Stressing... Stressing 127.0.0.1 using 100 concurrent threads per port for 30s
``` ```
@ -33,11 +32,13 @@ A simple TCP port scanner / stresser. If stressing, you can pass a payload via a
Usage: portnut [OPTIONS] --address <ADDRESS> Usage: portnut [OPTIONS] --address <ADDRESS>
Options: Options:
-a, --address <ADDRESS> IP address to scan -a, --address <ADDRESS> IP address to scan
-t, --timeout <TIMEOUT> Timeout for each connection in seconds [default: 1] -t, --timeout <TIMEOUT> Timeout for each connection in seconds [default: 1]
-w, --wait <WAIT> Number of milliseconds to wait in between scans when scanning OR duration of stress when stress testing (in seconds) [default: 30] -w, --wait <WAIT> Number of milliseconds to wait in between scans when scanning OR duration of stress when stress testing (in seconds) [default: 30]
-p, --ports <PORTS>... Ports to stress / scan, separated by commas (22,80) -p, --ports <PORTS>... Ports to stress / scan, separated by commas (22,80)
-s, --stress Set this flag to stress the ports instead of scanning them -s, --stress Set this flag to stress the ports instead of scanning them
-h, --help Print help -c, --cthreads <CTHREADS> How many threads per port when stressing (Concurrent Threads) [default: 5]
-V, --version Print version -h, --help Print help
-V, --version Print version
``` ```

View File

@ -13,6 +13,7 @@ fn main() -> std::io::Result<()> {
let timeout = Duration::from_secs(args.timeout); let timeout = Duration::from_secs(args.timeout);
let sleep = Duration::from_millis(args.wait); let sleep = Duration::from_millis(args.wait);
let ports = args.ports; let ports = args.ports;
let threads = args.cthreads;
//Reading the payload from stdin (if applicable) //Reading the payload from stdin (if applicable)
let mut payload = String::new(); let mut payload = String::new();
@ -25,7 +26,7 @@ fn main() -> std::io::Result<()> {
} }
if args.stress { if args.stress {
tcp_stress(payload, address, timeout, sleep, ports)?; tcp_stress(payload, address, timeout, sleep, ports, threads)?;
} else { } else {
tcp_scan(address, timeout, sleep, ports)?; tcp_scan(address, timeout, sleep, ports)?;
} }
@ -59,36 +60,42 @@ fn tcp_scan(address: String, timeout: Duration, sleep: Duration, ports: Vec<u32>
///Try to stress the remote machine by attempting to every given port at once and sending random ///Try to stress the remote machine by attempting to every given port at once and sending random
///data ///data
fn tcp_stress(payload: String, address: String, timeout: Duration, interval: Duration, ports: Vec<u32>) -> std::io::Result<()> { fn tcp_stress(payload: String, address: String, timeout: Duration, interval: Duration, ports: Vec<u32>, threads: u32) -> std::io::Result<()> {
let mut handles = vec![]; let mut handles = vec![];
for port in ports { for port in ports {
tcp_scan(address.clone(), timeout, interval, vec![port])?; tcp_scan(address.clone(), timeout, interval, vec![port])?;
let add = address.clone(); let mut threads_left = threads;
let pay = payload.clone();
let int = interval * 1000; loop {
let end_time = Instant::now() + int; let add = address.clone();
let pay = payload.clone();
let int = interval * 1000;
let end_time = Instant::now() + int;
handles.push(thread::spawn( move || { handles.push(thread::spawn( move || {
let socket = format!("{}:{}", &add, &port); let socket = format!("{}:{}", &add, &port);
let socket = socket.parse::<SocketAddr>().unwrap(); let socket = socket.parse::<SocketAddr>().unwrap();
loop { loop {
//Check if it is time to stop //Check if it is time to stop
if Instant::now() >= end_time { break; } if Instant::now() >= end_time { break; }
match TcpStream::connect_timeout(&socket, timeout) { match TcpStream::connect_timeout(&socket, timeout) {
Ok(mut s) => { Ok(mut s) => {
s.write(pay.as_bytes()).unwrap(); s.write(pay.as_bytes()).unwrap();
s.flush().unwrap(); s.flush().unwrap();
//s.read(&mut [0; 128]).unwrap(); //s.read(&mut [0; 128]).unwrap();
thread::sleep(Duration::from_millis(10)); thread::sleep(Duration::from_millis(10));
}, },
Err(_) => (), Err(_) => (),
}
} }
} }));
})); *&mut threads_left -=1;
if threads_left == 0 { break; }
}
} }
println!("\nStressing...\n"); println!("\nStressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval * 1000);
for handle in handles { for handle in handles {
let _ = handle.join(); let _ = handle.join();
} }
@ -116,4 +123,8 @@ struct Args {
///Set this flag to stress the ports instead of scanning them ///Set this flag to stress the ports instead of scanning them
#[arg(long, short, action, default_value_t = false)] #[arg(long, short, action, default_value_t = false)]
stress: bool, stress: bool,
///How many threads per port when stressing
///(Concurrent Threads)
#[arg(short, long, default_value_t = 5)]
cthreads: u32,
} }