mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
improvements to roku and fix output folder issue in sony_bdp
This commit is contained in:
+84
-34
@@ -7,43 +7,93 @@ pub static FILE_KEY: [u8; 16] = [
|
||||
|
||||
pub static FILE_IV: [u8; 16] = [0x00; 16];
|
||||
|
||||
#[derive(BinRead)]
|
||||
pub struct ImageHeader {
|
||||
_empty: [u8; 8],
|
||||
_magic_bytes: [u8; 8], //imgARMcC
|
||||
_target_bytes: [u8; 4],
|
||||
_platform_id: [u8; 4],
|
||||
pub image_type: u32,
|
||||
pub size1: u32,
|
||||
_size2: u32,
|
||||
pub data_start_offset: u32,
|
||||
_data_link_address: u32,
|
||||
_data_entry_point_offset: u32,
|
||||
pub flags: u32,
|
||||
_timestamp: u32,
|
||||
_build_host: [u8; 4],
|
||||
_unk: [u8; 4],
|
||||
_rest_of_header: [u8; 192],
|
||||
// u-boot-2011.06/include/aimage.h
|
||||
// (C) Copyright 2004-2008 Andre McCurdy, NXP Semiconductors
|
||||
|
||||
#[derive(Debug, BinRead)]
|
||||
pub struct AImageHeader {
|
||||
_vector: u32, // reserved for a branch instruction (if data_start_offset and data_entry_point_offset are 0)
|
||||
_vector2: u32, // reserved for a branch instruction branch delay slot
|
||||
_magic: u32, // 0x41676d69
|
||||
_magic2: u32, // 0x43634d52
|
||||
_release_id: u32, // toplevel build / release version
|
||||
_platform_id: u32, // target platform information
|
||||
pub image_type: u32, // image type
|
||||
pub lenght: u32, // length of entire image (header + data + trailing padding)
|
||||
_data_lenght: u32, // length of image data (ie from data_start_offset to start of trailing padding)
|
||||
pub data_start_offset: u32, // 0 if header is part of data, sizeof(aimage_v1_header_t) if header is prepended to data
|
||||
_data_link_address: u32, // for non-pic executable images, where should the image placed in memory in order to execute
|
||||
_data_entry_point_offset: u32, // 0 if execution entry point is at the beginning of image data
|
||||
pub flags: u32, // image flags
|
||||
_build_time: u32, // if non-zero, gives time when image was created (seconds since 1970)
|
||||
_build_host_offset: u32, // if non-zero, offset of a string in the image data giving build host information
|
||||
_signature: [u8; 128], // 32 32bit words == 1024 bit RSA signature
|
||||
_hash: [u8; 20], // raw sha1 hash (fallback if not checking signature)
|
||||
_usd: u32, // "un-signed data" (treated as 0 during hash and signature verification, regardless of actual value)
|
||||
_reserved: [u8; 28], // image type specific params etc (number tweaked to keep header size == 256 bytes)
|
||||
/*
|
||||
Note: The final 16 bytes of the header are used to form the
|
||||
IV for aimage images which are encrypted with AES (ie if
|
||||
IMG_FLAG_ENC RYPTED_V1 flag is set).
|
||||
From a security standpoint, the IV does _not_ have to be
|
||||
secret in any way, but it _should_ be unique for every
|
||||
image which is encrypted with a given AES key.
|
||||
*/
|
||||
_iv: [u8; 16], // space reserved for random data or timestamp to ensure IV is unique for every image which is signed
|
||||
}
|
||||
impl ImageHeader {
|
||||
pub fn is_encrypted(&self) -> bool {
|
||||
self.flags == 0x80
|
||||
impl AImageHeader {
|
||||
//pub fn release_id_str(&self) -> String {
|
||||
// let release_id_major = ((self.release_id) >> 21) & 0x3FF;
|
||||
// let release_id_minor = ((self.release_id) >> 15) & 0x3F;
|
||||
// let release_id_build = ((self.release_id) >> 1) & 0x3FFF;
|
||||
// return format!("{}.{}-{}", release_id_major, release_id_minor, release_id_build)
|
||||
//}
|
||||
|
||||
pub fn image_type_str(&self) -> &str {
|
||||
match self.image_type {
|
||||
0x00 => "invalid",
|
||||
0x01 => "debug_message",
|
||||
0x02 => "bloader",
|
||||
0x03 => "slaveloader", // [O]
|
||||
0x04 => "env",
|
||||
0x05 => "rbf",
|
||||
0x06 => "bootdata", // [O] ROKUBOOT_TYPE_PKG
|
||||
0x07 => "cexapp",
|
||||
0x08 => "slaveapp",
|
||||
0x09 => "zimage",
|
||||
0x0A => "initfs_cramfs", // [O] cramfs image
|
||||
0x0B => "initfs_zext2",
|
||||
0x0C => "appfs_ext2",
|
||||
0x0D => "appfs_cramfs", // [O] custom_pkg image
|
||||
0x0E => "firmware_blob", // [O] ROKUBOOT_TYPE_UBOOT //main u-boot
|
||||
0x0F => "bootcount",
|
||||
0x10 => "bootselection",
|
||||
0x11 => "gnfs_ext2",
|
||||
0x12 => "eth0mac",
|
||||
0x13 => "bloader_testmode",
|
||||
0x14 => "bloader_dfu",
|
||||
0x15 => "splashscreen",
|
||||
0x16 => "custom_pkg_token", // [O]
|
||||
0x17 => "initrd",
|
||||
0x18 => "uimage", // [O] ROKUBOOT_TYPE_KERNEL // linux
|
||||
0x19 => "uboot_mipsel",
|
||||
0x1A => "uboot_mipseb",
|
||||
0x1B => "initfs_squashfs",
|
||||
0x101 => "cramfs_auth", // [O] merkle tree for cramfs
|
||||
_ => "UNKNOWN",
|
||||
}
|
||||
}
|
||||
pub fn type_string(&self) -> &str {
|
||||
if self.image_type == 0xa {
|
||||
return "initfs"
|
||||
} else if self.image_type == 0x18 {
|
||||
return "uImage"
|
||||
} else if self.image_type == 0x3 {
|
||||
return "loader"
|
||||
} else if self.image_type == 0xd {
|
||||
return "app_cramfs"
|
||||
} else if self.image_type == 0x6 {
|
||||
return "Customization Package"
|
||||
} else if self.image_type == 0xe {
|
||||
return "firmware_blob"
|
||||
|
||||
pub fn encmode_str(&self) -> &str {
|
||||
let encmode_flags = self.flags & (7 << 6);
|
||||
if (encmode_flags & (1 << 6)) != 0 { // image data is encrypted before signing: CBC mode, entire image in one pass
|
||||
return "cbc_onepass"
|
||||
} else if (encmode_flags & (2 << 6)) != 0 { // image data is encrypted before signing: CBC mode, 4k byte blocks, block group iv = (iv + (first block's block offset))
|
||||
return "cbc_4kblocks"
|
||||
} else if (encmode_flags & (3 << 6)) != 0 { // image data is encrypted before signing: CTR mode, block iv = (iv + (block offset))
|
||||
return "ctr"
|
||||
} else {
|
||||
return "unknown"
|
||||
return "none/unknown"
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-10
@@ -4,7 +4,7 @@ use crate::AppContext;
|
||||
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::path::Path;
|
||||
use std::io::{Write, Seek, Read, Cursor};
|
||||
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
||||
use tar::Archive;
|
||||
use binrw::BinReaderExt;
|
||||
|
||||
@@ -38,6 +38,7 @@ pub fn extract_roku(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
|
||||
|
||||
for entry_result in tar_archive.entries_with_seek()? {
|
||||
let mut entry = entry_result?;
|
||||
|
||||
let path = entry.path()?.to_path_buf();
|
||||
|
||||
if path == std::path::Path::new("manifest") {
|
||||
@@ -58,26 +59,29 @@ pub fn extract_roku(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
|
||||
let mut i = 1;
|
||||
|
||||
while image_reader.stream_position()? < size as u64 {
|
||||
let image: ImageHeader = image_reader.read_le()?;
|
||||
println!("\nImage {} - Type: {:x}({}), Size: {}, Flags: {:x}{}, Data offset: {}",
|
||||
i ,image.image_type, image.type_string(), image.size1, image.flags, if image.is_encrypted(){"(Encrypted)"}else{" "}, image.data_start_offset);
|
||||
let image: AImageHeader = image_reader.read_le()?;
|
||||
println!(" #{} - Type: {}(0x{:x}), Lenght: {}, encmode: {}",
|
||||
i, image.image_type_str(), image.image_type, image.lenght, image.encmode_str());
|
||||
//println!("{:?}", image);
|
||||
|
||||
let data =
|
||||
if image.data_start_offset == 0 {
|
||||
common::read_exact(&mut image_reader, image.size1 as usize - 256)?
|
||||
if image.data_start_offset == 0 { // "0 if header is part of data"
|
||||
image_reader.seek(SeekFrom::Current(-256))?; //rewind header
|
||||
common::read_exact(&mut image_reader, image.lenght as usize)?
|
||||
|
||||
} else {
|
||||
let _extra_data = common::read_exact(&mut image_reader, image.data_start_offset as usize - 256)?;
|
||||
common::read_exact(&mut image_reader, image.size1 as usize - image.data_start_offset as usize)?
|
||||
let _skip_data = common::read_exact(&mut image_reader, image.data_start_offset as usize - 256)?;
|
||||
common::read_exact(&mut image_reader, image.lenght as usize - image.data_start_offset as usize)?
|
||||
};
|
||||
|
||||
let folder_path = Path::new(&app_ctx.output_dir).join(&path);
|
||||
let output_path = Path::new(&folder_path).join(format!("{}_{}.bin", i, image.type_string()));
|
||||
let output_path = Path::new(&folder_path).join(format!("{}_{}.bin", i, image.image_type_str()));
|
||||
|
||||
fs::create_dir_all(&folder_path)?;
|
||||
let mut out_file = OpenOptions::new().write(true).create(true).open(output_path)?;
|
||||
out_file.write_all(&data)?;
|
||||
|
||||
println!("- Saved file!");
|
||||
println!(" - Saved file!\n");
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,10 @@ pub fn extract_sony_bdp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(),
|
||||
|
||||
let mut last_file_path: Option<PathBuf> = None;
|
||||
let mut first_entry_offset = 0;
|
||||
let mut i = 1;
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if (i != 1) && (hdr_reader.position() >= first_entry_offset) {
|
||||
|
||||
if (i != 0) && (hdr_reader.position() >= first_entry_offset) {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -48,14 +49,14 @@ pub fn extract_sony_bdp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(),
|
||||
}
|
||||
|
||||
println!("\n#{} - Offset: {}, Size: {}", i, entry.offset, entry.size);
|
||||
if i == 1 {
|
||||
if i == 0 {
|
||||
first_entry_offset = entry.offset as u64;
|
||||
}
|
||||
|
||||
let obf_data = common::read_file(&file, entry.offset as u64, entry.size as usize)?;
|
||||
let data = hex_substitute(&obf_data);
|
||||
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", i));
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", i+1));
|
||||
last_file_path = Some(output_path.clone());
|
||||
|
||||
fs::create_dir_all(&app_ctx.output_dir)?;
|
||||
@@ -71,7 +72,7 @@ pub fn extract_sony_bdp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(),
|
||||
println!("\nChecking if it's also MTK BDP...");
|
||||
|
||||
let last_file = File::open(last_file_path.unwrap())?;
|
||||
let mtk_extraction_path = app_ctx.output_dir.join(format!("{}", i + 1));
|
||||
let mtk_extraction_path = app_ctx.output_dir.join(format!("{}", i));
|
||||
|
||||
//this is getting stupid...
|
||||
let ctx: AppContext = AppContext { input: InputTarget::File(last_file), output_dir: mtk_extraction_path, options: app_ctx.options.clone() };
|
||||
|
||||
Reference in New Issue
Block a user