use mbr_forensic::{
analyse,
findings::AnomalyKind,
vbr::{parse_bpb, Bpb},
};
use std::io::Cursor;
fn vbr(hidden_sectors: u32) -> [u8; 512] {
let mut s = [0u8; 512];
s[3..11].copy_from_slice(b"NTFS "); s[11..13].copy_from_slice(&512u16.to_le_bytes()); s[13] = 8; s[14..16].copy_from_slice(&0u16.to_le_bytes()); s[28..32].copy_from_slice(&hidden_sectors.to_le_bytes()); s[510] = 0x55;
s[511] = 0xAA;
s
}
#[test]
fn parse_bpb_reads_hidden_sectors() {
let bpb: Bpb = parse_bpb(&vbr(2048)).expect("valid BPB");
assert_eq!(bpb.bytes_per_sector, 512);
assert_eq!(bpb.sectors_per_cluster, 8);
assert_eq!(bpb.hidden_sectors, 2048);
}
#[test]
fn parse_bpb_rejects_garbage() {
assert!(parse_bpb(&[0u8; 512]).is_none()); let mut bad = vbr(0);
bad[11] = 7; bad[12] = 0;
assert!(parse_bpb(&bad).is_none());
}
fn entry(type_code: u8, lba_start: u32, lba_count: u32) -> [u8; 16] {
let mut e = [0u8; 16];
e[4] = type_code;
e[8..12].copy_from_slice(&lba_start.to_le_bytes());
e[12..16].copy_from_slice(&lba_count.to_le_bytes());
e
}
fn disk_with_vbr(lba_start: u32, hidden_sectors: u32) -> Vec<u8> {
let mut disk = vec![0u8; 4096 * 512];
disk[510] = 0x55;
disk[511] = 0xAA;
disk[446..462].copy_from_slice(&entry(0x07, lba_start, 1000));
let off = (lba_start as usize) * 512;
disk[off..off + 512].copy_from_slice(&vbr(hidden_sectors));
disk
}
#[test]
fn analyse_flags_hidden_sectors_mismatch() {
let analysis = analyse(&mut Cursor::new(disk_with_vbr(2048, 63)), 4096 * 512).unwrap();
assert!(
analysis.anomalies.iter().any(|a| matches!(
a.kind,
AnomalyKind::VbrHiddenSectorsMismatch { index: 0, .. }
)),
"got: {:?}",
analysis
.anomalies
.iter()
.map(|a| a.code)
.collect::<Vec<_>>()
);
}
#[test]
fn analyse_no_flag_when_hidden_sectors_match() {
let analysis = analyse(&mut Cursor::new(disk_with_vbr(2048, 2048)), 4096 * 512).unwrap();
assert!(!analysis
.anomalies
.iter()
.any(|a| matches!(a.kind, AnomalyKind::VbrHiddenSectorsMismatch { .. })));
}
#[test]
fn analyse_no_flag_when_hidden_sectors_zero() {
let analysis = analyse(&mut Cursor::new(disk_with_vbr(2048, 0)), 4096 * 512).unwrap();
assert!(!analysis
.anomalies
.iter()
.any(|a| matches!(a.kind, AnomalyKind::VbrHiddenSectorsMismatch { .. })));
}