try another library

This commit is contained in:
🪞👃🪞 2025-02-19 23:46:55 +02:00
parent 8946a571ae
commit 33546ccfb4
4 changed files with 465 additions and 93 deletions

View file

@ -9,7 +9,7 @@ syscalls = "0.6.18"
object = { version = "0.36.7", features = [ "read_core", "write_core", "elf", "pe" ] }
hexy = "0.1.4"
pretty-hex = "0.4.1"
#exe = "0.5.6"
exe = "0.5.6"
#elf = "0.7.4"
#goblin = "0.9.3"
#lancelot = "0.9.7"

View file

@ -14,9 +14,11 @@ fn main () -> Usually<()> {
let mut vestal = Vestal::default();
vestal.search_paths.push(std::env::current_dir()?);
vestal.search_paths.push("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32".into());
for path in vestal.search_paths.iter() {
println!("(search {path:?})")
}
if let Some(path) = vestal.resolve(path.to_str().expect("path must be unicode"))? {
vestal.load(&path)?;
vestal.inspect();
vestal.run_main(&path)?;
} else {
panic!("Could not find: {path:?}")
@ -28,12 +30,13 @@ fn main () -> Usually<()> {
}
#[derive(Default, Debug)]
struct Vestal {
search_paths: Vec<PathBuf>,
paths_visited: HashSet<Arc<PathBuf>>,
path_to_bang: HashMap<Arc<PathBuf>, Arc<[u8]>>,
path_to_data: HashMap<Arc<PathBuf>, Arc<[u8]>>,
path_to_exports: HashMap<Arc<PathBuf>, Vec<Export>>,
path_to_imports: HashMap<Arc<PathBuf>, Vec<Import>>,
search_paths: Vec<PathBuf>,
paths_visited: HashSet<Arc<PathBuf>>,
path_to_bang: HashMap<Arc<PathBuf>, Arc<[u8]>>,
path_to_data: HashMap<Arc<PathBuf>, Arc<[u8]>>,
path_to_pe: HashMap<Arc<PathBuf>, Arc<VecPE>>,
//path_to_exports: HashMap<Arc<PathBuf>, Vec<ImageExportDescriptor>>,
//path_to_imports: HashMap<Arc<PathBuf>, Vec<ImageImportDescriptor>>,
}
#[derive(Debug)]
struct Export {
@ -76,93 +79,117 @@ impl Vestal {
let path = Arc::new(path.clone());
println!("(load {path:?})");
self.paths_visited.insert(path.clone());
let (bang, data) = slice_shebang(read(path.as_path())?.as_slice());
self.path_to_bang.insert(path.clone(), bang.into());
self.path_to_data.insert(path.clone(), data.clone().into());
let dll: PeFile<'_, ImageNtHeaders64, &[u8]> = PeFile::parse(data.as_slice())?;
if let Some(exports) = dll.export_table()? {
let mut collected = vec![];
for export_ref in exports.exports()?.iter() {
collected.push(Export {
id: export_ref.ordinal,
name: export_ref.name.map(|name|name.into()),
target: match export_ref.target {
ExportTarget::Address(addr) =>
Target::Addr(addr),
ExportTarget::ForwardByName(dll, name) =>
Target::Name(dll.into(), name.into()),
_ =>
todo!("unsupported export target {:?}", &export_ref.target)
}
});
}
self.path_to_exports.insert(path.clone(), collected);
}
if let Some(imports) = dll.import_table()? {
let mut collected = vec![];
for import in imports.descriptors()? {
let name = imports.name(import?.name.get(LittleEndian))?.to_vec();
let name = String::from_utf8(name.to_vec())?;
let name = name.to_lowercase();
if let Some(path) = self.resolve(&name)? {
if !self.paths_visited.contains(&path) {
//println!("(import {name:?})");
self.load(&path)?;
}
} else {
panic!("not found: {name:?}");
}
}
self.path_to_imports.insert(path.clone(), collected);
}
let data = self.load_bang_data(&path)?;
let dll = self.load_pe(&path, &data)?;
let imports = self.load_imports(&path, &dll);
let exports = self.load_exports(&path, &dll);
println!("(entrypoint {:?})", dll.get_entrypoint()?);
}
Ok(())
}
fn inspect (&self) {
for path in self.search_paths.iter() {
println!("(search {path:?})")
}
for path in self.paths_visited.iter() {
println!("(visited {path:?})")
}
for (path, bang) in self.path_to_bang.iter() {
if bang.len() > 0 {
println!("(bang {path:?} {:x})", bang.len())
fn load_imports (&mut self, path: &PathBuf, dll: &VecPE) -> Usually<()> {
let directory = ImportDirectory::parse(dll)?;
for descriptor in directory.descriptors {
print!(" (module {} ", descriptor.get_name(dll)?.as_str()?);
for import in descriptor.get_imports(dll)? {
match import {
ImportData::Ordinal(x) => print!("\n (ordi 0x{x:>04x})"),
ImportData::ImportByName(n) => print!("\n (name {n})"),
}
}
println!(")")
}
for (path, data) in self.path_to_data.iter() {
println!("(buffer {:p} 0x{:08x} {path:?})", data.as_ptr(), data.len())
}
for (path, exports) in self.path_to_exports.iter() {
//println!("(exports {path:?}\n {exports:?})")
}
for (path, imports) in self.path_to_imports.iter() {
//print!("(imports {path:?}");
//for import in imports.iter() {
//print!("\n {import:?}");
//}
//println!(")");
Ok(())
}
fn load_exports (&mut self, path: &PathBuf, dll: &VecPE) -> Usually<()> {
Ok(())
}
fn load_bang_data (&mut self, path: &Arc<PathBuf>) -> Usually<Arc<[u8]>> {
let (bang, data) = slice_shebang(read(path.as_path())?.as_slice());
self.path_to_bang.insert(path.clone(), bang.clone());
if bang.len() > 0 {
println!("(bang {path:?} {:x})", bang.len())
}
self.path_to_data.insert(path.clone(), data.clone());
println!("(buffer {:p} 0x{:08x} {path:?})", data.as_ptr(), data.len());
Ok(data)
}
fn load_pe (&mut self, path: &Arc<PathBuf>, data: &Arc<[u8]>) -> Usually<Arc<VecPE>> {
let pe = Arc::new(VecPE::from_disk_data(data));
self.path_to_pe.insert(path.clone(), pe.clone());
Ok(pe)
}
fn inspect (&self) {
//for (path, exports) in self.path_to_exports.iter() {
////println!("(exports {path:?}\n {exports:?})")
//}
//for (path, imports) in self.path_to_imports.iter() {
////print!("(imports {path:?}");
////for import in imports.iter() {
////print!("\n {import:?}");
////}
////println!(")");
//}
}
fn run_main (&self, path: &PathBuf) -> Usually<()> {
let data = self.path_to_data.get(path);
let len = data.as_ref().unwrap().len();
let data = data.as_ref().unwrap();
println!();
println!("{:?}", data[0..512].hex_dump());
println!("{:?}", data[0..256].hex_dump());
println!();
let exports = self.path_to_exports.get(path).expect("no exports");
for export in exports.iter() {
if export.name_string() == Some("VSTPluginMain".to_string()) {
println!("{export:?}");
println!("{}", export.name_string().unwrap());
let addr = (export.addr() as usize);
println!();
println!("{:?}", data[addr..addr+512].hex_dump());
println!();
return Ok(())
}
}
panic!("no main");
//let exports = self.path_to_exports.get(path).expect("no exports");
//for export in exports.iter() {
//if export.name_string() == Some("VSTPluginMain".to_string()) {
//println!("{export:?}");
//println!("{}", export.name_string().unwrap());
//let addr = (export.addr() as usize);
//println!();
//println!("{:?}", data[addr..addr+512].hex_dump());
//println!();
//return Ok(())
//}
//}
//panic!("no main");
Ok(())
}
}
//if let Some(exports) = dll.export_table()? {
//let mut collected = vec![];
//for export_ref in exports.exports()?.iter() {
//collected.push(Export {
//id: export_ref.ordinal,
//name: export_ref.name.map(|name|name.into()),
//target: match export_ref.target {
//ExportTarget::Address(addr) =>
//Target::Addr(addr),
//ExportTarget::ForwardByName(dll, name) =>
//Target::Name(dll.into(), name.into()),
//_ =>
//todo!("unsupported export target {:?}", &export_ref.target)
//}
//});
//}
//self.path_to_exports.insert(path.clone(), collected);
//}
//if let Some(imports) = dll.import_table()? {
//let mut collected = vec![];
//for import in imports.descriptors()? {
//let name = imports.name(import?.name.get(LittleEndian))?.to_vec();
//let name = String::from_utf8(name.to_vec())?;
//let name = name.to_lowercase();
//if let Some(path) = self.resolve(&name)? {
//if !self.paths_visited.contains(&path) {
////println!("(import {name:?})");
//self.load(&path)?;
//}
//} else {
//panic!("not found: {name:?}");
//}
//}
//self.path_to_imports.insert(path.clone(), collected);
//}
//}
//Ok(())
//}

View file

@ -7,21 +7,22 @@ pub(crate) use std::fs::{read, canonicalize};
//pub(crate) use ::lancelot::loader::pe::{PE, reloc::apply_relocations};
//pub(crate) use ::goblin::{error, Object, pe::{import::Import, export::Export}};
pub(crate) use ::object::endian::LittleEndian;
pub(crate) use ::object::pe::ImageNtHeaders64;
pub(crate) use ::object::read::pe::{PeFile, ExportTarget};
//pub(crate) use ::object::pe::ImageNtHeaders64;
//pub(crate) use ::object::read::pe::{PeFile, ExportTarget};
pub(crate) use ::object::write::elf::Writer as ElfWriter;
pub(crate) use ::pretty_hex::*;
pub(crate) use ::exe::{PE, VecPE, PtrPE, types::*, headers::*};
pub(crate) type Usually<T> = Result<T, Box<dyn std::error::Error>>;
/// You can manually patch DLLs by prepending
/// a `#!/usr/bin/env vestal` line to them.
pub fn slice_shebang (buffer: &[u8]) -> (Vec<u8>, Vec<u8>) {
pub fn slice_shebang (buffer: &[u8]) -> (Arc<[u8]>, Arc<[u8]>) {
if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') {
if let Some((bang, data)) = buffer.split_once(|x|*x==0x0a) {
(bang.to_vec(), data.to_vec())
(bang.to_vec().into(), data.to_vec().into())
} else {
(buffer.to_vec(), vec![])
(buffer.to_vec().into(), vec![].into())
}
} else {
(vec![], buffer.to_vec())
(vec![].into(), buffer.to_vec().into())
}
}