Skip to content

Commit

Permalink
Merge pull request ReFirmLabs#788 from ReFirmLabs/dkbs
Browse files Browse the repository at this point in the history
Added DKBS firmware header signature
  • Loading branch information
devttys0 authored Dec 2, 2024
2 parents 4bd2697 + 703d03d commit 487c34d
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 0 deletions.
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)
}

0 comments on commit 487c34d

Please sign in to comment.