mirror of
https://codeberg.org/unspeaker/vestal.git
synced 2025-12-06 15:06:42 +01:00
try another library
This commit is contained in:
parent
8946a571ae
commit
33546ccfb4
4 changed files with 465 additions and 93 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue