From 45a13f26950bf16fa3c2be628a0eac70d2f1f732 Mon Sep 17 00:00:00 2001 From: theubusu <80545678+theubusu@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:43:08 +0100 Subject: [PATCH] much needed overhaul to msd10 and msd11 --- src/formats/msd10.rs | 178 +++++++++++++++++++++---------------------- src/formats/msd11.rs | 131 ++++++++++++++++--------------- 2 files changed, 153 insertions(+), 156 deletions(-) diff --git a/src/formats/msd10.rs b/src/formats/msd10.rs index 8f90d75..2a66f49 100644 --- a/src/formats/msd10.rs +++ b/src/formats/msd10.rs @@ -1,18 +1,35 @@ use std::fs::{self, File, OpenOptions}; use std::path::{Path}; use std::io::{Cursor, Write, Seek, SeekFrom}; +use binrw::{BinRead, BinReaderExt}; use crate::common; use crate::keys; - use crate::formats::msd::{decrypt_aes_salted_old, decrypt_aes_salted_tizen, decrypt_aes_tizen}; -pub fn is_msd10_file(file: &File) -> bool { - let header = common::read_file(&file, 0, 6).expect("Failed to read from file."); - if header == b"MSDU10" { - true - } else { - false +#[derive(BinRead)] +struct FileHeader { + #[br(count = 6)] _magic_bytes: Vec, + section_count: u32 +} + +#[derive(BinRead)] +struct SectionEntry { + index: u32, + offset: u32, + size: u32, +} + +#[derive(BinRead)] +struct HeaderEntry { + offset: u32, + size: u32, + _name_length: u8, + #[br(count = _name_length)] name_bytes: Vec, +} +impl HeaderEntry { + fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) } } @@ -23,60 +40,72 @@ struct Section { name: String, } -pub fn extract_msd10(mut file: &File, output_folder: &str) -> Result<(), Box> { - - let _magic = common::read_exact(&mut file, 6)?; //MSDU10 magic +#[derive(BinRead)] +struct TizenTocEntry { + #[br(count = 44)] _unk1: Vec, + _name_length: u8, + #[br(count = _name_length)] name_bytes: Vec, + #[br(count = 314)] _unk2: Vec, + #[br(count = 8)] salt: Vec, + #[br(count = 13)] _unk3: Vec, +} +impl TizenTocEntry { + fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} - let section_count_bytes = common::read_exact(&mut file, 4)?; - let section_count = u32::from_le_bytes(section_count_bytes.try_into().unwrap()); - println!("\nNumber of sections: {}", section_count); +#[derive(BinRead)] +struct OldTocEntry { + #[br(count = 4)] _magic: Vec, + segment_length: u32, + segment_size: u32, + #[br(count = 26)] _unk: Vec, + name_lenght: u8, + #[br(count = name_lenght)] name_bytes: Vec, +} +impl OldTocEntry { + fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} + +pub fn is_msd10_file(file: &File) -> bool { + let header = common::read_file(&file, 0, 6).expect("Failed to read from file."); + if header == b"MSDU10" { + true + } else { + false + } +} + +pub fn extract_msd10(mut file: &File, output_folder: &str) -> Result<(), Box> { + let header: FileHeader = file.read_le()?; + println!("\nNumber of sections: {}", header.section_count); let mut sections: Vec
= Vec::new(); - //parse sections - for _i in 0..section_count { - let index_bytes = common::read_exact(&mut file, 4)?; - let index = u32::from_le_bytes(index_bytes.try_into().unwrap()); - - let offset_bytes = common::read_exact(&mut file, 4)?; - let offset = u32::from_le_bytes(offset_bytes.try_into().unwrap()); - - let size_bytes = common::read_exact(&mut file, 4)?; - let size = u32::from_le_bytes(size_bytes.try_into().unwrap()); - - println!("Section {}: offset: {}, size: {}", index, offset, size); - sections.push(Section { index, offset, size , name: "".to_string() }); + for _i in 0..header.section_count { + let section: SectionEntry = file.read_le()?; + println!("Section {}: offset: {}, size: {}", section.index, section.offset, section.size); + sections.push(Section {index: section.index, offset: section.offset, size: section.size, name: "".to_owned()}); } let _0 = common::read_exact(&mut file, 4)?; //0000 - let header_count_bytes = common::read_exact(&mut file, 4)?; let header_count = u32::from_le_bytes(header_count_bytes.try_into().unwrap()); println!("\nNumber of headers: {}", header_count); - let mut headers: Vec
= Vec::new(); + let mut headers: Vec = Vec::new(); - //parse headers for i in 0..header_count { - let offset_bytes = common::read_exact(&mut file, 4)?; - let offset = u32::from_le_bytes(offset_bytes.try_into().unwrap()); - - let size_bytes = common::read_exact(&mut file, 4)?; - let size = u32::from_le_bytes(size_bytes.try_into().unwrap()); - - let name_length_byte = common::read_exact(&mut file, 1)?; - let name_length = u8::from_le_bytes(name_length_byte.try_into().unwrap()); - - let name_bytes = common::read_exact(&mut file, name_length as usize)?; - let name = String::from_utf8(name_bytes)?; - - println!("Header {}: {}, offset: {}, size: {}", i + 1, name, offset, size); - - headers.push(Section { index: 0, offset, size , name }); + let header: HeaderEntry = file.read_le()?; + println!("Header {}: {}, offset: {}, size: {}", i + 1, header.name(), header.offset, header.size); + headers.push(header); } //use first header - let firmware_name = &headers[0].name; + let firmware_name = &headers[0].name(); println!("\nFirmware name: {}", firmware_name); let mut passphrase: Option<&str> = None; @@ -112,32 +141,19 @@ pub fn extract_msd10(mut file: &File, output_folder: &str) -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box, + #[br(count = 12)] _unk: Vec, + section_count: u32 +} + +#[derive(BinRead)] +struct SectionEntry { + index: u32, + offset: u64, + size: u64, +} + +#[derive(BinRead)] +struct HeaderEntry { + offset: u64, + size: u32, + _name_length: u8, + #[br(count = _name_length)] name_bytes: Vec, +} +impl HeaderEntry { + fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} + +struct Section { + index: u32, + offset: u64, + size: u64, +} + +#[derive(BinRead)] +struct TocEntry { + #[br(count = 74)] _unk1: Vec, + _name_length: u8, + #[br(count = _name_length)] name_bytes: Vec, + #[br(count = 39)] _unk2: Vec, + #[br(count = 8)] salt: Vec, + #[br(count = 267)] _unk3: Vec, +} +impl TocEntry { + fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} + pub fn is_msd11_file(file: &File) -> bool { let header = common::read_file(&file, 0, 6).expect("Failed to read from file."); if header == b"MSDU11" { @@ -16,67 +64,32 @@ pub fn is_msd11_file(file: &File) -> bool { } } -struct Section { - index: u32, - offset: u64, - size: u64, - name: String, -} - pub fn extract_msd11(mut file: &File, output_folder: &str) -> Result<(), Box> { - - let _magic = common::read_exact(&mut file, 6)?; //MSDU11 magic - - let _ = common::read_exact(&mut file, 12)?; - - let section_count_bytes = common::read_exact(&mut file, 4)?; - let section_count = u32::from_le_bytes(section_count_bytes.try_into().unwrap()); - println!("\nNumber of sections: {}", section_count); + let header: FileHeader = file.read_le()?; + println!("\nNumber of sections: {}", header.section_count); let mut sections: Vec
= Vec::new(); - //parse sections - for _i in 0..section_count { - let index_bytes = common::read_exact(&mut file, 4)?; - let index = u32::from_le_bytes(index_bytes.try_into().unwrap()); - - let offset_bytes = common::read_exact(&mut file, 8)?; - let offset = u64::from_le_bytes(offset_bytes.try_into().unwrap()); - - let size_bytes = common::read_exact(&mut file, 8)?; - let size = u64::from_le_bytes(size_bytes.try_into().unwrap()); - - println!("Section {}: offset: {}, size: {}", index, offset, size); - sections.push(Section { index, offset, size , name: "".to_string() }); + for _i in 0..header.section_count { + let section: SectionEntry = file.read_le()?; + println!("Section {}: offset: {}, size: {}", section.index, section.offset, section.size); + sections.push(Section {index: section.index, offset: section.offset, size: section.size}); } let header_count_bytes = common::read_exact(&mut file, 4)?; let header_count = u32::from_le_bytes(header_count_bytes.try_into().unwrap()); println!("\nNumber of headers: {}", header_count); - let mut headers: Vec
= Vec::new(); + let mut headers: Vec = Vec::new(); - //parse headers for i in 0..header_count { - let offset_bytes = common::read_exact(&mut file, 8)?; - let offset = u64::from_le_bytes(offset_bytes.try_into().unwrap()); - - let size_bytes = common::read_exact(&mut file, 4)?; - let size = u32::from_le_bytes(size_bytes.try_into().unwrap()); - - let name_length_byte = common::read_exact(&mut file, 1)?; - let name_length = u8::from_le_bytes(name_length_byte.try_into().unwrap()); - - let name_bytes = common::read_exact(&mut file, name_length as usize)?; - let name = String::from_utf8(name_bytes)?; - - println!("Header {}: {}, offset: {}, size: {}", i + 1, name, offset, size); - - headers.push(Section { index: 0, offset, size: size as u64 , name }); + let header: HeaderEntry = file.read_le()?; + println!("Header {}: {}, offset: {}, size: {}", i + 1, header.name(), header.offset, header.size); + headers.push(header); } //use first header - let firmware_name = &headers[0].name; + let firmware_name = &headers[0].name(); println!("\nFirmware name: {}", firmware_name); let mut passphrase: Option<&str> = None; @@ -101,38 +114,25 @@ pub fn extract_msd11(mut file: &File, output_folder: &str) -> Result<(), Box Result<(), Box