separate load/show/main

This commit is contained in:
🪞👃🪞 2025-02-21 18:40:38 +02:00
parent 09bdc91701
commit 5490fef835
3 changed files with 131 additions and 111 deletions

View file

@ -33,7 +33,7 @@ impl Vestal {
let ilt = descriptor.get_original_first_thunk(dll)?; let ilt = descriptor.get_original_first_thunk(dll)?;
let lookups = descriptor.get_lookup_thunks(dll)?; let lookups = descriptor.get_lookup_thunks(dll)?;
let resolved = Arc::new(self.resolve(&dep)?.expect("no path for {name}")); let resolved = Arc::new(self.resolve(&dep)?.expect("no path for {name}"));
print!("\n (module {BOLD}{dep:?}{RESET} N=0x{:>08x} IAT=0x{:>08x} ILT=0x{:>08x}\n {resolved:?}", print!(" (module {BOLD}{dep:?}{RESET} N=0x{:>08x} IAT=0x{:>08x} ILT=0x{:>08x}\n {resolved:?}",
&descriptor.name.0, &descriptor.name.0,
&descriptor.first_thunk.0, &descriptor.first_thunk.0,
&descriptor.original_first_thunk.0); &descriptor.original_first_thunk.0);
@ -56,13 +56,13 @@ impl Vestal {
let call_via = descriptor.first_thunk.0 + index as u32 * 8; let call_via = descriptor.first_thunk.0 + index as u32 * 8;
let name = match import { let name = match import {
ImportData::Ordinal(x) => { ImportData::Ordinal(x) => {
print!("\n (import-ordinal {BOLD}0x{:>08x}{RESET} IAT={} ILT={} LU={} 0x{:>04x})", //print!("\n (import-ordinal {BOLD}0x{:>08x}{RESET} IAT={} ILT={} LU={} 0x{:>04x})",
call_via, thunk, orig, lookup, x); //call_via, thunk, orig, lookup, x);
format!("___VESTAL___ORD___{x}___") format!("___VESTAL___ORD___{x}___")
}, },
ImportData::ImportByName(name) => { ImportData::ImportByName(name) => {
print!("\n (import-by-name {BOLD}0x{:>08x}{RESET} IAT={} ILT={} LU={} {:?})", //print!("\n (import-by-name {BOLD}0x{:>08x}{RESET} IAT={} ILT={} LU={} {:?})",
call_via, thunk, orig, lookup, name); //call_via, thunk, orig, lookup, name);
format!("{name}") format!("{name}")
}, },
}; };

View file

@ -1,6 +1,7 @@
#![feature(slice_split_once)] #![feature(slice_split_once)]
mod util; mod util;
mod load; mod load;
mod show;
pub(crate) use self::util::*; pub(crate) use self::util::*;
use clap::{arg, command, value_parser, ArgAction, Command}; use clap::{arg, command, value_parser, ArgAction, Command};
fn main () -> Usually<()> { fn main () -> Usually<()> {
@ -42,114 +43,17 @@ impl Vestal {
fn enter (&mut self, path: &PathBuf) -> Usually<()> { fn enter (&mut self, path: &PathBuf) -> Usually<()> {
let mut total = 0usize; let mut total = 0usize;
self.load(&path)?; self.load(&path)?;
let data = self.path_to_data.get(path);
let len = data.as_ref().unwrap().len();
let data = data.as_ref().unwrap();
//println!();
//println!();
for (dll_path, dll) in self.path_to_pe.iter() { for (dll_path, dll) in self.path_to_pe.iter() {
let ep_rva = dll.get_entrypoint()?; self.show_dll(dll_path)?;
let ep_off = dll.rva_to_offset(ep_rva)?; let dll_data = self.path_to_data.get(dll_path).unwrap();
println!("\n\n{:p} 0x{:x?} {:x?} {:x?}\n{dll_path:?}\n", let len = dll_data.len();
dll.as_ptr(), println!(" (bytes {len} 0x{len:x})");
dll.get_image_base()?, self.show_calls(dll_path, dll_path.as_ref() == path)?;
ep_rva, total += len;
ep_off); //println!("{:?}", dll_data.hex_dump());
if true || dll_path.as_ref() == path {
let dll_data = self.path_to_data.get(dll_path).unwrap();
total += dll_data.len();
println!("{:?}", dll_data.hex_dump());
let buf = dll.get_buffer();
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;
let section_data = &buf[section_ptr..section_ptr+section_len];
let mut decoder = iced_x86::Decoder::with_ip(64, section_data, 0x1000, 0);
while decoder.can_decode() {
let position = decoder.position();
let instruction = decoder.decode();
let opcodes = &section_data[position..position+instruction.len()];
//println!("0x{position:08x} {opcodes:32} {instruction}");
if (instruction.flow_control() == iced_x86::FlowControl::IndirectBranch
|| instruction.flow_control() == iced_x86::FlowControl::IndirectCall)
&& instruction.op0_kind() == iced_x86::OpKind::Memory {
match opcodes[0] {
0xff => match opcodes[1] {
0x10 | 0x12 | 0x13 |
0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 |
0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => continue,
_ => {},
},
0x41 | 0x42 | 0x43 | 0x49 => match opcodes[1] {
0xff => continue,
_ => {},
},
0x48 => match opcodes[2] {
0x20 | 0x60 | 0x62 | 0xa0 | 0xa2 => continue,
_ => {},
},
_ => {}
}
let offset = (position + section_ptr) as u32;
let offset_rva = dll.offset_to_rva(Offset(offset))?.0;
let call_target = match opcodes[0] {
0xff => match opcodes[1] {
0x15 | 0x25 =>
offset_rva + opcodes.len() as u32 + u32::from_le_bytes([
opcodes[2],
opcodes[3],
opcodes[4],
opcodes[5]
]),
_ => 0x0
},
0x48 => match opcodes[1] {
0xff => match opcodes[2] {
0x15 | 0x25 =>
offset_rva + opcodes.len() as u32 + u32::from_le_bytes([
opcodes[3],
opcodes[4],
opcodes[5],
opcodes[6]
]),
_ => 0x0
},
_ => 0x0
}
_ => 0x0
};
println!("{BOLD}{:20?}{RESET} O=0x{:08x} {BOLD}R=0x{:08x}{RESET} {:25} {:40} 0x{:08x} {:?}",
dll_path.file_name().unwrap(),
offset,
offset_rva,
opcodes.iter().map(|x|format!("{x:>02x}")).collect::<Vec<_>>().join(" "),
instruction,
call_target,
self.addr_to_import.get(&call_target));
//println!("0x{:08x} {}", decoder.position(), instruction);
//return Ok(())
}
}
}
} }
//let exports = self.path_to_exports.get(path).expect("no exports"); //self.show_addr_to_import();
//for export in exports.iter() { println!("(bytes-total {total} (0x{total:x})");
//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");
for addr in self.addr_to_import.keys() {
let (dll, export) = self.addr_to_import.get(addr).unwrap();
println!("{BOLD}0x{addr:>08x}{RESET} {dll:>20} {export:<40}");
}
//println!("{:#?}", &self.addr_to_import);
println!("Total code bytes: {total} (0x{total:x})");
Ok(()) Ok(())
} }
} }

116
crates/vestal/src/show.rs Normal file
View file

@ -0,0 +1,116 @@
use crate::*;
impl Vestal {
pub fn show_addr_to_import (&self) {
for (addr, (dll, export)) in self.addr_to_import.iter() {
println!("{BOLD}0x{addr:>08x}{RESET} {dll:>20} {export:<40}");
}
}
pub fn show_vst_entrypoint (&self, path: &PathBuf) {
//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");
//println!("{:#?}", &self.addr_to_import);
}
pub fn show_dll (&self, path: &PathBuf) -> Usually<()> {
let dll = self.path_to_pe.get(path).expect("no such library");
let ep_rva = dll.get_entrypoint()?;
let ep_off = dll.rva_to_offset(ep_rva)?;
println!("\n({:p} 0x{:x?} {:x?} {:x?}\n {path:?})",
dll.as_ptr(),
dll.get_image_base()?,
ep_rva,
ep_off);
Ok(())
}
pub fn show_calls (&self, path: &PathBuf, verbose: bool) -> Usually<()> {
let mut calls = 0;
let dll = self.path_to_pe.get(path).expect("no such library");
let buf = dll.get_buffer();
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;
let section_data = &buf[section_ptr..section_ptr+section_len];
let mut decoder = iced_x86::Decoder::with_ip(64, section_data, 0x1000, 0);
while decoder.can_decode() {
let position = decoder.position();
let instruction = decoder.decode();
let opcodes = &section_data[position..position+instruction.len()];
//println!("0x{position:08x} {opcodes:32} {instruction}");
if (instruction.flow_control() == iced_x86::FlowControl::IndirectBranch
|| instruction.flow_control() == iced_x86::FlowControl::IndirectCall)
&& instruction.op0_kind() == iced_x86::OpKind::Memory {
match opcodes[0] {
0xff => match opcodes[1] {
0x10 | 0x12 | 0x13 |
0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 |
0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => continue,
_ => {},
},
0x41 | 0x42 | 0x43 | 0x49 => match opcodes[1] {
0xff => continue,
_ => {},
},
0x48 => match opcodes[2] {
0x20 | 0x60 | 0x62 | 0xa0 | 0xa2 => continue,
_ => {},
},
_ => {}
}
let offset = (position + section_ptr) as u32;
let offset_rva = dll.offset_to_rva(Offset(offset))?.0;
let call_target = match opcodes[0] {
0xff => match opcodes[1] {
0x15 | 0x25 =>
offset_rva + opcodes.len() as u32 + u32::from_le_bytes([
opcodes[2],
opcodes[3],
opcodes[4],
opcodes[5]
]),
_ => 0x0
},
0x48 => match opcodes[1] {
0xff => match opcodes[2] {
0x15 | 0x25 =>
offset_rva + opcodes.len() as u32 + u32::from_le_bytes([
opcodes[3],
opcodes[4],
opcodes[5],
opcodes[6]
]),
_ => 0x0
},
_ => 0x0
}
_ => 0x0
};
let unknown = (String::from("unknown"), String::from("unknown"));
let external = format!("{}::{}",
self.addr_to_import.get(&call_target).unwrap_or(&unknown).0,
self.addr_to_import.get(&call_target).unwrap_or(&unknown).1);
let dependent = path.file_name().unwrap();
if verbose {
println!(" ({BOLD}{external:30}{RESET} O=0x{:08x} {BOLD}R=0x{:08x}{RESET} {:25} {:40} 0x{:08x}",
offset,
offset_rva,
opcodes.iter().map(|x|format!("{x:>02x}")).collect::<Vec<_>>().join(" "),
instruction,
call_target,
);
}
calls += 1;
}
}
println!(" (calls {calls})");
Ok(())
}
}