ares/decoders/
binary_decoder.rs

1use crate::checkers::CheckerTypes;
2use crate::decoders::interface::check_string_success;
3
4use super::crack_results::CrackResult;
5use super::interface::Crack;
6use super::interface::Decoder;
7
8use log::{debug, info, trace};
9
10///! Binary Decoder
11pub struct BinaryDecoder;
12
13impl Crack for Decoder<BinaryDecoder> {
14    fn new() -> Decoder<BinaryDecoder> {
15        Decoder {
16            name: "Binary",
17            description: "A binary code represents text, computer processor instructions, or any other data using a two-symbol system. The two-symbol system used is often \"0\" and \"1\" from the binary number system. The binary code assigns a pattern of binary digits, also known as bits, to each character, instruction, etc.",
18            link: "https://en.wikipedia.org/wiki/Binary_code",
19            tags: vec!["binary", "base", "decoder"],
20            popularity: 1.0,
21            phantom: std::marker::PhantomData,
22        }
23    }
24
25    /// This function does the actual decoding
26    /// It returns an Option<string> if it was successful
27    /// Else the Option returns nothing and the error is logged in Trace
28    fn crack(&self, text: &str, checker: &CheckerTypes) -> CrackResult {
29        trace!("Trying binary with text {:?}", text);
30        let mut results = CrackResult::new(self, text.to_string());
31        let mut decoded_strings = Vec::new();
32
33        for shift in 1..25 {
34            let decoded_text = binary_to_string(text, shift);
35
36            let decoded_text = decoded_text;
37            decoded_strings.push(decoded_text);
38            let borrowed_decoded_text = &decoded_strings[decoded_strings.len() - 1];
39            if !check_string_success(borrowed_decoded_text, text) {
40                debug!(
41                    "Failed to decode binary because binary returned false on string {}. This means the string is 'funny' as it wasn't modified.",
42                    borrowed_decoded_text
43                );
44                return results;
45            }
46            let checker_result = checker.check(borrowed_decoded_text);
47            // If checkers return true, exit early with the correct result
48            if checker_result.is_identified {
49                info!("Found a match with binary bit {}", shift);
50                results.unencrypted_text = Some(vec![borrowed_decoded_text.to_string()]);
51                results.update_checker(&checker_result);
52                return results;
53            }
54        }
55        results.unencrypted_text = Some(decoded_strings);
56        results
57    }
58    /// Gets all tags for this decoder
59    fn get_tags(&self) -> &Vec<&str> {
60        &self.tags
61    }
62    /// Gets the name for the current decoder
63    fn get_name(&self) -> &str {
64        self.name
65    }
66}
67
68/// Decodes binary to string
69/// bit is the byte length
70fn binary_to_string(binary: &str, bit: u8) -> String {
71    let mut out = String::new();
72    let mut iter = binary.as_bytes().iter().filter_map(|byte| match byte {
73        b'0' => Some(0),
74        b'1' => Some(1),
75        _ => None,
76    });
77    loop {
78        let byte = iter
79            .by_ref()
80            .take(usize::from(bit))
81            .reduce(|acc, elem| (acc << 1) | elem);
82        match byte {
83            Some(byte) => out.push(char::from(byte)),
84            None => break,
85        }
86    }
87    out
88}
89
90#[cfg(test)]
91mod tests {
92    use super::BinaryDecoder;
93    use crate::{
94        checkers::{
95            athena::Athena,
96            checker_type::{Check, Checker},
97            CheckerTypes,
98        },
99        decoders::interface::{Crack, Decoder},
100    };
101
102    // helper for tests
103    fn get_athena_checker() -> CheckerTypes {
104        let athena_checker = Checker::<Athena>::new();
105        CheckerTypes::CheckAthena(athena_checker)
106    }
107
108    #[test]
109    fn binary_bit_7_decodes_successfully() {
110        // This tests if Binary can decode Binary bit 7 successfully
111        let decoder = Decoder::<BinaryDecoder>::new();
112        let result = decoder.crack("1010011111000011010001101001110111011110000100000110111111001100100000110001011011001100001110001111010110100000111000111101011100001111001011101001111010010110001000001101010111010111001001100111110010101000001101101111100101000001110110110111111101110101110", &get_athena_checker());
113        assert_eq!(
114            result.unencrypted_text.unwrap()[0],
115            "Sphinx of black quartz, judge my vow."
116        );
117    }
118
119    #[test]
120    fn binary_bit_8_decodes_successfully() {
121        // This tests if Binary can decode Binary bit 8 successfully
122        let decoder = Decoder::<BinaryDecoder>::new();
123        let result = decoder.crack("0110100001100101011011000110110001101111001000000111011101101111011100100110110001100100", &get_athena_checker());
124        assert_eq!(result.unencrypted_text.unwrap()[0], "hello world");
125    }
126
127    #[test]
128    fn binary_bit_12_with_delimiters_decodes_successfully() {
129        // This tests if Binary can decode Binary bit 12 with delimiters successfully
130        let decoder = Decoder::<BinaryDecoder>::new();
131        let result = decoder.crack("000001101000;000001110100;000001110100;000001110000;000001110011;000000111010;000000101111;000000101111;000001110111;000001110111;000001110111;000000101110;000001100111;000001101111;000001101111;000001100111;000001101100;000001100101;000000101110;000001100011;000001101111;000001101101", &get_athena_checker());
132        assert_eq!(
133            result.unencrypted_text.unwrap()[0],
134            "https://www.google.com"
135        );
136    }
137
138    #[test]
139    fn binary_bit_15_with_a_lot_of_delimiters_decodes_successfully() {
140        // This tests if Binary can decode Binary bit 15 with a lot of delimiters successfully
141        let decoder = Decoder::<BinaryDecoder>::new();
142        let result = decoder.crack(r"000+00\0001\010||100;00[000]00{}011'010'00;0'000:000:0110:10;01;0.00.000.001.11.00.11;000 ,000,000,1 00,000;0$00 0$000 0$1101$001;0!00 !00000!1 1100!1 1;000`000`000`100~000;00~000-00=0110_0011;00\\000\00\/011/0111/1 ;00?000<>000}110{11150;09008goodluck003005011h10110;00,00m00b0011f0s11f11;0h00j0r00c001t1011*00;00* 000%00011#101301;0070040 08001-1101=00;000_0 0.0001,100 .101;00090006 00113001 ~00;00d00-0 000-0101=110", &get_athena_checker());
143        assert_eq!(result.unencrypted_text.unwrap()[0], "This is convoluted.");
144    }
145
146    #[test]
147    fn binary_handles_panics() {
148        // This tests if Binary can handle panics
149        // It should return None
150        let binary_decoder = Decoder::<BinaryDecoder>::new();
151        let result = binary_decoder
152            .crack(
153                "hello my name is panicky mc panic face!",
154                &get_athena_checker(),
155            )
156            .unencrypted_text;
157        assert!(result.is_none());
158    }
159
160    #[test]
161    fn binary_handles_panic_if_empty_string() {
162        // This tests if Binary can handle an empty string
163        // It should return None
164        let citrix_ctx1_decoder = Decoder::<BinaryDecoder>::new();
165        let result = citrix_ctx1_decoder
166            .crack("", &get_athena_checker())
167            .unencrypted_text;
168        assert!(result.is_none());
169    }
170
171    #[test]
172    fn binary_handles_panic_if_emoji() {
173        // This tests if Binary can handle an emoji
174        // It should return None
175        let base64_url_decoder = Decoder::<BinaryDecoder>::new();
176        let result = base64_url_decoder
177            .crack("😂", &get_athena_checker())
178            .unencrypted_text;
179        assert!(result.is_none());
180    }
181}