mirror of
https://codeberg.org/unspeaker/vestal.git
synced 2025-12-06 12:56:41 +01:00
resolve broader
This commit is contained in:
parent
1d24f6e71f
commit
88ee260cde
2 changed files with 55 additions and 86 deletions
|
|
@ -91,10 +91,8 @@ impl Vestal {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn resolve_calls (&self, dll: &Dll, recurse: bool, verbose: bool) -> Usually<()> {
|
fn resolve_calls (&self, dll: &Dll, recurse: bool, verbose: bool) -> Usually<()> {
|
||||||
println!("--------------------------------");
|
println!("{:11}{BOLD}{}{RESET}", "", dll.name);
|
||||||
for (addr, call) in dll.calls_by_source.iter() {
|
for (addr, call) in dll.calls_by_source.iter() {
|
||||||
println!();
|
|
||||||
println!("{:11}{BOLD}{}{RESET}", "", dll.name);
|
|
||||||
self.resolve_call(dll, *addr, call, recurse, verbose)?;
|
self.resolve_call(dll, *addr, call, recurse, verbose)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -108,7 +106,7 @@ impl Vestal {
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
) -> Usually<()> {
|
) -> Usually<()> {
|
||||||
let addr = (addr - dll.code_base) as usize;
|
let addr = (addr - dll.code_base) as usize;
|
||||||
Show::call_site(&dll, addr, call.length, 1);
|
dll.show_call_site(addr, call.length, 1);
|
||||||
Show::call_module_method(Some(call));
|
Show::call_module_method(Some(call));
|
||||||
if let Some(method) = dll.parse_call(call) {
|
if let Some(method) = dll.parse_call(call) {
|
||||||
let module_name = call.module.as_ref().unwrap();
|
let module_name = call.module.as_ref().unwrap();
|
||||||
|
|
@ -136,41 +134,18 @@ impl Vestal {
|
||||||
}
|
}
|
||||||
fn resolve_call_recurse (
|
fn resolve_call_recurse (
|
||||||
&self,
|
&self,
|
||||||
dll: &Dll,
|
dll: &Dll,
|
||||||
addr: usize,
|
address: usize,
|
||||||
module_name: &Arc<str>,
|
module_name: &Arc<str>,
|
||||||
method_name: &Arc<str>,
|
method_name: &Arc<str>,
|
||||||
) -> Usually<()> {
|
) -> Usually<()> {
|
||||||
println!("\n {RESET} {BOLD}{} ({method_name}){RESET}", &dll.name);
|
let mut decoder = Decoder::with_ip(64, &dll.text_section[address..], 0, DecoderOptions::NONE);
|
||||||
//dll.collect_call(
|
|
||||||
//&dll.name,
|
|
||||||
//&dll.pe,
|
|
||||||
//&dll.text_section_start,
|
|
||||||
//&dll.text_section,
|
|
||||||
//);
|
|
||||||
let mut decoder = Decoder::with_ip(64, &dll.text_section[addr..], 0, DecoderOptions::NONE);
|
|
||||||
while decoder.can_decode() {
|
while decoder.can_decode() {
|
||||||
let position = decoder.position();
|
let position = decoder.position();
|
||||||
let instruction = decoder.decode();
|
if let Some(call) = dll.collect_call(&mut decoder, true)? {
|
||||||
let opcodes = &dll.text_section[position..position+instruction.len()];
|
println!("(call {call:#?}");
|
||||||
if Call::matches(&instruction) && !Call::skip(opcodes) {
|
|
||||||
let addr = addr + position;
|
|
||||||
let start = dll.text_section_start;
|
|
||||||
let offset = (position + start) as u32;
|
|
||||||
let offset_rva = dll.pe.offset_to_rva(Offset(offset))?.0 as u32;
|
|
||||||
println!("{opcodes:?} {addr:x} {position:x} {start:x} {offset:x} {offset_rva:x}");
|
|
||||||
let target = Call::target(opcodes, offset_rva);
|
|
||||||
Show::call_site(&dll, addr, instruction.len(), 1);
|
|
||||||
println!("{target:?}");
|
|
||||||
if let Some(target) = target {
|
|
||||||
println!("{target:x} {:?}", dll.deps_by_address.get(&(target as u32)));
|
|
||||||
println!("{target:x} {:?}", dll.calls_by_source.get(&(target as u32)))
|
|
||||||
} else {
|
|
||||||
println!("???");
|
|
||||||
};
|
|
||||||
Show::call_module_method(dll.calls_by_source.get(&(addr as u32)));
|
|
||||||
}
|
}
|
||||||
if dll.text_section[addr + position] == 0xc3 {
|
if dll.text_section[address + position] == 0xc3 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -236,15 +211,15 @@ impl Dll {
|
||||||
let size = code.size_of_raw_data as usize;
|
let size = code.size_of_raw_data as usize;
|
||||||
let text = &data[start..start+size];
|
let text = &data[start..start+size];
|
||||||
let mut dll = Self {
|
let mut dll = Self {
|
||||||
name: name.clone(),
|
|
||||||
path: path.clone(),
|
|
||||||
bang,
|
bang,
|
||||||
exports: Default::default(),
|
name: name.clone(),
|
||||||
deps_by_library: Default::default(),
|
path: path.clone(),
|
||||||
deps_by_address: Default::default(),
|
exports: Default::default(),
|
||||||
calls_by_source: Default::default(),
|
deps_by_library: Default::default(),
|
||||||
calls_by_target: Default::default(),
|
deps_by_address: Default::default(),
|
||||||
text_section: Arc::from(text),
|
calls_by_source: Default::default(),
|
||||||
|
calls_by_target: Default::default(),
|
||||||
|
text_section: Arc::from(text),
|
||||||
text_section_start: start,
|
text_section_start: start,
|
||||||
text_section_size: size,
|
text_section_size: size,
|
||||||
code_base: match pe.get_valid_nt_headers()? {
|
code_base: match pe.get_valid_nt_headers()? {
|
||||||
|
|
|
||||||
|
|
@ -7,52 +7,19 @@ pub fn fmt_bytes (bytes: &[u8]) -> Arc<str> {
|
||||||
|
|
||||||
pub struct Show;
|
pub struct Show;
|
||||||
|
|
||||||
impl Show {
|
impl Dll {
|
||||||
pub fn num (n: usize) -> Arc<str> {
|
pub fn show_instruction (&self, addr: usize) {
|
||||||
format!("0x{n:>08x}").into()
|
let mut decoder = Decoder::with_ip(64, &self.text_section[addr..], 0x1000, DecoderOptions::NONE);
|
||||||
}
|
|
||||||
pub fn call (dll: &Dll, addr: usize, call: Option<&Arc<Call>>) {
|
|
||||||
let mut decoder = Decoder::with_ip(64, &dll.text_section[addr..], 0x1000, DecoderOptions::NONE);
|
|
||||||
let instruction = decoder.decode();
|
let instruction = decoder.decode();
|
||||||
let is_stack = instruction.is_stack_instruction();
|
let is_stack = instruction.is_stack_instruction();
|
||||||
let is_link = Call::matches(&instruction);
|
let is_link = Call::matches(&instruction);
|
||||||
let style = if is_stack || is_link { BOLD } else { DIM };
|
let style = if is_stack || is_link { BOLD } else { DIM };
|
||||||
print!("{style}{} {:20}{RESET}", Show::num(addr), &dll.name);
|
print!("{style}{} {:20}{RESET}", Show::num(addr), &self.name);
|
||||||
print!(" {style}{:26}{RESET}", fmt_bytes(&dll.text_section[addr..addr+instruction.len()]));
|
print!(" {style}{:26}{RESET}", fmt_bytes(&self.text_section[addr..addr+instruction.len()]));
|
||||||
println!(" {style}{instruction}{RESET}");
|
println!(" {style}{instruction}{RESET}");
|
||||||
}
|
}
|
||||||
pub fn call_target_addrs (
|
pub fn show_call_site (&self, addr: usize, length: usize, context: usize) {
|
||||||
call: Option<&Arc<Call>>
|
let base = self.code_base as usize;
|
||||||
) {
|
|
||||||
println!(" {}{}{}",
|
|
||||||
call.map(|call|format!(" (offset {})", Show::num(call.offset as usize)))
|
|
||||||
.unwrap_or(String::new()),
|
|
||||||
call.map(|call|format!(" (source {})", Show::num(call.source as usize)))
|
|
||||||
.unwrap_or(String::new()),
|
|
||||||
call.map(|call|format!(" (target {})", Show::num(call.target as usize)))
|
|
||||||
.unwrap_or(String::new()));
|
|
||||||
}
|
|
||||||
pub fn call_module_method (
|
|
||||||
call: Option<&Arc<Call>>
|
|
||||||
) {
|
|
||||||
let module = call.map(|call|call.module.as_ref()).flatten();
|
|
||||||
let method = call.map(|call|call.method.as_ref()).flatten();
|
|
||||||
if module.is_some() || method.is_some() {
|
|
||||||
println!(" ╰-------> {GREEN}{}{}{}{RESET}",
|
|
||||||
module.map(|x|x.as_ref()).unwrap_or(&""),
|
|
||||||
if module.is_some() && method.is_some() { "::" } else { "" },
|
|
||||||
method.map(|x|x.as_ref()).unwrap_or(&""));
|
|
||||||
} else {
|
|
||||||
println!(" ╰-------> {RED}(unresolved){RESET} {call:?}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn call_site (
|
|
||||||
dll: &Dll,
|
|
||||||
addr: usize,
|
|
||||||
length: usize,
|
|
||||||
context: usize,
|
|
||||||
) {
|
|
||||||
let base = dll.code_base as usize;
|
|
||||||
let line = 16;
|
let line = 16;
|
||||||
let group = 2;
|
let group = 2;
|
||||||
let snap = |x|(x/line)*line;
|
let snap = |x|(x/line)*line;
|
||||||
|
|
@ -63,9 +30,9 @@ impl Show {
|
||||||
write!(&mut output, "{DIM}");
|
write!(&mut output, "{DIM}");
|
||||||
if byte % line == 0 {
|
if byte % line == 0 {
|
||||||
if (byte >= snap(addr)) && (byte < snap(addr) + line) {
|
if (byte >= snap(addr)) && (byte < snap(addr) + line) {
|
||||||
write!(&mut output, "{RESET} ╭");
|
write!(&mut output, "{RESET}╭─");
|
||||||
} else if byte >= snap(addr) + line {
|
} else if byte >= snap(addr) + line {
|
||||||
write!(&mut output, " ┊");
|
write!(&mut output, "┊ ");
|
||||||
} else {
|
} else {
|
||||||
write!(&mut output, " ");
|
write!(&mut output, " ");
|
||||||
}
|
}
|
||||||
|
|
@ -84,11 +51,11 @@ impl Show {
|
||||||
write!(&mut output, "{}", " ");
|
write!(&mut output, "{}", " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(&mut output, "{:02x}", dll.text_section[byte]);
|
write!(&mut output, "{:02x}", self.text_section[byte]);
|
||||||
write!(&mut output, "{RESET}");
|
write!(&mut output, "{RESET}");
|
||||||
if byte % line == line - 1 {
|
if byte % line == line - 1 {
|
||||||
if snap(byte) == snap(addr) {
|
if snap(byte) == snap(addr) {
|
||||||
let dasm = Self::call_dasm(&dll.text_section[addr..], addr);
|
let dasm = Show::call_dasm(&self.text_section[addr..], addr);
|
||||||
write!(&mut output, " -> {dasm}");
|
write!(&mut output, " -> {dasm}");
|
||||||
}
|
}
|
||||||
write!(&mut output, " \n");
|
write!(&mut output, " \n");
|
||||||
|
|
@ -96,6 +63,33 @@ impl Show {
|
||||||
}
|
}
|
||||||
print!("{output}");
|
print!("{output}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Show {
|
||||||
|
pub fn num (n: usize) -> Arc<str> {
|
||||||
|
format!("0x{n:>08x}").into()
|
||||||
|
}
|
||||||
|
pub fn call_target_addrs (call: Option<&Arc<Call>>) {
|
||||||
|
println!(" {}{}{}",
|
||||||
|
call.map(|call|format!(" (offset {})", Show::num(call.offset as usize)))
|
||||||
|
.unwrap_or(String::new()),
|
||||||
|
call.map(|call|format!(" (source {})", Show::num(call.source as usize)))
|
||||||
|
.unwrap_or(String::new()),
|
||||||
|
call.map(|call|format!(" (target {})", Show::num(call.target as usize)))
|
||||||
|
.unwrap_or(String::new()));
|
||||||
|
}
|
||||||
|
pub fn call_module_method (call: Option<&Arc<Call>>) {
|
||||||
|
let module = call.map(|call|call.module.as_ref()).flatten();
|
||||||
|
let method = call.map(|call|call.method.as_ref()).flatten();
|
||||||
|
if module.is_some() || method.is_some() {
|
||||||
|
println!("╰--------> {GREEN}{}{}{}{RESET}",
|
||||||
|
module.map(|x|x.as_ref()).unwrap_or(&""),
|
||||||
|
if module.is_some() && method.is_some() { "::" } else { "" },
|
||||||
|
method.map(|x|x.as_ref()).unwrap_or(&""));
|
||||||
|
} else {
|
||||||
|
println!("╰--------> {RED}(unresolved){RESET} {call:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn call_dasm (bytes: &[u8], rip: usize) -> Arc<str> {
|
pub fn call_dasm (bytes: &[u8], rip: usize) -> Arc<str> {
|
||||||
let mut decoder = Decoder::with_ip(64, bytes, 0x1000 + rip as u64, DecoderOptions::NONE);
|
let mut decoder = Decoder::with_ip(64, bytes, 0x1000 + rip as u64, DecoderOptions::NONE);
|
||||||
while decoder.can_decode() {
|
while decoder.can_decode() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue