commit fffa933fe3e36aec8f6b80b6865ca1155930abca
parent 30846c47600dfea75436c17bfce037f9e4e7fe1a
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Tue, 28 Mar 2023 13:35:50 -0700
auto solve captcha difficulty 1
Diffstat:
2 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/src/lechatphp/mod.rs b/src/lechatphp/mod.rs
@@ -0,0 +1,105 @@
+use std::collections::HashMap;
+use base64::{engine::general_purpose, Engine as _};
+use image::{ColorType, DynamicImage};
+use lazy_static::lazy_static;
+
+const B64_PREFIX: &'static str = "R0lGODlhCAAOAIAAAAAAAAAAACH5BAgAAAAALAAAAAAIAA4AgAQCBPz+/AI";
+const _ALPHABET: &'static str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+const _ALPHABET1: &'static str = "abdcefgh1ijkImnpoqrstyQuvwxzABCDEGJKMNHLORPFSTlUVWXYZ023456789";
+
+lazy_static! {
+ static ref B64_MAP: HashMap<&'static str, char> = HashMap::from([
+ ("VhI8Qkbv3FIvGMeiQ1fPSzSXiSAIFADs=", '0'),
+ ("UhI8QkcvnHlpJSXgNbdnO2FViVQAAOw==", '1'),
+ ("UhI+hcWruGkMgSmrfvGnrtVDiKBYAOw==", '2'),
+ ("UhH+hatyBEkTuzVjpldWtHIUiUgAAOw==", '3'),
+ ("VhI8XkcvqIFiGTmbvdRFl2TzJSCYFADs=", '4'),
+ ("WhG+hG6CYGnwrygedRIw3jGlhRpZGAQA7", '5'),
+ ("XhI+hcWruGoiJrRcha5fPTS0bQpamUQAAOw==", '6'),
+ ("ThG+hq5jhQEPz1OeuhJT3CIZiAQA7", '7'),
+ ("XhI+hcWruGosRLPYwxLnaqXEXQpYmUgAAOw==", '8'),
+ ("VhI+hcWru2kosTjAjxduydyHiSBoFADs=", '9'),
+ ("VhI8Qkbv3FIvGMeiQ3RlT+X3JSBoFADs=", 'A'),
+ ("VhG+hm3EK4GMtLimtntlmeHXISJYFADs=", 'B'),
+ ("VhI+hatyLAIwuhSgv1edWt1TYSAIFADs=", 'C'),
+ ("WhG+hm3EK4GNTNhvpdZXnvHjISJZAAQA7", 'D'),
+ ("UhG+hG6CYGnyTSYrw0RE6K3niaBQAOw==", 'E'),
+ ("ThG+hy5jhgIpsSugs0oe/CIZiAQA7", 'F'),
+ ("VhI+hatyLXgQuhbMqhfhWl13TSB4FADs=", 'G'),
+ ("UhG8RqMr93Gm0xjVhlkl3BIaiUQAAOw==", 'H'),
+ ("UhH+hi4rmXmzhgZmq1JQuboUiUAAAOw==", 'I'),
+ ("UhI8QG6mdlpMRInqhpRI/64TiUQAAOw==", 'J'),
+ ("XhG8RqHruQIQrNXbfirLO2oUaQpamUQAAOw==", 'K'),
+ ("UhG8RmMvKAHwOTVvP1bmpH4UiUgAAOw==", 'L'),
+ ("WhG8RqJ0NI1DTUVgrPZg7vz3ISJZGAQA7", 'M'),
+ ("WhG8RqH3tAFTJUSgXzpvTGlXISJZGAQA7", 'N'),
+ ("VhI+hcWru2kpTxlfxBZBx/23ISJYFADs=", 'O'),
+ ("ThG+hG6DI4JJsPuQavhJnD4ZiAQA7", 'P'),
+ ("WhI+hcWru2kpTxjdhXSxeDjDISJZAAQA7", 'Q'),
+ ("WhG+hG6DI4JJs1vNc07jlNHXISJZGAQA7", 'R'),
+ ("UhH+hC4obkHGywVjpw1tbC1XiiBQAOw==", 'S'),
+ ("UhG+hq9cIHpIuwGghTXn2eoXiVQAAOw==", 'T'),
+ ("UhG8RqMr93GlrQivT1UBmioTiiBQAOw==", 'U'),
+ ("VhG8RqMr9gJOLpjon1bsefiHiSIoFADs=", 'V'),
+ ("UhG8RqMr93GnLUWBhplzyh4TiaBQAOw==", 'W'),
+ ("UhG8RqMrrQJQNUXvfjG5S72GiWAAAOw==", 'X'),
+ ("UhG8RqMrrQJQNUXvtPDst/WHiiBQAOw==", 'Y'),
+ ("UhG+hG5jtVIRHIlvpcwBnpnHiWAAAOw==", 'Z'),
+ ("ThI+pq+FuYAyNvitnfuB2yoRKAQA7", 'a'),
+ ("WhG8RmMvKAFSONukaPDRji4VgRJZHAQA7", 'b'),
+ ("RhI+pq+FuYHwt1CWBfJn5VAAAOw==", 'c'),
+ ("VhI8YkbD93JtMrmoutpvmeEnNSB4FADs=", 'd'),
+ ("RhI+pq+FxnJEyvntXBRWzzxQAOw==", 'e'),
+ ("VhI8QG7f2VJNwoliZpQm7XSXiSBoFADs=", 'f'),
+ ("VhI+pm+EO3nnQwBqDpXvRq03aFy4FADs=", 'g'),
+ ("VhG8RmMvKAFSONukaPDTjrXlgRJYFADs=", 'h'),
+ ("ThI8Qkcrd1kMrzlNTpldKCIZAAQA7", 'i'),
+ ("UhI8XkbANF0uPTlTxVSw/P0kZVAAAOw==", 'j'),
+ ("VhH8RaMrgWJwrQrUSRs7Sll3PSB4FADs=", 'k'),
+ ("RhI+haMueAgPw1CZfjvrODxYAOw==", 'l'),
+ ("ThI+piwHh4ItUWkjn1Rl3x4RKAQA7", 'm'),
+ ("UhI+pixHgHnSG0hNljY1jvzHiUgAAOw==", 'n'),
+ ("ThI+pq+FxnJEyPvSgBbXyy4RMAQA7", 'o'),
+ ("VhI+pixHgHnSG0hNljS3vOUlXxygFADs=", 'p'),
+ ("VhI+pq+HwHnTS0IBuxpLaiCXVMSIFADs=", 'q'),
+ ("ShI+pixHgnInzyXTbw1uzDxoFADs=", 'r'),
+ ("RhI+pm+EPHHphUanorLeyvxQAOw==", 's'),
+ ("UhI95EcrIYlsTVuqueYD3qIQiUgAAOw==", 't'),
+ ("ThI+pixHt3onSUOggyJvHzoRLAQA7", 'u'),
+ ("ThI+pixHt3nGAVmnt1VtOz4RLAQA7", 'v'),
+ ("UhI+pixHt3onPAXprzJliyzHiUgAAOw==", 'w'),
+ ("ThI+pixH9nJHTPZjsBVTSyoRLAQA7", 'x'),
+ ("VhI+pixHt3onSUOggyJvHXlkPxS0FADs=", 'y'),
+ ("PhI+pm+GvXAuzIjkfZXwVADs=", 'z'),
+ ]);
+}
+
+pub fn solve_b64(b64_str: &str) -> Option<String> {
+ let img_dec = general_purpose::STANDARD.decode(b64_str.strip_prefix("data:image/gif;base64,").unwrap()).unwrap();
+ let img = image::load_from_memory(&img_dec).unwrap();
+ solve_difficulty1(img)
+}
+
+fn solve_difficulty1(img: DynamicImage) -> Option<String> {
+ let mut answer = String::new();
+ let mut x = 5;
+ for i in 0..5 {
+ let sub_img = img.crop_imm(x, 7, 8, 14);
+ let mut buf = vec![];
+ {
+ let mut enc = image::codecs::gif::GifEncoder::new(&mut buf);
+ enc.encode(sub_img.as_bytes(), 8, 14, ColorType::Rgba8).unwrap();
+ }
+ let letter_b64 = general_purpose::STANDARD.encode(&buf);
+ let letter_b64 = letter_b64.strip_prefix(B64_PREFIX).unwrap();
+ if let Some(val) = B64_MAP.get(letter_b64) {
+ answer.push(val.clone());
+ } else {
+ sub_img.save(format!("captcha_{}.gif", i)).unwrap();
+ println!("{} {}", i, letter_b64);
+ return None;
+ }
+ x += 8+1;
+ }
+ Some(answer)
+}
+\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
@@ -1,4 +1,5 @@
mod util;
+mod lechatphp;
use base64::{engine::general_purpose, Engine as _};
use chrono::{DateTime, Datelike, NaiveDateTime, Utc};
@@ -808,8 +809,9 @@ impl LeChatPHPClient {
let mut captcha_input = String::new();
if self.manual_captcha {
let captcha_img = doc.find(Name("img")).next().unwrap().attr("src").unwrap();
-
- if let Some(dkf_api_key) = self.dkf_api_key.clone() {
+ if let Some(answer) = lechatphp::solve_b64(captcha_img) {
+ captcha_input = answer;
+ } else if let Some(dkf_api_key) = self.dkf_api_key.clone() {
// If we have the DKF_API_KEY, auto solve captcha using the api
let params = vec![("captcha", captcha_img)];
let resp = self