Skip to content
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 @@ -866,6 +866,17 @@ pub fn patterns() -> Vec<signatures::common::Signature> {
description: signatures::luks::DESCRIPTION.to_string(),
extractor: None,
},
// TP-Link RTOS
signatures::common::Signature {
name: "tplink_rtos".to_string(),
short: false,
magic_offset: 0,
always_display: false,
magic: signatures::tplink::tplink_rtos_magic(),
parser: signatures::tplink::tplink_rtos_parser,
description: signatures::tplink::RTOS_DESCRIPTION.to_string(),
extractor: None,
},
];

binary_signatures
Expand Down
2 changes: 1 addition & 1 deletion src/signatures/lzma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub fn lzma_parser(file_data: &[u8], offset: usize) -> Result<SignatureResult, S
lzma_header.properties,
lzma_header.dictionary_size,
result.size,
lzma_header.decompressed_size
lzma_header.decompressed_size as i64
);
return Ok(result);
}
Expand Down
37 changes: 36 additions & 1 deletion src/signatures/tplink.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::signatures::common::{SignatureError, SignatureResult, CONFIDENCE_MEDIUM};
use crate::structures::tplink::parse_tplink_header;
use crate::structures::tplink::{parse_tplink_header, parse_tplink_rtos_header};

/// Human readable description
pub const DESCRIPTION: &str = "TP-Link firmware header";
Expand Down Expand Up @@ -36,3 +36,38 @@ pub fn tplink_parser(file_data: &[u8], offset: usize) -> Result<SignatureResult,

Err(SignatureError)
}

/// Human readable description
pub const RTOS_DESCRIPTION: &str = "TP-Link RTOS firmware";

/// TP-Link RTOS firmware start with these magic bytes
pub fn tplink_rtos_magic() -> Vec<Vec<u8>> {
vec![b"\x00\x14\x2F\xC0".to_vec()]
}

/// Parse and validate TP-Link RTOS firmware header
pub fn tplink_rtos_parser(
file_data: &[u8],
offset: usize,
) -> Result<SignatureResult, SignatureError> {
let mut result = SignatureResult {
offset,
description: RTOS_DESCRIPTION.to_string(),
confidence: CONFIDENCE_MEDIUM,
..Default::default()
};

if let Ok(fw_header) = parse_tplink_rtos_header(&file_data[offset..]) {
result.description = format!("{}, model number: {:X}, hardware version: {:X}.{:X}, header size: {} bytes, total size: {} bytes",
result.description,
fw_header.model_number,
fw_header.hardware_rev_major,
fw_header.hardware_rev_minor,
fw_header.header_size,
fw_header.total_size,
);
return Ok(result);
}

Err(SignatureError)
}
44 changes: 44 additions & 0 deletions src/structures/tplink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,47 @@ pub fn parse_tplink_header(tplink_data: &[u8]) -> Result<TPLinkFirmwareHeader, S

Err(StructureError)
}

/// Stores info about a TP-Link RTOS firmware header
#[derive(Debug, Default, Clone)]
pub struct TPLinkRTOSFirmwareHeader {
pub header_size: usize,
pub total_size: usize,
pub model_number: usize,
pub hardware_rev_major: usize,
pub hardware_rev_minor: usize,
}

/// Parse a TP-Link RTOS firmware header
pub fn parse_tplink_rtos_header(
tplink_data: &[u8],
) -> Result<TPLinkRTOSFirmwareHeader, StructureError> {
const HEADER_SIZE: usize = 0x94;
const MAGIC2_VALUE: usize = 0x494D4730;
const TOTAL_SIZE_OFFSET: usize = 20;

let tplink_rtos_structure = vec![
("magic1", "u32"),
("unknown1", "u64"),
("unknown2", "u64"),
("magic2", "u32"),
("data_size", "u32"),
("model_number", "u16"),
("hardware_revision_major", "u8"),
("hardware_revision_minor", "u8"),
];

if let Ok(header) = common::parse(tplink_data, &tplink_rtos_structure, "big") {
if header["magic2"] == MAGIC2_VALUE {
return Ok(TPLinkRTOSFirmwareHeader {
header_size: HEADER_SIZE,
total_size: header["data_size"] + TOTAL_SIZE_OFFSET,
model_number: header["model_number"],
hardware_rev_major: header["hardware_revision_major"],
hardware_rev_minor: header["hardware_revision_minor"],
});
}
}

Err(StructureError)
}