mirror of
https://codeberg.org/unspeaker/vestal.git
synced 2025-12-06 08:36:41 +01:00
link call/jmp to library targets
This commit is contained in:
parent
6796e3e50f
commit
d61606fe48
3 changed files with 73 additions and 28 deletions
|
|
@ -1,6 +1,4 @@
|
|||
use crate::*;
|
||||
const RESET: &str = "\u{001b}[0m";
|
||||
const BOLD: &str = "\u{001b}[1m";
|
||||
|
||||
impl Vestal {
|
||||
pub fn resolve (&self, name: &str) -> Usually<Option<PathBuf>> {
|
||||
|
|
@ -27,14 +25,14 @@ impl Vestal {
|
|||
Ok(())
|
||||
}
|
||||
pub fn load_imports (&mut self, path: &PathBuf, dll: &VecPE) -> Usually<()> {
|
||||
let mut import_map = HashMap::new();
|
||||
let mut import_map = BTreeMap::new();
|
||||
let directory = ImportDirectory::parse(dll)?;
|
||||
for descriptor in directory.descriptors {
|
||||
let dep = descriptor.get_name(dll)?.as_str()?;
|
||||
let iat = descriptor.get_first_thunk(dll)?;
|
||||
let ilt = descriptor.get_original_first_thunk(dll)?;
|
||||
let lookups = descriptor.get_lookup_thunks(dll)?;
|
||||
let resolved = 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:?}",
|
||||
&descriptor.name.0,
|
||||
&descriptor.first_thunk.0,
|
||||
|
|
@ -56,15 +54,23 @@ impl Vestal {
|
|||
descriptor.get_imports(dll)?
|
||||
).enumerate() {
|
||||
let call_via = descriptor.first_thunk.0 + index as u32 * 8;
|
||||
match import {
|
||||
ImportData::Ordinal(x) =>
|
||||
let name = match import {
|
||||
ImportData::Ordinal(x) => {
|
||||
print!("\n (import-ordinal {BOLD}0x{:>08x}{RESET} IAT={} ILT={} LU={} 0x{:>04x})",
|
||||
call_via, thunk, orig, lookup, x),
|
||||
ImportData::ImportByName(name) =>
|
||||
call_via, thunk, orig, lookup, x);
|
||||
format!("___VESTAL___ORD___{x}___")
|
||||
},
|
||||
ImportData::ImportByName(name) => {
|
||||
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}")
|
||||
},
|
||||
};
|
||||
imports.push((thunk, orig, import));
|
||||
if self.addr_to_import.contains_key(&call_via) {
|
||||
panic!("addr space overlap");
|
||||
}
|
||||
self.addr_to_import.insert(call_via, (dep.to_string(), name));
|
||||
}
|
||||
import_map.insert(dep, (resolved, imports));
|
||||
println!(")")
|
||||
|
|
|
|||
|
|
@ -28,14 +28,15 @@ 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_pe: HashMap<Arc<PathBuf>, Arc<VecPE>>,
|
||||
path_to_rpe: HashMap<Arc<PathBuf>, Arc<VecPE>>,
|
||||
//path_to_exports: HashMap<Arc<PathBuf>, Vec<ImageExportDescriptor>>,
|
||||
//path_to_imports: HashMap<Arc<PathBuf>, Vec<ImageImportDescriptor>>,
|
||||
search_paths: Vec<PathBuf>,
|
||||
paths_visited: BTreeSet<Arc<PathBuf>>,
|
||||
path_to_bang: BTreeMap<Arc<PathBuf>, Arc<[u8]>>,
|
||||
path_to_data: BTreeMap<Arc<PathBuf>, Arc<[u8]>>,
|
||||
path_to_pe: BTreeMap<Arc<PathBuf>, Arc<VecPE>>,
|
||||
path_to_rpe: BTreeMap<Arc<PathBuf>, Arc<VecPE>>,
|
||||
addr_to_import: BTreeMap<u32, (String, String)>,
|
||||
//path_to_exports: BTreeMap<Arc<PathBuf>, Vec<ImageExportDescriptor>>,
|
||||
//path_to_imports: BTreeMap<Arc<PathBuf>, Vec<ImageImportDescriptor>>,
|
||||
}
|
||||
impl Vestal {
|
||||
fn enter (&mut self, path: &PathBuf) -> Usually<()> {
|
||||
|
|
@ -43,9 +44,9 @@ impl Vestal {
|
|||
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!();
|
||||
//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)?;
|
||||
|
|
@ -54,7 +55,7 @@ impl Vestal {
|
|||
dll.get_image_base()?,
|
||||
ep_rva,
|
||||
ep_off);
|
||||
if dll_path.as_ref() == path {
|
||||
if true || dll_path.as_ref() == path {
|
||||
let buf = dll.get_buffer();
|
||||
let section = dll.get_section_by_name(".text")?;
|
||||
let section_ptr = section.pointer_to_raw_data.0 as usize;
|
||||
|
|
@ -71,7 +72,8 @@ impl Vestal {
|
|||
&& instruction.op0_kind() == iced_x86::OpKind::Memory {
|
||||
match opcodes[0] {
|
||||
0xff => match opcodes[1] {
|
||||
0x10 | 0x12 | 0x13 | 0x50 | 0x52 | 0x53 | 0x55 | 0x56 | 0x57 |
|
||||
0x10 | 0x12 | 0x13 |
|
||||
0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 |
|
||||
0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => continue,
|
||||
_ => {},
|
||||
},
|
||||
|
|
@ -86,11 +88,41 @@ impl Vestal {
|
|||
_ => {}
|
||||
}
|
||||
let offset = (position + section_ptr) as u32;
|
||||
println!("0x{:08x} (0x{:08x}) {:32} {}",
|
||||
position + section_ptr,
|
||||
dll.offset_to_rva(Offset(offset))?.0,
|
||||
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);
|
||||
instruction,
|
||||
call_target,
|
||||
self.addr_to_import.get(&call_target));
|
||||
//println!("0x{:08x} {}", decoder.position(), instruction);
|
||||
//return Ok(())
|
||||
}
|
||||
|
|
@ -109,6 +141,11 @@ impl Vestal {
|
|||
//}
|
||||
//}
|
||||
//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);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ pub(crate) use std::pin::Pin;
|
|||
pub(crate) use std::sync::Arc;
|
||||
pub(crate) use std::error::Error;
|
||||
pub(crate) use std::path::{Path, PathBuf};
|
||||
pub(crate) use std::collections::{HashMap, HashSet};
|
||||
pub(crate) use std::collections::{BTreeMap, BTreeSet};
|
||||
pub(crate) use std::fs::{read, canonicalize};
|
||||
pub(crate) use itertools::izip;
|
||||
//pub(crate) use ::lancelot::loader::pe::{PE, reloc::apply_relocations};
|
||||
|
|
@ -14,6 +14,8 @@ pub(crate) use ::object::write::elf::Writer as ElfWriter;
|
|||
pub(crate) use ::pretty_hex::*;
|
||||
pub(crate) use ::exe::{Buffer, PE, VecPE, PtrPE, types::*, headers::*};
|
||||
pub(crate) type Usually<T> = Result<T, Box<dyn std::error::Error>>;
|
||||
pub const RESET: &str = "\u{001b}[0m";
|
||||
pub const BOLD: &str = "\u{001b}[1m";
|
||||
/// You can manually patch DLLs by prepending
|
||||
/// a `#!/usr/bin/env vestal` line to them.
|
||||
pub fn slice_shebang (buffer: &[u8]) -> (Arc<[u8]>, Arc<[u8]>) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue