feat: improve cli tool

This commit is contained in:
2024-04-17 22:49:47 +02:00
parent 0dea9a7b01
commit 94ce29d4de
4 changed files with 106 additions and 27 deletions

19
enmacompat/README.md Normal file
View File

@@ -0,0 +1,19 @@
# Enma Compat
Library with CLI tool to work with Enma Engine's emedded data
## CLI
You can use the CLI to inspect data contained in the binary
```sh
# Only need to run this once
enmacompat --path path/to/exe analyze
# This is for inspecting
enmacompat --path path/to/exe extract
```
## Blender Script
TODO;

View File

@@ -1,4 +1,5 @@
pub mod area;
pub mod meta;
pub mod section;
mod util;
pub mod windows_pe;

View File

@@ -1,44 +1,56 @@
use clap::{command, Parser};
use enmacompat::{
area::{find_area_array_location, read_area, EnmaAreaRaw},
windows_pe::WindowsPEFile,
};
use clap::{command, Parser, Subcommand};
use enmacompat::{area::read_area, meta::EnmaMeta, windows_pe::WindowsPEFile};
use std::fs::File;
#[derive(Parser, Debug)]
#[derive(Parser)]
#[command(version, about)]
struct Args {
#[clap(subcommand)]
command: Commands,
#[clap(short, long)]
path: std::path::PathBuf,
}
#[derive(Subcommand)]
enum Commands {
#[clap(about = "Analyze the file and generate a metadata file")]
Analyze,
#[clap(about = "Extract data from the file")]
Extract,
}
fn main() {
let args = Args::parse();
let file = File::open(&args.path).expect("Failed to open file");
let mut windows_pe_file = WindowsPEFile::from(file);
println!("\x1b[34m\x1b[1mSearching for Area Array Location\x1b[0m");
let location = Some(0x1417cc980); //find_area_array_location(&mut windows_pe_file).unwrap();
if let Some(location) = location {
println!(
"\x1b[32m\x1b[1mArea Array Location\x1b[0m: \x1b[4m{:#x}\x1b[0m (Memory), \x1b[4m{:#x}\x1b[0m (File)",
location,
windows_pe_file.get_file_address(location).unwrap()
);
let mut i = 1;
loop {
let address = windows_pe_file.read_addr::<u64>(location + i * 8).unwrap();
if address == 0 {
break;
}
let area = read_area(&windows_pe_file, address).unwrap();
let file = File::create(format!("out/{}.json", area.name)).unwrap();
match args.command {
Commands::Analyze => {
let file = File::create(args.path.with_extension("json")).unwrap();
let mut writer = std::io::BufWriter::new(file);
serde_json::to_writer_pretty(&mut writer, &area).unwrap();
i += 1;
serde_json::to_writer_pretty(
&mut writer,
&EnmaMeta::from_analysis(&mut windows_pe_file).unwrap(),
)
.unwrap();
}
Commands::Extract => {
let meta_file = File::open(args.path.with_extension("json"))
.expect("Missing meta file, did you forget to run the analyze command?");
let meta: EnmaMeta = serde_json::from_reader(meta_file)
.expect("Failed to read meta file, try running the analyze command again?");
for i in 1..meta.area_array_count {
let address = windows_pe_file
.read_addr::<u64>(meta.area_array_addr + i as u64 * 8)
.unwrap();
let area = read_area(&windows_pe_file, address).unwrap();
let file = File::create(format!("out/{}.json", area.name)).unwrap();
let mut writer = std::io::BufWriter::new(file);
serde_json::to_writer_pretty(&mut writer, &area).unwrap();
}
}
} else {
println!("\x1b[31mArea array location could not found\x1b[0m");
}
}

47
enmacompat/src/meta.rs Normal file
View File

@@ -0,0 +1,47 @@
use serde::{Deserialize, Serialize};
use crate::{area::find_area_array_location, windows_pe::WindowsPEFile};
#[derive(Debug, Serialize, Deserialize)]
pub struct EnmaMeta {
pub area_array_addr: u64,
pub area_array_count: i32,
}
impl EnmaMeta {
/// Performs an analysis from a WindowsPE executable to find specific data locations
pub fn from_analysis(windows_pe_file: &mut WindowsPEFile) -> Result<Self, std::io::Error> {
println!("\x1b[34m\x1b[1mSearching for Area Array Location\x1b[0m");
let area_array_addr = find_area_array_location(windows_pe_file)?.ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"Could not find Area Array Location",
)
})?;
let mut area_array_count = 1;
loop {
let area_array =
windows_pe_file.read_addr::<u64>(area_array_addr + area_array_count as u64 * 8)?;
if area_array == 0 {
break;
}
let id = windows_pe_file.read_addr::<u64>(area_array)?;
if id != area_array_count as u64 {
break;
}
area_array_count += 1;
}
println!(
"\x1b[32m\x1b[1mArea Array\x1b[0m: \x1b[4m{:#x} ({} items)\x1b[0m",
area_array_addr, area_array_count
);
Ok(Self {
area_array_addr,
area_array_count,
})
}
}