feat: parse and display security info (M3)
Implement security info parsing including RSA signature, encrypted AES key, image/region/media flags, load address, SHA-1 digests, and page descriptors with section type classification. Add comprehensive unit and integration tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use xex2tractor::header::{ModuleFlags, XEX2_MAGIC};
|
||||
use xex2tractor::optional::{CompressionType, EncryptionType, SystemFlags};
|
||||
use xex2tractor::security::{ImageFlags, MediaFlags, RegionFlags};
|
||||
|
||||
fn sample_data() -> Vec<u8> {
|
||||
let path = format!("{}/tests/data/default.xex", env!("CARGO_MANIFEST_DIR"));
|
||||
@@ -120,6 +121,70 @@ fn test_optional_import_libraries() {
|
||||
assert!(!imports.libraries.is_empty());
|
||||
}
|
||||
|
||||
// ── Security info tests ───────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn test_security_info_parsed() {
|
||||
let data = sample_data();
|
||||
let xex = xex2tractor::parse(&data).unwrap();
|
||||
let sec = &xex.security_info;
|
||||
|
||||
assert_eq!(sec.header_size, 0x00000F34);
|
||||
assert_eq!(sec.image_size, 0x00920000);
|
||||
assert_eq!(sec.unk_108, 0x00000174);
|
||||
assert_eq!(sec.load_address, 0x82000000);
|
||||
assert_eq!(sec.import_table_count, 2);
|
||||
assert_eq!(sec.export_table, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_security_flags() {
|
||||
let data = sample_data();
|
||||
let xex = xex2tractor::parse(&data).unwrap();
|
||||
let sec = &xex.security_info;
|
||||
|
||||
assert_eq!(sec.image_flags, ImageFlags(0x00000008));
|
||||
assert_eq!(sec.region, RegionFlags(0xFFFFFFFF));
|
||||
assert_eq!(sec.allowed_media_types, MediaFlags(0x00000004));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_security_page_descriptors() {
|
||||
let data = sample_data();
|
||||
let xex = xex2tractor::parse(&data).unwrap();
|
||||
let sec = &xex.security_info;
|
||||
|
||||
assert_eq!(sec.page_descriptor_count, 146);
|
||||
assert_eq!(sec.page_descriptors.len(), 146);
|
||||
|
||||
// First descriptor has page_count = 19
|
||||
assert_eq!(sec.page_descriptors[0].page_count, 19);
|
||||
|
||||
// Page size should be 64KB (4KB flag is not set)
|
||||
assert_eq!(sec.image_flags.page_size(), 0x10000);
|
||||
|
||||
// Each page descriptor should have a valid page_count
|
||||
for desc in &sec.page_descriptors {
|
||||
assert!(desc.page_count > 0, "page_count should be positive");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_security_crypto_fields() {
|
||||
let data = sample_data();
|
||||
let xex = xex2tractor::parse(&data).unwrap();
|
||||
let sec = &xex.security_info;
|
||||
|
||||
// RSA signature starts with 2C94EBE6
|
||||
assert_eq!(sec.rsa_signature[0..4], [0x2C, 0x94, 0xEB, 0xE6]);
|
||||
|
||||
// XGD2 media ID starts with 3351
|
||||
assert_eq!(sec.xgd2_media_id[0..2], [0x33, 0x51]);
|
||||
|
||||
// AES key starts with EACB
|
||||
assert_eq!(sec.aes_key[0..2], [0xEA, 0xCB]);
|
||||
}
|
||||
|
||||
// ── CLI tests ─────────────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
@@ -154,6 +219,15 @@ fn test_cli_runs_with_sample() {
|
||||
assert!(stdout.contains("xboxkrnl.exe"));
|
||||
assert!(stdout.contains("default.pe")); // original PE name
|
||||
assert!(stdout.contains("PAL50_INCOMPATIBLE")); // system flags
|
||||
|
||||
// Security info section
|
||||
assert!(stdout.contains("Security Info"));
|
||||
assert!(stdout.contains("0x00000F34")); // header size
|
||||
assert!(stdout.contains("0x00920000")); // image size
|
||||
assert!(stdout.contains("XGD2_MEDIA_ONLY")); // image flags
|
||||
assert!(stdout.contains("ALL REGIONS")); // region
|
||||
assert!(stdout.contains("DVD_CD")); // media type
|
||||
assert!(stdout.contains("Page Descriptors")); // page descriptors section
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user