Skip to content

Commit

Permalink
Merge pull request #739 from ReFirmLabs/dlink_mh01
Browse files Browse the repository at this point in the history
Adds D-Link firmware signature; adds sanity check to openssl signature
  • Loading branch information
devttys0 authored Nov 6, 2024
2 parents 1d4d3b4 + 7ea0e6c commit 4f6b10c
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/magic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,17 @@ pub fn patterns() -> Vec<signatures::common::Signature> {
description: signatures::dahua_zip::DESCRIPTION.to_string(),
extractor: Some(extractors::dahua_zip::dahua_zip_extractor()),
},
// DLink MH01
signatures::common::Signature {
name: "mh01".to_string(),
short: false,
magic_offset: 0,
always_display: false,
magic: signatures::mh01::mh01_magic(),
parser: signatures::mh01::mh01_parser,
description: signatures::mh01::DESCRIPTION.to_string(),
extractor: None,
},
];

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 @@ -146,6 +146,7 @@ pub mod lzfse;
pub mod lzma;
pub mod lzop;
pub mod mbr;
pub mod mh01;
pub mod ntfs;
pub mod openssl;
pub mod packimg;
Expand Down
35 changes: 35 additions & 0 deletions src/signatures/mh01.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::signatures::common::{SignatureError, SignatureResult, CONFIDENCE_MEDIUM};
use crate::structures::mh01::parse_mh01_header;

/// Human readable description
pub const DESCRIPTION: &str = "D-Link MH01 firmware image";

/// MH01 firmware images always start with these bytes
pub fn mh01_magic() -> Vec<Vec<u8>> {
vec![b"MH01".to_vec()]
}

/// Validates the MH01 header
pub fn mh01_parser(file_data: &[u8], offset: usize) -> Result<SignatureResult, SignatureError> {
// Successful return value
let mut result = SignatureResult {
offset,
description: DESCRIPTION.to_string(),
confidence: CONFIDENCE_MEDIUM,
..Default::default()
};

if let Ok(mh01_header) = parse_mh01_header(&file_data[offset..]) {
result.size = mh01_header.header_size;
result.description = format!(
"{}, header size: {} bytes, data size: {} bytes, data hash: {}",
result.description,
mh01_header.header_size,
mh01_header.data_size,
mh01_header.data_hash,
);
return Ok(result);
}

Err(SignatureError)
}
1 change: 1 addition & 0 deletions src/structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ pub mod lzfse;
pub mod lzma;
pub mod lzop;
pub mod mbr;
pub mod mh01;
pub mod ntfs;
pub mod openssl;
pub mod packimg;
Expand Down
51 changes: 51 additions & 0 deletions src/structures/mh01.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::common::get_cstring;
use crate::structures::common::{self, StructureError};

/// Struct to store MH01 header info
#[derive(Debug, Default, Clone)]
pub struct MH01Header {
pub data_size: usize,
pub header_size: usize,
pub data_hash: String,
}

/// Parses an MH01 header
pub fn parse_mh01_header(mh01_data: &[u8]) -> Result<MH01Header, StructureError> {
let mh01_structure = vec![
("magic1", "u32"),
("image_size", "u32"),
("footer_size", "u32"),
("unknown1", "u32"),
("magic2", "u32"),
("hash_size", "u32"),
("encrypted_data_size", "u32"),
("unknown2", "u32"),
// hash string of length hash_size immediately follows
];

// Parse the header
if let Ok(header) = common::parse(mh01_data, &mh01_structure, "little") {
// Make sure the expected magic bytes match
if header["magic1"] == header["magic2"] {
// Calculate the start and end bytes of the payload hash (ASCII hex)
let hash_bytes_start = common::size(&mh01_structure);
let hash_bytes_end = hash_bytes_start + header["hash_size"];

// Get the payload hash string
if let Some(hash_bytes) = mh01_data.get(hash_bytes_start..hash_bytes_end) {
let hash_string = get_cstring(hash_bytes);

// Make sure we got a string of the expected length
if hash_string.len() == header["hash_size"] {
return Ok(MH01Header {
data_size: header["encrypted_data_size"],
header_size: hash_bytes_end,
data_hash: hash_string.trim().to_string(),
});
}
}
}
}

Err(StructureError)
}
8 changes: 5 additions & 3 deletions src/structures/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ pub fn parse_openssl_crypt_header(ssl_data: &[u8]) -> Result<OpenSSLCryptHeader,
let ssl_structure = vec![("magic", "u64"), ("salt", "u64")];

if let Ok(ssl_header) = common::parse(ssl_data, &ssl_structure, "big") {
return Ok(OpenSSLCryptHeader {
salt: ssl_header["salt"],
});
if ssl_header["salt"] != 0 {
return Ok(OpenSSLCryptHeader {
salt: ssl_header["salt"],
});
}
}

Err(StructureError)
Expand Down

0 comments on commit 4f6b10c

Please sign in to comment.