Skip to content

Commit

Permalink
Added support for Autel encoded firmware
Browse files Browse the repository at this point in the history
  • Loading branch information
devttys0 committed Oct 25, 2024
1 parent 909df57 commit bcb1475
Show file tree
Hide file tree
Showing 8 changed files with 434 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/extractors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
pub mod androidsparse;
pub mod arcadyan;
pub mod autel;
pub mod bzip2;
pub mod cab;
pub mod common;
Expand Down
340 changes: 340 additions & 0 deletions src/extractors/autel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,340 @@
use crate::extractors::common::{Chroot, ExtractionResult, Extractor, ExtractorType};
use crate::structures::autel::parse_autel_header;

const BLOCK_SIZE: usize = 256;

/// Defines the internal extractor function for deobfuscating Autel firmware
pub fn autel_extractor() -> Extractor {
Extractor {
utility: ExtractorType::Internal(autel_deobfuscate),
..Default::default()
}
}

/// Internal extractor for obfuscated Autel firmware
/// https://gist.github.com/sector7-nl/3fc815cd2497817ad461bfbd393294cb
pub fn autel_deobfuscate(
file_data: &[u8],
offset: usize,
output_directory: Option<&String>,
) -> ExtractionResult {
const OUTPUT_FILE_NAME: &str = "autel.decoded";

let mut result = ExtractionResult {
..Default::default()
};

// Parse and validate the header
if let Ok(autel_header) = parse_autel_header(&file_data[offset..]) {
// Get the start and end offsets of the actual encoded data
let data_start = offset + autel_header.header_size;
let data_end = data_start + autel_header.data_size;

// Get the encoded data
if let Some(autel_data) = file_data.get(data_start..data_end) {
// Interate through each block of the encoded data
let mut block_iter = autel_data.chunks(BLOCK_SIZE);

loop {
match block_iter.next() {
None => {
// EOF
result.size = Some(autel_header.data_size);
result.success = true;
break;
}
Some(block_bytes) => {
// Decode the data block
let decoded_block = decode_autel_block(block_bytes);

// Write to file, if requested
if output_directory.is_some() {
let chroot = Chroot::new(output_directory);
if !chroot.append_to_file(OUTPUT_FILE_NAME, &decoded_block) {
break;
}
}
}
}
}
}
}

result
}

