[fix] fix race condition.
This commit is contained in:
@@ -7,7 +7,7 @@ edition = "2024"
|
||||
dynasmrt = "4.0.1"
|
||||
iced-x86 = { version = "1.21.0", features = ["code_asm"] }
|
||||
libc = "0.2.177"
|
||||
nix = { version = "0.30.1", features = ["ptrace", "uio"] }
|
||||
nix = { version = "0.30.1", features = ["ptrace", "uio", "signal"] }
|
||||
ctor = "0.6.0"
|
||||
libloading = "0.8.9"
|
||||
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
mod helper;
|
||||
|
||||
use nix::sys::ptrace;
|
||||
use nix::sys::signal::{Signal, kill};
|
||||
use nix::unistd::Pid;
|
||||
use std::arch::asm;
|
||||
use std::ffi::CString;
|
||||
|
||||
use helper::*;
|
||||
use iced_x86::code_asm::{eax, r8, r9, r10, rax, rdi, rdx, rsi, rcx, rsp, rbp};
|
||||
use iced_x86::code_asm::{eax, r8, r9, r10, rax, rbp, rcx, rdi, rdx, rsi, rsp};
|
||||
use libc::{RTLD_NEXT, c_void, dlsym};
|
||||
use libc::{ptrace, user_regs_struct};
|
||||
use std::fs;
|
||||
@@ -103,7 +104,7 @@ fn inject2(pid: Pid, seg_rw: (u64, u64)) -> Result<(), Box<dyn std::error::Error
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inject3(pid: Pid, seg_rw: (u64, u64)) -> Result<(), Box<dyn std::error::Error>> // thread inject
|
||||
fn inject3(pid: Pid, seg_rw: (u64, u64)) -> Result<i32, Box<dyn std::error::Error>> // thread inject
|
||||
{
|
||||
let regs = ptrace::getregs(pid)?;
|
||||
// Alloc rwx memory
|
||||
@@ -150,7 +151,11 @@ fn inject3(pid: Pid, seg_rw: (u64, u64)) -> Result<(), Box<dyn std::error::Error
|
||||
);
|
||||
|
||||
let injected_data = "[%d] I am the injected thread, I am running... \r\n";
|
||||
write_memory_vm(pid, page_addr + 0x200, &CString::new(injected_data).unwrap().as_bytes_with_nul())?;
|
||||
write_memory_vm(
|
||||
pid,
|
||||
page_addr + 0x200,
|
||||
&CString::new(injected_data).unwrap().as_bytes_with_nul(),
|
||||
)?;
|
||||
write_memory_vm(pid, page_addr + 0x300, &1i64.to_le_bytes())?;
|
||||
write_memory_vm(pid, page_addr + 0x308, &0u64.to_le_bytes())?;
|
||||
|
||||
@@ -184,8 +189,8 @@ fn inject3(pid: Pid, seg_rw: (u64, u64)) -> Result<(), Box<dyn std::error::Error
|
||||
println!("{GREEN}[trace]{RESET} write payload to {:#016x}", page_addr);
|
||||
|
||||
// Start Trigger
|
||||
let regs = ptrace::getregs(pid)?;
|
||||
// ptrace::setregs(pid, regs)?;
|
||||
// let regs = ptrace::getregs(pid)?;
|
||||
ptrace::setregs(pid, regs)?;
|
||||
|
||||
let injected_trigger = assemble(regs.rip as u64, |asm| {
|
||||
asm.mov(rax, 56u64)?; // Syscall 56 (clone)
|
||||
@@ -221,9 +226,34 @@ fn inject3(pid: Pid, seg_rw: (u64, u64)) -> Result<(), Box<dyn std::error::Error
|
||||
wait(pid);
|
||||
|
||||
let regs = ptrace::getregs(pid)?;
|
||||
let pid_new_thread = Pid::from_raw(regs.rax as i32);
|
||||
println!("{GREEN}[trace]{RESET} int3 at {:#016x}", regs.rip);
|
||||
println!(
|
||||
"{GREEN}[trace]{RESET} new thread is {}, which will be suspend.",
|
||||
pid_new_thread
|
||||
);
|
||||
|
||||
Ok(())
|
||||
ptrace::attach(pid_new_thread)?;
|
||||
wait(pid_new_thread);
|
||||
println!("{GREEN}[trace]{RESET} attached new thread.");
|
||||
|
||||
loop {
|
||||
let regs = ptrace::getregs(pid_new_thread)?;
|
||||
println!(
|
||||
"{GREEN}[trace]{RESET} rip in new thread is {:#016x}.",
|
||||
regs.rip
|
||||
);
|
||||
|
||||
if regs.rip >= page_addr as u64 && regs.rip < (page_addr + 0x1000) as u64 {
|
||||
println!("{GREEN}[trace]{RESET} rip in new thread return to inject payload.");
|
||||
break;
|
||||
}
|
||||
|
||||
ptrace::step(pid_new_thread, None)?;
|
||||
wait(pid_new_thread);
|
||||
}
|
||||
|
||||
Ok(pid_new_thread.as_raw())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
@@ -262,22 +292,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
ptrace::step(pid, None)?;
|
||||
wait(pid);
|
||||
|
||||
// ↓ Old behavior, but maybe the process stay in their libraries forever ?
|
||||
|
||||
// loop{
|
||||
// // Single-stepping, so that RIP returns to the user space of the process itself,
|
||||
// // rather than in some other library
|
||||
// let regs = ptrace::getregs(pid)?;
|
||||
// if is_address_in_range(regs.rip, &lines)
|
||||
// {
|
||||
// println!("{GREEN}[trace]{RESET} Address: {:#016x}", regs.rip);
|
||||
// break;
|
||||
// }
|
||||
// println!("{GREEN}[trace]{RESET} Skipped: {:#016x}", regs.rip);
|
||||
// ptrace::step(pid, None)?;
|
||||
// waitpid(pid, None)?;
|
||||
//}
|
||||
|
||||
// Save context
|
||||
let regs = ptrace::getregs(pid)?; // Save current registers
|
||||
let buffer = read_memory_vm(pid, seg_x.0 as usize, 4096)?; // Save current memory context
|
||||
@@ -296,7 +310,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Do inject here
|
||||
|
||||
inject3(pid, seg_rw)?;
|
||||
let c = inject3(pid, seg_rw)?;
|
||||
|
||||
// End inject logics
|
||||
|
||||
@@ -306,6 +320,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
write_memory_vm(pid, seg_rw.0 as usize, &buffer_rw)?;
|
||||
|
||||
ptrace::detach(pid, None)?;
|
||||
ptrace::detach(Pid::from_raw(c), None)?;
|
||||
|
||||
let mut input = String::new();
|
||||
std::io::stdin()
|
||||
.read_line(&mut input)
|
||||
.expect("Failed to read line");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -4,6 +4,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
@@ -11,6 +12,7 @@ int main()
|
||||
|
||||
while(true)
|
||||
{
|
||||
sleep(0);
|
||||
usleep(1000 * 300);
|
||||
write(1, ".", 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user