mirror of
https://codeberg.org/unspeaker/vestal.git
synced 2025-12-06 08:36:41 +01:00
start tracing call instructions
This commit is contained in:
parent
33546ccfb4
commit
e5baca6c31
4 changed files with 89 additions and 106 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -313,6 +313,15 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iced-x86"
|
||||
version = "1.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c447cff8c7f384a7d4f741cfcff32f75f3ad02b406432e8d6c878d56b1edf6b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.1"
|
||||
|
|
@ -675,6 +684,7 @@ dependencies = [
|
|||
"clap",
|
||||
"exe",
|
||||
"hexy",
|
||||
"iced-x86",
|
||||
"object",
|
||||
"pretty-hex",
|
||||
"syscalls",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ object = { version = "0.36.7", features = [ "read_core", "write_core", "elf", "p
|
|||
hexy = "0.1.4"
|
||||
pretty-hex = "0.4.1"
|
||||
exe = "0.5.6"
|
||||
iced-x86 = "1.21.0"
|
||||
#elf = "0.7.4"
|
||||
#goblin = "0.9.3"
|
||||
#lancelot = "0.9.7"
|
||||
|
|
|
|||
|
|
@ -38,32 +38,69 @@ struct Vestal {
|
|||
//path_to_exports: HashMap<Arc<PathBuf>, Vec<ImageExportDescriptor>>,
|
||||
//path_to_imports: HashMap<Arc<PathBuf>, Vec<ImageImportDescriptor>>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct Export {
|
||||
id: u32,
|
||||
name: Option<Arc<[u8]>>,
|
||||
target: Target,
|
||||
}
|
||||
impl Export {
|
||||
fn name_string (&self) -> Option<String> {
|
||||
String::from_utf8(self.name.as_ref()?.to_vec()).ok()
|
||||
}
|
||||
fn addr (&self) -> u32 {
|
||||
if let Target::Addr(addr) = self.target {
|
||||
addr
|
||||
} else {
|
||||
panic!("no addr")
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Target {
|
||||
Addr(u32),
|
||||
Name(Arc<[u8]>, Arc<[u8]>),
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct Import {}
|
||||
impl Vestal {
|
||||
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..256].hex_dump());
|
||||
println!();
|
||||
for (dll_path, dll) in self.path_to_pe.iter() {
|
||||
let ep_rva = dll.get_entrypoint()?;
|
||||
let ep_off = dll.rva_to_offset(ep_rva)?;
|
||||
println!("\n\n{:p} 0x{:x?} {:x?} {:x?}\n{dll_path:?}\n",
|
||||
dll.as_ptr(),
|
||||
dll.get_image_base()?,
|
||||
ep_rva,
|
||||
ep_off);
|
||||
if dll_path.as_ref() == path {
|
||||
let buf = dll.get_buffer();
|
||||
//println!("{:?}\n", &buf[0..128]);
|
||||
//println!("{:?}\n", &buf[0x000c8900..0x000c8900+128].hex_dump());
|
||||
//println!("{:?}", &buf[0x000c9500..0x000c9500+128].hex_dump());
|
||||
let section = dll.get_section_by_name(".text")?;
|
||||
let section_ptr = section.pointer_to_raw_data.0 as usize;
|
||||
let section_len = section.size_of_raw_data as usize;
|
||||
//println!("{section:?}");
|
||||
//println!("{:?}\n", &buf[section_ptr..section_ptr+128].hex_dump());
|
||||
//println!("{:?}", &buf[ep_off.0 as usize..ep_off.0 as usize+128].hex_dump());
|
||||
let section_data = &buf[section_ptr..section_ptr+section_len];
|
||||
println!("0x{:x}", section_data.len());
|
||||
let mut decoder = iced_x86::Decoder::with_ip(64, section_data, 0, 0);
|
||||
while decoder.can_decode() {
|
||||
let position = decoder.position();
|
||||
let instruction = decoder.decode();
|
||||
let opcodes = §ion_data[position..position+instruction.len()].iter().map(|x|format!("{x:>02x}")).collect::<Vec<_>>().join(" ");
|
||||
//println!("0x{position:08x} {opcodes:32} {instruction}");
|
||||
if instruction.is_call_far() {
|
||||
//println!("0x{:08x} {}", decoder.position(), instruction);
|
||||
} else if instruction.is_call_far_indirect() {
|
||||
//println!("0x{:08x} {}", decoder.position(), instruction);
|
||||
} else if instruction.is_call_near() {
|
||||
//println!("0x{:08x} {}", decoder.position(), instruction);
|
||||
} else if instruction.is_call_near_indirect() {
|
||||
println!("0x{:08x} {opcodes:32} {instruction}", position+section_ptr);
|
||||
//println!("0x{:08x} {}", decoder.position(), instruction);
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//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!();
|
||||
//return Ok(())
|
||||
//}
|
||||
//}
|
||||
//panic!("no main");
|
||||
Ok(())
|
||||
}
|
||||
fn resolve (&self, name: &str) -> Usually<Option<PathBuf>> {
|
||||
for base in self.search_paths.iter() {
|
||||
let mut path = base.clone();
|
||||
|
|
@ -77,28 +114,36 @@ impl Vestal {
|
|||
fn load (&mut self, path: &PathBuf) -> Usually<()> {
|
||||
if !self.paths_visited.contains(path) {
|
||||
let path = Arc::new(path.clone());
|
||||
println!("(load {path:?})");
|
||||
println!("\n(load {path:?})");
|
||||
self.paths_visited.insert(path.clone());
|
||||
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 load_imports (&mut self, path: &PathBuf, dll: &VecPE) -> Usually<()> {
|
||||
let mut import_map = HashMap::new();
|
||||
let directory = ImportDirectory::parse(dll)?;
|
||||
for descriptor in directory.descriptors {
|
||||
print!(" (module {} ", descriptor.get_name(dll)?.as_str()?);
|
||||
let dep = descriptor.get_name(dll)?.as_str()?;
|
||||
let resolved = self.resolve(&dep)?.expect("no path for {name}");
|
||||
print!("\n (module\n {dep:?}\n {:?}", &resolved);
|
||||
let mut imports = Vec::new();
|
||||
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})"),
|
||||
ImportData::Ordinal(x) => print!("\n (import-ordinal 0x{x:>04x})"),
|
||||
ImportData::ImportByName(n) => print!("\n (import-by-name {n:?})"),
|
||||
}
|
||||
imports.push(import);
|
||||
}
|
||||
import_map.insert(dep, (resolved, imports));
|
||||
println!(")")
|
||||
}
|
||||
for (name, (path, imports)) in import_map.iter() {
|
||||
self.load(path)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn load_exports (&mut self, path: &PathBuf, dll: &VecPE) -> Usually<()> {
|
||||
|
|
@ -108,10 +153,10 @@ impl Vestal {
|
|||
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())
|
||||
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());
|
||||
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>> {
|
||||
|
|
@ -119,77 +164,4 @@ impl Vestal {
|
|||
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..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");
|
||||
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(())
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub(crate) use ::object::endian::LittleEndian;
|
|||
//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) use ::exe::{Buffer, 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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue