From 88ee260cdeb05483226572a1baf5cb9828a951a4 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 23 Feb 2025 00:15:54 +0200 Subject: [PATCH] resolve broader --- crates/vestal/src/main.rs | 59 ++++++++-------------------- crates/vestal/src/show.rs | 82 ++++++++++++++++++--------------------- 2 files changed, 55 insertions(+), 86 deletions(-) diff --git a/crates/vestal/src/main.rs b/crates/vestal/src/main.rs index e4fc7d8..fbd12d4 100644 --- a/crates/vestal/src/main.rs +++ b/crates/vestal/src/main.rs @@ -91,10 +91,8 @@ impl Vestal { Ok(None) } 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() { - println!(); - println!("{:11}{BOLD}{}{RESET}", "", dll.name); self.resolve_call(dll, *addr, call, recurse, verbose)?; } Ok(()) @@ -108,7 +106,7 @@ impl Vestal { verbose: bool, ) -> Usually<()> { 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)); if let Some(method) = dll.parse_call(call) { let module_name = call.module.as_ref().unwrap(); @@ -136,41 +134,18 @@ impl Vestal { } fn resolve_call_recurse ( &self, - dll: &Dll, - addr: usize, + dll: &Dll, + address: usize, module_name: &Arc, method_name: &Arc, ) -> Usually<()> { - println!("\n {RESET} {BOLD}{} ({method_name}){RESET}", &dll.name); - //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); + let mut decoder = Decoder::with_ip(64, &dll.text_section[address..], 0, DecoderOptions::NONE); while decoder.can_decode() { - let position = decoder.position(); - let instruction = decoder.decode(); - let opcodes = &dll.text_section[position..position+instruction.len()]; - 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))); + let position = decoder.position(); + if let Some(call) = dll.collect_call(&mut decoder, true)? { + println!("(call {call:#?}"); } - if dll.text_section[addr + position] == 0xc3 { + if dll.text_section[address + position] == 0xc3 { break } } @@ -236,15 +211,15 @@ impl Dll { let size = code.size_of_raw_data as usize; let text = &data[start..start+size]; let mut dll = Self { - name: name.clone(), - path: path.clone(), bang, - exports: Default::default(), - deps_by_library: Default::default(), - deps_by_address: Default::default(), - calls_by_source: Default::default(), - calls_by_target: Default::default(), - text_section: Arc::from(text), + name: name.clone(), + path: path.clone(), + exports: Default::default(), + deps_by_library: Default::default(), + deps_by_address: Default::default(), + calls_by_source: Default::default(), + calls_by_target: Default::default(), + text_section: Arc::from(text), text_section_start: start, text_section_size: size, code_base: match pe.get_valid_nt_headers()? { diff --git a/crates/vestal/src/show.rs b/crates/vestal/src/show.rs index f1f9738..fc13679 100644 --- a/crates/vestal/src/show.rs +++ b/crates/vestal/src/show.rs @@ -7,52 +7,19 @@ pub fn fmt_bytes (bytes: &[u8]) -> Arc { pub struct Show; -impl Show { - pub fn num (n: usize) -> Arc { - format!("0x{n:>08x}").into() - } - pub fn call (dll: &Dll, addr: usize, call: Option<&Arc>) { - let mut decoder = Decoder::with_ip(64, &dll.text_section[addr..], 0x1000, DecoderOptions::NONE); +impl Dll { + pub fn show_instruction (&self, addr: usize) { + let mut decoder = Decoder::with_ip(64, &self.text_section[addr..], 0x1000, DecoderOptions::NONE); let instruction = decoder.decode(); let is_stack = instruction.is_stack_instruction(); let is_link = Call::matches(&instruction); let style = if is_stack || is_link { BOLD } else { DIM }; - print!("{style}{} {:20}{RESET}", Show::num(addr), &dll.name); - print!(" {style}{:26}{RESET}", fmt_bytes(&dll.text_section[addr..addr+instruction.len()])); + print!("{style}{} {:20}{RESET}", Show::num(addr), &self.name); + print!(" {style}{:26}{RESET}", fmt_bytes(&self.text_section[addr..addr+instruction.len()])); println!(" {style}{instruction}{RESET}"); } - pub fn call_target_addrs ( - call: Option<&Arc> - ) { - 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> - ) { - 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; + pub fn show_call_site (&self, addr: usize, length: usize, context: usize) { + let base = self.code_base as usize; let line = 16; let group = 2; let snap = |x|(x/line)*line; @@ -63,9 +30,9 @@ impl Show { write!(&mut output, "{DIM}"); if byte % line == 0 { if (byte >= snap(addr)) && (byte < snap(addr) + line) { - write!(&mut output, "{RESET} ╭"); + write!(&mut output, "{RESET}╭─"); } else if byte >= snap(addr) + line { - write!(&mut output, " ┊"); + write!(&mut output, "┊ "); } else { write!(&mut output, " "); } @@ -84,11 +51,11 @@ impl Show { write!(&mut output, "{}", " "); } } - write!(&mut output, "{:02x}", dll.text_section[byte]); + write!(&mut output, "{:02x}", self.text_section[byte]); write!(&mut output, "{RESET}"); if byte % line == line - 1 { 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, " \n"); @@ -96,6 +63,33 @@ impl Show { } print!("{output}"); } +} + +impl Show { + pub fn num (n: usize) -> Arc { + format!("0x{n:>08x}").into() + } + pub fn call_target_addrs (call: Option<&Arc>) { + 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>) { + 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 { let mut decoder = Decoder::with_ip(64, bytes, 0x1000 + rip as u64, DecoderOptions::NONE); while decoder.can_decode() {