[fix] fix race condition.

This commit is contained in:
rootacite
2025-10-24 13:44:27 +08:00
parent 22173f034a
commit ea1821480f
4 changed files with 48 additions and 26 deletions

View File

@@ -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"

View File

@@ -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.

View File

@@ -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);
}
}