Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dynamic): support running binaries with CLI arguments #49

Merged
merged 2 commits into from
Sep 23, 2024
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::os::windows::fs::MetadataExt;
pub struct FileInfo<'a> {
/// Path of the file.
pub path: &'a str,
/// Arguments of the file.
pub arguments: Option<Vec<&'a str>>,
/// Bytes of the file.
pub bytes: &'a [u8],
/// Whether if the file is read only.
Expand Down Expand Up @@ -70,14 +72,15 @@ pub struct FileDateInfo {
impl<'a> FileInfo<'a> {
/// Constructs a new instance.
#[cfg(not(target_os = "windows"))]
pub fn new(path: &'a str, bytes: &'a [u8]) -> Result<Self> {
pub fn new(path: &'a str, arguments: Option<Vec<&'a str>>, bytes: &'a [u8]) -> Result<Self> {
let metadata = fs::metadata(path)?;
let mode = metadata.permissions().mode();

let users = Users::new_with_refreshed_list();
let groups = Groups::new_with_refreshed_list();
Ok(Self {
path,
arguments,
bytes,
is_read_only: false,
name: PathBuf::from(path)
Expand Down Expand Up @@ -150,7 +153,7 @@ impl<'a> FileInfo<'a> {
}

#[cfg(target_os = "windows")]
pub fn new(path: &'a str, bytes: &'a [u8]) -> Result<Self> {
pub fn new(path: &'a str, arguments: Option<Vec<&'a str>>, bytes: &'a [u8]) -> Result<Self> {
unimplemented!()
}

Expand Down
13 changes: 10 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use file::FileInfo;
use prelude::*;
use ratatui::backend::CrosstermBackend;
use ratatui::Terminal;
use std::{env, fs, io};
use std::{env, fs, io, path::PathBuf};
use tui::{state::State, ui::Tab, Tui};

/// Runs binsider.
Expand All @@ -43,6 +43,13 @@ pub fn run(mut args: Args) -> Result<()> {
args.files.push(env::current_exe()?);
}
let mut path = args.files[args.files.len() - 1].clone();
let mut arguments = None;
let path_str = path.to_string_lossy().to_string();
let mut parts = path_str.split_whitespace();
if let Some(bin) = parts.next() {
path = PathBuf::from(bin);
arguments = Some(parts.collect());
}
if !path.exists() {
let resolved_path = which::which(path.to_string_lossy().to_string())?;
if let Some(file) = args.files.iter_mut().find(|f| **f == path) {
Expand All @@ -52,7 +59,7 @@ pub fn run(mut args: Args) -> Result<()> {
}
let file_data = fs::read(&path)?;
let bytes = file_data.as_slice();
let file_info = FileInfo::new(path.to_str().unwrap_or_default(), bytes)?;
let file_info = FileInfo::new(path.to_str().unwrap_or_default(), arguments, bytes)?;
let analyzer = Analyzer::new(file_info, args.min_strings_len, args.files.clone())?;
start_tui(analyzer, args)
}
Expand Down Expand Up @@ -105,7 +112,7 @@ pub fn start_tui(analyzer: Analyzer, args: Args) -> Result<()> {
Event::Trace => {
state.system_calls_loaded = false;
tui.toggle_pause()?;
tracer::trace_syscalls(state.analyzer.file.path, tui.events.sender.clone());
tracer::trace_syscalls(&state.analyzer.file, tui.events.sender.clone());
}
#[cfg(feature = "dynamic-analysis")]
Event::TraceResult(syscalls) => {
Expand Down
10 changes: 7 additions & 3 deletions src/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ use lurk_cli::Tracer;
use nix::sys::wait::{waitpid, WaitPidFlag};

use crate::error::{Error, Result};
use crate::file::FileInfo;
use crate::tui::event::Event;
use crate::TraceData;

use nix::unistd::{fork, ForkResult};

/// Trace system calls and signals.
pub fn trace_syscalls(command: &str, event_sender: mpsc::Sender<Event>) {
pub fn trace_syscalls(file: &FileInfo, event_sender: mpsc::Sender<Event>) {
let event_sender = event_sender.clone();
let command = command.to_string();
let mut command = vec![file.path.to_string()];
if let Some(args) = &file.arguments {
command.extend(args.iter().map(|s| s.to_string()));
}
thread::spawn(move || {
let run_tracer = || -> Result<()> {
let pid = match unsafe { fork() } {
Ok(ForkResult::Child) => {
return lurk_cli::run_tracee(&[command], &[], &None)
return lurk_cli::run_tracee(&command, &[], &None)
.map_err(|e| Error::TraceError(e.to_string()))
}
Ok(ForkResult::Parent { child }) => child,
Expand Down