From 8e183c25f10ae54157b563b7f2824ba93ce21f0a Mon Sep 17 00:00:00 2001 From: minish Date: Mon, 14 Jul 2025 21:17:20 -0400 Subject: [PATCH] initial --- .gitignore | 1 + Cargo.lock | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 8 ++++ src/main.rs | 99 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 227 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..80b431a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,119 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "brotli" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "object" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" +dependencies = [ + "flate2", + "memchr", + "ruzstd", +] + +[[package]] +name = "ruzstd" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "tauriunpack" +version = "0.1.0" +dependencies = [ + "brotli", + "object", +] + +[[package]] +name = "twox-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..447a6bb --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tauriunpack" +version = "0.1.0" +edition = "2024" + +[dependencies] +brotli = "8" +object = "0.37" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..111c963 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,99 @@ +use std::{ + env, + error::Error, + fmt, fs, + io::{Cursor, Read}, + path::PathBuf, +}; + +use object::{Object, ObjectSection, read::pe::PeFile64}; + +type Result = std::result::Result>; + +#[derive(Debug)] +enum MyError { + NoParentDir, + NoSection, + NoData, +} +impl fmt::Display for MyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::NoParentDir => write!(f, "no parent dir for path"), + Self::NoSection => write!(f, "no section found"), + Self::NoData => write!(f, "no data"), + } + } +} +impl Error for MyError {} + +fn next_u64_le(r: &mut impl Read) -> Result { + let mut b = [0u8; 8]; + r.read_exact(&mut b)?; + Ok(u64::from_le_bytes(b)) +} + +fn main() -> Result<()> { + // read args + let mut args = env::args().skip(1); + let table_base: u64 = args + .next() + .and_then(|s| u64::from_str_radix(&s, 16).ok()) + .expect("no table base provided"); + let table_len: u64 = args + .next() + .and_then(|s| s.parse().ok()) + .expect("no table len provided"); + let path = args.next().expect("no *.exe provided"); + + // read file + let data = fs::read(path)?; + + // parse file + let file = PeFile64::parse(&*data)?; + + // find section + let section = file + .sections() + .find(|s| (s.address()..s.address() + s.size()).contains(&table_base)) + .ok_or(MyError::NoSection)?; + + // dump table + for i in 0..table_len { + // get entry + let ptr_entry = table_base + 32 * i; + let entry = section.data_range(ptr_entry, 32)?.ok_or(MyError::NoData)?; + + // parse entry + let mut c = Cursor::new(entry); + let ptr_name = next_u64_le(&mut c)?; + let len_name = next_u64_le(&mut c)?; + let ptr_data = next_u64_le(&mut c)?; + let len_data = next_u64_le(&mut c)?; + + // read name/data + let name = section + .data_range(ptr_name, len_name)? + .ok_or(MyError::NoData)?; + let data = section + .data_range(ptr_data, len_data)? + .ok_or(MyError::NoData)?; + + // print name + let mut name = String::from_utf8(name.to_vec())?; + println!("saving {name}"); + + // make path + let mut p = PathBuf::from("./save"); + name.insert(0, '.'); + p.push(name); + + // open file + let parent = p.parent().ok_or(MyError::NoParentDir)?; + fs::create_dir_all(parent)?; + let mut file = fs::File::create_new(p)?; + brotli::BrotliDecompress(&mut &data[..], &mut file)?; + } + + Ok(()) +}