From 4b26921eab951d4b6d7414c4726f70eada463d54 Mon Sep 17 00:00:00 2001 From: devttys0 Date: Sun, 22 Dec 2024 18:11:06 -0500 Subject: [PATCH 1/6] Added MH01 firmware decryption --- Cargo.lock | 341 +++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 2 + src/extractors/mh01.rs | 44 ++++-- 3 files changed, 360 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a75a0044f..952a190cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -93,12 +102,38 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide 0.8.0", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + [[package]] name = "base64" version = "0.22.1" @@ -118,6 +153,7 @@ dependencies = [ "colored", "crc32-v2", "crc32c", + "delink", "entropy", "env_logger", "flate2", @@ -148,6 +184,15 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -166,6 +211,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + [[package]] name = "bzip2" version = "0.4.4" @@ -330,6 +381,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + [[package]] name = "crc32-v2" version = "0.0.4" @@ -354,6 +414,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "delink" +version = "0.1.0" +dependencies = [ + "env_logger", + "hex", + "hmac", + "log", + "md5", + "rust-crypto", + "sha1", + "sha256", + "thiserror 2.0.9", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "dirs" version = "5.0.1" @@ -513,6 +609,28 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -521,7 +639,7 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -534,6 +652,12 @@ dependencies = [ "weezl", ] +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "heck" version = "0.5.0" @@ -552,6 +676,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "humantime" version = "2.1.0" @@ -721,6 +854,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -752,6 +894,12 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + [[package]] name = "pkg-config" version = "0.3.30" @@ -828,9 +976,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -844,6 +992,29 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +dependencies = [ + "libc", + "rand 0.4.6", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.8.5" @@ -852,7 +1023,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -862,9 +1033,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", ] +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.6.4" @@ -874,6 +1060,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_users" version = "0.4.6" @@ -882,7 +1077,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -914,6 +1109,31 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +dependencies = [ + "gcc", + "libc", + "rand 0.3.23", + "rustc-serialize", + "time", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-serialize" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" + [[package]] name = "rustc_version" version = "0.4.1" @@ -976,6 +1196,41 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha256" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2", + "tokio", +] + [[package]] name = "shlex" version = "1.3.0" @@ -994,11 +1249,17 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" -version = "2.0.77" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", @@ -1021,7 +1282,16 @@ version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.63", +] + +[[package]] +name = "thiserror" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", ] [[package]] @@ -1035,6 +1305,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "threadpool" version = "1.8.1" @@ -1044,12 +1325,40 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "tokio" +version = "1.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +dependencies = [ + "backtrace", + "bytes", + "pin-project-lite", +] + [[package]] name = "ttf-parser" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -1069,7 +1378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", - "rand", + "rand 0.8.5", "uuid-macro-internal", ] @@ -1084,6 +1393,12 @@ dependencies = [ "syn", ] +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" @@ -1094,6 +1409,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index e1e6772fb..f5c115cad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,8 @@ serde = { version = "1.0", features = ["derive"]} clap = { version = "4.5.16", features = ["derive"] } xxhash-rust = { version = "0.8.12", features = ["xxh32"] } hex = "0.4.3" +#delink = { git = "https://github.com/devttys0/delink" } +delink = { path = "../delink" } [dependencies.uuid] version = "1.10.0" diff --git a/src/extractors/mh01.rs b/src/extractors/mh01.rs index de0840f5d..a493ee067 100644 --- a/src/extractors/mh01.rs +++ b/src/extractors/mh01.rs @@ -40,6 +40,7 @@ pub fn extract_mh01_image( const IV_FILE_NAME: &str = "iv.bin"; const SIGNATURE_FILE_NAME: &str = "signature.bin"; const ENCRYPTED_DATA_FILE_NAME: &str = "encrypted.bin"; + const DECRYPTED_DATA_FILE_NAME: &str = "decrypted.bin"; let mut result = ExtractionResult { ..Default::default() @@ -55,23 +56,32 @@ pub fn extract_mh01_image( if output_directory.is_some() { let chroot = Chroot::new(output_directory); - // Extract each part of the firmware image, ensuring that each one extracts without error - result.success = chroot.carve_file( - IV_FILE_NAME, - mh01_data, - mh01_header.iv_offset, - mh01_header.iv_size, - ) && chroot.carve_file( - SIGNATURE_FILE_NAME, - mh01_data, - mh01_header.signature_offset, - mh01_header.signature_size, - ) && chroot.carve_file( - ENCRYPTED_DATA_FILE_NAME, - mh01_data, - mh01_header.encrypted_data_offset, - mh01_header.encrypted_data_size, - ); + // Try to decrypt the firmware + match delink::mh01::decrypt(mh01_data) { + Ok(decrypted_data) => { + // Write decrypted data to disk + result.success = chroot.create_file(DECRYPTED_DATA_FILE_NAME, &decrypted_data); + }, + Err(_) => { + // Decryption failture; extract each part of the firmware image, ensuring that each one extracts without error + result.success = chroot.carve_file( + IV_FILE_NAME, + mh01_data, + mh01_header.iv_offset, + mh01_header.iv_size, + ) && chroot.carve_file( + SIGNATURE_FILE_NAME, + mh01_data, + mh01_header.signature_offset, + mh01_header.signature_size, + ) && chroot.carve_file( + ENCRYPTED_DATA_FILE_NAME, + mh01_data, + mh01_header.encrypted_data_offset, + mh01_header.encrypted_data_size, + ); + } + } // No extraction requested, just return success } else { result.success = true; From 3ee46a6dda9d60245b37cbde193847ff219adf33 Mon Sep 17 00:00:00 2001 From: devttys0 Date: Sun, 22 Dec 2024 18:22:50 -0500 Subject: [PATCH 2/6] Added encfw decryptor --- src/extractors.rs | 1 + src/extractors/encfw.rs | 55 +++++++++++++++++++++++++++++++++++++++++ src/magic.rs | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/extractors/encfw.rs diff --git a/src/extractors.rs b/src/extractors.rs index b9c16a761..d6e5305a0 100644 --- a/src/extractors.rs +++ b/src/extractors.rs @@ -157,6 +157,7 @@ pub mod dxbc; pub mod gif; pub mod gpg; pub mod gzip; +pub mod encfw; pub mod inflate; pub mod iso9660; pub mod jboot; diff --git a/src/extractors/encfw.rs b/src/extractors/encfw.rs new file mode 100644 index 000000000..1d4c76c14 --- /dev/null +++ b/src/extractors/encfw.rs @@ -0,0 +1,55 @@ +use crate::extractors::common::{Chroot, ExtractionResult, Extractor, ExtractorType}; + +/// Defines the internal extractor function for decrypting known encrypted firmware +/// +/// ``` +/// use std::io::ErrorKind; +/// use std::process::Command; +/// use binwalk::extractors::common::ExtractorType; +/// use binwalk::extractors::encfw::encfw_extractor; +/// +/// match encfw_extractor().utility { +/// ExtractorType::None => panic!("Invalid extractor type of None"), +/// ExtractorType::Internal(func) => println!("Internal extractor OK: {:?}", func), +/// ExtractorType::External(cmd) => { +/// if let Err(e) = Command::new(&cmd).output() { +/// if e.kind() == ErrorKind::NotFound { +/// panic!("External extractor '{}' not found", cmd); +/// } else { +/// panic!("Failed to execute external extractor '{}': {}", cmd, e); +/// } +/// } +/// } +/// } +/// ``` +pub fn encfw_extractor() -> Extractor { + Extractor { + utility: ExtractorType::Internal(encfw_decrypt), + ..Default::default() + } +} + +/// Attempts to decrypt known encrypted firmware images +pub fn encfw_decrypt( + file_data: &[u8], + offset: usize, + output_directory: Option<&str>, +) -> ExtractionResult { + const OUTPUT_FILE_NAME: &str = "decrypted.bin"; + + let mut result = ExtractionResult { + ..Default::default() + }; + + if let Ok(decrypted_data) = delink::decrypt(&file_data[offset..]) { + result.success = true; + + // Write to file, if requested + if output_directory.is_some() { + let chroot = Chroot::new(output_directory); + result.success = chroot.create_file(OUTPUT_FILE_NAME, &decrypted_data); + } + } + + result +} diff --git a/src/magic.rs b/src/magic.rs index ce06da42a..7062133b1 100644 --- a/src/magic.rs +++ b/src/magic.rs @@ -1117,7 +1117,7 @@ pub fn patterns() -> Vec { magic: signatures::encfw::encfw_magic(), parser: signatures::encfw::encfw_parser, description: signatures::encfw::DESCRIPTION.to_string(), - extractor: None, + extractor: Some(extractors::encfw::encfw_extractor()), }, ]; From 28a68cf6693ee5eda79a139fb13207109b7bd69c Mon Sep 17 00:00:00 2001 From: devttys0 Date: Sun, 22 Dec 2024 18:25:21 -0500 Subject: [PATCH 3/6] Added DKBS extractor --- src/magic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/magic.rs b/src/magic.rs index 7062133b1..02c747348 100644 --- a/src/magic.rs +++ b/src/magic.rs @@ -1106,7 +1106,7 @@ pub fn patterns() -> Vec { magic: signatures::dkbs::dkbs_magic(), parser: signatures::dkbs::dkbs_parser, description: signatures::dkbs::DESCRIPTION.to_string(), - extractor: None, + extractor: Some(extractors::encfw::encfw_extractor()), }, // known encrypted firmware signatures::common::Signature { From 0961b80e93501a7f3d2380e2ae8ad76c471c9579 Mon Sep 17 00:00:00 2001 From: devttys0 Date: Sun, 22 Dec 2024 18:34:00 -0500 Subject: [PATCH 4/6] Finished delink extractor integration --- src/extractors.rs | 5 +-- src/extractors/dlink_tlv.rs | 66 ---------------------------- src/extractors/dlke.rs | 86 ------------------------------------- src/extractors/mh01.rs | 5 ++- src/extractors/shrs.rs | 71 ------------------------------ src/magic.rs | 8 ++-- 6 files changed, 8 insertions(+), 233 deletions(-) delete mode 100644 src/extractors/dlink_tlv.rs delete mode 100644 src/extractors/dlke.rs delete mode 100644 src/extractors/shrs.rs diff --git a/src/extractors.rs b/src/extractors.rs index d6e5305a0..5c0643fb9 100644 --- a/src/extractors.rs +++ b/src/extractors.rs @@ -148,16 +148,14 @@ pub mod cab; pub mod common; pub mod csman; pub mod dahua_zip; -pub mod dlink_tlv; -pub mod dlke; pub mod dmg; pub mod dtb; pub mod dumpifs; pub mod dxbc; +pub mod encfw; pub mod gif; pub mod gpg; pub mod gzip; -pub mod encfw; pub mod inflate; pub mod iso9660; pub mod jboot; @@ -177,7 +175,6 @@ pub mod rar; pub mod riff; pub mod romfs; pub mod sevenzip; -pub mod shrs; pub mod squashfs; pub mod srec; pub mod svg; diff --git a/src/extractors/dlink_tlv.rs b/src/extractors/dlink_tlv.rs deleted file mode 100644 index d2bf6738e..000000000 --- a/src/extractors/dlink_tlv.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::extractors::common::{Chroot, ExtractionResult, Extractor, ExtractorType}; -use crate::structures::dlink_tlv::parse_dlink_tlv_header; - -/// Defines the internal extractor function for carving out D-Link TLV firmware images -/// -/// ``` -/// use std::io::ErrorKind; -/// use std::process::Command; -/// use binwalk::extractors::common::ExtractorType; -/// use binwalk::extractors::dlink_tlv::dlink_tlv_extractor; -/// -/// match dlink_tlv_extractor().utility { -/// ExtractorType::None => panic!("Invalid extractor type of None"), -/// ExtractorType::Internal(func) => println!("Internal extractor OK: {:?}", func), -/// ExtractorType::External(cmd) => { -/// if let Err(e) = Command::new(&cmd).output() { -/// if e.kind() == ErrorKind::NotFound { -/// panic!("External extractor '{}' not found", cmd); -/// } else { -/// panic!("Failed to execute external extractor '{}': {}", cmd, e); -/// } -/// } -/// } -/// } -/// ``` -pub fn dlink_tlv_extractor() -> Extractor { - Extractor { - utility: ExtractorType::Internal(extract_dlink_tlv_image), - ..Default::default() - } -} - -/// Internal extractor for carve pieces of D-Link TLV images to disk -pub fn extract_dlink_tlv_image( - file_data: &[u8], - offset: usize, - output_directory: Option<&str>, -) -> ExtractionResult { - const OUTPUT_FILE_NAME: &str = "image.bin"; - - let mut result = ExtractionResult { - ..Default::default() - }; - - // Get the D-Link TLV image data - if let Some(tlv_data) = file_data.get(offset..) { - // Parse the TLV header - if let Ok(tlv_header) = parse_dlink_tlv_header(tlv_data) { - result.success = true; - result.size = Some(tlv_header.header_size + tlv_header.data_size); - - // If extraction was requested, do it - if output_directory.is_some() { - let chroot = Chroot::new(output_directory); - result.success = chroot.carve_file( - OUTPUT_FILE_NAME, - tlv_data, - tlv_header.header_size, - tlv_header.data_size, - ); - } - } - } - - result -} diff --git a/src/extractors/dlke.rs b/src/extractors/dlke.rs deleted file mode 100644 index 3a58e1cc4..000000000 --- a/src/extractors/dlke.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::extractors::common::{Chroot, ExtractionResult, Extractor, ExtractorType}; -use crate::structures::jboot::parse_jboot_arm_header; - -/// Defines the internal extractor function for carving out D-Link TLV firmware images -/// -/// ``` -/// use std::io::ErrorKind; -/// use std::process::Command; -/// use binwalk::extractors::common::ExtractorType; -/// use binwalk::extractors::dlke::dlke_extractor; -/// -/// match dlke_extractor().utility { -/// ExtractorType::None => panic!("Invalid extractor type of None"), -/// ExtractorType::Internal(func) => println!("Internal extractor OK: {:?}", func), -/// ExtractorType::External(cmd) => { -/// if let Err(e) = Command::new(&cmd).output() { -/// if e.kind() == ErrorKind::NotFound { -/// panic!("External extractor '{}' not found", cmd); -/// } else { -/// panic!("Failed to execute external extractor '{}': {}", cmd, e); -/// } -/// } -/// } -/// } -/// ``` -pub fn dlke_extractor() -> Extractor { - Extractor { - utility: ExtractorType::Internal(extract_dlke_image), - ..Default::default() - } -} - -/// Internal extractor for carve pieces of encrypted DLKE firmware images to disk -pub fn extract_dlke_image( - file_data: &[u8], - offset: usize, - output_directory: Option<&str>, -) -> ExtractionResult { - const ENCRYPTED_FILE_NAME: &str = "encrypted.bin"; - const SIGNATURE_FILE_NAME: &str = "signature.bin"; - - let mut result = ExtractionResult { - ..Default::default() - }; - - // Parse the first header, which describes the size of the firmware signature - if let Some(dlke_sig_header_data) = file_data.get(offset..) { - if let Ok(dlke_signature_header) = parse_jboot_arm_header(dlke_sig_header_data) { - // Second header should immediately follow the first - if let Some(dlke_crypt_header_data) = file_data - .get(offset + dlke_signature_header.header_size + dlke_signature_header.data_size..) - { - // Parse the second header, which describes the size of the encrypted data - if let Ok(dlke_crypt_header) = parse_jboot_arm_header(dlke_crypt_header_data) { - result.success = true; - result.size = Some( - dlke_signature_header.header_size - + dlke_signature_header.data_size - + dlke_crypt_header.header_size - + dlke_crypt_header.data_size, - ); - - if output_directory.is_some() { - let chroot = Chroot::new(output_directory); - - if !chroot.carve_file( - SIGNATURE_FILE_NAME, - dlke_sig_header_data, - dlke_signature_header.header_size, - dlke_signature_header.data_size, - ) || !chroot.carve_file( - ENCRYPTED_FILE_NAME, - dlke_crypt_header_data, - dlke_crypt_header.header_size, - dlke_crypt_header.data_size, - ) { - result.success = false; - } - } - } - } - } - } - - result -} diff --git a/src/extractors/mh01.rs b/src/extractors/mh01.rs index a493ee067..ce7ed0140 100644 --- a/src/extractors/mh01.rs +++ b/src/extractors/mh01.rs @@ -60,8 +60,9 @@ pub fn extract_mh01_image( match delink::mh01::decrypt(mh01_data) { Ok(decrypted_data) => { // Write decrypted data to disk - result.success = chroot.create_file(DECRYPTED_DATA_FILE_NAME, &decrypted_data); - }, + result.success = + chroot.create_file(DECRYPTED_DATA_FILE_NAME, &decrypted_data); + } Err(_) => { // Decryption failture; extract each part of the firmware image, ensuring that each one extracts without error result.success = chroot.carve_file( diff --git a/src/extractors/shrs.rs b/src/extractors/shrs.rs deleted file mode 100644 index b0d7b4f73..000000000 --- a/src/extractors/shrs.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::extractors::common::{Chroot, ExtractionResult, Extractor, ExtractorType}; -use crate::structures::shrs::parse_shrs_header; - -/// Defines the internal extractor function for carving out D-Link SHRS firmware images -/// -/// ``` -/// use std::io::ErrorKind; -/// use std::process::Command; -/// use binwalk::extractors::common::ExtractorType; -/// use binwalk::extractors::shrs::shrs_extractor; -/// -/// match shrs_extractor().utility { -/// ExtractorType::None => panic!("Invalid extractor type of None"), -/// ExtractorType::Internal(func) => println!("Internal extractor OK: {:?}", func), -/// ExtractorType::External(cmd) => { -/// if let Err(e) = Command::new(&cmd).output() { -/// if e.kind() == ErrorKind::NotFound { -/// panic!("External extractor '{}' not found", cmd); -/// } else { -/// panic!("Failed to execute external extractor '{}': {}", cmd, e); -/// } -/// } -/// } -/// } -/// ``` -pub fn shrs_extractor() -> Extractor { - Extractor { - utility: ExtractorType::Internal(extract_shrs_image), - ..Default::default() - } -} - -/// Internal extractor for carve pieces of encrypted SHRS firmware images to disk -pub fn extract_shrs_image( - file_data: &[u8], - offset: usize, - output_directory: Option<&str>, -) -> ExtractionResult { - const IV_FILE_NAME: &str = "iv.bin"; - const ENCRYPTED_FILE_NAME: &str = "encrypted.bin"; - - let mut result = ExtractionResult { - ..Default::default() - }; - - // Parse the header - if let Some(shrs_header_data) = file_data.get(offset..) { - if let Ok(shrs_header) = parse_shrs_header(shrs_header_data) { - result.success = true; - result.size = Some(shrs_header.header_size + shrs_header.data_size); - - // Carve out the IV and encrypted data blob - if output_directory.is_some() { - let chroot = Chroot::new(output_directory); - - if !chroot.create_file(IV_FILE_NAME, &shrs_header.iv) - || !chroot.carve_file( - ENCRYPTED_FILE_NAME, - file_data, - shrs_header.header_size, - shrs_header.data_size, - ) - { - result.success = false; - } - } - } - } - - result -} diff --git a/src/magic.rs b/src/magic.rs index 02c747348..1fe603a6d 100644 --- a/src/magic.rs +++ b/src/magic.rs @@ -1007,7 +1007,7 @@ pub fn patterns() -> Vec { magic: signatures::dlink_tlv::dlink_tlv_magic(), parser: signatures::dlink_tlv::dlink_tlv_parser, description: signatures::dlink_tlv::DESCRIPTION.to_string(), - extractor: Some(extractors::dlink_tlv::dlink_tlv_extractor()), + extractor: Some(extractors::encfw::encfw_extractor()), }, // DLKE encrypted firmware signatures::common::Signature { @@ -1018,7 +1018,7 @@ pub fn patterns() -> Vec { magic: signatures::dlke::dlke_magic(), parser: signatures::dlke::dlke_parser, description: signatures::dlke::DESCRIPTION.to_string(), - extractor: Some(extractors::dlke::dlke_extractor()), + extractor: Some(extractors::encfw::encfw_extractor()), }, // SHRS encrypted firmware signatures::common::Signature { @@ -1029,7 +1029,7 @@ pub fn patterns() -> Vec { magic: signatures::shrs::shrs_magic(), parser: signatures::shrs::shrs_parser, description: signatures::shrs::DESCRIPTION.to_string(), - extractor: Some(extractors::shrs::shrs_extractor()), + extractor: Some(extractors::encfw::encfw_extractor()), }, // PKCS DER hashes signatures::common::Signature { @@ -1062,7 +1062,7 @@ pub fn patterns() -> Vec { magic: signatures::encrpted_img::encrpted_img_magic(), parser: signatures::encrpted_img::encrpted_img_parser, description: signatures::encrpted_img::DESCRIPTION.to_string(), - extractor: None, + extractor: Some(extractors::encfw::encfw_extractor()), }, // Android boot image signatures::common::Signature { From b83882a42faeeacd403edf68da7bbae14ac61a51 Mon Sep 17 00:00:00 2001 From: devttys0 Date: Sun, 22 Dec 2024 18:36:58 -0500 Subject: [PATCH 5/6] Updated to use delink git repo --- Cargo.lock | 1 + Cargo.toml | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 952a190cd..79facb86e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -427,6 +427,7 @@ dependencies = [ [[package]] name = "delink" version = "0.1.0" +source = "git+https://github.com/devttys0/delink#3e799997d568297326b970839da15fd6ba0b1dad" dependencies = [ "env_logger", "hex", diff --git a/Cargo.toml b/Cargo.toml index f5c115cad..a4f2eb88a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,7 @@ serde = { version = "1.0", features = ["derive"]} clap = { version = "4.5.16", features = ["derive"] } xxhash-rust = { version = "0.8.12", features = ["xxh32"] } hex = "0.4.3" -#delink = { git = "https://github.com/devttys0/delink" } -delink = { path = "../delink" } +delink = { git = "https://github.com/devttys0/delink" } [dependencies.uuid] version = "1.10.0" From 8c37ee32b4b3f295329bc8aaba89ab833bf16906 Mon Sep 17 00:00:00 2001 From: devttys0 Date: Sun, 22 Dec 2024 18:41:55 -0500 Subject: [PATCH 6/6] Added support for OpenSSL encrypted firmware --- src/magic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/magic.rs b/src/magic.rs index 1fe603a6d..994b24fdc 100644 --- a/src/magic.rs +++ b/src/magic.rs @@ -688,7 +688,7 @@ pub fn patterns() -> Vec { magic: signatures::openssl::openssl_crypt_magic(), parser: signatures::openssl::openssl_crypt_parser, description: signatures::openssl::DESCRIPTION.to_string(), - extractor: None, + extractor: Some(extractors::encfw::encfw_extractor()), }, // lzfse signatures::common::Signature {