Created
September 7, 2022 00:22
-
-
Save janoglezcampos/04ddcf7c870f38c0ae8f619c80dfa196 to your computer and use it in GitHub Desktop.
Pls dont judge me
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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