summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2023-10-20 22:40:26 +0200
committerSanto Cariotti <santo@dcariotti.me>2023-10-20 22:40:26 +0200
commit10f48592388c78f93487ea96bcc9ad40c4864584 (patch)
treebfff7a3980baa242c86f478fee11679a37142878
parent2fa8e3c69079f9fa4ebbf0adba7ac319a55fa8fe (diff)
Show buffer value
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--src/registers.rs40
-rw-r--r--src/trace.rs56
-rw-r--r--src/ui.rs4
5 files changed, 92 insertions, 16 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ab31cd2..c68ac81 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -96,6 +96,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -431,6 +437,7 @@ name = "sigma"
version = "0.0.1"
dependencies = [
"anyhow",
+ "byteorder",
"chrono",
"clap",
"crossterm",
diff --git a/Cargo.toml b/Cargo.toml
index aecc7e7..ce7ba77 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ authors = ["Santo Cariotti <santo@dcariotti.me>"]
[dependencies]
anyhow = "1.0.75"
+byteorder = "1.5.0"
chrono = "0.4.31"
clap = { version = "4.4.6", features = ["derive"] }
crossterm = "0.27.0"
diff --git a/src/registers.rs b/src/registers.rs
index c42bb12..44d7271 100644
--- a/src/registers.rs
+++ b/src/registers.rs
@@ -1,5 +1,5 @@
use chrono::{DateTime, Local};
-use nix::libc::user_regs_struct;
+use nix::{libc::user_regs_struct, unistd::Pid};
use owo_colors::OwoColorize;
use ratatui::{
prelude::{Line, Span, Style},
@@ -10,9 +10,10 @@ use ratatui::{
use crate::arch::linux::x86_64::*;
#[cfg(not(all(target_arch = "x86_64", target_os = "linux")))]
use crate::arch::syscall_name;
+use crate::trace::read_memory;
/// Struct used to manipulate registers data from https://docs.rs/libc/0.2.147/libc/struct.user_regs_struct.html
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
pub struct RegistersData {
timestamp: DateTime<Local>,
orig_rax: u64,
@@ -52,10 +53,10 @@ impl RegistersData {
}
/// Returns a good string which shows the output for a line
- pub fn output(&self) -> String {
+ pub fn output(&self, pid: Pid) -> String {
let mut output = format!("[{}]: ", self.date());
- if self.name().len() > 0 {
+ if !self.name().is_empty() {
output.push_str(&format!("{}(", self.name().bold()));
} else {
output.push_str(&format!("{}(", self.orig_rax.yellow().bold()));
@@ -73,9 +74,16 @@ impl RegistersData {
];
for param in params {
- if param.1.len() != 0 {
+ if !param.1.is_empty() {
let output_param = param.1.to_owned() + ":";
- output.push_str(&format!("{} {}, ", output_param.blue(), param.0));
+ let output_value = if output_param.starts_with("const char *")
+ || output_param.starts_with("char *")
+ {
+ read_memory(pid, param.0)
+ } else {
+ param.0.to_string()
+ };
+ output.push_str(&format!("{} {}, ", output_param.blue(), output_value));
has_param = true;
}
}
@@ -90,10 +98,10 @@ impl RegistersData {
}
/// Returns a good line for TUI
- pub fn output_ui(&self) -> Line {
+ pub fn output_ui(&self, pid: Pid) -> Line {
let mut spans: Vec<Span> = vec![];
spans.push(Span::raw(format!("[{}]: ", self.date())));
- if self.name().len() > 0 {
+ if !self.name().is_empty() {
spans.push(Span::styled(
format!("{}(", self.name()),
Style::default().add_modifier(Modifier::BOLD),
@@ -117,13 +125,25 @@ impl RegistersData {
];
for param in params {
- if param.1.len() != 0 {
+ if !param.1.is_empty() {
let output_param = param.1.to_owned() + ":";
spans.push(Span::styled(
format!("{} ", output_param),
Style::default().fg(Color::Blue),
));
- spans.push(Span::styled(format!("{}, ", param.0), Style::default()));
+
+ // FIXME: read memory does not work
+ let output_value = if output_param.starts_with("const char *")
+ || output_param.starts_with("char *")
+ {
+ read_memory(pid, param.0)
+ } else {
+ param.0.to_string()
+ };
+ spans.push(Span::styled(
+ format!("{}, ", output_value),
+ Style::default(),
+ ));
}
}
diff --git a/src/trace.rs b/src/trace.rs
index 157f2e7..e424d09 100644
--- a/src/trace.rs
+++ b/src/trace.rs
@@ -1,5 +1,6 @@
use crate::cli::Args;
use crate::registers::RegistersData;
+use byteorder::{LittleEndian, WriteBytesExt};
use nix::{
sys::{
ptrace,
@@ -11,7 +12,7 @@ use nix::{
use std::{
fs::File,
io::{self, Write},
- os::unix::process::CommandExt,
+ os::{raw::c_void, unix::process::CommandExt},
process::{Command, Stdio},
str,
};
@@ -60,7 +61,7 @@ pub fn trace(pid: Pid, args: &Args) -> anyhow::Result<Vec<RegistersData>> {
let mut have_to_print = true;
let filters: Vec<&str> = match &args.filter {
- Some(filter) => filter.split(",").collect::<Vec<&str>>(),
+ Some(filter) => filter.split(',').collect::<Vec<&str>>(),
None => vec![],
};
while let Some(reg) = trace_next(pid)? {
@@ -71,11 +72,11 @@ pub fn trace(pid: Pid, args: &Args) -> anyhow::Result<Vec<RegistersData>> {
}
if let Some(ref mut f) = f {
- writeln!(f, "{}", reg.output())?;
+ writeln!(f, "{}", reg.output(pid))?;
}
if args.no_tui {
- writeln!(io::stdout(), "{}", reg.output())?;
+ writeln!(io::stdout(), "{}", reg.output(pid))?;
}
lines.push(reg);
@@ -84,6 +85,53 @@ pub fn trace(pid: Pid, args: &Args) -> anyhow::Result<Vec<RegistersData>> {
Ok(lines)
}
+/// Read memory and returns a string.
+/// Thank you https://github.com/JakWai01/lurk/blob/e3a3d6c026bbf818fe1329f8d458be544c3c5ebc/src/arch/mod.rs#L66
+pub fn read_memory(pid: Pid, address: u64) -> String {
+ let mut string = String::new();
+
+ let mut count = 0;
+ let word_size = 8;
+
+ loop {
+ let address = unsafe { (address as *mut c_void).offset(count) };
+
+ match ptrace::read(pid, address) {
+ Ok(read) => {
+ let mut bytes: Vec<u8> = vec![];
+ bytes.write_i64::<LittleEndian>(read).unwrap_or_else(|err| {
+ panic!("Failed to write {read} as i64 LittleEndian: {err}");
+ });
+
+ if !bytes
+ .iter()
+ .filter(|&b| *b == 0x0)
+ .collect::<Vec<&u8>>()
+ .is_empty()
+ {
+ break;
+ }
+
+ bytes.iter().for_each(|b| {
+ string.push(*b as char);
+ });
+
+ count += word_size;
+ }
+ Err(_) => break,
+ };
+ }
+
+ if string.len() > 24 {
+ string = string[..24].to_string();
+ string.push_str("...");
+ }
+
+ string = string.replace('\n', "\\n");
+
+ format!("\"{string}\"")
+}
+
/// Get the next step for a ptrace process
pub fn trace_next(pid: Pid) -> anyhow::Result<Option<RegistersData>> {
ptrace::syscall(pid, None)?;
diff --git a/src/ui.rs b/src/ui.rs
index b7e342d..f846349 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -35,7 +35,7 @@ impl UI {
}
pub fn get_paragraph(&self, pid: Pid) -> Paragraph {
- let lines: Vec<Line> = self.lines.iter().map(|x| x.output_ui()).collect();
+ let lines: Vec<Line> = self.lines.iter().map(|x| x.output_ui(pid)).collect();
let paragraph = Paragraph::new(lines)
.block(
Block::default()
@@ -77,7 +77,7 @@ impl UI {
}
let filters: Vec<&str> = match &args.filter {
- Some(filter) => filter.split(",").collect::<Vec<&str>>(),
+ Some(filter) => filter.split(',').collect::<Vec<&str>>(),
None => vec![],
};
while !should_quit {