mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
Generated
+32
@@ -52,6 +52,12 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.36"
|
version = "1.2.36"
|
||||||
@@ -108,6 +114,21 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
|
||||||
|
dependencies = [
|
||||||
|
"crc-catalog",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc-catalog"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -151,6 +172,16 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lzma-rs"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"crc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell_polyfill"
|
name = "once_cell_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@@ -210,6 +241,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"lz4",
|
"lz4",
|
||||||
|
"lzma-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
+2
-1
@@ -5,4 +5,5 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5", features = ["derive"] }
|
clap = { version = "4.5", features = ["derive"] }
|
||||||
lz4 = "1.23.1"
|
lz4 = "1.23.1"
|
||||||
|
lzma-rs = "0.3"
|
||||||
+69
-33
@@ -1,14 +1,15 @@
|
|||||||
use std::fs::{self, File, OpenOptions};
|
use std::fs::{self, File, OpenOptions};
|
||||||
use std::path::{Path};
|
use std::path::{Path};
|
||||||
use std::io::{Write};
|
use std::io::{Write, Cursor};
|
||||||
use lz4::block::decompress;
|
use lz4::block::decompress;
|
||||||
|
use lzma_rs::lzma_decompress;
|
||||||
use crate::common;
|
use crate::common;
|
||||||
|
|
||||||
pub fn is_mstar_file(file: &File) -> bool {
|
pub fn is_mstar_file(file: &File) -> bool {
|
||||||
let header = common::read_file(&file, 0, 32768).expect("Failed to read from file.");
|
let header = common::read_file(&file, 0, 32768).expect("Failed to read from file.");
|
||||||
let header_string = String::from_utf8_lossy(&header);
|
let header_string = String::from_utf8_lossy(&header);
|
||||||
|
|
||||||
if header_string.contains("filepartload") & header_string.contains("MstarUpgrade") | header_string.contains("CtvUpgrade") {
|
if header_string.contains("filepartload") & header_string.contains("MstarUpgrade") | header_string.contains("CtvUpgrade") | header_string.contains("LetvUpgrade"){
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -23,6 +24,14 @@ fn parse_number(s: &str) -> Option<u64> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decompress_lzma(compressed_data: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||||||
|
let mut input = Cursor::new(compressed_data);
|
||||||
|
let mut output = Vec::new();
|
||||||
|
|
||||||
|
lzma_decompress(&mut input, &mut output)?;
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
fn decompress_lz4(compressed_data: &[u8], original_size: i32) -> Result<Vec<u8>, std::io::Error> {
|
fn decompress_lz4(compressed_data: &[u8], original_size: i32) -> Result<Vec<u8>, std::io::Error> {
|
||||||
match decompress(compressed_data, Some(original_size)) {
|
match decompress(compressed_data, Some(original_size)) {
|
||||||
Ok(decompressed) => Ok(decompressed),
|
Ok(decompressed) => Ok(decompressed),
|
||||||
@@ -32,6 +41,7 @@ fn decompress_lz4(compressed_data: &[u8], original_size: i32) -> Result<Vec<u8>,
|
|||||||
|
|
||||||
pub fn extract_mstar(file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn extract_mstar(file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
let mut script = common::read_file(&file, 0, 32768)?;
|
let mut script = common::read_file(&file, 0, 32768)?;
|
||||||
|
|
||||||
if let Some(pos) = script.iter().position(|x| [0x00, 0xFF].contains(x)) {
|
if let Some(pos) = script.iter().position(|x| [0x00, 0xFF].contains(x)) {
|
||||||
@@ -40,11 +50,15 @@ pub fn extract_mstar(file: &File, output_folder: &str) -> Result<(), Box<dyn std
|
|||||||
|
|
||||||
let mut script_string = String::from_utf8_lossy(&script);
|
let mut script_string = String::from_utf8_lossy(&script);
|
||||||
//println!("{}", script_string);
|
//println!("{}", script_string);
|
||||||
|
|
||||||
if script_string == "" {
|
if script_string == "" {
|
||||||
//try ts hisense
|
//try for hisense
|
||||||
println!("Failed to get script at 0x0, trying 0x1000...");
|
println!("Failed to get script at 0x0, trying 0x1000...");
|
||||||
script = common::read_file(&file, 4096, 32768)?;
|
script = common::read_file(&file, 4096, 32768)?;
|
||||||
|
|
||||||
|
if let Some(pos) = script.iter().position(|x| [0x00, 0xFF].contains(x)) {
|
||||||
|
script.truncate(pos);
|
||||||
|
}
|
||||||
|
|
||||||
script_string = String::from_utf8_lossy(&script);
|
script_string = String::from_utf8_lossy(&script);
|
||||||
|
|
||||||
if script_string == "" {
|
if script_string == "" {
|
||||||
@@ -77,16 +91,27 @@ pub fn extract_mstar(file: &File, output_folder: &str) -> Result<(), Box<dyn std
|
|||||||
let mut j = i + 1;
|
let mut j = i + 1;
|
||||||
while j < lines.len() && !lines[j].starts_with("filepartload") {
|
while j < lines.len() && !lines[j].starts_with("filepartload") {
|
||||||
//get compression method
|
//get compression method
|
||||||
if lines[j].contains("mscompress7") {
|
if lines[j].starts_with("mscompress7"){
|
||||||
compression = "lzma";
|
if compression == "none" {
|
||||||
} else if lines[j].contains("lz4") {
|
compression = "lzma";
|
||||||
compression = "lz4";
|
} else if compression == "lzma" {
|
||||||
|
//thank the turks
|
||||||
|
compression = "double_lzma";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lines[j].starts_with("lz4"){
|
if lines[j].starts_with("lz4"){
|
||||||
|
compression = "lz4";
|
||||||
let parts: Vec<&str> = lines[j].split_whitespace().collect();
|
let parts: Vec<&str> = lines[j].split_whitespace().collect();
|
||||||
lz4_expect_size = parse_number(parts[5]).unwrap_or(0);
|
lz4_expect_size = parse_number(parts[5]).unwrap_or(0);
|
||||||
}
|
}
|
||||||
|
if lines[j].starts_with("mmc unlzo"){
|
||||||
|
compression = "lzo";
|
||||||
|
let parts: Vec<&str> = lines[j].split_whitespace().collect();
|
||||||
|
// get part name from mmc unlzo
|
||||||
|
if partname == "unknown" {
|
||||||
|
partname = parts[4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if its boot partition
|
// check if its boot partition
|
||||||
if lines[j].starts_with("mmc write.boot") {
|
if lines[j].starts_with("mmc write.boot") {
|
||||||
@@ -106,40 +131,51 @@ pub fn extract_mstar(file: &File, output_folder: &str) -> Result<(), Box<dyn std
|
|||||||
j += 1;
|
j += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("offset: {} size: {} --> {} (compression: {})", offset, size, partname, compression);
|
println!("Part - Offset: {}, Size: {} --> {}.bin", offset, size, partname);
|
||||||
|
|
||||||
let data = common::read_file(&file, offset, size.try_into().unwrap())?;
|
if partname == "unknown"{
|
||||||
|
println!("- Unknown destination, skipping!");
|
||||||
//println!("{:02x?}", &data[0]);
|
|
||||||
//println!("{}", data.len());
|
|
||||||
|
|
||||||
let out_data;
|
|
||||||
|
|
||||||
if compression == "lzma" {
|
|
||||||
// TODO: do lzma decompression
|
|
||||||
out_data = data;
|
|
||||||
} else if compression == "lz4" {
|
|
||||||
println!("- Decompressing lz4, expected size: {}", lz4_expect_size);
|
|
||||||
out_data = decompress_lz4(&data, lz4_expect_size.try_into().unwrap())?;
|
|
||||||
//out_data = data;
|
|
||||||
} else {
|
} else {
|
||||||
out_data = data;
|
let data = common::read_file(&file, offset, size.try_into().unwrap())?;
|
||||||
}
|
let out_data;
|
||||||
|
|
||||||
let output_path = Path::new(&output_folder).join(partname.to_owned() + ".bin");
|
if compression == "lzma" {
|
||||||
|
println!("- Decompressing LZMA...");
|
||||||
|
out_data = decompress_lzma(&data)?;
|
||||||
|
} else if compression == "double_lzma" {
|
||||||
|
println!("- Decompressing LZMA (Pass 1)...");
|
||||||
|
let pass_1 = decompress_lzma(&data)?;
|
||||||
|
println!("- Decompressing LZMA (Pass 2)...");
|
||||||
|
out_data = decompress_lzma(&pass_1)?;
|
||||||
|
} else if compression == "lz4" {
|
||||||
|
println!("- Decompressing lz4, expected size: {}", lz4_expect_size);
|
||||||
|
out_data = decompress_lz4(&data, lz4_expect_size.try_into().unwrap())?;
|
||||||
|
} else if compression == "lzo" {
|
||||||
|
//TODO: add lzo
|
||||||
|
println!("- Decompressing lzo...");
|
||||||
|
out_data = data;
|
||||||
|
}else {
|
||||||
|
out_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
fs::create_dir_all(&output_folder)?;
|
let output_path = Path::new(&output_folder).join(partname.to_owned() + ".bin");
|
||||||
let mut out_file = OpenOptions::new()
|
|
||||||
.append(true)
|
|
||||||
.create(true)
|
|
||||||
.open(output_path)?;
|
|
||||||
|
|
||||||
out_file.write_all(&out_data)?;
|
fs::create_dir_all(&output_folder)?;
|
||||||
|
let mut out_file = OpenOptions::new()
|
||||||
|
.append(true)
|
||||||
|
.create(true)
|
||||||
|
.open(output_path)?;
|
||||||
|
|
||||||
|
out_file.write_all(&out_data)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Extraction finished!");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user