mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-16 05:04:22 +02:00
pfl_upg: handle folders, fix incorrect decryption bug
This commit is contained in:
+21
-15
@@ -2,7 +2,7 @@ use std::fs::{File};
|
|||||||
use rsa::{RsaPublicKey, BigUint};
|
use rsa::{RsaPublicKey, BigUint};
|
||||||
use hex::decode;
|
use hex::decode;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::io::{Cursor, Write};
|
use std::io::{Read, Cursor, Write};
|
||||||
use std::fs::{self, OpenOptions};
|
use std::fs::{self, OpenOptions};
|
||||||
|
|
||||||
use aes::Aes256;
|
use aes::Aes256;
|
||||||
@@ -35,7 +35,7 @@ struct FileHeader {
|
|||||||
real_size: u32,
|
real_size: u32,
|
||||||
stored_size: u32,
|
stored_size: u32,
|
||||||
_header_size: u32,
|
_header_size: u32,
|
||||||
_attributes: u32,
|
#[br(count = 4)] attributes: Vec<u8>,
|
||||||
}
|
}
|
||||||
impl FileHeader {
|
impl FileHeader {
|
||||||
fn file_name(&self) -> String {
|
fn file_name(&self) -> String {
|
||||||
@@ -96,7 +96,7 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<d
|
|||||||
println!("Description: \n{}", header.description());
|
println!("Description: \n{}", header.description());
|
||||||
println!("Data size: {}", header.data_size);
|
println!("Data size: {}", header.data_size);
|
||||||
|
|
||||||
let decrypted_data;
|
let mut decrypted_data;
|
||||||
if (header.mask & 0x2000_0000) != 0 {
|
if (header.mask & 0x2000_0000) != 0 {
|
||||||
println!("File is encrypted.");
|
println!("File is encrypted.");
|
||||||
let mut key = None;
|
let mut key = None;
|
||||||
@@ -136,9 +136,14 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<d
|
|||||||
let aes_key = &decrypted[20..52];
|
let aes_key = &decrypted[20..52];
|
||||||
println!("AES key: {}\n", hex::encode(aes_key));
|
println!("AES key: {}\n", hex::encode(aes_key));
|
||||||
|
|
||||||
let encrypted_data = common::read_exact(&mut file, header.data_size as usize)?;
|
//for encrypted data we need to read file to end
|
||||||
|
let mut encrypted_data = Vec::new();
|
||||||
|
file.read_to_end(&mut encrypted_data)?;
|
||||||
|
|
||||||
println!("Decrypting data...");
|
println!("Decrypting data...");
|
||||||
decrypted_data = decrypt_aes256_ecb(aes_key, &encrypted_data)?;
|
decrypted_data = decrypt_aes256_ecb(aes_key, &encrypted_data)?;
|
||||||
|
decrypted_data.truncate(header.data_size as usize);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
println!("File is not encrypted.");
|
println!("File is not encrypted.");
|
||||||
decrypted_data = common::read_exact(&mut file, header.data_size as usize)?;
|
decrypted_data = common::read_exact(&mut file, header.data_size as usize)?;
|
||||||
@@ -149,23 +154,24 @@ pub fn extract_pfl_upg(mut file: &File, output_folder: &str) -> Result<(), Box<d
|
|||||||
while (data_reader.position() as usize) < data_reader.get_ref().len() {
|
while (data_reader.position() as usize) < data_reader.get_ref().len() {
|
||||||
let file_header: FileHeader = data_reader.read_le()?;
|
let file_header: FileHeader = data_reader.read_le()?;
|
||||||
|
|
||||||
println!("\nFile: {}, Size: {}", file_header.file_name(), file_header.real_size);
|
//its a folder not a file
|
||||||
|
if (file_header.attributes[3] & (1 << 1)) != 0 {
|
||||||
|
println!("\nFolder: {}", file_header.file_name());
|
||||||
|
let output_path = Path::new(&output_folder).join(file_header.file_name().trim_start_matches('/'));
|
||||||
|
fs::create_dir_all(output_path)?;
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\nFile: {}, Size: {}", file_header.file_name(), file_header.real_size);
|
||||||
let data = common::read_exact(&mut data_reader, file_header.stored_size as usize)?;
|
let data = common::read_exact(&mut data_reader, file_header.stored_size as usize)?;
|
||||||
|
|
||||||
let mut output_path = Path::new(&output_folder).join(file_header.file_name().trim_start_matches('/'));
|
let output_path = Path::new(&output_folder).join(file_header.file_name().trim_start_matches('/'));
|
||||||
let output_path_parent = output_path.parent().expect("Failed to get parent of the output path!");
|
let output_path_parent = output_path.parent().expect("Failed to get parent of the output path!");
|
||||||
|
|
||||||
//prevent collisions because philips is dumb
|
//prevent collisions
|
||||||
if output_path_parent.exists() && output_path_parent.is_file() {
|
if output_path_parent.exists() && output_path_parent.is_file() {
|
||||||
let fixed_file_name = if let Some((a, b)) = file_header.file_name().rsplit_once('/') {
|
println!("[!] Warning: File collision detected, Skipping this file!");
|
||||||
format!("{}_{}", a, b)
|
continue
|
||||||
} else {
|
|
||||||
file_header.file_name()
|
|
||||||
};
|
|
||||||
|
|
||||||
output_path = Path::new(&output_folder).join(file_header.file_name().trim_start_matches('/'));
|
|
||||||
println!("[!] Warning: File collision detected, this file will be saved to: {}", fixed_file_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(parent) = output_path.parent() {
|
if let Some(parent) = output_path.parent() {
|
||||||
|
|||||||
Reference in New Issue
Block a user