Skip to content

Instantly share code, notes, and snippets.

@janoglezcampos
Created September 7, 2022 00:22
Show Gist options
  • Save janoglezcampos/04ddcf7c870f38c0ae8f619c80dfa196 to your computer and use it in GitHub Desktop.
Save janoglezcampos/04ddcf7c870f38c0ae8f619c80dfa196 to your computer and use it in GitHub Desktop.
Pls dont judge me
#![allow(non_snake_case)]
/*
[dependencies]
winapi = {version = "0.3.9", features = ["ntdef", "winnt"]}
ntapi = "0.3.7"
*/
use std::arch::{global_asm, asm};
use std::ptr::addr_of;
use std::str;
use core::slice;
use ntapi::FIELD_OFFSET;
use ntapi::ntldr::PLDR_DATA_TABLE_ENTRY;
use winapi::shared::minwindef::{PWORD, PUSHORT};
use winapi::shared::ntdef::{OBJECT_ATTRIBUTES, HANDLE, NULL, NTSTATUS, PVOID, ULONG, PUCHAR, PLIST_ENTRY};
use winapi::um::winnt::{PROCESS_VM_WRITE, PROCESS_VM_READ, PIMAGE_DOS_HEADER, PIMAGE_DATA_DIRECTORY, PIMAGE_NT_HEADERS, PIMAGE_EXPORT_DIRECTORY};
use std::mem::size_of;
use ntapi::ntpebteb::{PPEB, TEB};
use ntapi::ntpsapi::PPEB_LDR_DATA;
#[allow(unused_macros)]
macro_rules! syscall {
($function_name:expr, $($y:expr), +) => {
{
let ssn = get_ssn(obf!($function_name));
let mut result:u32 = 0;
$(
let _ = $y;
result = result + 1;
)+
unsafe {
do_syscall(ssn, result, $($y), +)
}
}}
}
macro_rules! obf {
($s:expr) => {{
static HASH: u32 = dbj2_hash_str($s);
HASH
}
};
}
const fn dbj2_hash_str(arg : &str) -> u32
{
dbj2_hash(arg.as_bytes())
}
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;
}
#[cfg(target_arch = "x86_64")]
pub unsafe fn __readgsqword(Offset: u32) -> u64 {
let out: u64;
asm!(
"mov {}, gs:[{:e}]",
lateout(reg) out,
in(reg) Offset,
options(nostack, pure, readonly),
);
out
}
#[cfg(target_arch = "x86")]
pub unsafe fn __readfsdword(Offset: DWORD) -> DWORD {
let out: u32;
asm!(
"mov {:e}, fs:[{:e}]",
lateout(reg) out,
in(reg) Offset,
options(nostack, pure, readonly),
);
out
}
#[repr(C)]
pub struct CLIENT_ID {
pub UniqueProcess: HANDLE,
pub UniqueThread: HANDLE,
}
global_asm!("
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
");
extern "C" {
fn do_syscall(
ssn: u16,
n_args: u32,
...
) -> i32;
}
pub unsafe fn NtCurrentTeb() -> *mut TEB {
use winapi::um::winnt::NT_TIB;
let teb_offset = FIELD_OFFSET!(NT_TIB, _Self) as u32;
#[cfg(target_arch = "x86_64")] {
__readgsqword(teb_offset) as *mut TEB
}
#[cfg(target_arch = "x86")] {
__readfsdword(teb_offset) as *mut TEB
}
}
pub unsafe fn NtCurrentPeb() -> PPEB {
(*NtCurrentTeb()).ProcessEnvironmentBlock
}
fn get_module_addr( hash: ULONG ) -> PVOID
{
let ldr : PPEB_LDR_DATA;
let header : PLIST_ENTRY;
let mut dt_entry : PLDR_DATA_TABLE_ENTRY;
let mut entry : PLIST_ENTRY;
let mut mod_hash : ULONG;
let mut mod_name : &[u8];
let mut mod_len : usize;
unsafe {
ldr = (*NtCurrentPeb()).Ldr;
header = addr_of!((*ldr).InLoadOrderModuleList) as PLIST_ENTRY;
entry = (*header).Flink;
while header as u64 != entry as u64 {
dt_entry = entry as PLDR_DATA_TABLE_ENTRY;
mod_len = ((*dt_entry).BaseDllName.Length) as usize;
mod_name = slice::from_raw_parts((*dt_entry).BaseDllName.Buffer as *const u8,
mod_len);
mod_hash = dbj2_hash(mod_name) as ULONG;
if mod_hash == hash {
return (*dt_entry).DllBase
}
entry = (*entry).Flink;
}
}
NULL
}
fn get_cstr_len(pointer: *const char) -> usize{
let mut tmp: u64 = pointer as u64;
unsafe {
while *(tmp as *const u8) != 0{
tmp += 1;
}
}
(tmp - pointer as u64) as _
}
fn get_function_addr(moduleAddr: PVOID, hash: u32) -> PVOID{
let dos_header : PIMAGE_DOS_HEADER;
let nt_header : PIMAGE_NT_HEADERS;
let data_dir : PIMAGE_DATA_DIRECTORY;
let exp_dir : PIMAGE_EXPORT_DIRECTORY;
let addr_funcs : PWORD;
let addr_names : PWORD;
let addr_ords : PUSHORT;
let mut str_addr : PUCHAR;
let mut str_len : usize;
let addr_list : &[u32];
let name_list : &[u32];
let ord_list : &[u16];
dos_header = moduleAddr as PIMAGE_DOS_HEADER;
unsafe {
nt_header = (dos_header as u64 + (*dos_header).e_lfanew as u64) as PIMAGE_NT_HEADERS;
data_dir = addr_of!((*nt_header).OptionalHeader.DataDirectory[0]) as PIMAGE_DATA_DIRECTORY;
if (*data_dir).VirtualAddress != 0 {
exp_dir = (dos_header as u64 + (*data_dir).VirtualAddress as u64) as PIMAGE_EXPORT_DIRECTORY;
addr_funcs = (dos_header as u64 + (*exp_dir).AddressOfFunctions as u64 ) as PWORD;
addr_names = (dos_header as u64 + (*exp_dir).AddressOfNames as u64) as PWORD;
addr_ords = (dos_header as u64 + (*exp_dir).AddressOfNameOrdinals as u64) as PUSHORT;
name_list = slice::from_raw_parts(addr_names as *const u32, (*exp_dir).NumberOfNames as usize);
ord_list = slice::from_raw_parts(addr_ords as *const u16, (*exp_dir).NumberOfNames as usize);
addr_list = slice::from_raw_parts(addr_funcs as *const u32, (*exp_dir).NumberOfNames as usize);
for iter in 0..(*exp_dir).NumberOfNames as usize {
str_addr = (dos_header as u64 + name_list[iter] as u64) as PUCHAR;
str_len = get_cstr_len(str_addr as _);
if hash == dbj2_hash(slice::from_raw_parts(str_addr as _, str_len)){
return (dos_header as u64 + addr_list[ord_list[iter] as usize] as u64) as PVOID;
}
}
}
}
NULL
}
fn get_ssn(hash: u32) -> u16 {
let ntdll_addr : PVOID;
let funct_addr : PVOID;
let ssn : u16;
ntdll_addr = get_module_addr(obf!("ntdll.dll"));
funct_addr = get_function_addr(ntdll_addr, hash);
unsafe {
ssn = *((funct_addr as u64 + 4) as *const u16);
}
ssn
}
fn main() {
let pid : u64 = 2740;
let mut handle : HANDLE = NULL;
let mut status : NTSTATUS;
let oa : OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES {
Length: size_of::<OBJECT_ATTRIBUTES>() as _,
RootDirectory: NULL,
ObjectName: NULL as _,
Attributes: 0,
SecurityDescriptor: NULL,
SecurityQualityOfService: NULL
};
let cid : CLIENT_ID = CLIENT_ID {
UniqueProcess: pid as _,
UniqueThread: 0 as _
};
status = syscall!("NtOpenProcess", &mut handle, PROCESS_VM_WRITE | PROCESS_VM_READ, &oa, &cid);
println!("\n\t[-] NtOpenProcess status: {:#02X}", status);
if status != 0 {
return;
}
status = syscall!("NtClose", handle);
println!("\t[-] NtClose status: {:#02X}", status);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment