From ff86d80941109104b3c15cb694ad4d054cc849f8 Mon Sep 17 00:00:00 2001 From: d0ntrash Date: Wed, 27 Jul 2022 14:17:51 +0200 Subject: [PATCH] Added PEB_Walk --- PEB_Walk/Cargo.toml | 22 +++++++++ PEB_Walk/src/main.rs | 105 ++++++++++++++++++++++++++++++++++++++++++ PEB_Walk/src/types.rs | 10 ++++ README.md | 11 +++-- 4 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 PEB_Walk/Cargo.toml create mode 100644 PEB_Walk/src/main.rs create mode 100644 PEB_Walk/src/types.rs diff --git a/PEB_Walk/Cargo.toml b/PEB_Walk/Cargo.toml new file mode 100644 index 0000000..829e739 --- /dev/null +++ b/PEB_Walk/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "PEB_Walk" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[dependencies.windows-sys] +version = "0.36.1" +features = [ + "Win32_Foundation", + "Win32_Security", + "Win32_System_Threading", + "Win32_UI_WindowsAndMessaging", + "Win32_System_LibraryLoader", + "Win32_System_Kernel", + "Win32_System_WindowsProgramming", + "Win32_System_SystemServices", + "Win32_System_Diagnostics_Debug" +] \ No newline at end of file diff --git a/PEB_Walk/src/main.rs b/PEB_Walk/src/main.rs new file mode 100644 index 0000000..4666a42 --- /dev/null +++ b/PEB_Walk/src/main.rs @@ -0,0 +1,105 @@ +use core::arch::asm; +use windows_sys::Win32::UI::WindowsAndMessaging::MB_OK; +use windows_sys::Win32::Foundation::*; +use windows_sys::Win32::System::Threading::PEB; +use windows_sys::Win32::System::WindowsProgramming::LDR_DATA_TABLE_ENTRY; +use windows_sys::Win32::System::SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY}; +use windows_sys::Win32::System::Diagnostics::Debug::{IMAGE_NT_HEADERS64, IMAGE_DATA_DIRECTORY}; + +mod types; + +#[inline] +#[cfg(target_pointer_width = "64")] +pub unsafe fn __readgsqword(offset: types::DWORD) -> types::DWORD64 { + let out: u64; + asm!( + "mov {}, gs:[{:e}]", + lateout(reg) out, + in(reg) offset, + options(nostack, pure, readonly), + ); + out +} + +fn get_module_base_addr(module_name: &str) -> HINSTANCE { + unsafe { + let peb_offset: *const u64 = __readgsqword(0x60) as *const u64; + let rf_peb: *const PEB = peb_offset as * const PEB; + let peb = *rf_peb; + + let mut p_ldr_data_table_entry: *const LDR_DATA_TABLE_ENTRY = (*peb.Ldr).InMemoryOrderModuleList.Flink as *const LDR_DATA_TABLE_ENTRY; + let mut p_list_entry = (*peb.Ldr).InMemoryOrderModuleList.Flink; + + loop { + let buffer = std::slice::from_raw_parts( + (*p_ldr_data_table_entry).FullDllName.Buffer, + (*p_ldr_data_table_entry).FullDllName.Length as usize); + let dll_name = String::from_utf16_lossy(buffer); + if dll_name.to_lowercase().starts_with(module_name) { + let module_base: HINSTANCE = (*p_ldr_data_table_entry).Reserved2[0] as HINSTANCE; + return module_base; + } + p_list_entry = (*p_list_entry).Flink; + p_ldr_data_table_entry = (*p_list_entry).Flink as *const LDR_DATA_TABLE_ENTRY; + + if p_list_entry == (*peb.Ldr).InMemoryOrderModuleList.Flink { + println!("Module not found!"); + return 0; + } + } + } +} + +fn get_proc_addr(module_handle: HINSTANCE, function_name: &str) -> FARPROC { + let mut address_array: types::UINT_PTR; + let mut name_array: types::UINT_PTR; + let mut name_ordinals: types::UINT_PTR; + let nt_headers: *const IMAGE_NT_HEADERS64; + let data_directory: *const IMAGE_DATA_DIRECTORY; + let export_directory: *const IMAGE_EXPORT_DIRECTORY; + let dos_headers: *const IMAGE_DOS_HEADER; + unsafe { + dos_headers = module_handle as *const IMAGE_DOS_HEADER; + nt_headers = (module_handle as u64 + (*dos_headers).e_lfanew as u64) as *const IMAGE_NT_HEADERS64; + data_directory = (&(*nt_headers).OptionalHeader.DataDirectory[0]) as *const IMAGE_DATA_DIRECTORY; + export_directory = (module_handle as u64 + (*data_directory).VirtualAddress as u64) as *const IMAGE_EXPORT_DIRECTORY; + address_array = (module_handle as u64 + (*export_directory).AddressOfFunctions as u64) as types::UINT_PTR; + name_array = (module_handle as u64 + (*export_directory).AddressOfNames as u64) as types::UINT_PTR; + name_ordinals = (module_handle as u64 + (*export_directory).AddressOfNameOrdinals as u64) as types::UINT_PTR; + loop { + let name_offest: u32 = *(name_array as *const u32); + let current_function_name = std::ffi::CStr::from_ptr( + (module_handle as u64 + name_offest as u64) as *const i8 + ).to_str().unwrap(); + + if current_function_name == function_name { + address_array = address_array + (*(name_ordinals as *const u16) as u64 * (std::mem::size_of::() as u64)); + let fun_addr: FARPROC = std::mem::transmute(module_handle as u64 + *(address_array as *const u32) as u64); + return fun_addr; + } + name_array = name_array + std::mem::size_of::() as u64; + name_ordinals = name_ordinals + std::mem::size_of::() as u64; + } + } +} + +fn main() { + unsafe{ + println!("[+] Getting base address of kernel32.dll"); + let kernel32_base_address: HINSTANCE = get_module_base_addr("kernel32.dll"); + + println!("[+] Dynamically resolving LoadLibraryA"); + let dn_load_library_a: types::LoadLibraryA = std::mem::transmute(get_proc_addr(kernel32_base_address, "LoadLibraryA")); + + println!("[+] Load user32.dll"); + dn_load_library_a("user32.dll\0".as_ptr()); + + println!("[+] Getting base address of user32.dll"); + let user32_base_address: HINSTANCE = get_module_base_addr("user32.dll"); + + println!("[+] Dynamically resolve MessageBoxA"); + let dn_message_box_a: types::MessageBoxA = std::mem::transmute(get_proc_addr(user32_base_address, "MessageBoxA")); + + dn_message_box_a(0, "Resolved dynamically\0".as_ptr(), "MessageBoxA\0".as_ptr(), MB_OK); + } +} diff --git a/PEB_Walk/src/types.rs b/PEB_Walk/src/types.rs new file mode 100644 index 0000000..ad3dd33 --- /dev/null +++ b/PEB_Walk/src/types.rs @@ -0,0 +1,10 @@ +use windows_sys::Win32::Foundation::HWND; +use windows_sys::core::PCSTR; +use std::os::raw::c_ulong; + +pub type DWORD = c_ulong; +pub type __uint64 = u64; +pub type DWORD64 = __uint64; +pub type UINT_PTR = __uint64; +pub type MessageBoxA = unsafe extern "system" fn (HWND, PCSTR, PCSTR, u32) -> i32; +pub type LoadLibraryA = unsafe extern "system" fn (PCSTR) -> i32; \ No newline at end of file diff --git a/README.md b/README.md index 3eef05e..a0fc426 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ My experiments in weaponizing [Rust](https://www.rust-lang.org/) for implant dev | [Kernel_Driver_Exploit](../master/Kernel_Driver_Exploit/src/main.rs) | Kernel Driver exploit for a simple buffer overflow | | [Named_Pipe_Client](../master/Named_Pipe_Client/src/main.rs) | Named Pipe Client | | [Named_Pipe_Server](../master/Named_Pipe_Server/src/main.rs) | Named Pipe Server | +| [PEB_Walk](../master/PEB_Walk/src/main.rs) | Dynamically resolve and invoke Windows APIs | | [Process_Injection_CreateThread](../master/Process_Injection_CreateThread/src/main.rs) | Process Injection in running process with CreateThread | | [Process_Injection_CreateRemoteThread](../master/Process_Injection_CreateRemoteThread/src/main.rs) | Process Injection in remote process with CreateRemoteThread | | [Process_Injection_Self_EnumSystemGeoID](../master/Process_Injection_Self_EnumSystemGeoID/src/main.rs) | Self injector that uses the EnumSystemsGeoID API call to run shellcode. | @@ -52,17 +53,17 @@ My experiments in weaponizing [Rust](https://www.rust-lang.org/) for implant dev | [http-https-requests](../master/http-https-requests/src/main.rs) | HTTP/S requests by ignoring cert check for GET/POST | | [patch_etw](../master/patch_etw/src/main.rs) | Patch ETW | | [ppid_spoof](../master/ppid_spoof/src/main.rs) | Spoof parent process for created process | -| [tcp_ssl_client](../master/tcp_ssl_client/src/main.rs) | TCP client with SSL that ignores cert check (Requires openssl and perl to be installed for compiling) | +| [tcp_ssl_client](../master/tcp_ssl_client/src/main.rs) | TCP client with SSL that ignores cert check (Requires openssl and perl to be installed for compiling) | | [tcp_ssl_server](../master/tcp_ssl_server/src/main.rs) | TCP Server, with port parameter(Requires openssl and perl to be installed for compiling) | | [wmi_execute](../master/wmi_execute/src/main.rs) | Executes WMI query to obtain the AV/EDRs in the host | | [Windows.h+ Bindings](../master/bindings.rs) | This file contains structures of Windows.h plus complete customized LDR,PEB,etc.. that are undocumented officially by Microsoft, add at the top of your file include!("../bindings.rs"); | | [UUID_Shellcode_Execution](../master/UUID_Shellcode_Execution/src/main.rs) | Plants shellcode from UUID array into heap space and uses `EnumSystemLocalesA` Callback in order to execute the shellcode. | | [AMSI Bypass](../master/amsi_bypass/src/main.rs) | AMSI Bypass on Local Process | | [Injection_AES_Loader](../master/Injection_AES_Loader/src/main.rs) | NtTestAlert Injection with AES decryption | -| [Litcrypt_String_Encryption](../master/Litcrypt_String_Encryption/src/main.rs) | Using the [Litcrypt](https://github.com/anvie/litcrypt.rs) crate to encrypt literal strings at rest and in memory to defeat static AV. | -| [Api Hooking](../master/apihooking/src/main.rs) | Api Hooking using detour library | -| [memfd_create](../master/memfd_create/src/main.rs) | Execute payloads from memory using the memfd_create technique (For Linux) | -| [RC4_Encryption](../master/Injection_Rc4_Loader/src/main.rs) | RC4 Decrypted shellcode | +| [Litcrypt_String_Encryption](../master/Litcrypt_String_Encryption/src/main.rs) | Using the [Litcrypt](https://github.com/anvie/litcrypt.rs) crate to encrypt literal strings at rest and in memory to defeat static AV. | +| [Api Hooking](../master/apihooking/src/main.rs) | Api Hooking using detour library | +| [memfd_create](../master/memfd_create/src/main.rs) | Execute payloads from memory using the memfd_create technique (For Linux) | +| [RC4_Encryption](../master/Injection_Rc4_Loader/src/main.rs) | RC4 Decrypted shellcode | ## Compiling the examples in this repo