diff --git a/Cargo.toml b/Cargo.toml index 29bd05b..16b2c99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] ctor = "0.5.0" libc = "0.2.175" +pretty_env_logger = "0.5.0" # syscalls = "0.6.18" syscall_lib = { path = "syscall_lib" } syscaller = "0.2.2" diff --git a/README.md b/README.md index 5a9e618..0b57157 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ TODO: -[ ] - Copy memory over network +- [ ] - Copy memory over network +- [ ] - Stream std buffers over network Server: - [x] - Intercept syscalls - [x] - Transmit syscalls over network - [x] - Read memory from buffers. - [ ] - Mutate syscalls into Rust - [ ] - Figure out which system calls should be forwarded and not +- [x] - Intercept syscalls +- [x] - Transmit syscalls over network +- [x] - Read memory from buffers. +- [ ] - Mutate all syscalls into Rust +- [ ] - Figure out which system calls should be forwarded and not Mimic: - [x] - Execute syscalls - [ ] - Mutate syscalls back into C - [ ] - Create subprocess and mimic system calls in it. +- [x] - Execute syscalls +- [ ] - Mutate all syscalls back into C +- [ ] - Create subprocess and mimic system calls in it. diff --git a/client/Cargo.toml b/client/Cargo.toml index 69c4a8c..ae3ec10 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -4,4 +4,10 @@ version = "0.1.0" edition = "2024" [dependencies] +log = "0.4.27" +nix = { version = "0.30.1", features = ["ptrace"] } +pretty_env_logger = "0.5.0" +subprocess = "0.2.9" syscall_lib = { path = "../syscall_lib" } +syscalls = "0.6.18" +thiserror = "2.0.16" diff --git a/client/src/main.rs b/client/src/main.rs index 7867c26..2b8fa46 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,13 +1,33 @@ +use std::ffi::CString; +use std::io; +use std::net::TcpListener; +use std::time::Duration; use std::{ io::{Read, Write}, - net::{TcpListener, TcpStream}, + net::TcpStream, thread, }; +use log::{error, info, trace}; +use nix::libc::{self, MAP_ANONYMOUS, MAP_PRIVATE, PROT_READ, PROT_WRITE, user_regs_struct}; +use nix::unistd::Pid; +use subprocess::{Popen, PopenConfig, Redirection}; use syscall_lib::Syscall; +use syscalls::Sysno; -fn main() { - println!("This program has PID: {}", std::process::id()); +use crate::proc::UserProcess; + +mod proc; +mod sleeper; + +fn main() -> io::Result<()> { + pretty_env_logger::formatted_builder() + .filter_level(log::LevelFilter::Trace) + .init(); + + log::info!("This program has PID: {}", std::process::id()); + + // run()?; let listener = TcpListener::bind("127.0.0.1:1234").unwrap(); @@ -16,16 +36,20 @@ fn main() { thread::spawn(move || { let _ = handle_connection(&mut stream); - println!("Connection from {} closed", stream.peer_addr().unwrap()); + info!("Connection from {} closed", stream.peer_addr().unwrap()); }); } + + Ok(()) } fn handle_connection(stream: &mut TcpStream) -> Result<(), std::io::Error> { - println!("Got connection from {}", stream.peer_addr()?); + info!("Got connection from {}", stream.peer_addr()?); // let mut memory = ProgramMemory::default(); + let puppet = create_new_proc(); + loop { let mut size_buf = [0u8; 4]; stream.read_exact(&mut size_buf)?; @@ -35,19 +59,38 @@ fn handle_connection(stream: &mut TcpStream) -> Result<(), std::io::Error> { stream.read_exact(&mut buf)?; - let decoded = Syscall::decode(&buf).unwrap(); + let syscall = Syscall::decode(&buf).unwrap(); - println!("{:?} -> ", decoded); + trace!("{:?}", syscall); // let result = match decoded { // Syscall::Write(..) => 0, // _ => syscall_exec::execute_syscall(decoded), // }; - let result = unsafe { decoded.execute_syscall() }; + + let args = syscall.to_syscall_args(); + + let result = puppet.sys_call( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], + ); + + let result = match result { + Ok(n) => n, + Err(e) => { + error!("Error: {}", e.to_string()); + return Ok(()); + } + }; + + let result = result.rax; + + // let result: u64 = result.unwrap().rax; + + // result.r // let result = 0; - println!("{:?}", result); + trace!("{:?} -> {:?}", syscall, result); let bytes: [u8; 8] = result.to_be_bytes(); stream.write_all(&bytes)?; @@ -85,3 +128,63 @@ fn handle_connection(stream: &mut TcpStream) -> Result<(), std::io::Error> { // println!("{:?}", decoded); } } + +fn create_new_proc() -> UserProcess { + //TODO: Improve + let mut p = Popen::create( + &["sleep", "9999999999s"], + PopenConfig { + // stdout: Redirection::Pipe, + ..Default::default() + }, + ) + .unwrap(); + + let pid = Pid::from_raw(p.pid().unwrap() as libc::pid_t); + + // Attach to the process + UserProcess::attach(pid).unwrap() +} + +// fn run() -> io::Result<()> { +// // Refactor out the expect later, but the input should never fail because we know the input does not contain an internal 0 byte. +// let output_message = CString::new("/tmp").expect("CString::new failed"); + +// // We want the bytes of the Cstring. +// let output_message = output_message.as_bytes(); + +// // Allocate 8 bytes of data, i64 is 8 bytes +// let mut user_memory = user_process +// .allocate_memory( +// 0, +// output_message.len() as u64, +// (PROT_READ | PROT_WRITE) as u64, +// (MAP_PRIVATE | MAP_ANONYMOUS) as u64, +// u64::MAX, +// 0, +// ) +// .unwrap(); + +// log::info!("UserMemory Result Address: {:#X}", user_memory.address()); + +// // Read the memory and demonstrate it is zero'd out +// let read = user_process +// .read_user_memory(&user_memory, user_memory.len() as usize) +// .unwrap(); +// log::info!("Allocated Memory: {:?}", read); + +// // Write to the memory out cstring +// user_process +// .write_user_memory(&mut user_memory, 0, output_message) +// .unwrap(); + +// // We can check if the call succeeded by the resultant rax value. +// let result = user_process +// .sys_call(Sysno::chdir, user_memory.address(), 0, 0, 0, 0, 0) +// .unwrap() +// .rax; + +// log::info!("Result {result:?}"); + +// Ok(()) +// } diff --git a/client/src/proc.rs b/client/src/proc.rs new file mode 100644 index 0000000..12eb8f4 --- /dev/null +++ b/client/src/proc.rs @@ -0,0 +1,273 @@ +// Full credit to https://github.com/ohchase/ptrace_syscalls/tree/master + +use std::vec; + +use nix::{ + libc::user_regs_struct, + sys::{ + ptrace, + signal::Signal::SIGTRAP, + wait::{WaitStatus, waitpid}, + }, + unistd::Pid, +}; +use syscalls::Sysno; + +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum HostError { + #[error("Process not found `{0}`")] + ProcessNotFound(String), + #[error("Nix Error `{0}`")] + NixError(#[from] nix::errno::Errno), + #[error("Unexpected Wait Status `{0:#?}`")] + UnexpectedWaitStatus(WaitStatus), + #[error("StdIo Error `{0}`")] + Io(#[from] std::io::Error), + #[error("Mmap Error `{0:#?}`")] + MmapBadAddress(u64), + #[error("Munmap Error `{0:#?}`")] + MunmapFailed(u64), +} + +pub type HostResult = Result; + +pub struct UserProcessMemory<'a> { + address: u64, + owner: &'a UserProcess, + len: u64, +} + +impl<'a> UserProcessMemory<'a> { + /// Getter for UserProcessMemory's start address + pub fn address(&self) -> u64 { + self.address + } + + /// Getter for UserProcessMemory's length + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> u64 { + self.len + } +} + +impl<'a> Drop for UserProcessMemory<'a> { + /// Munmap's the memory on drop + fn drop(&mut self) { + match self.owner.deallocate_memory(self.address, self.len) { + Ok(()) => log::trace!( + "Successfully deallocated memory {:#X} with length {}", + self.address, + self.len + ), + Err(err) => log::error!( + "Failed to deallocate memory {:#X} with length {}, Error: {:#?}", + self.address, + self.len, + err + ), + } + } +} + +pub struct UserProcess { + pid: Pid, +} + +impl UserProcess { + /// Initializes the UserProcess + /// Given you have a UserProcess instance it means the attach must of succeeded. + /// Attach should be the only way to acquire a UserProcess. + pub fn attach(pid: Pid) -> HostResult { + ptrace::attach(pid)?; + + log::info!("New UserProcess successfully attached to pid: {}", pid); + Ok(Self { pid }) + } + + /// Getter for UserProcess actively connected pid + pub fn pid(&self) -> Pid { + self.pid + } + + /// Uses mmap syscall with ptrace to allocate user process memory + pub fn allocate_memory( + &self, + address: u64, + len: u64, + prot: u64, + flags: u64, + fd: u64, + offset: u64, + ) -> HostResult { + let mmap_result = + self.sys_call(Sysno::mmap as u64, address, len, prot, flags, fd, offset)?; + let mmap_result = mmap_result.rax; + + // invalid address + // TODO not quite right... + if mmap_result == 0 { + return Err(HostError::MmapBadAddress(address)); + } + + Ok(UserProcessMemory { + address: mmap_result, + owner: self, + len, + }) + } + + /// Uses munmap syscall with ptrace to deallocate user process memory + fn deallocate_memory(&self, address: u64, len: u64) -> HostResult<()> { + let munmap_result = self.sys_call(Sysno::munmap as u64, address, len, 0, 0, 0, 0)?; + let munmap_result = munmap_result.rax; + + // not a zero return value means a failure + if munmap_result != 0 { + return Err(HostError::MunmapFailed(address)); + } + + Ok(()) + } + + /// Write to the user process memory + pub fn write_user_memory( + &self, + user_memory: &mut UserProcessMemory, + offset: u64, + bytes: &[u8], + ) -> HostResult { + self.write_memory(user_memory.address + offset, bytes) + } + + /// Read from user process memory + pub fn read_user_memory( + &self, + user_memory: &UserProcessMemory, + len: usize, + ) -> HostResult> { + self.read_memory(user_memory.address, len) + } + + /// String to the proc's memory file + /// Reference: https://crates.io/crates/pete + fn proc_mem_path(&self) -> String { + format!("/proc/{}/mem", self.pid.as_raw() as u32) + } + + /// Common wrapper around writing memory + /// Returns the amount of bytes written + /// Reference: https://crates.io/crates/pete + fn write_memory(&self, addr: u64, data: &[u8]) -> HostResult { + use std::os::unix::fs::FileExt; + let mem = std::fs::OpenOptions::new() + .read(true) + .write(true) + .open(self.proc_mem_path())?; + let len = mem.write_at(data, addr)?; + Ok(len) + } + + /// Common wrapper around reading memory + /// Returns a vector to the memory bytes + /// Reference: https://crates.io/crates/pete + fn read_memory(&self, addr: u64, len: usize) -> HostResult> { + use std::os::unix::fs::FileExt; + + let mut data = vec![0u8; len]; + let mem = std::fs::File::open(self.proc_mem_path())?; + let len_read = mem.read_at(&mut data, addr)?; + + data.truncate(len_read); + Ok(data) + } + + /// Invokes a syscall in the userprocess + /// Accepts up to six arguments + #[allow(clippy::too_many_arguments)] + pub fn sys_call( + &self, + sys_call: u64, + rdi: u64, + rsi: u64, + rdx: u64, + r10: u64, + r8: u64, + r9: u64, + ) -> HostResult { + log::trace!("UserProcess {} Syscall: {:#?}", self.pid, sys_call); + let syscall_instruction = [0x0Fu8, 0x05u8]; + + // Cache original registers, original instruction pointer (rip), and the original instructions + let original_registers = ptrace::getregs(self.pid)?; + let original_ip = original_registers.rip; + let original_instructions = self.read_memory(original_ip, syscall_instruction.len())?; + + // Write over our shell code 0x0F05 for sys call + self.write_memory(original_ip, &syscall_instruction)?; + + // Create a copy of the original registers + // Set the sys_call index and args[0..5] (six arguments) + let mut new_registers = original_registers; + new_registers.rax = sys_call; + new_registers.rdi = rdi; + new_registers.rsi = rsi; + new_registers.rdx = rdx; + new_registers.r10 = r10; + new_registers.r8 = r8; + new_registers.r9 = r9; + + // Apply the new registers, and new instructions then single step waiting for SIG_TRAP + ptrace::setregs(self.pid, new_registers)?; + + // Single step the process and wait for a SIGTRAP signal + self.single_step()?; + + // Cache the resultant registers + let result = ptrace::getregs(self.pid)?; + + // Restore original instructions, and original registers to continue normal program control flow + self.write_memory(original_ip, &original_instructions)?; + ptrace::setregs(self.pid, original_registers)?; + + Ok(result) + } + + /// Single steps the process + /// Fails if the next signal is not a SIGTRAP + fn single_step(&self) -> HostResult<()> { + ptrace::step(self.pid, None)?; + self.wait_trap() + } + + /// Waits for the next signal + /// Returns an error if that signal is not a SIGTRAP + fn wait_trap(&self) -> HostResult<()> { + match self.wait()? { + WaitStatus::Stopped(_, SIGTRAP) => Ok(()), + status => Err(HostError::UnexpectedWaitStatus(status)), + } + } + + /// Waits on the current process + fn wait(&self) -> HostResult { + waitpid(self.pid, None).map_err(HostError::NixError) + } +} + +impl Drop for UserProcess { + /// Drop implementation for the UserProcess + /// Attempts to detach from the process, does not panic on error instead only logs + fn drop(&mut self) { + if let Err(err) = ptrace::detach(self.pid, None) { + log::error!( + "UserProcess failed to detach from: {}, with Err: {:#?}", + self.pid, + err + ); + } else { + log::trace!("UserProcess successfully detached from: {}", self.pid); + } + } +} diff --git a/client/src/sleeper.rs b/client/src/sleeper.rs new file mode 100644 index 0000000..44034c0 --- /dev/null +++ b/client/src/sleeper.rs @@ -0,0 +1,105 @@ +use std::{ + fs::File, + io::{self, Write}, +}; + +const FILENAME: &'static str = "/tmp/sleeper"; + +pub fn create_sleeper() -> io::Result<()> { + // ELF header for x86_64 Linux executable + let mut binary_bytes = Vec::new(); + + // ELF Magic number and identification + binary_bytes.extend_from_slice(&[ + 0x7f, 0x45, 0x4c, 0x46, // ELF magic + 0x02, // 64-bit + 0x01, // Little endian + 0x01, // ELF version + 0x00, // System V ABI + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Padding + ]); + + // ELF header continuation + binary_bytes.extend_from_slice(&[ + 0x02, 0x00, // Executable file + 0x3e, 0x00, // x86_64 + 0x01, 0x00, 0x00, 0x00, // Version 1 + ]); + + // Entry point (0x401000) + binary_bytes.extend_from_slice(&[0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00]); + + // Program header offset (64 bytes) + binary_bytes.extend_from_slice(&[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + + // Section header offset (0 - no sections) + binary_bytes.extend_from_slice(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + + // Flags, header size, program header size, program header count + binary_bytes.extend_from_slice(&[ + 0x00, 0x00, 0x00, 0x00, // Flags + 0x40, 0x00, // ELF header size (64 bytes) + 0x38, 0x00, // Program header size (56 bytes) + 0x01, 0x00, // Program header count (1) + 0x00, 0x00, // Section header size + 0x00, 0x00, // Section header count + 0x00, 0x00, // String table index + ]); + + // Program header (LOAD segment) + binary_bytes.extend_from_slice(&[ + 0x01, 0x00, 0x00, 0x00, // PT_LOAD + 0x05, 0x00, 0x00, 0x00, // PF_X | PF_R (executable + readable) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Offset in file + 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // Virtual address + 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, // Physical address + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size in file + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Size in memory + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment + ]); + + // Pad to entry point (0x401000 - current position) + while binary_bytes.len() < 0x1000 { + binary_bytes.push(0x00); + } + + // Assembly code that loops and sleeps + // This is x86_64 assembly for: + // loop: + // mov rax, 35 ; sys_nanosleep + // mov rdi, timespec ; pointer to timespec struct + // mov rsi, 0 ; remaining time (NULL) + // syscall + // jmp loop + // + // timespec struct (1 second sleep): + // .quad 1 ; seconds + // .quad 0 ; nanoseconds + + binary_bytes.extend_from_slice(&[ + // Main loop + 0x48, 0xc7, 0xc0, 0x23, 0x00, 0x00, 0x00, // mov rax, 35 (sys_nanosleep) + 0x48, 0xc7, 0xc7, 0x18, 0x10, 0x40, 0x00, // mov rdi, 0x401018 (timespec address) + 0x48, 0x31, 0xf6, // xor rsi, rsi (NULL) + 0x0f, 0x05, // syscall + 0xeb, 0xf1, // jmp -15 (back to mov rax, 35) + // timespec struct at 0x401018 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 second + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 nanoseconds + ]); + + // Write the binary to /tmp + let mut file = File::create(FILENAME)?; + file.write_all(&binary_bytes)?; + + // Make it executable + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = file.metadata()?.permissions(); + perms.set_mode(0o755); + std::fs::set_permissions(FILENAME, perms)?; + } + + Ok(()) +} diff --git a/src/host.rs b/src/host.rs index 64129a5..e9a9e2d 100644 --- a/src/host.rs +++ b/src/host.rs @@ -43,10 +43,10 @@ impl Host { let mut response = [0u8; 8]; self.reader.read_exact(&mut response).unwrap(); - let response = isize::from_be_bytes(response); + let response = u64::from_be_bytes(response); println!("{:?}", response); - response + response as isize } } diff --git a/src/lib.rs b/src/lib.rs index 6858cec..f101cb2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,17 +19,17 @@ static mut HOST: Option> = None; #[ctor::ctor] fn start() { - // unsafe { - // HOST = Some({ - // match Host::new() { - // Ok(host) => Mutex::new(host), - // Err(e) => { - // eprintln!("Failed to connect to server: {}", e); - // exit(1); - // } - // } - // }); - // } + unsafe { + HOST = Some({ + match Host::new() { + Ok(host) => Mutex::new(host), + Err(e) => { + eprintln!("Failed to connect to server: {}", e); + exit(1); + } + } + }); + } unsafe { set_hook_fn(hook) }; } @@ -102,17 +102,17 @@ extern "C" fn hook( return InterceptResult::Forward; } - *result = unsafe { syscall.execute_syscall() }; + // *result = unsafe { syscall.execute_syscall() }; + + unsafe { + #[allow(static_mut_refs)] + if let Some(host) = HOST.as_ref() { + *result = host.lock().unwrap().execute(&syscall); + } + } println!("{:?} -> {}", syscall, result); - // unsafe { - // #[allow(static_mut_refs)] - // if let Some(host) = HOST.as_ref() { - // *result = host.lock().unwrap().execute(&syscall); - // } - // } - unsafe { set_hook_fn(hook); } diff --git a/syscall_lib/src/syscall/create.rs b/syscall_lib/src/syscall/create.rs index cddd1e4..dd2b8d6 100644 --- a/syscall_lib/src/syscall/create.rs +++ b/syscall_lib/src/syscall/create.rs @@ -923,9 +923,9 @@ impl Syscall { // rqtp: args[2] as ConstPtr, // rmtp: args[3] as Ptr, // }, - libc::SYS_exit_group => Syscall::ExitGroup { - error_code: args[0] as libc::c_int, - }, + // libc::SYS_exit_group => Syscall::ExitGroup { + // error_code: args[0] as libc::c_int, + // }, // libc::SYS_epoll_wait => Syscall::EpollWait { // epfd: args[0] as libc::c_int, // events: args[1] as Ptr, diff --git a/syscall_lib/src/syscall/exec.rs b/syscall_lib/src/syscall/exec.rs index 43339f1..4bd6d78 100644 --- a/syscall_lib/src/syscall/exec.rs +++ b/syscall_lib/src/syscall/exec.rs @@ -1,30 +1,30 @@ use crate::{AsPtr, Syscall}; -use syscaller::{syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}; +// use syscaller::{syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}; // fn syscall0(number: isize) -> isize { -// unsafe { syscaller::syscall0(number as usize) } +// unsafe { syscaller::syscall0(number as libc::c_ulong) } // } // fn syscall1(number: isize, arg0: isize) -> isize { -// unsafe { syscaller::syscall1(number as usize, arg0 as usize) } +// unsafe { syscaller::syscall1(number as libc::c_ulong, arg0 as libc::c_ulong) } // } // fn syscall2(number: isize, arg0: isize, arg1: isize) -> isize { -// unsafe { syscaller::syscall2(number as usize, arg0 as usize, arg1 as usize) } +// unsafe { syscaller::syscall2(number as libc::c_ulong, arg0 as libc::c_ulong, arg1 as libc::c_ulong) } // } // fn syscall3(number: isize, arg0: isize, arg1: isize, arg2: isize) -> isize { -// unsafe { syscaller::syscall3(number as usize, arg0 as usize, arg1 as usize, arg2 as usize) } +// unsafe { syscaller::syscall3(number as libc::c_ulong, arg0 as libc::c_ulong, arg1 as libc::c_ulong, arg2 as libc::c_ulong) } // } // fn syscall4(number: isize, arg0: isize, arg1: isize, arg2: isize, arg3: isize) -> isize { // unsafe { // syscaller::syscall4( -// number as usize, -// arg0 as usize, -// arg1 as usize, -// arg2 as usize, -// arg3 as usize, +// number as libc::c_ulong, +// arg0 as libc::c_ulong, +// arg1 as libc::c_ulong, +// arg2 as libc::c_ulong, +// arg3 as libc::c_ulong, // ) // } // } @@ -39,12 +39,12 @@ use syscaller::{syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, sysc // ) -> isize { // unsafe { // syscaller::syscall5( -// number as usize, -// arg0 as usize, -// arg1 as usize, -// arg2 as usize, -// arg3 as usize, -// arg4 as usize, +// number as libc::c_ulong, +// arg0 as libc::c_ulong, +// arg1 as libc::c_ulong, +// arg2 as libc::c_ulong, +// arg3 as libc::c_ulong, +// arg4 as libc::c_ulong, // ) // } // } @@ -60,47 +60,79 @@ use syscaller::{syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, sysc // ) -> isize { // unsafe { // syscaller::syscall6( -// number as usize, -// arg0 as usize, -// arg1 as usize, -// arg2 as usize, -// arg3 as usize, -// arg4 as usize, -// arg5 as usize, +// number as libc::c_ulong, +// arg0 as libc::c_ulong, +// arg1 as libc::c_ulong, +// arg2 as libc::c_ulong, +// arg3 as libc::c_ulong, +// arg4 as libc::c_ulong, +// arg5 as libc::c_ulong, // ) // } // } +pub type Args = [libc::c_ulong; 7]; + // The Syscall enum and type aliases from the previous response are assumed to be present here. -#[allow(unused_unsafe, unsafe_op_in_unsafe_fn)] +// #[allow(unused_unsafe, unsafe_op_in_unsafe_fn)] impl Syscall { - pub unsafe fn execute_syscall(&self) -> isize { + pub fn to_syscall_args(&self) -> Args { match self { - Syscall::Read { fd, buf, len } => syscall3( - libc::SYS_read as usize, - *fd as usize, + Syscall::Read { fd, buf, len } => [ + libc::SYS_read as libc::c_ulong, + *fd as libc::c_ulong, buf.as_ptr(), - *len as usize, - ), - Syscall::Write { fd, buf, len } => syscall3( - libc::SYS_write as usize, - *fd as usize, + *len as libc::c_ulong, + 0, + 0, + 0, + ], + Syscall::Write { fd, buf, len } => [ + libc::SYS_write as libc::c_ulong, + *fd as libc::c_ulong, buf.as_ptr(), - *len as usize, - ), - Syscall::Open { path, flags, mode } => syscall3( - libc::SYS_read as usize, + *len as libc::c_ulong, + 0, + 0, + 0, + ], + Syscall::Open { path, flags, mode } => [ + libc::SYS_read as libc::c_ulong, path.as_ptr(), - *flags as usize, - *mode as usize, - ), - Syscall::Close { fd } => syscall1(libc::SYS_read as usize, *fd as usize), - Syscall::Stat { path, statbuf } => { - syscall2(libc::SYS_stat as usize, path.as_ptr(), statbuf.as_ptr()) - } - Syscall::Fstat { fd, statbuf } => { - syscall2(libc::SYS_stat as usize, *fd as usize, statbuf.as_ptr()) - } + *flags as libc::c_ulong, + *mode as libc::c_ulong, + 0, + 0, + 0, + ], + Syscall::Close { fd } => [ + libc::SYS_read as libc::c_ulong, + *fd as libc::c_ulong, + 0, + 0, + 0, + 0, + 0, + ], + + Syscall::Stat { path, statbuf } => [ + libc::SYS_stat as libc::c_ulong, + path.as_ptr(), + statbuf.as_ptr(), + 0, + 0, + 0, + 0, + ], + Syscall::Fstat { fd, statbuf } => [ + libc::SYS_stat as libc::c_ulong, + *fd as libc::c_ulong, + statbuf.as_ptr(), + 0, + 0, + 0, + 0, + ], // Syscall::Fstat(arg0, arg1) => unsafe { syscall2(5, arg0, arg1) }, // Syscall::Lstat(arg0, arg1) => unsafe { syscall2(6, arg0, arg1) }, // Syscall::Poll(arg0, arg1, arg2) => unsafe { syscall3(7, arg0, arg1, arg2) }, @@ -112,15 +144,15 @@ impl Syscall { flags, fd, offset, - } => syscall6( - libc::SYS_mmap as usize, + } => [ + libc::SYS_mmap as libc::c_ulong, addr.as_ptr(), - *len as usize, - *prot as usize, - *flags as usize, - *fd as usize, - *offset as usize, - ), + *len as libc::c_ulong, + *prot as libc::c_ulong, + *flags as libc::c_ulong, + *fd as libc::c_ulong, + *offset as libc::c_ulong, + ], // Syscall::Mmap(arg0, arg1, arg2, arg3, arg4, arg5) => unsafe { // syscall6(9, arg0, arg1, arg2, arg3, arg4, arg5) // }, @@ -409,9 +441,15 @@ impl Syscall { // Syscall::ClockNanosleep(arg0, arg1, arg2, arg3) => unsafe { // syscall4(230, arg0, arg1, arg2, arg3) // }, - Syscall::ExitGroup { error_code } => unsafe { - syscall1(libc::SYS_exit_group as usize, *error_code as usize) - }, + Syscall::ExitGroup { error_code } => [ + libc::SYS_exit_group as libc::c_ulong, + *error_code as libc::c_ulong, + 0, + 0, + 0, + 0, + 0, + ], // Syscall::EpollWait(arg0, arg1, arg2, arg3) => unsafe { // syscall4(232, arg0, arg1, arg2, arg3) // }, @@ -462,13 +500,15 @@ impl Syscall { filename, flags, mode, - } => syscall4( - libc::SYS_openat as usize, - *dfd as usize, + } => [ + libc::SYS_openat as libc::c_ulong, + *dfd as libc::c_ulong, filename.as_ptr(), - *flags as usize, - *mode as usize, - ), + *flags as libc::c_ulong, + *mode as libc::c_ulong, + 0, + 0, + ], // Syscall::Openat(arg0, arg1, arg2, arg3) => unsafe { syscall4(257, arg0, arg1, arg2, arg3) }, // Syscall::Mkdirat(arg0, arg1, arg2) => unsafe { syscall3(258, arg0, arg1, arg2) }, // Syscall::Mknodat(arg0, arg1, arg2, arg3) => unsafe { diff --git a/syscall_lib/src/types/buf.rs b/syscall_lib/src/types/buf.rs index 7b058f9..13d5b04 100644 --- a/syscall_lib/src/types/buf.rs +++ b/syscall_lib/src/types/buf.rs @@ -33,7 +33,7 @@ impl Debug for Buf { } impl AsPtr for Buf { - fn as_ptr(&self) -> usize { - self.0 as usize + fn as_ptr(&self) -> libc::c_ulong { + self.0 as libc::c_ulong } } diff --git a/syscall_lib/src/types/mod.rs b/syscall_lib/src/types/mod.rs index d0c3284..068eeb4 100644 --- a/syscall_lib/src/types/mod.rs +++ b/syscall_lib/src/types/mod.rs @@ -16,5 +16,5 @@ pub use x86_64::*; const MAX_STR_LEN: usize = 30; pub trait AsPtr { - fn as_ptr(&self) -> usize; + fn as_ptr(&self) -> libc::c_ulong; } diff --git a/syscall_lib/src/types/ptr.rs b/syscall_lib/src/types/ptr.rs index ef445d9..916830a 100644 --- a/syscall_lib/src/types/ptr.rs +++ b/syscall_lib/src/types/ptr.rs @@ -28,8 +28,8 @@ impl Debug for Ptr { } impl AsPtr for Ptr { - fn as_ptr(&self) -> usize { - self.0 as usize + fn as_ptr(&self) -> libc::c_ulong { + self.0 as libc::c_ulong } } diff --git a/syscall_lib/src/types/ptr_void.rs b/syscall_lib/src/types/ptr_void.rs index 3a28d63..cbeda91 100644 --- a/syscall_lib/src/types/ptr_void.rs +++ b/syscall_lib/src/types/ptr_void.rs @@ -20,7 +20,7 @@ impl Debug for PtrVoid { } impl AsPtr for PtrVoid { - fn as_ptr(&self) -> usize { - self.0 as usize + fn as_ptr(&self) -> libc::c_ulong { + self.0 as libc::c_ulong } } diff --git a/syscall_lib/src/types/str_ref.rs b/syscall_lib/src/types/str_ref.rs index c626a2c..f1e075d 100644 --- a/syscall_lib/src/types/str_ref.rs +++ b/syscall_lib/src/types/str_ref.rs @@ -39,7 +39,7 @@ impl Debug for StrRef { } impl AsPtr for StrRef { - fn as_ptr(&self) -> usize { - self.0 as usize + fn as_ptr(&self) -> libc::c_ulong { + self.0 as libc::c_ulong } }