mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
prepare for encrypted hdr epk2/epk3
This commit is contained in:
@@ -8,3 +8,4 @@ pub mod msd10;
|
|||||||
pub mod msd11;
|
pub mod msd11;
|
||||||
pub mod sddl_sec;
|
pub mod sddl_sec;
|
||||||
pub mod epk2;
|
pub mod epk2;
|
||||||
|
pub mod epk;
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use crate::common;
|
||||||
|
use crate::formats;
|
||||||
|
|
||||||
|
pub fn is_epk_file(file: &File) -> bool {
|
||||||
|
let versions = common::read_file(&file, 1712, 36).expect("Failed to read from file.");
|
||||||
|
|
||||||
|
if check_epk_version(&versions).is_some() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_epk_version(versions: &[u8]) -> Option<String> {
|
||||||
|
let epk2_pattern = "____XXXX.XXXX.XXXX__XX.XX.XXX_______";
|
||||||
|
let epk3_pattern = "____X.X.X___________X.X.X___________";
|
||||||
|
|
||||||
|
if match_with_pattern(&versions, epk2_pattern) {
|
||||||
|
Some("epk2".to_string())
|
||||||
|
} else if match_with_pattern(&versions, epk3_pattern) {
|
||||||
|
Some("epk3".to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn match_with_pattern(data: &[u8], pattern: &str) -> bool {
|
||||||
|
for (&b, p) in data.iter().zip(pattern.bytes()) {
|
||||||
|
match p {
|
||||||
|
b'_' if b != 0x00 => return false,
|
||||||
|
b'X' if !b.is_ascii_digit() => return false,
|
||||||
|
b'.' if b != b'.' => return false,
|
||||||
|
_ if p != b'_' && p != b'X' && p != b'.' => return false,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_epk(file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
|
let versions = common::read_file(&file, 1712, 36)?;
|
||||||
|
let epk_version = check_epk_version(&versions);
|
||||||
|
|
||||||
|
if epk_version == Some("epk2".to_string()) {
|
||||||
|
println!("EPK2 detected!\n");
|
||||||
|
formats::epk2::extract_epk2(file, output_folder)?;
|
||||||
|
} else if epk_version == Some("epk3".to_string()) {
|
||||||
|
println!("EPK3 detected! Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+19
-2
@@ -38,7 +38,17 @@ fn decrypt_aes128_ecb(key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Box<dyn
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_epk2(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_epk2(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _epak = common::read_exact(&mut file, 4)?; // epak magic
|
|
||||||
|
file.seek(SeekFrom::Start(128))?;
|
||||||
|
|
||||||
|
//check if header is encrypted
|
||||||
|
let epak = common::read_exact(&mut file, 4)?; // epak magic
|
||||||
|
if epak == b"epak" {
|
||||||
|
println!("Header is not encrypted.");
|
||||||
|
} else {
|
||||||
|
println!("Header is encrypted. Not supported yet");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let file_size_bytes = common::read_exact(&mut file, 4)?;
|
let file_size_bytes = common::read_exact(&mut file, 4)?;
|
||||||
let file_size = u32::from_le_bytes(file_size_bytes.try_into().unwrap());
|
let file_size = u32::from_le_bytes(file_size_bytes.try_into().unwrap());
|
||||||
@@ -79,7 +89,14 @@ pub fn extract_epk2(mut file: &File, output_folder: &str) -> Result<(), Box<dyn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Saturn7/BCM3556
|
// Saturn7/BCM3556
|
||||||
let key = "2F2E2D2C2B2A29281716151413121110";
|
//let key = "2F2E2D2C2B2A29281716151413121110";
|
||||||
|
|
||||||
|
// new BCM35230
|
||||||
|
let key = "6856A0482475A8B41728A35474810203";
|
||||||
|
|
||||||
|
//mtk5369 - Mediatek GP4 - HE_DTV_GP4I_AFAAATAA
|
||||||
|
//let key = "7184C9C428D03C445188234D5A827196";
|
||||||
|
|
||||||
let key_bytes = hex::decode(key)?;
|
let key_bytes = hex::decode(key)?;
|
||||||
|
|
||||||
let mut signature_count = 0;
|
let mut signature_count = 0;
|
||||||
|
|||||||
@@ -71,10 +71,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("EPK1 file detected!");
|
println!("EPK1 file detected!");
|
||||||
formats::epk1::extract_epk1(&file, &output_path)?;
|
formats::epk1::extract_epk1(&file, &output_path)?;
|
||||||
}
|
}
|
||||||
|
//epk2 with unencrypted header
|
||||||
else if formats::epk2::is_epk2_file(&file) {
|
else if formats::epk2::is_epk2_file(&file) {
|
||||||
println!("EPK2 file detected!");
|
println!("EPK2 file detected!");
|
||||||
formats::epk2::extract_epk2(&file, &output_path)?;
|
formats::epk2::extract_epk2(&file, &output_path)?;
|
||||||
}
|
}
|
||||||
|
//epk with encrypted header - it can be epk2 or epk3 so we need to check
|
||||||
|
else if formats::epk::is_epk_file(&file) {
|
||||||
|
println!("EPK file detected!");
|
||||||
|
formats::epk::extract_epk(&file, &output_path)?;
|
||||||
|
}
|
||||||
else if formats::pfl_upg::is_pfl_upg_file(&file) {
|
else if formats::pfl_upg::is_pfl_upg_file(&file) {
|
||||||
println!("PFL UPG file detected!");
|
println!("PFL UPG file detected!");
|
||||||
formats::pfl_upg::extract_pfl_upg(&file, &output_path)?;
|
formats::pfl_upg::extract_pfl_upg(&file, &output_path)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user