This commit is contained in:
minish 2025-07-14 21:17:20 -04:00
commit 8e183c25f1
Signed by: min
SSH Key Fingerprint: SHA256:h4k7JNrfe1dzv1WE3oGVeAY9DPSZXIu3/j89+6DtHWE
4 changed files with 227 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

119
Cargo.lock generated Normal file
View File

@ -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"

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "tauriunpack"
version = "0.1.0"
edition = "2024"
[dependencies]
brotli = "8"
object = "0.37"

99
src/main.rs Normal file
View File

@ -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<T> = std::result::Result<T, Box<dyn Error>>;
#[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<u64> {
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(())
}