Skip to content

Commit aa21d50

Browse files
authored
Merge pull request #8 from s-b-repo/ipv6-patch
Ipv6 patch
2 parents 8250c92 + 626aa3f commit aa21d50

25 files changed

+1731
-742
lines changed

Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ colored = "3.0.0"
2525
rustyline = "15.0.0"
2626
#ftp brute force module
2727
async_ftp = "6.0.0"
28-
2928
tokio-socks = "0.5.2"
29+
rustls = "0.23.26"
30+
webpki-roots = "0.26.8"
31+
suppaftp = { version = "6.2.0", features = ["async", "async-native-tls","native-tls"] }
32+
native-tls = "0.2.14"
33+
sysinfo = { version = "0.34.2", features = ["multithread"] }
3034

3135
#telnet
3236
threadpool = "1.8.1"
@@ -55,7 +59,7 @@ md5 = "0.7.0"
5559

5660
#ssh rce race condition
5761
libc = "0.2.172"
58-
62+
futures = "0.3.31"
5963
#spotube exploit
6064
serde_json = "1.0.140"
6165
futures-util = "0.3.31"

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ Convert exploits and add modules
1414

1515
# completed
1616
```
17+
added ipv6 support for rstp rdp and ssh cant find any ipv6 address i cant test on so untested
18+
added ftps support
19+
added ipv6 support to ftp anon and brute
20+
added rdp ipv6 support unable to find rpd ipv6 device to test on with shodan
1721
added exploit openssh server race condition 9.8.p1 |Server Destruction fork |
1822
bomb Persistence create SSH user | Remote Root Shell
1923
@@ -45,9 +49,19 @@ dynamic modules listing and colored listing
4549
```
4650

4751
---
48-
52+
```
4953
## 🚀 Building & Running
54+
## 📦🛠️ requirements
55+
```
56+
```
57+
sudo apt update
58+
sudo apt install freerdp2-x11
5059
60+
for rdp bruteforce modudle
61+
62+
63+
```
64+
```
5165
### 📦 Clone the Repository
5266
5367
```

extra.txt

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
Required Signature
2+
3+
The module must contain this exact public async function:
4+
5+
pub async fn run(target: &str) -> anyhow::Result<()>
6+
7+
Or any variant like:
8+
9+
pub async fn run(_target: &str) -> anyhow::Result<()>
10+
11+
Or even:
12+
13+
pub async fn run(host: &str) -> anyhow::Result<()>
14+
15+
16+
Refactor this module to work with the auto-dispatch system. Do not remove any functionality or features. Make sure it defines a pub async fn run(target: &str) -> Result<()> entry point that internally calls the correct logic. Rename any conflicting functions if needed, but preserve all capabilities and structure.
17+
18+
119
Refactor this code to a Rust module so that it fully integrates into my RouterSploit-inspired Rust auto-dispatch framework.
220

321
✅ Preserve all functionality and existing logic — do not remove or simplify any capabilities.
@@ -24,4 +42,32 @@ Refactor this code to a Rust module so that it fully integrates into my RouterS
2442

2543
Here is the original module that needs to be refactored:
2644

27-
.
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+
63+
64+
65+
66+
67+
68+
Would you like a Dynamic/Auto-Scaler version too? 🚀
69+
(Example: start at 500 concurrency, grow to 5000 if CPU/RAM is good.)
70+
71+
Want me to show it too? 🔥
72+
You said:
73+
yes Dynamic/Auto-Scaler show function to add

src/commands/mod.rs

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ pub mod creds;
55
use anyhow::Result;
66
use crate::cli::Cli;
77
use walkdir::WalkDir;
8+
use crate::utils::normalize_target;
89

