1use std::io::{self, Write};
2use std::net::{TcpStream, UdpSocket};
3use std::sync::Arc;
4use std::thread;
5use std::time::Duration;
6
7#[derive(Clone, Debug)]
8pub enum Protocol {
9 TCP,
10 UDP,
11}
12
13pub struct Pentest {
14 ip: String,
15 port: u16,
16 counter: usize,
17 protocol: Protocol,
18 payload: Vec<u8>,
19 concurrency: usize,
20}
21
22impl Pentest {
23 pub fn new(
24 ip: &str,
25 port: u16,
26 counter: usize,
27 protocol: Protocol,
28 payload: Vec<u8>,
29 concurrency: usize,
30 ) -> Pentest {
31 Pentest {
32 ip: ip.to_string(),
33 port,
34 counter,
35 protocol,
36 payload,
37 concurrency,
38 }
39 }
40
41 pub fn run(&self) -> io::Result<()> {
42 let tasks = self.counter / self.concurrency;
43 let tasks_remainder = self.counter % self.concurrency;
44 let ip = Arc::new(self.ip.clone());
45 let payload = Arc::new(self.payload.clone());
46
47 let mut threads = vec![];
48
49 println!("Starting test with {} threads", self.concurrency);
50
51 for _ in 0..self.concurrency {
52 let ip = Arc::clone(&ip);
53 let payload = Arc::clone(&payload);
54 let pentest = Pentest {
55 ip: ip.to_string(),
56 port: self.port,
57 counter: tasks,
58 protocol: self.protocol.clone(),
59 payload: payload.to_vec(),
60 concurrency: 1,
61 };
62
63 threads.push(thread::spawn(move || {
64 pentest.run_inner().unwrap();
65 }));
66 }
67
68 if tasks_remainder > 0 {
69 let pentest = Pentest {
70 ip: self.ip.clone(),
71 port: self.port,
72 counter: tasks_remainder,
73 protocol: self.protocol.clone(),
74 payload: self.payload.clone(),
75 concurrency: 1,
76 };
77
78 pentest.run_inner()?;
79 }
80
81 for (i, thread) in threads.into_iter().enumerate() {
82 println!("Joining thread {}", i + 1);
83 match thread.join() {
84 Ok(_) => println!("Thread {} joined", i + 1),
85 Err(err) => eprintln!("Error in thread {}: {:?}", i + 1, err),
86 }
87 }
88
89 Ok(())
90 }
91
92 fn run_inner(&self) -> io::Result<()> {
93 match self.protocol {
94 Protocol::TCP => self.run_tcp(),
95 Protocol::UDP => self.run_udp(),
96 }
97 }
98
99 fn run_tcp(&self) -> io::Result<()> {
100 let addr = format!("{}:{}", self.ip, self.port);
101
102 for i in 0..self.counter {
103 println!("Sending TCP packet {} to {}:{}", i + 1, self.ip, self.port);
104 match TcpStream::connect(&addr) {
105 Ok(mut stream) => {
106 stream.set_write_timeout(Some(Duration::from_secs(1)))?;
107 stream.write_all(&self.payload)?;
108 }
109 Err(err) => eprintln!("Failed to send TCP packet {}: {}", i + 1, err),
110 }
111 }
112
113 println!("Finished sending TCP packets");
114
115 Ok(())
116 }
117
118 fn run_udp(&self) -> io::Result<()> {
119 let socket = UdpSocket::bind("0.0.0.0:0")?;
120 socket.set_write_timeout(Some(Duration::from_secs(1)))?;
121
122 let addr = format!("{}:{}", self.ip, self.port);
123
124 for i in 0..self.counter {
125 println!("Sending UDP packet {} to {}:{}", i + 1, self.ip, self.port);
126 if let Err(err) = socket.send_to(&self.payload, &addr) {
127 eprintln!("Failed to send UDP packet {}: {}", i + 1, err);
128 }
129 }
130
131 println!("Finished sending UDP packets");
132
133 Ok(())
134 }
135}