Skip to content

Commit

Permalink
Indirect Syscall
Browse files Browse the repository at this point in the history
Indirect system calls using Single stub with runtime SSN resolving for windows.
  • Loading branch information
Whitecat18 committed Dec 13, 2024
1 parent bcf8baf commit a930c56
Show file tree
Hide file tree
Showing 16 changed files with 2,312 additions and 0 deletions.
12 changes: 12 additions & 0 deletions syscalls/indirect_syscalls/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "indirect_syscalls"
version = "0.1.0"
edition = "2021"

[dependencies]
winapi = { version = "0.3.9", features = ["wtsapi32","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"] }
ntapi = "0.4.1"
# Add the following for systemcall stub !
# rust_syscalls = {path = "..\rust_syscalls\\src", features = ["_INDIRECT_"]}

rust_syscalls = {path = "./rust_syscalls/", features = ["_INDIRECT_"]}
13 changes: 13 additions & 0 deletions syscalls/indirect_syscalls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Indirect Syscall

Implementing indirect system calls using Single stub with runtime SSN resolving for windows.

![indiect_syscall](./indirect_syscall.png)


## Credits
* https://github.com/janoglezcampos/rust_syscalls.git
* https://redops.at/en/blog/direct-syscalls-vs-indirect-syscalls
* https://www.ired.team/offensive-security/code-injection-process-injection/ntcreatesection-+-ntmapviewofsection-code-injection

by @5mukx
Binary file added syscalls/indirect_syscalls/indirect_syscall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions syscalls/indirect_syscalls/rust_syscalls/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "rust_syscalls"
version = "0.1.0"
edition = "2021"
authors = ["Yxel <https://github.com/janoglezcampos>"]
repository = "https://github.com/janoglezcampos/rust_syscalls"

[features]
_INDIRECT_ = []
_DIRECT_ = []

[dependencies]
winapi = {version = "0.3.9", features = ["ntdef", "winnt"]}
ntapi = "0.4.0"
9 changes: 9 additions & 0 deletions syscalls/indirect_syscalls/rust_syscalls/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[cfg(all(feature = "_DIRECT_", feature = "_INDIRECT_"))]
compile_error!("\t [!] RUST_SYSCALLS ERROR: feature \"_DIRECT_\" and feature \"_INDIRECT_\" cannot be enabled at the same time");

#[cfg(not(any(feature = "_DIRECT_", feature = "_INDIRECT_")))]
compile_error!("\t [!] RUST_SYSCALLS ERROR: feature \"_DIRECT_\" or feature \"_INDIRECT_\" must be enabled");

pub mod syscall;
pub mod syscall_resolve;
pub mod obf;
35 changes: 35 additions & 0 deletions syscalls/indirect_syscalls/rust_syscalls/src/obf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#[macro_export]
macro_rules! obf {
($s:expr) => {{
static HASH: u32 = $crate::obf::dbj2_hash_str($s);
HASH
}
};
}

pub const fn dbj2_hash_str(arg : &str) -> u32
{
dbj2_hash(arg.as_bytes())
}

pub const fn dbj2_hash(buffer : &[u8]) -> u32
{
let mut hsh : u32 = 5381;
let mut iter: usize = 0;
let mut cur : u8;

while iter < buffer.len()
{
cur = buffer[iter];
if cur == 0 {
iter += 1;
continue;
}
if cur >= ('a' as u8) {
cur -= 0x20;
}
hsh = ((hsh << 5).wrapping_add(hsh)) + cur as u32;
iter += 1;
};
return hsh;
}
242 changes: 242 additions & 0 deletions syscalls/indirect_syscalls/rust_syscalls/src/syscall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
#[allow(unused_imports)]
use std::arch::global_asm;

#[cfg(all(feature = "_DIRECT_", not(feature = "_INDIRECT_")))]
#[macro_export]
macro_rules! syscall {
($function_name:expr, $($y:expr), +) => {
{
let ssn = $crate::syscall_resolve::get_ssn($crate::obf!($function_name));
let mut cnt:u32 = 0;
$(
let _ = $y;
cnt += 1;
)+
$crate::syscall::do_syscall(ssn, cnt, $($y), +)
}}
}

#[cfg(all(feature = "_INDIRECT_", not(feature = "_DIRECT_")))]
#[macro_export]
macro_rules! syscall {
($function_name:expr, $($y:expr), +) => {
{
let (ssn, addr) = $crate::syscall_resolve::get_ssn($crate::obf!($function_name));
let mut cnt:u32 = 0;
$(
let _ = $y;
cnt += 1;
)+
$crate::syscall::do_syscall(ssn, addr, cnt, $($y), +)
}}
}

