├── blackwater_install.sh ├── Makefile ├── .gitignore ├── Cargo.toml ├── src ├── main.rs ├── async_utils.rs ├── output.rs ├── lib.rs ├── service.rs └── params.rs ├── LICENSE └── README.md /blackwater_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "blackwater install" 3 | echo "https://github.com/dollarkillerx/blackwater" 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | cargo install cross 3 | 4 | build: 5 | make build-linux 6 | make build-win 7 | 8 | build-linux: 9 | @echo 'Building for Linux' 10 | cross build --release --target=x86_64-unknown-linux-musl 11 | 12 | build-win: 13 | @echo 'Building for Windows' 14 | cross build --release --target=x86_64-pc-windows-gnu -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | .idea 12 | 13 | tokio_test/target -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blackwater" 3 | version = "1.0.1" 4 | authors = ["dollarkillerx "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | tokio = { version = "1.8.3", features = ["full"] } 11 | structopt = "0.3.21" 12 | 13 | [profile.release] 14 | opt-level = 3 15 | codegen-units = 1 16 | panic = 'abort' 17 | lto = true 18 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use blackwater::*; 2 | use structopt::StructOpt; 3 | 4 | #[tokio::main] 5 | async fn main() -> Result<()> { 6 | let opt: Params = Params::from_args(); 7 | println!("{}", LOGO); 8 | if opt.ip == None { 9 | println!("Please -h"); 10 | return Ok(()); 11 | } 12 | 13 | // println!("{:#?}",opt); 14 | 15 | let ports = opt.get_ports().await?; 16 | if ports.len() == 0 { 17 | println!("Parameter Error"); 18 | return Ok(()); 19 | } 20 | 21 | let mut core = Core::new(&opt).await; 22 | core.run(ports).await?; 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /src/async_utils.rs: -------------------------------------------------------------------------------- 1 | use tokio::sync::{Mutex}; 2 | use tokio::time; 3 | use std::cell::Cell; 4 | 5 | pub struct WaitGroup { 6 | // Remaining Tasks 7 | task: Mutex> 8 | } 9 | 10 | impl WaitGroup { 11 | pub async fn new() -> WaitGroup { 12 | WaitGroup { 13 | task: Mutex::new(Cell::new(0)), 14 | } 15 | } 16 | 17 | pub async fn add(&self) { 18 | let task = self.task.lock().await; 19 | task.set(task.get() + 1); 20 | } 21 | 22 | pub async fn done(&self) { 23 | let task = self.task.lock().await; 24 | task.set(task.get() - 1); 25 | } 26 | 27 | pub async fn wait(&self) { 28 | loop { 29 | let tk = self.task.lock().await; 30 | if tk.get() == 0 { 31 | break; 32 | } 33 | 34 | time::sleep(time::Duration::from_millis(100)).await; 35 | } 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Dollarkillerx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/output.rs: -------------------------------------------------------------------------------- 1 | use tokio::fs::File; 2 | use std::path::PathBuf; 3 | use tokio::io::AsyncWriteExt; 4 | use tokio::sync::mpsc::UnboundedReceiver; 5 | 6 | pub struct Output { 7 | rec: UnboundedReceiver, 8 | outfile: Option, 9 | } 10 | 11 | impl Output { 12 | pub fn new(rec: UnboundedReceiver, outfile: Option) -> Output { 13 | Output { 14 | rec, 15 | outfile, 16 | } 17 | } 18 | 19 | pub async fn run(&mut self) { 20 | let mut output: Option; 21 | match &self.outfile { 22 | None => { 23 | output = None 24 | } 25 | Some(file) => { 26 | output = Some(File::create(file).await.unwrap()); 27 | } 28 | }; 29 | 30 | 'a: 31 | loop { 32 | match self.rec.recv().await { 33 | Some(r) => { 34 | match output { 35 | None => { 36 | println!("{}", r); 37 | } 38 | Some(_) => { 39 | println!("{}", r); 40 | let r = format!("{} \n", r); 41 | output.as_mut().unwrap().write_all(r.as_bytes()).await.unwrap(); 42 | output.as_mut().unwrap().flush().await.unwrap(); 43 | 44 | } 45 | } 46 | } 47 | None => { 48 | break 'a; 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod params; 2 | mod service; 3 | mod async_utils; 4 | mod output; 5 | 6 | pub use params::Params; 7 | 8 | pub use async_utils::*; 9 | 10 | pub use output::*; 11 | 12 | pub use service::Core; 13 | 14 | pub type Result = std::result::Result>; 15 | 16 | pub const LOGO: &str = r" 17 | ▄▄▄▄ ██▓ ▄▄▄ ▄████▄ ██ ▄█▀ █ █░ ▄▄▄ ▄▄▄█████▓▓█████ ██▀███ 18 | ▓█████▄ ▓██▒ ▒████▄ ▒██▀ ▀█ ██▄█▒ ▓█░ █ ░█░▒████▄ ▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ 19 | ▒██▒ ▄██▒██░ ▒██ ▀█▄ ▒▓█ ▄ ▓███▄░ ▒█░ █ ░█ ▒██ ▀█▄ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒ 20 | ▒██░█▀ ▒██░ ░██▄▄▄▄██ ▒▓▓▄ ▄██▒▓██ █▄ ░█░ █ ░█ ░██▄▄▄▄██ ░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ 21 | ░▓█ ▀█▓░██████▒ ▓█ ▓██▒▒ ▓███▀ ░▒██▒ █▄░░██▒██▓ ▓█ ▓██▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒ 22 | ░▒▓███▀▒░ ▒░▓ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░▒ ▒▒ ▓▒░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░ 23 | ▒░▒ ░ ░ ░ ▒ ░ ▒ ▒▒ ░ ░ ▒ ░ ░▒ ▒░ ▒ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░ ░▒ ░ ▒░ 24 | ░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ 25 | ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 26 | ░ ░ 27 | 28 | Black Water v1.0.1 29 | Asynchronous Port Scanner written in rust 30 | https://github.com/dollarkillerx/blackwater 31 | "; 32 | 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | #[test] 37 | fn str_p() { 38 | // let p1 = "90-100".to_string(); 39 | let p1 = "90-100".to_string(); 40 | let idx1 = p1.find("-").unwrap(); 41 | println!("{} {} ", &p1[..idx1], &p1[idx1 + 1..]); 42 | let p_i = *&p1[..idx1].parse::().unwrap(); 43 | let p_e = *&p1[idx1 + 1..].parse::().unwrap(); 44 | for i in p_i..=p_e { 45 | println!("{}", i); 46 | } 47 | } 48 | 49 | #[test] 50 | fn str_p1() { 51 | let p1 = "80,443,50,65,56 ,565".to_string(); 52 | let b: Vec<&str> = p1.split(",").collect(); 53 | for i in &b { 54 | // *i = "sadsad"; 55 | println!("{}", i) 56 | } 57 | println!("{:?}", b); 58 | } 59 | 60 | 61 | // use async_std::task; 62 | // use async_std::net::TcpStream; 63 | // 64 | // #[test] 65 | // fn tcp_connect() { 66 | // let t = async { 67 | // let t = TcpStream::connect("192.168.88.11:443").await; 68 | // println!("{:#?}", t); 69 | // }; 70 | // 71 | // task::block_on(t); 72 | // } 73 | } 74 | -------------------------------------------------------------------------------- /src/service.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::sync::Arc; 3 | use tokio::net::{TcpStream}; 4 | use tokio::sync::{mpsc, Mutex}; 5 | // use tokio::prelude::*; 6 | use tokio::time; 7 | 8 | pub struct Core<'a> { 9 | param: &'a params::Params, 10 | } 11 | 12 | impl<'a> Core<'a> { 13 | pub async fn new(param: &'a params::Params) -> Core<'a> { 14 | Core { 15 | param 16 | } 17 | } 18 | 19 | pub async fn run(&mut self, ports: Vec) -> Result<()> { 20 | let (sen_file, rec_file) = mpsc::unbounded_channel(); 21 | // let mut output = Arc::new(Output::new(rec_file, self.param.outfile.clone())); 22 | let mut output = Output::new(rec_file, self.param.outfile.clone()); 23 | 24 | // run output 25 | tokio::spawn(async move { 26 | output.run().await; 27 | }); 28 | 29 | // Concurrency Control 30 | let (sen_limit, rec_limit) = mpsc::channel(self.param.concurrency as usize); 31 | let rec_limit = Arc::new(Mutex::new(rec_limit)); 32 | let wg = Arc::new(WaitGroup::new().await); 33 | let ip = self.param.ip.as_ref().unwrap(); 34 | let mut timeout = self.param.timeout; 35 | if timeout == 0 { 36 | timeout = 800 37 | } 38 | 39 | for port in ports { 40 | sen_limit.send(1).await.unwrap(); 41 | wg.add().await; 42 | 43 | let wg = wg.clone(); 44 | let rec_limit = rec_limit.clone(); 45 | let sen_file = sen_file.clone(); 46 | let ip = ip.clone(); 47 | tokio::spawn(async move { 48 | match Self::blasting(format!("{}:{}", ip, port), timeout).await { 49 | Ok(data) => { 50 | sen_file.send(data).unwrap(); 51 | // sen_file.send(data).await.unwrap(); 52 | } 53 | _ => {} 54 | } 55 | wg.done().await; 56 | 57 | rec_limit.lock().await.recv().await.unwrap(); 58 | }); 59 | } 60 | 61 | wg.wait().await; 62 | 63 | Ok(()) 64 | } 65 | 66 | async fn blasting(addr: String, timeout: u64) -> Result { 67 | // let conn: std::result::Result = TcpStream::connect(&addr).timeout(Duration::from_millis(timeout)).await?; 68 | let conn = time::timeout( 69 | time::Duration::from_millis(timeout), 70 | TcpStream::connect(&addr), 71 | ).await; 72 | 73 | match conn { 74 | Ok(r) => { 75 | if let Ok(_) = r { 76 | return Ok(addr) 77 | }; 78 | 79 | Err("conn error".into()) 80 | } 81 | _ => { 82 | Err("conn error".into()) 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/params.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use structopt::StructOpt; 4 | 5 | use super::*; 6 | 7 | #[derive(StructOpt, Debug)] 8 | #[structopt(name = "blackwater", about = "Asynchronous Port Scanner written in rust https://github.com/dollarkillerx/blackwater")] 9 | pub struct Params { 10 | /// Scanned IP address 11 | #[structopt(short = "i", long = "ip")] 12 | pub ip: Option, 13 | 14 | /// Number of concurrent scans 15 | #[structopt(short = "c", long = "concurrency", default_value = "65535")] 16 | pub concurrency: u32, 17 | 18 | /// Port Range or or 19 | #[structopt(short = "p", long = "port", default_value = "21,22,23,25,69,79,80-89,110,111,113,115,119,135,137,138,139,143,152,153,158,161,162,179,194,201,209,213,218,220,259,264,308,389,443,445,512,513,514,524,530,531,532,540,542,544,546,547,548,554,556,563,591,593,604,631,636,647,648,652,665,666,674,691,692,695,699,700,701,702,706,771,720,749,782,829,860,873,901,902,904,981,989,990,991,992,993,995,1025,1433,1521,2082,2083,2086,2087,2095,2096,2077,2078,2222,2601,2604,3128,3306,3311,3312,3389,5432,5560,5900,5984,6379,7001,7002,7778,8080-9090,9200,9300,9418,10000,11211,27017,27018,50000,50030,50070")] 20 | pub port: String, 21 | 22 | /// Result output file address 23 | #[structopt(short = "f", long = "outfile", parse(from_os_str))] 24 | pub outfile: Option, 25 | 26 | /// Timeout Milliseconds 27 | #[structopt(short = "t", long = "timeout", default_value = "800")] 28 | pub timeout: u64, 29 | 30 | /// Scanning with UDP 31 | #[structopt(short = "u", long = "udp")] 32 | pub udp: bool, 33 | } 34 | 35 | impl Params { 36 | pub async fn get_ports(&self) -> Result> { 37 | let idx1 = match self.port.find("-") { 38 | Some(idx) => idx, 39 | None => 0, 40 | }; 41 | 42 | let idx2 = match self.port.find(",") { 43 | Some(idx) => idx, 44 | None => 0, 45 | }; 46 | 47 | if idx1 == 0 && idx2 == 0 { 48 | return match self.port.parse::() { 49 | Ok(i) => { 50 | Ok(vec![format!("{}", i)]) 51 | } 52 | Err(_) => { 53 | Err("Parameter Error".into()) 54 | } 55 | }; 56 | } 57 | let mut lists = Vec::new(); 58 | 59 | // 处理情况: 80,84,86-89,59 60 | if idx1 != 0 && idx2 != 0 { 61 | let sli: Vec<&str> = self.port.split(",").collect(); 62 | for i in sli { 63 | if let Some(t) = i.find("-") { 64 | let start = i[..t].parse::().unwrap(); 65 | let end = i[t + 1..].parse::().unwrap(); 66 | for ic in start..=end { 67 | lists.push(format!("{}", ic)); 68 | } 69 | } else { 70 | lists.push(i.trim().to_string()); 71 | } 72 | } 73 | 74 | return Ok(lists); 75 | } 76 | 77 | // param1 78 | if idx1 != 0 { 79 | let start = *&self.port[..idx1].parse::().unwrap(); 80 | let end = *&self.port[idx1 + 1..].parse::().unwrap(); 81 | for i in start..=end { 82 | lists.push(format!("{}", i)); 83 | } 84 | return Ok(lists); 85 | } 86 | 87 | // param2 88 | let sli: Vec<&str> = self.port.split(",").collect(); 89 | for i in sli { 90 | lists.push(i.trim().to_string()); 91 | } 92 | 93 | Ok(lists) 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blackwater 2 | Blaskwate rust port scanner tool 3 | 4 | Scan all ports in one second, basically no missing 5 | ### Install 6 | `sudo curl -L "https://cdn.jsdelivr.net/gh/dollarkillerx/st/blackwater/v1.0.1/blackwater" -o /usr/local/bin/blackwater` 7 | 8 | `sudo chmod +x /usr/local/bin/blackwater` 9 | 10 | ### Usage 11 | `blackwater -h` 12 | 13 | ``` 14 | blackwater 0.1.0 15 | Asynchronous Port Scanner written in rust https://github.com/dollarkillerx/blackwater 16 | 17 | USAGE: 18 | blackwater [FLAGS] [OPTIONS] 19 | 20 | FLAGS: 21 | -h, --help Prints help information 22 | -u, --udp Scanning with UDP 23 | -V, --version Prints version information 24 | 25 | OPTIONS: 26 | -c, --concurrency Number of concurrent scans [default: 65535] 27 | -i, --ip Scanned IP address 28 | -f, --outfile Result output file address 29 | -p, --port Port Range or [default: 30 | 21,22,23,25,69,79,80,88,110,113,119,220,443,1433,1521,2082,2083,2086,2087,2095,2096,2077,2078,3306,3389,5432,6379,8080,9000,9001,9200,9300,11211,27017] 31 | -t, --timeout Timeout Milliseconds [default: 800] 32 | ``` 33 | 34 | ### speed 35 | Amazing speed Not a single port is missed 36 | ``` 37 | ubuntu@ubuntu:~/$ time blackwater -i 110.242.68.3 -p1-65535 38 | 39 | ▄▄▄▄ ██▓ ▄▄▄ ▄████▄ ██ ▄█▀ █ █░ ▄▄▄ ▄▄▄█████▓▓█████ ██▀███ 40 | ▓█████▄ ▓██▒ ▒████▄ ▒██▀ ▀█ ██▄█▒ ▓█░ █ ░█░▒████▄ ▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ 41 | ▒██▒ ▄██▒██░ ▒██ ▀█▄ ▒▓█ ▄ ▓███▄░ ▒█░ █ ░█ ▒██ ▀█▄ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒ 42 | ▒██░█▀ ▒██░ ░██▄▄▄▄██ ▒▓▓▄ ▄██▒▓██ █▄ ░█░ █ ░█ ░██▄▄▄▄██ ░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ 43 | ░▓█ ▀█▓░██████▒ ▓█ ▓██▒▒ ▓███▀ ░▒██▒ █▄░░██▒██▓ ▓█ ▓██▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒ 44 | ░▒▓███▀▒░ ▒░▓ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░▒ ▒▒ ▓▒░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░ 45 | ▒░▒ ░ ░ ░ ▒ ░ ▒ ▒▒ ░ ░ ▒ ░ ░▒ ▒░ ▒ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░ ░▒ ░ ▒░ 46 | ░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ 47 | ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 48 | ░ ░ 49 | 50 | Black Water 51 | Asynchronous Port Scanner written in rust 52 | https://github.com/dollarkillerx/blackwater 53 | 54 | 110.242.68.3:80 55 | 110.242.68.3:443 56 | 110.242.68.3:2000 57 | 110.242.68.3:5060 58 | 59 | real 0m1.637s 60 | user 0m1.196s 61 | sys 0m1.672s 62 | 63 | ubuntu@ubuntu:~/$ time ./blackwater -i www.baidu.com -p1-65535 64 | 65 | ▄▄▄▄ ██▓ ▄▄▄ ▄████▄ ██ ▄█▀ █ █░ ▄▄▄ ▄▄▄█████▓▓█████ ██▀███ 66 | ▓█████▄ ▓██▒ ▒████▄ ▒██▀ ▀█ ██▄█▒ ▓█░ █ ░█░▒████▄ ▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ 67 | ▒██▒ ▄██▒██░ ▒██ ▀█▄ ▒▓█ ▄ ▓███▄░ ▒█░ █ ░█ ▒██ ▀█▄ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒ 68 | ▒██░█▀ ▒██░ ░██▄▄▄▄██ ▒▓▓▄ ▄██▒▓██ █▄ ░█░ █ ░█ ░██▄▄▄▄██ ░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ 69 | ░▓█ ▀█▓░██████▒ ▓█ ▓██▒▒ ▓███▀ ░▒██▒ █▄░░██▒██▓ ▓█ ▓██▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒ 70 | ░▒▓███▀▒░ ▒░▓ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░▒ ▒▒ ▓▒░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░ 71 | ▒░▒ ░ ░ ░ ▒ ░ ▒ ▒▒ ░ ░ ▒ ░ ░▒ ▒░ ▒ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░ ░▒ ░ ▒░ 72 | ░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ 73 | ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 74 | ░ ░ 75 | 76 | Black Water 77 | Asynchronous Port Scanner written in rust 78 | https://github.com/dollarkillerx/blackwater 79 | 80 | www.baidu.com:80 81 | www.baidu.com:2000 82 | www.baidu.com:443 83 | www.baidu.com:5060 84 | 85 | real 0m1.151s 86 | user 0m0.654s 87 | sys 0m0.697s 88 | 89 | ubuntu@ubuntu:~/$ time ./blackwater -i www.bing.com -p1-65535 90 | 91 | ▄▄▄▄ ██▓ ▄▄▄ ▄████▄ ██ ▄█▀ █ █░ ▄▄▄ ▄▄▄█████▓▓█████ ██▀███ 92 | ▓█████▄ ▓██▒ ▒████▄ ▒██▀ ▀█ ██▄█▒ ▓█░ █ ░█░▒████▄ ▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ 93 | ▒██▒ ▄██▒██░ ▒██ ▀█▄ ▒▓█ ▄ ▓███▄░ ▒█░ █ ░█ ▒██ ▀█▄ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒ 94 | ▒██░█▀ ▒██░ ░██▄▄▄▄██ ▒▓▓▄ ▄██▒▓██ █▄ ░█░ █ ░█ ░██▄▄▄▄██ ░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ 95 | ░▓█ ▀█▓░██████▒ ▓█ ▓██▒▒ ▓███▀ ░▒██▒ █▄░░██▒██▓ ▓█ ▓██▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒ 96 | ░▒▓███▀▒░ ▒░▓ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░▒ ▒▒ ▓▒░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░ 97 | ▒░▒ ░ ░ ░ ▒ ░ ▒ ▒▒ ░ ░ ▒ ░ ░▒ ▒░ ▒ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░ ░▒ ░ ▒░ 98 | ░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ 99 | ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 100 | ░ ░ 101 | 102 | Black Water 103 | Asynchronous Port Scanner written in rust 104 | https://github.com/dollarkillerx/blackwater 105 | 106 | www.bing.com:80 107 | www.bing.com:443 108 | www.bing.com:2000 109 | 110 | real 0m1.079s 111 | user 0m0.589s 112 | sys 0m0.442s 113 | 114 | ubuntu@ubuntu:~/$ time ./blackwater -i github.com -p1-65535 115 | 116 | ▄▄▄▄ ██▓ ▄▄▄ ▄████▄ ██ ▄█▀ █ █░ ▄▄▄ ▄▄▄█████▓▓█████ ██▀███ 117 | ▓█████▄ ▓██▒ ▒████▄ ▒██▀ ▀█ ██▄█▒ ▓█░ █ ░█░▒████▄ ▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ 118 | ▒██▒ ▄██▒██░ ▒██ ▀█▄ ▒▓█ ▄ ▓███▄░ ▒█░ █ ░█ ▒██ ▀█▄ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒ 119 | ▒██░█▀ ▒██░ ░██▄▄▄▄██ ▒▓▓▄ ▄██▒▓██ █▄ ░█░ █ ░█ ░██▄▄▄▄██ ░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ 120 | ░▓█ ▀█▓░██████▒ ▓█ ▓██▒▒ ▓███▀ ░▒██▒ █▄░░██▒██▓ ▓█ ▓██▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒ 121 | ░▒▓███▀▒░ ▒░▓ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░▒ ▒▒ ▓▒░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░ 122 | ▒░▒ ░ ░ ░ ▒ ░ ▒ ▒▒ ░ ░ ▒ ░ ░▒ ▒░ ▒ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░ ░▒ ░ ▒░ 123 | ░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ ░ ░ ░ ▒ ░ ░ ░░ ░ 124 | ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 125 | ░ ░ 126 | 127 | Black Water 128 | Asynchronous Port Scanner written in rust 129 | https://github.com/dollarkillerx/blackwater 130 | 131 | github.com:2000 132 | github.com:22 133 | github.com:80 134 | github.com:443 135 | github.com:5060 136 | 137 | real 0m1.137s 138 | user 0m0.685s 139 | sys 0m0.756s 140 | ``` 141 | 142 | ### build 143 | `make build` 144 | 145 | ### Development Plan 146 | - [ ] c-segment scanning 147 | - [ ] File import batch scanning 148 | - [ ] Distributed 149 | - [ ] Fingerprint recognition 150 | 151 | ## Parameter adjustment, solve the problem of packet loss 152 | There are many reasons for packet loss, roughly divided into two. 153 | 1. network problems (solution: 1. switch to a better network 2. modify the `-t` timeout time) 154 | 2. cpu processing super link performance is insufficient (solution: reduce the number of concurrent) 155 | - Extranet scan, not missing a port 156 | - Modify thread parameters `-c` Calculation formula: Number of current CPU logical cores * 100 157 | - Example: Current CPU logical core is 4 cores Parameter is `blackwater -i github.com -c 400 -p 1-65535 ` 158 | - Intranet scan, not missing a port 159 | - Modify thread parameters `-c` Calculation formula: Number of current CPU logical cores * 250 160 | - Example: Current CPU logical core is 4 cores Parameter is `blackwater -i 192.168.88.11 -c 1000 -p 1-65535 ` 161 | --------------------------------------------------------------------------------