/// Block decoder for autel encoded firmware.
/// block_data *must* be 256 bytes in size, or less.
fn decode_autel_block(block_data: &[u8]) -> Vec<u8> {
// Lookup table for encoding/decoding bytes
let encoding_table: Vec<(usize, usize)> = vec![
(54, 147),
(96, 129),
(59, 193),
(191, 0),
(45, 130),
(96, 144),
(27, 129),
(152, 0),
(44, 180),
(118, 141),
(115, 129),
(210, 0),
(13, 164),
(27, 133),
(20, 192),
(139, 0),
(28, 166),
(17, 133),
(19, 193),
(224, 0),
(20, 161),
(145, 0),
(14, 193),
(12, 132),
(18, 161),
(17, 140),
(29, 192),
(246, 0),
(115, 178),
(28, 132),
(155, 0),
(12, 132),
(31, 165),
(20, 136),
(27, 193),
(142, 0),
(96, 164),
(18, 133),
(145, 0),
(23, 132),
(13, 165),
(13, 148),
(23, 193),
(19, 132),
(27, 178),
(83, 137),
(146, 0),
(145, 0),
(18, 166),
(96, 148),
(13, 193),
(159, 0),
(96, 166),
(20, 129),
(20, 193),
(27, 132),
(9, 160),
(96, 148),
(13, 192),
(159, 0),
(96, 180),
(142, 0),
(31, 193),
(155, 0),
(7, 166),
(224, 0),
(20, 192),
(27, 132),
(28, 160),
(17, 149),
(19, 193),
(96, 132),
(76, 164),
(208, 0),
(80, 192),
(78, 132),
(96, 160),
(27, 144),
(24, 193),
(140, 0),
(96, 178),
(17, 141),
(12, 193),
(224, 0),
(14, 161),
(17, 141),
(151, 0),
(14, 132),
(16, 165),
(96, 137),
(13, 193),
(155, 0),
(20, 161),
(29, 141),
(23, 192),
(24, 132),
(27, 178),
(10, 133),
(96, 192),
(140, 0),
(14, 180),
(17, 133),
(16, 192),
(144, 0),
(11, 163),
(13, 141),
(96, 192),
(17, 132),
(12, 178),
(96, 141),
(28, 192),
(27, 132),
(27, 130),
(18, 141),
(96, 193),
(31, 132),
(96, 181),
(13, 140),
(23, 193),
(224, 0),
(27, 166),
(142, 0),
(27, 192),
(24, 132),
(12, 183),
(96, 133),
(84, 192),
(14, 132),
(27, 178),
(10, 140),
(155, 0),
(9, 132),
(17, 160),
(56, 133),
(96, 192),
(82, 132),
(13, 160),
(27, 137),
(20, 193),
(139, 0),
(28, 161),
(145, 0),
(19, 192),
(118, 132),
(115, 165),
(20, 132),
(145, 0),
(14, 132),
(12, 167),
(146, 0),
(17, 193),
(29, 132),
(96, 176),
(28, 144),
(27, 193),
(140, 0),
(31, 180),
(148, 0),
(27, 192),
(14, 132),
(83, 160),
(18, 137),
(17, 193),
(23, 132),
(13, 165),
(13, 145),
(151, 0),
(147, 0),
(27, 178),
(96, 137),
(19, 193),
(159, 0),
(14, 160),
(25, 148),
(17, 193),
(142, 0),
(16, 180),
(27, 136),
(14, 193),
(224, 0),
(17, 178),
(12, 144),
(224, 0),
(28, 132),
(27, 160),
(13, 141),
(11, 193),
(96, 132),
(27, 165),
(30, 140),
(224, 0),
(146, 0),
(31, 165),
(29, 129),
(96, 192),
(140, 0),
(31, 161),
(24, 145),
(140, 0),
(96, 132),
(27, 165),
(29, 140),
(31, 192),
(154, 0),
(14, 161),
(27, 145),
(140, 0),
(18, 132),
(23, 167),
(96, 140),
(21, 129),
(14, 132),
(17, 165),
(9, 137),
(12, 193),
(155, 0),
(18, 161),
(96, 141),
(27, 192),
(148, 0),
(29, 178),
(23, 133),
(24, 192),
(155, 0),
(10, 180),
(96, 133),
(28, 192),
(14, 132),
(31, 130),
(28, 129),
(18, 193),
(31, 132),
(12, 180),
(13, 144),
(96, 193),
(31, 132),
(96, 160),
(13, 141),
(27, 193),
(18, 132),
(23, 181),
(26, 140),
(27, 193),
(156, 0),
(96, 166),
(79, 141),
(211, 0),
(76, 132),
(77, 160),
(75, 133),
(206, 0),
(182, 0),
(96, 129),
(59, 133),
(191, 0),
(173, 0),
];

assert!(block_data.len() <= BLOCK_SIZE);

let mut decoded_block: Vec<u8> = vec![];

for (i, byte) in block_data.iter().enumerate() {
let encoding = encoding_table[i];

decoded_block.push(((((*byte as usize) + encoding.0) ^ encoding.1) % 256) as u8);
}

decoded_block
}
11 changes: 11 additions & 0 deletions src/magic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,17 @@ pub fn patterns() -> Vec<signatures::common::Signature> {
description: signatures::binhdr::DESCRIPTION.to_string(),
extractor: None,
},
// Autel obfuscated firmware
signatures::common::Signature {
name: "autel".to_string(),
short: false,
magic_offset: 0,
always_display: false,
magic: signatures::autel::autel_magic(),
parser: signatures::autel::autel_parser,
description: signatures::autel::DESCRIPTION.to_string(),
extractor: Some(extractors::autel::autel_extractor()),
},
];

binary_signatures
Expand Down
1 change: 1 addition & 0 deletions src/signatures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
pub mod aes;
pub mod androidsparse;
pub mod arcadyan;
pub mod autel;
pub mod binhdr;
pub mod bzip2;
pub mod cab;
Expand Down
Loading

0 comments on commit bcb1475

Please sign in to comment.