Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DKBS firmware header signature #788

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/magic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,17 @@ pub fn patterns() -> Vec<signatures::common::Signature> {
description: signatures::dms::DESCRIPTION.to_string(),
extractor: Some(extractors::swapped::swapped_extractor_u16()),
},
// dkbs firmware
signatures::common::Signature {
name: "dkbs".to_string(),
short: false,
magic_offset: 0,
always_display: false,
magic: signatures::dkbs::dkbs_magic(),
parser: signatures::dkbs::dkbs_parser,
description: signatures::dkbs::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 @@ -125,6 +125,7 @@ pub mod cramfs;
pub mod csman;
pub mod dahua_zip;
pub mod deb;
pub mod dkbs;
pub mod dlink_tlv;
pub mod dlke;
pub mod dlob;
Expand Down
56 changes: 56 additions & 0 deletions src/signatures/dkbs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::signatures::common::{
SignatureError, SignatureResult, CONFIDENCE_HIGH, CONFIDENCE_MEDIUM,
};
use crate::structures::dkbs::parse_dkbs_header;

/// Human readable description
pub const DESCRIPTION: &str = "DKBS firmware header";

/// DKBS firmware magic
pub fn dkbs_magic() -> Vec<Vec<u8>> {
vec![b"_dkbs_".to_vec()]
}

/// Validates the DKBS header
pub fn dkbs_parser(file_data: &[u8], offset: usize) -> Result<SignatureResult, SignatureError> {
const MAGIC_OFFSET: usize = 7;

// Successful return value
let mut result = SignatureResult {
description: DESCRIPTION.to_string(),
confidence: CONFIDENCE_MEDIUM,
..Default::default()
};

// Sanity check the magic bytes offset
if offset >= MAGIC_OFFSET {
// Magic bytes occur 7 bytes into the actual firmware header
result.offset = offset - MAGIC_OFFSET;

// Parse the firmware header
if let Ok(dkbs_header) = parse_dkbs_header(&file_data[result.offset..]) {
// Calculate the total bytes available after the firmware header
let available_data: usize = file_data.len() - result.offset;

// Sanity check on the total reported DKBS firmware size
if available_data >= (dkbs_header.header_size + dkbs_header.data_size) {
// If this header starts at the beginning of the file, confidence is high
if result.offset == 0 {
result.confidence = CONFIDENCE_HIGH;
}

// Report header size and description
result.size = dkbs_header.header_size;
result.description = format!(
"{}, board ID: {}, firmware version: {}, boot device: {}, header size: {} bytes, data size: {}",
result.description, dkbs_header.board_id, dkbs_header.version, dkbs_header.boot_device, dkbs_header.header_size, dkbs_header.data_size
);

// Return OK
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 @@ -109,6 +109,7 @@ pub mod cpio;
pub mod cramfs;
pub mod csman;
pub mod deb;
pub mod dkbs;
pub mod dlink_tlv;
pub mod dlob;
pub mod dmg;
Expand Down
61 changes: 61 additions & 0 deletions src/structures/dkbs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use crate::common::get_cstring;
use crate::structures::common::{self, StructureError};

/// Struct to store DKBS header info
#[derive(Debug, Default, Clone)]
pub struct DKBSHeader {
pub data_size: usize,
pub header_size: usize,
pub board_id: String,
pub version: String,
pub boot_device: String,
}

/// Parses a DKBS header
pub fn parse_dkbs_header(dkbs_data: &[u8]) -> Result<DKBSHeader, StructureError> {
// Header is a fixed size
const HEADER_SIZE: usize = 0xA0;

// Constant offsets for strings and known header fields
const BOARD_ID_START: usize = 0;
const BOARD_ID_END: usize = 0x20;
const VERSION_START: usize = 0x28;
const VERSION_END: usize = 0x48;
const BOOT_DEVICE_START: usize = 0x70;
const BOOT_DEVICE_END: usize = 0x90;
const DATA_SIZE_START: usize = 0x68;
const DATA_SIZE_END: usize = DATA_SIZE_START + 4;

let data_size_field = vec![("size", "u32")];

let mut header = DKBSHeader {
header_size: HEADER_SIZE,
..Default::default()
};

// Available data should be at least big enough for the header to fit
if dkbs_data.len() >= HEADER_SIZE {
// Parse the version, board ID, and boot device strings
header.version = get_cstring(&dkbs_data[VERSION_START..VERSION_END]);
header.board_id = get_cstring(&dkbs_data[BOARD_ID_START..BOARD_ID_END]);
header.boot_device = get_cstring(&dkbs_data[BOOT_DEVICE_START..BOOT_DEVICE_END]);

// Sanity check to make sure the strings were retrieved
if !header.version.is_empty()
&& !header.board_id.is_empty()
&& !header.boot_device.is_empty()
{
// Parse the payload size field
if let Ok(data_size) = common::parse(
&dkbs_data[DATA_SIZE_START..DATA_SIZE_END],
&data_size_field,
"big",
) {
header.data_size = data_size["size"];
return Ok(header);
}
}
}

Err(StructureError)
}