mirror of
https://codeberg.org/unspeaker/vestal.git
synced 2025-12-06 10:46:42 +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::*;
|
use crate::*;
|
||||||
const RESET: &str = "\u{001b}[0m";
|
|
||||||
const BOLD: &str = "\u{001b}[1m";
|
|
||||||
|
|
||||||
impl Vestal {
|
impl Vestal {
|
||||||
pub fn resolve (&self, name: &str) -> Usually<Option<PathBuf>> {
|
pub fn resolve (&self, name: &str) -> Usually<Option<PathBuf>> {
|
||||||
|
|
@ -27,14 +25,14 @@ impl Vestal {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn load_imports (&mut self, path: &PathBuf, dll: &VecPE) -> Usually<()> {
|
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)?;
|
let directory = ImportDirectory::parse(dll)?;
|
||||||
for descriptor in directory.descriptors {
|
for descriptor in directory.descriptors {
|
||||||
let dep = descriptor.get_name(dll)?.as_str()?;
|
let dep = descriptor.get_name(dll)?.as_str()?;
|
||||||
let iat = descriptor.get_first_thunk(dll)?;
|
let iat = descriptor.get_first_thunk(dll)?;
|
||||||
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 = 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!("\n (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,
|
||||||
|
|
@ -56,15 +54,23 @@ impl Vestal {
|
||||||
descriptor.get_imports(dll)?
|
descriptor.get_imports(dll)?
|
||||||
).enumerate() {
|
).enumerate() {
|
||||||
let call_via = descriptor.first_thunk.0 + index as u32 * 8;
|
let call_via = descriptor.first_thunk.0 + index as u32 * 8;
|
||||||
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);
|
||||||
ImportData::ImportByName(name) =>
|
format!("___VESTAL___ORD___{x}___")
|
||||||
|
},
|
||||||
|
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}")
|
||||||
|
},
|
||||||
|
};
|
||||||
imports.push((thunk, orig, import));
|
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));
|
import_map.insert(dep, (resolved, imports));
|
||||||
println!(")")
|
println!(")")
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,14 @@ fn main () -> Usually<()> {
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
struct Vestal {
|
struct Vestal {
|
||||||
search_paths: Vec<PathBuf>,
|
search_paths: Vec<PathBuf>,
|
||||||
paths_visited: HashSet<Arc<PathBuf>>,
|
paths_visited: BTreeSet<Arc<PathBuf>>,
|
||||||
path_to_bang: HashMap<Arc<PathBuf>, Arc<[u8]>>,
|
path_to_bang: BTreeMap<Arc<PathBuf>, Arc<[u8]>>,
|
||||||
path_to_data: HashMap<Arc<PathBuf>, Arc<[u8]>>,
|
path_to_data: BTreeMap<Arc<PathBuf>, Arc<[u8]>>,
|
||||||
path_to_pe: HashMap<Arc<PathBuf>, Arc<VecPE>>,
|
path_to_pe: BTreeMap<Arc<PathBuf>, Arc<VecPE>>,
|
||||||
path_to_rpe: HashMap<Arc<PathBuf>, Arc<VecPE>>,
|
path_to_rpe: BTreeMap<Arc<PathBuf>, Arc<VecPE>>,
|
||||||
//path_to_exports: HashMap<Arc<PathBuf>, Vec<ImageExportDescriptor>>,
|
addr_to_import: BTreeMap<u32, (String, String)>,
|
||||||
//path_to_imports: HashMap<Arc<PathBuf>, Vec<ImageImportDescriptor>>,
|
//path_to_exports: BTreeMap<Arc<PathBuf>, Vec<ImageExportDescriptor>>,
|
||||||
|
//path_to_imports: BTreeMap<Arc<PathBuf>, Vec<ImageImportDescriptor>>,
|
||||||
}
|
}
|
||||||
impl Vestal {
|
impl Vestal {
|
||||||
fn enter (&mut self, path: &PathBuf) -> Usually<()> {
|
fn enter (&mut self, path: &PathBuf) -> Usually<()> {
|
||||||
|
|
@ -43,9 +44,9 @@ impl Vestal {
|
||||||
let data = self.path_to_data.get(path);
|
let data = self.path_to_data.get(path);
|
||||||
let len = data.as_ref().unwrap().len();
|
let len = data.as_ref().unwrap().len();
|
||||||
let data = data.as_ref().unwrap();
|
let data = data.as_ref().unwrap();
|
||||||
println!();
|
//println!();
|
||||||
println!("{:?}", data[0..256].hex_dump());
|
//println!("{:?}", data[0..256].hex_dump());
|
||||||
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()?;
|
let ep_rva = dll.get_entrypoint()?;
|
||||||
let ep_off = dll.rva_to_offset(ep_rva)?;
|
let ep_off = dll.rva_to_offset(ep_rva)?;
|
||||||
|
|
@ -54,7 +55,7 @@ impl Vestal {
|
||||||
dll.get_image_base()?,
|
dll.get_image_base()?,
|
||||||
ep_rva,
|
ep_rva,
|
||||||
ep_off);
|
ep_off);
|
||||||
if dll_path.as_ref() == path {
|
if true || dll_path.as_ref() == path {
|
||||||
let buf = dll.get_buffer();
|
let buf = dll.get_buffer();
|
||||||
let section = dll.get_section_by_name(".text")?;
|
let section = dll.get_section_by_name(".text")?;
|
||||||
let section_ptr = section.pointer_to_raw_data.0 as usize;
|
let section_ptr = section.pointer_to_raw_data.0 as usize;
|
||||||
|
|
@ -71,7 +72,8 @@ impl Vestal {
|
||||||
&& instruction.op0_kind() == iced_x86::OpKind::Memory {
|
&& instruction.op0_kind() == iced_x86::OpKind::Memory {
|
||||||
match opcodes[0] {
|
match opcodes[0] {
|
||||||
0xff => match opcodes[1] {
|
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,
|
0x60 | 0x90 | 0x92 | 0x93 | 0x94 | 0x97 => continue,
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
|
|
@ -86,11 +88,41 @@ impl Vestal {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let offset = (position + section_ptr) as u32;
|
let offset = (position + section_ptr) as u32;
|
||||||
println!("0x{:08x} (0x{:08x}) {:32} {}",
|
let offset_rva = dll.offset_to_rva(Offset(offset))?.0;
|
||||||
position + section_ptr,
|
let call_target = match opcodes[0] {
|
||||||
dll.offset_to_rva(Offset(offset))?.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(" "),
|
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);
|
//println!("0x{:08x} {}", decoder.position(), instruction);
|
||||||
//return Ok(())
|
//return Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -109,6 +141,11 @@ impl Vestal {
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
//panic!("no main");
|
//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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ pub(crate) use std::pin::Pin;
|
||||||
pub(crate) use std::sync::Arc;
|
pub(crate) use std::sync::Arc;
|
||||||
pub(crate) use std::error::Error;
|
pub(crate) use std::error::Error;
|
||||||
pub(crate) use std::path::{Path, PathBuf};
|
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 std::fs::{read, canonicalize};
|
||||||
pub(crate) use itertools::izip;
|
pub(crate) use itertools::izip;
|
||||||
//pub(crate) use ::lancelot::loader::pe::{PE, reloc::apply_relocations};
|
//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 ::pretty_hex::*;
|
||||||
pub(crate) use ::exe::{Buffer, 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>>;
|
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
|
/// You can manually patch DLLs by prepending
|
||||||
/// a `#!/usr/bin/env vestal` line to them.
|
/// a `#!/usr/bin/env vestal` line to them.
|
||||||
pub fn slice_shebang (buffer: &[u8]) -> (Arc<[u8]>, Arc<[u8]>) {
|
pub fn slice_shebang (buffer: &[u8]) -> (Arc<[u8]>, Arc<[u8]>) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue