mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
add dump_dec_hdrs option + fix header offset in old_mtk_pkg
This commit is contained in:
@@ -15,6 +15,8 @@ Arguments:
|
|||||||
If an output folder is not provided, extracted files will be saved in folder `_<INPUT_TARGET>`.
|
If an output folder is not provided, extracted files will be saved in folder `_<INPUT_TARGET>`.
|
||||||
Options:
|
Options:
|
||||||
`-o, --options <OPTIONS>` - Format specific or global(for all formats that implement it) options, see the list below for format specific options. You can use this multiple times to activate multiple options.
|
`-o, --options <OPTIONS>` - Format specific or global(for all formats that implement it) options, see the list below for format specific options. You can use this multiple times to activate multiple options.
|
||||||
|
## Global options
|
||||||
|
`dump_dec_hdrs` - For formats with an encrypted header - dump the decrypted header(s).
|
||||||
|
|
||||||
# Supported formats
|
# Supported formats
|
||||||
## Amlogic burning image
|
## Amlogic burning image
|
||||||
@@ -40,11 +42,15 @@ Options:
|
|||||||
**Used in:** LG TVs since ~2010
|
**Used in:** LG TVs since ~2010
|
||||||
**Notes:** **Depends on keys** - see keys.rs (most common keys should be included)
|
**Notes:** **Depends on keys** - see keys.rs (most common keys should be included)
|
||||||
**Thanks to:** https://github.com/openlgtv/epk2extract
|
**Thanks to:** https://github.com/openlgtv/epk2extract
|
||||||
|
**Options:**
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## EPK v3
|
## EPK v3
|
||||||
**Used in:** LG webOS-based TVs
|
**Used in:** LG webOS-based TVs
|
||||||
**Notes:** **Depends on keys** - see keys.rs
|
**Notes:** **Depends on keys** - see keys.rs
|
||||||
**Thanks to:** https://github.com/openlgtv/epk2extract
|
**Thanks to:** https://github.com/openlgtv/epk2extract
|
||||||
|
**Options:**
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## Funai BDP
|
## Funai BDP
|
||||||
**Used in:** Funai & Funai-made Philips Blu-Ray player/HTS (USA market)
|
**Used in:** Funai & Funai-made Philips Blu-Ray player/HTS (USA market)
|
||||||
@@ -69,6 +75,7 @@ Options:
|
|||||||
**Options:**
|
**Options:**
|
||||||
`msd10:save_cmac` - Save CMAC data for files that is skipped by default.
|
`msd10:save_cmac` - Save CMAC data for files that is skipped by default.
|
||||||
`msd:print_ouith` - Prints the entire parsed OUITH header.
|
`msd:print_ouith` - Prints the entire parsed OUITH header.
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## MSD 1.1
|
## MSD 1.1
|
||||||
**Used in:** Samsung TVs 2016+
|
**Used in:** Samsung TVs 2016+
|
||||||
@@ -76,10 +83,13 @@ Options:
|
|||||||
**Thanks to:** https://github.com/bugficks/msddecrypt
|
**Thanks to:** https://github.com/bugficks/msddecrypt
|
||||||
**Options:**
|
**Options:**
|
||||||
`msd:print_ouith` - Prints the entire parsed OUITH header.
|
`msd:print_ouith` - Prints the entire parsed OUITH header.
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## MStar upgrade bin
|
## MStar upgrade bin
|
||||||
**Used in:** Many MStar-based TVs (Hisense, Toshiba...)
|
**Used in:** Many MStar-based TVs (Hisense, Toshiba...)
|
||||||
**Notes:** All files should be supported, includes lzop, lz4, lzma, sparse_write support
|
**Notes:** All files should be supported, includes lzop, lz4, lzma, sparse_write support
|
||||||
|
**Options:**
|
||||||
|
※ Support `dump_dec_hdrs` option (will save the script)
|
||||||
|
|
||||||
## MediaTek BDP
|
## MediaTek BDP
|
||||||
**Used in:** Many MediaTek-based Blu-Ray players (LG, Samsung, Philips, Panasonic...)
|
**Used in:** Many MediaTek-based Blu-Ray players (LG, Samsung, Philips, Panasonic...)
|
||||||
@@ -90,12 +100,14 @@ Options:
|
|||||||
**Notes:** **Depends on keys** - see keys.rs (Keys for Philips and Sony included)
|
**Notes:** **Depends on keys** - see keys.rs (Keys for Philips and Sony included)
|
||||||
**Options:**
|
**Options:**
|
||||||
`mtk_pkg:no_del_comp` - Don't delete LZHS compressed partition file after decompressing.
|
`mtk_pkg:no_del_comp` - Don't delete LZHS compressed partition file after decompressing.
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## MediaTek PKG (Old)
|
## MediaTek PKG (Old)
|
||||||
**Used in:** Older MediaTek-based TVs (Philips, Sony, Hisense...)
|
**Used in:** Older MediaTek-based TVs (Philips, Sony, Hisense...)
|
||||||
**Notes:** All files should be supported, decryption + decompression
|
**Notes:** All files should be supported, decryption + decompression
|
||||||
**Options:**
|
**Options:**
|
||||||
`mtk_pkg:no_del_comp` - Don't delete LZHS compressed partition file after decompressing.
|
`mtk_pkg:no_del_comp` - Don't delete LZHS compressed partition file after decompressing.
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## MediaTek PKG
|
## MediaTek PKG
|
||||||
**Used in:** MediaTek-based TVs (Sony, Philips, Panasonic, Sharp...)
|
**Used in:** MediaTek-based TVs (Sony, Philips, Panasonic, Sharp...)
|
||||||
@@ -103,6 +115,7 @@ Options:
|
|||||||
**Thanks to:** https://github.com/openlgtv/epk2extract
|
**Thanks to:** https://github.com/openlgtv/epk2extract
|
||||||
**Options:**
|
**Options:**
|
||||||
`mtk_pkg:no_del_comp` - Don't delete LZHS compressed partition file after decompressing.
|
`mtk_pkg:no_del_comp` - Don't delete LZHS compressed partition file after decompressing.
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## Novatek PKG (NFWB)
|
## Novatek PKG (NFWB)
|
||||||
**Used in:** Some older Novatek-based TVs (LG, Philips)
|
**Used in:** Some older Novatek-based TVs (LG, Philips)
|
||||||
@@ -117,6 +130,7 @@ Options:
|
|||||||
**Notes:** **Depends on keys** - see keys.rs (Included keys should work for 99% of players released in and before 2014, and some released in 2018), Note that there is currently an issue with MAIN in some very ancient files not extracting correctly.
|
**Notes:** **Depends on keys** - see keys.rs (Included keys should work for 99% of players released in and before 2014, and some released in 2018), Note that there is currently an issue with MAIN in some very ancient files not extracting correctly.
|
||||||
**Options:**
|
**Options:**
|
||||||
`pana_dvd:split_main` - Automatically split the MAIN module into seperate partitions.
|
`pana_dvd:split_main` - Automatically split the MAIN module into seperate partitions.
|
||||||
|
※ Support `dump_dec_hdrs` option
|
||||||
|
|
||||||
## Philips UPG (Autorun.upg, 2SWU3TXV)
|
## Philips UPG (Autorun.upg, 2SWU3TXV)
|
||||||
**Used in:** Philips pre-TPVision TVs 200?-2013
|
**Used in:** Philips pre-TPVision TVs 200?-2013
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::io::{Write, Seek, SeekFrom, Cursor};
|
|||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use crate::formats::epk::{decrypt_aes_ecb_auto, find_key};
|
use crate::formats::epk::{decrypt_aes_ecb_auto, find_key};
|
||||||
use include::*;
|
use include::*;
|
||||||
@@ -45,6 +46,8 @@ pub fn extract_epk2(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
|
|||||||
println!("Found valid key: {}", key_name);
|
println!("Found valid key: {}", key_name);
|
||||||
matching_key = Some(key_bytes);
|
matching_key = Some(key_bytes);
|
||||||
header = decrypt_aes_ecb_auto(matching_key.as_ref().unwrap(), &stored_header)?;
|
header = decrypt_aes_ecb_auto(matching_key.as_ref().unwrap(), &stored_header)?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return Err("No valid key found!".into());
|
return Err("No valid key found!".into());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::io::{Write, Cursor};
|
|||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use crate::formats::epk::{decrypt_aes_ecb_auto, find_key};
|
use crate::formats::epk::{decrypt_aes_ecb_auto, find_key};
|
||||||
use include::*;
|
use include::*;
|
||||||
@@ -33,6 +34,7 @@ pub fn extract_epk3(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
|
|||||||
matching_key = Some(key_bytes);
|
matching_key = Some(key_bytes);
|
||||||
_header_signature = &stored_header[..128];
|
_header_signature = &stored_header[..128];
|
||||||
header = decrypt_aes_ecb_auto(matching_key.as_ref().unwrap(), &stored_header[128..])?;
|
header = decrypt_aes_ecb_auto(matching_key.as_ref().unwrap(), &stored_header[128..])?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||||
|
|
||||||
//try for new format epk3 (new type 256 byte signature)
|
//try for new format epk3 (new type 256 byte signature)
|
||||||
} else if let Some((key_name, key_bytes)) = find_key(&keys::EPK, &stored_header[256..], b"EPK3")? {
|
} else if let Some((key_name, key_bytes)) = find_key(&keys::EPK, &stored_header[256..], b"EPK3")? {
|
||||||
@@ -40,6 +42,7 @@ pub fn extract_epk3(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
|
|||||||
matching_key = Some(key_bytes);
|
matching_key = Some(key_bytes);
|
||||||
_header_signature = &stored_header[..256];
|
_header_signature = &stored_header[..256];
|
||||||
header = decrypt_aes_ecb_auto(matching_key.as_ref().unwrap(), &stored_header[256..])?;
|
header = decrypt_aes_ecb_auto(matching_key.as_ref().unwrap(), &stored_header[256..])?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||||
new_type = true;
|
new_type = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -72,6 +75,8 @@ pub fn extract_epk3(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<
|
|||||||
//PKG INFO
|
//PKG INFO
|
||||||
let pkg_info_encrypted = common::read_exact(&mut file, hdr.package_info_size as usize)?;
|
let pkg_info_encrypted = common::read_exact(&mut file, hdr.package_info_size as usize)?;
|
||||||
let pkg_info = decrypt_aes_ecb_auto(matching_key_bytes, &pkg_info_encrypted)?;
|
let pkg_info = decrypt_aes_ecb_auto(matching_key_bytes, &pkg_info_encrypted)?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &pkg_info, "pkg_info")?;
|
||||||
|
|
||||||
let mut pkg_info_reader = Cursor::new(pkg_info);
|
let mut pkg_info_reader = Cursor::new(pkg_info);
|
||||||
let pkg_info_hdr: PkgInfoHeader = pkg_info_reader.read_le()?;
|
let pkg_info_hdr: PkgInfoHeader = pkg_info_reader.read_le()?;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::io::{Write, Seek, SeekFrom};
|
|||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use crate::formats::msd::{decrypt_aes_salted_old, decrypt_aes_salted_tizen, decrypt_aes_tizen};
|
use crate::formats::msd::{decrypt_aes_salted_old, decrypt_aes_salted_tizen, decrypt_aes_tizen};
|
||||||
use crate::formats::msd::msd_ouith_parser_old::{parse_ouith_blob};
|
use crate::formats::msd::msd_ouith_parser_old::{parse_ouith_blob};
|
||||||
@@ -82,6 +83,8 @@ pub fn extract_msd10(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
|
|||||||
//parse TOC
|
//parse TOC
|
||||||
if firmware_type == "tizen" {
|
if firmware_type == "tizen" {
|
||||||
let toc = decrypt_aes_salted_tizen(&toc_data, &passphrase_bytes)?;
|
let toc = decrypt_aes_salted_tizen(&toc_data, &passphrase_bytes)?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &toc, "toc")?;
|
||||||
|
|
||||||
let (items, info) = parse_blob_1_8(&toc, print_ouith_tree)?;
|
let (items, info) = parse_blob_1_8(&toc, print_ouith_tree)?;
|
||||||
|
|
||||||
if let Some(info) = info {
|
if let Some(info) = info {
|
||||||
@@ -122,6 +125,8 @@ pub fn extract_msd10(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
|
|||||||
|
|
||||||
} else if firmware_type == "old" {
|
} else if firmware_type == "old" {
|
||||||
let toc = decrypt_aes_salted_old(&toc_data, &passphrase_bytes)?;
|
let toc = decrypt_aes_salted_old(&toc_data, &passphrase_bytes)?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &toc, "toc")?;
|
||||||
|
|
||||||
let (items, info) = parse_ouith_blob(&toc, print_ouith_tree)?;
|
let (items, info) = parse_ouith_blob(&toc, print_ouith_tree)?;
|
||||||
|
|
||||||
if let Some(info) = info {
|
if let Some(info) = info {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::io::Write;
|
|||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use crate::formats::msd::{decrypt_aes_salted_tizen, decrypt_aes_tizen};
|
use crate::formats::msd::{decrypt_aes_salted_tizen, decrypt_aes_tizen};
|
||||||
use crate::formats::msd::msd_ouith_parser_tizen_1_9::{parse_blob_1_9};
|
use crate::formats::msd::msd_ouith_parser_tizen_1_9::{parse_blob_1_9};
|
||||||
@@ -74,6 +75,8 @@ pub fn extract_msd11(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
|
|||||||
let toc_data = common::read_file(&file, toc_offset as u64, toc_size as usize)?;
|
let toc_data = common::read_file(&file, toc_offset as u64, toc_size as usize)?;
|
||||||
|
|
||||||
let toc = decrypt_aes_salted_tizen(&toc_data, &passphrase_bytes)?;
|
let toc = decrypt_aes_salted_tizen(&toc_data, &passphrase_bytes)?;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &toc, "toc")?;
|
||||||
|
|
||||||
let (items, info) = parse_blob_1_9(&toc, print_ouith_tree)?;
|
let (items, info) = parse_blob_1_9(&toc, print_ouith_tree)?;
|
||||||
|
|
||||||
if let Some(info) = info {
|
if let Some(info) = info {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use std::path::Path;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::utils::compression::{decompress_lzma, decompress_lz4};
|
use crate::utils::compression::{decompress_lzma, decompress_lz4};
|
||||||
use crate::utils::lzop::{unlzop_to_file};
|
use crate::utils::lzop::{unlzop_to_file};
|
||||||
use crate::utils::sparse::{unsparse_to_file};
|
use crate::utils::sparse::{unsparse_to_file};
|
||||||
@@ -50,6 +51,7 @@ pub fn extract_mstar(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box
|
|||||||
return Err("Failed to get script".into());
|
return Err("Failed to get script".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
opt_dump_dec_hdr(app_ctx, &script, "script")?;
|
||||||
|
|
||||||
let lines: Vec<&str> = script_string.lines().map(|l| l.trim()).collect();
|
let lines: Vec<&str> = script_string.lines().map(|l| l.trim()).collect();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use std::io::{Write, Cursor, Seek, SeekFrom};
|
|||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use lzhs::{decompress_lzhs_fs_file2file};
|
use lzhs::{decompress_lzhs_fs_file2file};
|
||||||
@@ -47,6 +48,8 @@ pub fn extract_mtk_pkg(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Bo
|
|||||||
|
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
let header = ctx.decrypted_header;
|
let header = ctx.decrypted_header;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||||
|
|
||||||
let mut hdr_reader = Cursor::new(header);
|
let mut hdr_reader = Cursor::new(header);
|
||||||
let hdr: Header = hdr_reader.read_le()?;
|
let hdr: Header = hdr_reader.read_le()?;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use std::io::{Write, Cursor, Seek, SeekFrom};
|
|||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use crate::formats::mtk_pkg::lzhs::{decompress_lzhs_fs_file2file};
|
use crate::formats::mtk_pkg::lzhs::{decompress_lzhs_fs_file2file};
|
||||||
@@ -55,6 +56,7 @@ pub fn extract_mtk_pkg_new(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<()
|
|||||||
let key_array = ctx.matching_key_key;
|
let key_array = ctx.matching_key_key;
|
||||||
let iv_array = ctx.matching_key_iv;
|
let iv_array = ctx.matching_key_iv;
|
||||||
let header = ctx.decrypted_header;
|
let header = ctx.decrypted_header;
|
||||||
|
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||||
|
|
||||||
let mut hdr_reader = Cursor::new(header);
|
let mut hdr_reader = Cursor::new(header);
|
||||||
let hdr: Header = hdr_reader.read_le()?;
|
let hdr: Header = hdr_reader.read_le()?;
|
||||||
|
|||||||
@@ -5,42 +5,50 @@ use crate::AppContext;
|
|||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::fs::{self, OpenOptions};
|
use std::fs::{self, OpenOptions};
|
||||||
use std::io::{Write, Cursor, Seek};
|
use std::io::{Cursor, Seek, SeekFrom, Write};
|
||||||
use binrw::BinReaderExt;
|
use binrw::BinReaderExt;
|
||||||
|
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::formats::mtk_pkg::lzhs::{decompress_lzhs_fs_file2file_old};
|
use crate::formats::mtk_pkg::lzhs::{decompress_lzhs_fs_file2file_old};
|
||||||
use crate::formats::mtk_pkg::include::{PartEntry, MTK_HEADER_MAGIC, MTK_META_MAGIC, MTK_META_PAD_MAGIC};
|
use crate::formats::mtk_pkg::include::{PartEntry, MTK_HEADER_MAGIC, MTK_META_MAGIC, MTK_META_PAD_MAGIC};
|
||||||
use mtk_crypto::{decrypt};
|
use mtk_crypto::{decrypt};
|
||||||
use include::*;
|
use include::*;
|
||||||
|
|
||||||
|
pub struct MtkPkgOldContext {
|
||||||
|
header_offset: u64,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_mtk_pkg_old_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
pub fn is_mtk_pkg_old_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
|
||||||
let mut file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
|
||||||
|
|
||||||
let encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
let encrypted_header = common::read_file(&file, 0, HEADER_SIZE)?;
|
||||||
let header = decrypt(&encrypted_header, KEY, Some(HEADER_XOR_MASK));
|
let header = decrypt(&encrypted_header, KEY, Some(HEADER_XOR_MASK));
|
||||||
if &header[4..12] == MTK_HEADER_MAGIC {
|
if &header[4..12] == MTK_HEADER_MAGIC {
|
||||||
Ok(Some(Box::new(())))
|
Ok(Some(Box::new(MtkPkgOldContext {header_offset: 0})))
|
||||||
} else if &header[68..76] == MTK_HEADER_MAGIC {
|
} else if &header[68..76] == MTK_HEADER_MAGIC {
|
||||||
//check for 64 byte additional header used in some Sony and Philips firmwares and skip it
|
//check for 64 byte additional header used in some Sony and Philips firmwares
|
||||||
file.seek(std::io::SeekFrom::Start(64))?;
|
Ok(Some(Box::new(MtkPkgOldContext {header_offset: 64})))
|
||||||
Ok(Some(Box::new(())))
|
|
||||||
} else if &header[132..140] == MTK_HEADER_MAGIC {
|
} else if &header[132..140] == MTK_HEADER_MAGIC {
|
||||||
//check for 128 byte additional header used in some Philips firmwares and skip it
|
//check for 128 byte additional header used in some Philips firmwares
|
||||||
file.seek(std::io::SeekFrom::Start(128))?;
|
Ok(Some(Box::new(MtkPkgOldContext {header_offset: 128})))
|
||||||
Ok(Some(Box::new(())))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_mtk_pkg_old(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mtk_pkg_old(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
|
||||||
|
let ctx = ctx.downcast::<MtkPkgOldContext>().expect("Missing context");
|
||||||
let no_del_comp = app_ctx.options.iter().any(|e| e == "mtk_pkg:no_del_comp");
|
let no_del_comp = app_ctx.options.iter().any(|e| e == "mtk_pkg:no_del_comp");
|
||||||
|
|
||||||
let file_size = file.metadata()?.len();
|
let file_size = file.metadata()?.len();
|
||||||
|
|
||||||
|
file.seek(SeekFrom::Start(ctx.header_offset))?;
|
||||||
let encrypted_header = common::read_exact(&mut file, HEADER_SIZE)?;
|
let encrypted_header = common::read_exact(&mut file, HEADER_SIZE)?;
|
||||||
let header = decrypt(&encrypted_header, KEY, Some(HEADER_XOR_MASK));
|
let header = decrypt(&encrypted_header, KEY, Some(HEADER_XOR_MASK));
|
||||||
|
opt_dump_dec_hdr(app_ctx, &header, "header")?;
|
||||||
|
|
||||||
let mut hdr_reader = Cursor::new(header);
|
let mut hdr_reader = Cursor::new(header);
|
||||||
let hdr: Header = hdr_reader.read_le()?;
|
let hdr: Header = hdr_reader.read_le()?;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use binrw::BinReaderExt;
|
|||||||
|
|
||||||
use crate::keys;
|
use crate::keys;
|
||||||
use crate::utils::common;
|
use crate::utils::common;
|
||||||
|
use crate::utils::global::opt_dump_dec_hdr;
|
||||||
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
||||||
use crate::utils::compression::{decompress_gzip_get_filename};
|
use crate::utils::compression::{decompress_gzip_get_filename};
|
||||||
use pana_dvd_crypto::{decrypt_data};
|
use pana_dvd_crypto::{decrypt_data};
|
||||||
@@ -114,7 +115,10 @@ fn extract_file(app_ctx: &AppContext, file_reader: &mut Cursor<Vec<u8>>, offset:
|
|||||||
file_reader.seek(SeekFrom::Start(offset + base_offset))?;
|
file_reader.seek(SeekFrom::Start(offset + base_offset))?;
|
||||||
|
|
||||||
let enc_header = common::read_exact(file_reader, MAX_HEADER_SIZE)?;
|
let enc_header = common::read_exact(file_reader, MAX_HEADER_SIZE)?;
|
||||||
let mut hdr_reader = Cursor::new(decrypt_data(&enc_header, &key));
|
let dec_header = decrypt_data(&enc_header, &key);
|
||||||
|
opt_dump_dec_hdr(app_ctx, &dec_header, "header")?;
|
||||||
|
|
||||||
|
let mut hdr_reader = Cursor::new(dec_header);
|
||||||
let mut modules: Vec<ModuleEntry> = Vec::new();
|
let mut modules: Vec<ModuleEntry> = Vec::new();
|
||||||
let split_main = app_ctx.options.iter().any(|e| e == "pana_dvd:split_main");
|
let split_main = app_ctx.options.iter().any(|e| e == "pana_dvd:split_main");
|
||||||
|
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ pub mod aes;
|
|||||||
pub mod lzop;
|
pub mod lzop;
|
||||||
pub mod sparse;
|
pub mod sparse;
|
||||||
pub mod compression;
|
pub mod compression;
|
||||||
|
pub mod global;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
use std::{fs::{self, OpenOptions}, io::Write, path::Path};
|
||||||
|
|
||||||
|
use crate::AppContext;
|
||||||
|
|
||||||
|
pub fn opt_dump_dec_hdr(app_ctx: &AppContext, data: &[u8], name: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if !app_ctx.options.iter().any(|e| e == "dump_dec_hdrs") {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = format!("_{}.bin", name);
|
||||||
|
let output_path = Path::new(&app_ctx.output_dir).join(&filename);
|
||||||
|
fs::create_dir_all(&app_ctx.output_dir)?;
|
||||||
|
|
||||||
|
let mut out_file = OpenOptions::new().write(true).create(true).open(output_path)?;
|
||||||
|
out_file.write_all(&data)?;
|
||||||
|
|
||||||
|
println!("[i] Saved {} to {}", name, filename);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user