9-
/// Handle CLI arguments like:
10-
/// --command scanner --module scanners/port_scanner --target 192.168.1.1
10+
/// CLI dispatcher: e.g. --command scanner --target "::1" --module scanners/port_scanner
1111
pub async fn handle_command(command: &str, cli_args: &Cli) -> Result<()> {
12-
let target = cli_args.target.clone().unwrap_or_default();
12+
let raw = cli_args.target.clone().unwrap_or_default();
13+
let target = normalize_target(&raw)?; // IPv6 wrap only, no port
1314
let module = cli_args.module.clone().unwrap_or_default();
1415

1516
match command {
@@ -33,15 +34,11 @@ pub async fn handle_command(command: &str, cli_args: &Cli) -> Result<()> {
3334
Ok(())
3435
}
3536

36-
/// Handle `run` in the interactive shell after `use <module>`
37-
/// Supports both full paths like "scanners/port_scanner" and short names like "port_scanner"
38-
pub async fn run_module(module_path: &str, target: &str) -> Result<()> {
37+
/// Interactive shell: handles `run` with raw target string
38+
pub async fn run_module(module_path: &str, raw_target: &str) -> Result<()> {
3939
let available = discover_modules();
4040

41-
// Exact match (e.g. "scanners/port_scanner")
4241
let full_match = available.iter().find(|m| m == &module_path);
43-
44-
// Short match (e.g. "port_scanner" from "scanners/port_scanner")
4542
let short_match = available.iter().find(|m| {
4643
m.rsplit_once('/')
4744
.map(|(_, short)| short == module_path)
@@ -54,47 +51,46 @@ pub async fn run_module(module_path: &str, target: &str) -> Result<()> {
5451
m
5552
} else {
5653
eprintln!("❌ Unknown module '{}'. Available modules:", module_path);
57-
for module in available {
58-
println!(" {}", module);
54+
for m in available {
55+
println!(" {}", m);
5956
}
6057
return Ok(());
6158
};
6259

60+
let target = normalize_target(raw_target)?;
61+
6362
let mut parts = resolved.splitn(2, '/');
6463
let category = parts.next().unwrap_or("");
6564
let module_name = parts.next().unwrap_or("");
6665

6766
match category {
68-
"exploits" => exploit::run_exploit(module_name, target).await?,
69-
"scanners" => scanner::run_scan(module_name, target).await?,
70-
"creds" => creds::run_cred_check(module_name, target).await?,
67+
"exploits" => exploit::run_exploit(module_name, &target).await?,
68+
"scanners" => scanner::run_scan(module_name, &target).await?,
69+
"creds" => creds::run_cred_check(module_name, &target).await?,
7170
_ => eprintln!("❌ Category '{}' is not supported.", category),
7271
}
7372

7473
Ok(())
7574
}
7675

77-
/// Walks src/modules/{exploits,scanners,creds} recursively and returns all `.rs` modules (excluding mod.rs)
76+
/// Finds all .rs module paths inside `src/modules/**`, excluding mod.rs
7877
pub fn discover_modules() -> Vec<String> {
7978
let mut modules = Vec::new();
8079
let categories = ["exploits", "scanners", "creds"];
8180

82-
for category in categories {
83-
let base_path = format!("src/modules/{}", category);
84-
let walker = WalkDir::new(&base_path).max_depth(6);
85-
86-
for entry in walker.into_iter().filter_map(|e| e.ok()) {
87-
let path = entry.path();
88-
89-
if path.is_file()
90-
&& path.extension().map_or(false, |e| e == "rs")
91-
&& path.file_name().map_or(true, |n| n != "mod.rs")
81+
for category in &categories {
82+
let base = format!("src/modules/{}", category);
83+
for entry in WalkDir::new(&base).max_depth(6).into_iter().filter_map(|e| e.ok()) {
84+
let p = entry.path();
85+
if p.is_file()
86+
&& p.extension().map_or(false, |e| e == "rs")
87+
&& p.file_name().map_or(true, |n| n != "mod.rs")
9288
{
93-
if let Ok(relative) = path.strip_prefix("src/modules") {
94-
let module_path = relative
95-
.with_extension("") // remove .rs
89+
if let Ok(rel) = p.strip_prefix("src/modules") {
90+
let module_path = rel
91+
.with_extension("")
9692
.to_string_lossy()
97-
.replace("\\", "/"); // Windows compatibility
93+
.replace("\\", "/");
9894
modules.push(module_path);
9995
}
10096
}

src/modules/creds/camera/acti/acti_camera_default.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use telnet::{Telnet, Event};
66
use std::{net::TcpStream, time::Duration};
77
use tokio::{join, task};
88

9+
10+
911
#[allow(dead_code)]
1012
/// Supported Acti services
1113
pub enum ServiceType {
@@ -25,6 +27,16 @@ pub struct Config {
2527
pub verbosity: bool,
2628
}
2729

30+
/// Helper to normalize IPv4, IPv6 (with any amount of brackets)
31+
fn normalize_target(target: &str, port: u16) -> String {
32+
let cleaned = target.trim_matches(|c| c == '[' || c == ']');
33+
if cleaned.contains(':') && !cleaned.contains('.') {
34+
format!("[{}]:{}", cleaned, port) // IPv6
35+
} else {
36+
format!("{}:{}", cleaned, port) // IPv4 or hostname
37+
}
38+
}
39+
2840
/// FTP check (async)
2941
pub async fn check_ftp(config: &Config) -> Result<()> {
3042
println!("[*] Checking FTP credentials on {}:{}", config.target, config.port);
@@ -34,7 +46,7 @@ pub async fn check_ftp(config: &Config) -> Result<()> {
3446
println!("[*] Trying FTP: {}:{}", username, password);
3547
}
3648

37-
let address = format!("{}:{}", config.target, config.port);
49+
let address = normalize_target(&config.target, config.port);
3850
match FtpStream::connect(address).await {
3951
Ok(mut ftp) => {
4052
if ftp.login(username, password).await.is_ok() {
@@ -53,7 +65,7 @@ pub async fn check_ftp(config: &Config) -> Result<()> {
5365
Ok(())
5466
}
5567

56-
/// SSH check (blocking, so we use spawn_blocking in our run function)
68+
/// SSH check (blocking, so we use spawn_blocking)
5769
pub fn check_ssh_blocking(config: &Config) -> Result<()> {
5870
println!("[*] Checking SSH credentials on {}:{}", config.target, config.port);
5971

@@ -62,7 +74,7 @@ pub fn check_ssh_blocking(config: &Config) -> Result<()> {
6274
println!("[*] Trying SSH: {}:{}", username, password);
6375
}
6476

65-
let address = format!("{}:{}", config.target, config.port);
77+
let address = normalize_target(&config.target, config.port);
6678
if let Ok(stream) = TcpStream::connect(address) {
6779
let mut session = Session::new().context("Failed to create SSH session")?;
6880
session.set_tcp_stream(stream);
@@ -81,7 +93,7 @@ pub fn check_ssh_blocking(config: &Config) -> Result<()> {
8193
Ok(())
8294
}
8395

84-
/// Telnet check (blocking, so we use spawn_blocking in our run function)
96+
/// Telnet check (blocking)
8597
pub fn check_telnet_blocking(config: &Config) -> Result<()> {
8698
println!("[*] Checking Telnet credentials on {}:{}", config.target, config.port);
8799

@@ -90,7 +102,15 @@ pub fn check_telnet_blocking(config: &Config) -> Result<()> {
90102
println!("[*] Trying Telnet: {}:{}", username, password);
91103
}
92104

93-
if let Ok(mut telnet) = Telnet::connect((config.target.as_str(), config.port), 500) {
105+
let address = normalize_target(&config.target, config.port);
106+
let parts: Vec<&str> = address.rsplitn(2, ':').collect();
107+
if parts.len() != 2 {
108+
continue;
109+
}
110+
let host = parts[1];
111+
let port: u16 = parts[0].parse().unwrap_or(23);
112+
113+
if let Ok(mut telnet) = Telnet::connect((host, port), 500) {
94114
let _ = telnet.write(format!("{}\r\n", username).as_bytes());
95115
let _ = telnet.write(format!("{}\r\n", password).as_bytes());
96116

@@ -122,7 +142,7 @@ pub async fn check_http_form(config: &Config) -> Result<()> {
122142
.timeout(Duration::from_secs(5))
123143
.build()?;
124144

125-
let url = format!("http://{}:{}/video.htm", config.target, config.port);
145+
let url = format!("http://{}:{}/video.htm", config.target.trim_matches(|c| c == '[' || c == ']'), config.port);
126146

127147
for (username, password) in &config.credentials {
128148
if config.verbosity {
@@ -179,21 +199,17 @@ pub async fn run(target: &str) -> Result<()> {
179199
let telnet_conf = Config { port: 23, ..base_config.clone() };
180200
let http_conf = Config { port: 80, ..base_config.clone() };
181201

182-
// Start all checks in parallel
183202
let (ftp_res, ssh_res, telnet_res, http_res) = join!(
184203
check_ftp(&ftp_conf),
185204
async {
186-
// run blocking ssh check in separate thread
187205
task::spawn_blocking(move || check_ssh_blocking(&ssh_conf)).await?
188206
},
189207
async {
190-
// run blocking telnet check in separate thread
191208
task::spawn_blocking(move || check_telnet_blocking(&telnet_conf)).await?
192209
},
193210
check_http_form(&http_conf),
194211
);
195212

196-
// Evaluate results
197213
ftp_res?;
198214
ssh_res?;
199215
telnet_res?;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use anyhow::{Result, anyhow};
2+
use std::process::Command;
3+
4+
/// Module entry point for raising ulimit
5+
pub async fn run(_target: &str) -> Result<()> {
6+
raise_ulimit().await
7+
}
8+
9+
/// Raise ulimit to 65535
10+
async fn raise_ulimit() -> Result<()> {
11+
println!("[*] Attempting to raise open file limit (ulimit -n 65535)");
12+
13+
// Try to set limit using bash
14+
let output = Command::new("bash")
15+
.arg("-c")
16+
.arg("ulimit -n 65535")
17+
.output()
18+
.map_err(|e| anyhow!("Failed to run bash: {}", e))?;
19+
20+
if !output.status.success() {
21+
println!("[-] Warning: Could not change ulimit. (maybe run as root?)");
22+
} else {
23+
println!("[+] Successfully ran ulimit -n 65535.");
24+
}
25+
26+
// Check current limit
27+
let check_output = Command::new("bash")
28+
.arg("-c")
29+
.arg("ulimit -n")
30+
.output()
31+
.map_err(|e| anyhow!("Failed to check ulimit: {}", e))?;
32+
33+
if check_output.status.success() {
34+
let limit = String::from_utf8_lossy(&check_output.stdout);
35+
println!("[+] Current open file limit: {}", limit.trim());
36+
} else {
37+
println!("[-] Warning: Could not verify new ulimit.");
38+
}
39+
40+
Ok(())
41+
}

0 commit comments

Comments
 (0)