janoglezcampos
rust_syscalls
Rust

Single stub direct and indirect syscalling with runtime SSN resolving for windows.

Last updated Jun 28, 2026
238
Stars
33
Forks
1
Issues
+1
Stars/day
Attention Score
25
Language breakdown
Rust 100.0%
โ–ธ Files click to expand
README

RUST_SYSCALLS

Single stub direct and indirect syscalling with runtime SSN resolving for windows.

Features:

  • One single line for all your syscalls
  • Function name hashing at compilation time
  • Direct or indirect sycalls
  • x86_64, WOW64 and x86 native support
  • Designed to allow the implementation of custom SSN fetching methods (check the end of this readme for more info)

How to use:

  • Add the git repository / local path to the library to your dependencies:
> rustsyscalls = {git = "https://github.com/janoglezcampos/rustsyscalls"}

or

> rust_syscalls = {path = <path to library folder>}

  • Choose direct or indirect method by setting DIRECT or INDIRECT as a feature:
> rustsyscalls = {path = <path to library folder>}, features = ["INDIRECT_"]}
  • Import
> use rust_syscalls::syscall;
  • Syscall:
> NTSTATUS status = syscall!("NtClose", handle);

Example:

#![allow(nonsnakecase)]
    use ntapi::ntapibase::CLIENTID;
    use rust_syscalls::syscall;

use winapi::shared::ntdef::{OBJECT_ATTRIBUTES, HANDLE, NULL, NTSTATUS, PVOID}; use winapi::um::winnt::{PROCESSVMWRITE, PROCESSVMREAD, MEMORYBASICINFORMATION}; use std::mem::size_of; fn main(){ let pid : u64 = 3268; //Process PID let currentProcess : HANDLE = -1isize as _; let meminfolen : usize = sizeof::<MEMORYBASICINFORMATION>() as ;

let mut handle : HANDLE = NULL; let mut status : NTSTATUS; let meminfo: MEMORYBASICINFORMATION = MEMORYBASIC_INFORMATION { BaseAddress: NULL, AllocationBase: NULL, AllocationProtect: 0, RegionSize: 0, State: 0, Protect: 0, Type: 0, };

let oa : OBJECTATTRIBUTES = OBJECTATTRIBUTES { Length: sizeof::<OBJECTATTRIBUTES>() as _, RootDirectory: NULL, ObjectName: NULL as _, Attributes: 0, SecurityDescriptor: NULL, SecurityQualityOfService: NULL };

let cid : CLIENTID = CLIENTID { UniqueProcess: pid as _, UniqueThread: 0 as _ };

unsafe { status = syscall!("NtOpenProcess", &mut handle, PROCESSVMWRITE | PROCESSVMREAD, &oa, &cid); } println!("\n\t[-] NtOpenProcess status: {:#02X}", status);

if status != 0 { return; }

unsafe { status = syscall!("NtQueryVirtualMemory", currentProcess, &pid, 0, &meminfo, meminfo_len, NULL as PVOID); } println!("\n\t[-] NtQueryVirtualMemory status: {:#02X}", status); if status != 0 { return; }

println!("\n\t[-] Protect value: {:#02X}\n\t", mem_info.Protect);

unsafe { status = syscall!("NtClose", handle); } println!("\t[-] NtClose status: {:#02X}", status); }

Implementing new SSN and syscall addresses runtime resolving methods:

All the code required to do the SSN and address fetching is included in the file src\syscall_resolve.rs.

There is one core function used to retrieve the values called get_ssn, with 4 implementations, where the received argument is the result of calling crate::obf!(\<your function name\>), and the return values are the ssn (u16), and, in case of indirect syscalling, the address of the syscall/sysenter instruction that you want to use.

  • x86_64 direct:
> fn get_ssn(hash: u32) -> (u16);
  • x86_64 indirect:
> fn get_ssn(hash: u32) -> (u16, u64);
  • x86 direct:
> fn get_ssn(hash: u32) -> (u16);
  • x86 indirect:
> fn get_ssn(hash: u32) -> (u16, u32);

Just reimplement this functions with your desired fetching method.


Thanks to SysWhispers3 for being a strong pilar on the development of this library

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท janoglezcampos/rust_syscalls ยท Updated daily from GitHub