Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ members = [
[profile.release]
debug = 0
strip = true
opt-level = 2
opt-level = 3
panic = 'unwind'

[profile.dev]
Expand Down
1 change: 0 additions & 1 deletion crates/libmwemu/src/banzai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,4 @@ impl Banzai {
pub fn add(&mut self, name: &str, nparams: i32) {
self.api_params.insert(name.to_string(), nparams);
}

}
13 changes: 10 additions & 3 deletions crates/libmwemu/src/breakpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ impl Default for Breakpoints {
}
}


impl Breakpoints {
// TODO: implementing clearing breakpoint for console
pub fn new() -> Self {
Expand Down Expand Up @@ -109,10 +108,18 @@ impl Breakpoints {
let instruction_str: Vec<String> = self.addr.iter().map(|a| format!("0x{:x}", a)).collect();
log::info!("break on instruction: [{}]", instruction_str.join(", ")); // Uses Debug formatting for the whole vector

let mem_read_str: Vec<String> = self.mem_read_addr.iter().map(|a| format!("0x{:x}", a)).collect();
let mem_read_str: Vec<String> = self
.mem_read_addr
.iter()
.map(|a| format!("0x{:x}", a))
.collect();
log::info!("break on memory read: [{}]", mem_read_str.join(", "));

let mem_write_str: Vec<String> = self.mem_write_addr.iter().map(|a| format!("0x{:x}", a)).collect();
let mem_write_str: Vec<String> = self
.mem_write_addr
.iter()
.map(|a| format!("0x{:x}", a))
.collect();
log::info!("break on memory write: [{}]", mem_write_str.join(", "));
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/libmwemu/src/colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub struct Colors {
pub clear_screen: String,
}


impl Default for Colors {
fn default() -> Self {
Self::new()
Expand Down
14 changes: 7 additions & 7 deletions crates/libmwemu/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use crate::{constants, definitions::Definition};
use serde::{Deserialize, Serialize};

#[derive(Clone, Serialize, Deserialize)]
pub struct Config {
pub filename: String, // filename with full path included
pub trace_mem: bool, // show memory operations in every step.
pub filename: String, // filename with full path included
pub trace_mem: bool, // show memory operations in every step.
pub trace_calls: bool, // trace every call
pub trace_regs: bool, // show all the regs in every step.
pub trace_reg: bool, // show value and content of a reg in every step.
pub trace_regs: bool, // show all the regs in every step.
pub trace_reg: bool, // show value and content of a reg in every step.
pub trace_filename: Option<String>,
pub trace_start: u64,
pub trace_string: bool,
Expand Down Expand Up @@ -39,7 +39,7 @@ pub struct Config {
pub skip_unimplemented: bool,
pub stack_addr: u64,
pub arguments: String,
pub enable_threading: bool, // Enable multi-threading support
pub enable_threading: bool, // Enable multi-threading support
pub verbose_at: Option<u64>,
pub command: Option<String>,
pub definitions: HashMap<u64, Definition>,
Expand Down Expand Up @@ -89,7 +89,7 @@ impl Config {
skip_unimplemented: false,
stack_addr: 0,
arguments: "".to_string(),
enable_threading: false, // Default to single-threaded for backward compatibility
enable_threading: false, // Default to single-threaded for backward compatibility
verbose_at: None,
command: None,
definitions: HashMap::new(),
Expand Down
73 changes: 36 additions & 37 deletions crates/libmwemu/src/console.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
use std::io::Write;
use std::num::ParseIntError;
use std::sync::atomic;
use crate::emu::Emu;
use crate::peb::peb32;
use crate::peb::peb64;
Expand All @@ -9,11 +6,15 @@ use crate::structures;
use crate::to32;
use crate::winapi::winapi32;
use crate::winapi::winapi64;
use std::io::Write;
use std::num::ParseIntError;
use std::sync::atomic;

// if the user types "r2 0x123" will execute radare2
use std::process::{Command, Stdio};
use crate::maps::mem64::Permission;
use std::fs;
use std::io;
use std::process::{Command, Stdio};

pub struct Console {}

Expand Down Expand Up @@ -163,22 +164,25 @@ impl Console {
}

pub fn spawn_radare2(addr: u64, emu: &mut Emu) {

let mem = match emu.maps.get_mem_by_addr(addr) {
Some(m) => m,
None => {
log::info!("address not found on any map");
return
return;
}
};

let tmpfile = format!("/tmp/{}.r2", mem.get_name());
mem.save_all(&tmpfile);

let base = format!("0x{:x}",mem.get_base());
let seek = format!("0x{:x}",addr);
let base = format!("0x{:x}", mem.get_base());
let seek = format!("0x{:x}", addr);
let bits;
if emu.cfg.is_64bits { bits = "64" } else { bits = "32" }
if emu.cfg.is_64bits {
bits = "64"
} else {
bits = "32"
}
let precmd = format!("dr rax={}?; dr rbx={}?; dr rcx={}?; dr rdx={}?; dr rsi={}?;
dr rdi={}?; dr rbp={}?; dr rsp={}?; dr rip={}?; dr r8={}?
dr r9={}?; dr r10={}?; dr r11={}?; dr r12={}?; dr r13={}?;
Expand All @@ -189,30 +193,25 @@ impl Console {
emu.regs().r11, emu.regs().r12, emu.regs().r13, emu.regs().r14,
emu.regs().r15);
let r2args = vec![
"-n",
"-a", "x86",
"-b", &bits,
"-m", &base,
"-s", &seek,
"-c", &precmd,
&tmpfile
"-n", "-a", "x86", "-b", &bits, "-m", &base, "-s", &seek, "-c", &precmd, &tmpfile,
];

log::info!("spawning radare2 software.");

match Command::new("radare2")
.args(&r2args)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn() {
Ok(mut child) => {
let _ = child.wait();
}
Err(e) => {
log::error!("Install radare first! {}", e);
return
}
.spawn()
{
Ok(mut child) => {
let _ = child.wait();
}
Err(e) => {
log::error!("Install radare first! {}", e);
return;
}
}

if let Err(e) = fs::remove_file(&tmpfile) {
Expand All @@ -222,7 +221,6 @@ impl Console {
}
}


pub fn spawn_console(emu: &mut Emu) {
if !emu.cfg.console_enabled {
return;
Expand Down Expand Up @@ -520,7 +518,7 @@ impl Console {
}
};
emu.maps
.create_map(&name, addr, sz)
.create_map(&name, addr, sz, Permission::READ_WRITE_EXECUTE)
.expect("cannot create map from console mc");
log::info!("allocated {} at 0x{:x} sz: {}", name, addr, sz);
}
Expand All @@ -546,7 +544,7 @@ impl Console {
};

emu.maps
.create_map(&name, addr, sz)
.create_map(&name, addr, sz, Permission::READ_WRITE_EXECUTE)
.expect("cannot create map from console mca");
log::info!("allocated {} at 0x{:x} sz: {}", name, addr, sz);
}
Expand Down Expand Up @@ -578,7 +576,10 @@ impl Console {
}
};

let mem = emu.maps.get_mem_by_addr(addr).expect("address not found on any map");
let mem = emu
.maps
.get_mem_by_addr(addr)
.expect("address not found on any map");
if emu.cfg.is_64bits {
log::info!(
"map: {} 0x{:x}-0x{:x} ({})",
Expand Down Expand Up @@ -1033,14 +1034,13 @@ impl Console {
if parts.len() >= 2 {
emu.maps.print_maps_keyword(&parts[1]);
}

} else if cmd.starts_with("r2 ") {
let parts: Vec<&str> = cmd.split_whitespace().collect();
if parts.len() >= 2 {
if let Ok(addr) = u64::from_str_radix(parts[1].trim_start_matches("0x"), 16) {

let parts: Vec<&str> = cmd.split_whitespace().collect();
if parts.len() >= 2 {
if let Ok(addr) =
u64::from_str_radix(parts[1].trim_start_matches("0x"), 16)
{
Console::spawn_radare2(addr, emu);

} else {
println!("wrong hexa parameter");
}
Expand All @@ -1052,11 +1052,10 @@ impl Console {
}
}
} // match commands

if emu.cfg.command.is_some() {
std::process::exit(1);
}

} // end loop
} // end commands function
}
6 changes: 2 additions & 4 deletions crates/libmwemu/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,8 @@ pub const INTERNET_FLAG_SECURE: u64 = 0x00800000;
// exceptions
pub const EXCEPTION_CONTINUE_EXECUTION32: u32 = 0xffffffff;
pub const EXCEPTION_CONTINUE_EXECUTION64: u64 = 0xffffffff_ffffffff;
pub const EXCEPTION_CONTINUE_SEARCH: u32 = 0x00000000;
pub const EXCEPTION_EXECUTE_HANDLER: u32 = 0x00000001;

pub const EXCEPTION_CONTINUE_SEARCH: u32 = 0x00000000;
pub const EXCEPTION_EXECUTE_HANDLER: u32 = 0x00000001;

pub const ERROR_NO_MORE_FILES: u64 = 18;
pub const CREATE_SUSPENDED: u64 = 0x00000004;
Expand All @@ -119,7 +118,6 @@ pub const STATUS_READING_XMM_OPERAND: u32 = 0xE000000A;
pub const STATUS_WRITING_XMM_OPERAND: u32 = 0xE000000B;
pub const STATUS_READING_RIP: u32 = 0xE000000C;


pub const PAGE_NOACCESS: u32 = 0x01;
pub const PAGE_EXECUTE: u32 = 0x00;
pub const PAGE_READONLY: u32 = 0x02;
Expand Down
6 changes: 3 additions & 3 deletions crates/libmwemu/src/crit_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::VecDeque;

#[derive(Debug, Clone)]
pub struct CritState {
pub owner_tid: Option<u64>, // Thread ID currently owning the lock
pub recursion_count: usize, // Recursive enter count
pub wait_queue: VecDeque<u64>, // Waiting thread IDs
pub owner_tid: Option<u64>, // Thread ID currently owning the lock
pub recursion_count: usize, // Recursive enter count
pub wait_queue: VecDeque<u64>, // Waiting thread IDs
}
44 changes: 25 additions & 19 deletions crates/libmwemu/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,17 @@ where
{
let s: String = serde::Deserialize::deserialize(deserializer)?;
if s.starts_with("0x") {
u64::from_str_radix(&s[2..], 16)
.map_err(|e| serde::de::Error::custom(e))
u64::from_str_radix(&s[2..], 16).map_err(|e| serde::de::Error::custom(e))
} else {
s.parse::<u64>()
.map_err(|e| serde::de::Error::custom(e))
s.parse::<u64>().map_err(|e| serde::de::Error::custom(e))
}
}

pub fn load_definitions(filename: &str) -> HashMap<u64, Definition> {
let contents = fs::read_to_string(filename)
.expect("Failed to read definitions file");

let definitions: Definitions = serde_yaml::from_str(&contents)
.expect("Failed to parse YAML");

let contents = fs::read_to_string(filename).expect("Failed to read definitions file");

let definitions: Definitions = serde_yaml::from_str(&contents).expect("Failed to parse YAML");

let mut map = HashMap::new();
for def in definitions.events {
map.insert(def.address, def);
Expand All @@ -69,18 +65,28 @@ impl Emu {
let rip = self.regs().rip;
let definitions = &self.cfg.definitions;
if let Some(definition) = definitions.get(&rip) {
log::info!("Event: {} (0x{:x}) - {}", definition.name, rip, definition.event_type);

log::info!(
"Event: {} (0x{:x}) - {}",
definition.name,
rip,
definition.event_type
);

// Store context if needed
if let Some(context_name) = &definition.store_context {
let mut context_values = HashMap::new();
for param in &definition.parameters {
let value = self.resolve_source(&param.source);
context_values.insert(param.name.clone(), value);
}
self.stored_contexts.insert(context_name.clone(), StoredContext { values: context_values });
self.stored_contexts.insert(
context_name.clone(),
StoredContext {
values: context_values,
},
);
}

// Display parameters
for param in &definition.parameters {
let value = self.resolve_source(&param.source);
Expand All @@ -89,10 +95,10 @@ impl Emu {
}
}
}

fn resolve_source(&self, source: &str) -> u64 {
let parts: Vec<&str> = source.split(':').collect();

match parts[0] {
"deref" => {
// deref:context:context_name:param_name or deref:register
Expand Down Expand Up @@ -128,7 +134,7 @@ impl Emu {
}
}
}

fn get_parameter_value(&self, source: &str) -> u64 {
match source {
"rcx" => self.regs().rcx,
Expand Down Expand Up @@ -156,7 +162,7 @@ impl Emu {
}
}
}

fn format_parameter_value(&self, value: u64, param_type: &str) -> String {
match param_type {
"pointer" => format!("0x{:x}", value),
Expand All @@ -176,4 +182,4 @@ impl Emu {
_ => format!("0x{:x}", value),
}
}
}
}
Loading
Loading