#[cfg(target_arch = "x86_64")]
#[cfg(all(feature = "_DIRECT_", not(feature = "_INDIRECT_")))]
global_asm!("
.global do_syscall
.section .text
do_syscall:
mov [rsp - 0x8], rsi
mov [rsp - 0x10], rdi
mov eax, ecx
mov rcx, rdx
mov r10, r8
mov rdx, r9
mov r8, [rsp + 0x28]
mov r9, [rsp + 0x30]
sub rcx, 0x4
jle skip
lea rsi, [rsp + 0x38]
lea rdi, [rsp + 0x28]
rep movsq
skip:
syscall
mov rsi, [rsp - 0x8]
mov rdi, [rsp - 0x10]
ret
");

#[cfg(target_arch = "x86_64")]
#[cfg(all(feature = "_INDIRECT_", not(feature = "_DIRECT_")))]
global_asm!("
.global do_syscall
.section .text
do_syscall:
mov [rsp - 0x8], rsi
mov [rsp - 0x10], rdi
mov [rsp - 0x18], r12
mov eax, ecx
mov r12, rdx
mov rcx, r8
mov r10, r9
mov rdx, [rsp + 0x28]
mov r8, [rsp + 0x30]
mov r9, [rsp + 0x38]
sub rcx, 0x4
jle skip
lea rsi, [rsp + 0x40]
lea rdi, [rsp + 0x28]
rep movsq
skip:
mov rcx, r12
mov rsi, [rsp - 0x8]
mov rdi, [rsp - 0x10]
mov r12, [rsp - 0x18]
jmp rcx
");

#[cfg(target_arch = "x86")]
#[cfg(all(feature = "_DIRECT_", not(feature = "_INDIRECT_")))]
global_asm!("
.global _do_syscall
.section .text
_do_syscall:
mov [esp - 0x04], esi
mov [esp - 0x08], edi
mov eax, [esp + 0x04]
mov ecx, [esp + 0x08]
lea esi, [esp + 0x0C]
lea edi, [esp + 0x04]
rep movsd
mov esi, [esp - 0x04]
mov edi, [esp - 0x08]
mov edx, fs:[0xc0]
test edx, edx
je native
call edx
ret
native:
call sysenter
ret
sysenter:
mov edx,esp
sysenter
");

#[cfg(target_arch = "x86")]
#[cfg(all(feature = "_INDIRECT_", not(feature = "_DIRECT_")))]
global_asm!("
.global _do_syscall
.section .text
_do_syscall:
mov ecx, [esp + 0x0C]
not ecx
add ecx, 1
lea edx, [esp + ecx * 4]
mov ecx, [esp]
mov [edx], ecx
mov [edx - 0x04], esi
mov [edx - 0x08], edi
mov eax, [esp + 0x04]
mov ecx, [esp + 0x0C]
lea esi, [esp + 0x10]
lea edi, [edx + 0x04]
rep movsd
mov esi, [edx - 0x04]
mov edi, [edx - 0x08]
mov ecx, [esp + 0x08]
mov esp, edx
mov edx, fs:[0xC0]
test edx, edx
je native
mov edx, fs:[0xC0]
jmp ecx
native:
mov edx, ecx
sub edx, 0x05
push edx
mov edx, esp
jmp ecx
ret
is_wow64:
");



#[cfg(target_arch = "x86_64")]
#[cfg(all(feature = "_DIRECT_", not(feature = "_INDIRECT_")))]
extern "C" {
pub fn do_syscall(
ssn: u16,
n_args: u32,
...
) -> i32;
}

#[cfg(target_arch = "x86_64")]
#[cfg(all(feature = "_INDIRECT_", not(feature = "_DIRECT_")))]
extern "C" {
pub fn do_syscall(
ssn: u16,
syscall_addr: u64,
n_args: u32,
...
) -> i32;
}

#[cfg(target_arch = "x86")]
#[cfg(all(feature = "_DIRECT_", not(feature = "_INDIRECT_")))]
extern "C" {
pub fn do_syscall(
ssn: u16,
n_args: u32,
...
) -> i32;
}

#[cfg(target_arch = "x86")]
#[cfg(all(feature = "_INDIRECT_", not(feature = "_DIRECT_")))]
extern "C" {
pub fn do_syscall(
ssn: u16,
n_args: u32,
syscall_addr: u32,
...
) -> i32;
}
Loading

0 comments on commit a930c56

Please sign in to comment.