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]
|
[lib]
|
||||||
name = "tetanus"
|
name = "tetanus"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "rustyneedle"
|
name = "needle"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#[ctor::ctor]
|
#[ctor::ctor]
|
||||||
fn constructor() {
|
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 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 clap::Parser;
|
||||||
|
use syscalls::prepare_exit;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
|
@ -13,7 +16,7 @@ struct NeedleArgs {
|
||||||
word: u32,
|
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();
|
let mut buffer = payload.to_vec();
|
||||||
|
|
||||||
while buffer.len() % word as usize != 0 {
|
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(())
|
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() {
|
fn main() {
|
||||||
let args = NeedleArgs::parse();
|
let args = NeedleArgs::parse();
|
||||||
let pid = Pid::from_raw(args.pid);
|
let pid = Pid::from_raw(args.pid);
|
||||||
|
@ -40,15 +90,17 @@ fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Attached to process #{}", args.pid);
|
if let Err(e) = waitpid(pid, None) {
|
||||||
|
eprintln!("Failed waiting for process to stop : {}", e);
|
||||||
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) = 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);
|
eprintln!("Could not resume process : {}", e);
|
||||||
} else {
|
} else {
|
||||||
println!("Released process #{}", args.pid);
|
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