#![allow(non_snake_case, non_camel_case_types, dead_code, unsafe_op_in_unsafe_fn, static_mut_refs)]
use core::ffi::c_void;
use core::arch::asm;
use core::ptr::null_mut;
use crate::types::*;
pub const fn hash_str(s: &str) -> u32 {
let mut hash: u32 = 0;
let bytes = s.as_bytes();
let mut i = 0;
while i < bytes.len() {
let c = bytes[i];
hash = (hash.rotate_right(13)).wrapping_add(c as u32);
i += 1;
}
hash
}
pub unsafe fn hash_name_w(ptr: *const u16, len: usize) -> u32 {
let mut hash: u32 = 0;
for i in 0..len {
let mut c = *ptr.add(i) as u32;
if c >= 'a' as u32 && c <= 'z' as u32 {
c -= 32;
}
hash = (hash.rotate_right(13)).wrapping_add(c);
}
hash
}
pub unsafe fn hash_name_a(ptr: *const u8) -> u32 {
let mut hash: u32 = 0;
let mut p = ptr;
while *p != 0 {
hash = (hash.rotate_right(13)).wrapping_add(*p as u32);
p = p.add(1);
}
hash
}
pub unsafe fn get_kernel32_base() -> *const u8 {
const KERNEL32_HASH: u32 = hash_str("KERNEL32.DLL");
let peb: *mut PEB;
asm!(
"mov {}, gs:[0x60]",
out(reg) peb,
);
let ldr = (*peb).Ldr;
let head = &mut (*ldr).InMemoryOrderModuleList as *mut LIST_ENTRY;
let mut current = (*head).Flink;
while current != head {
let entry = (current as *const u8).sub(16) as *const LDR_DATA_TABLE_ENTRY;
let hash = hash_name_w((*entry).BaseDllName.Buffer, ((*entry).BaseDllName.Length / 2) as usize);
if hash == KERNEL32_HASH {
return (*entry).DllBase as *const u8;
}
current = (*current).Flink;
}
null_mut()
}
pub unsafe fn get_proc_address(base: *const u8, func_hash: u32) -> *const c_void {
let dos_header = &*(base as *const IMAGE_DOS_HEADER);
if dos_header.e_magic != 0x5A4D { return null_mut();
}
let nt_headers = &*(base.offset(dos_header.e_lfanew as isize) as *const IMAGE_NT_HEADERS64);
if nt_headers.Signature != 0x00004550 { return null_mut();
}
let export_dir_rva = nt_headers.OptionalHeader.DataDirectory[0].VirtualAddress;
if export_dir_rva == 0 {
return null_mut();
}
let export_dir = &*(base.add(export_dir_rva as usize) as *const IMAGE_EXPORT_DIRECTORY);
let names_rva = export_dir.AddressOfNames;
let funcs_rva = export_dir.AddressOfFunctions;
let ords_rva = export_dir.AddressOfNameOrdinals;
let names_ptr = base.add(names_rva as usize) as *const u32; let ords_ptr = base.add(ords_rva as usize) as *const u16; let funcs_ptr = base.add(funcs_rva as usize) as *const u32;
for i in 0..export_dir.NumberOfNames {
let name_rva = *names_ptr.add(i as usize);
let name_ptr = base.add(name_rva as usize) as *const u8;
let hash = hash_name_a(name_ptr);
if hash == func_hash {
let ordinal = *ords_ptr.add(i as usize);
let func_rva = *funcs_ptr.add(ordinal as usize);
return base.add(func_rva as usize) as *const c_void;
}
}
null_mut()
}
type FnLoadLibraryA = unsafe extern "system" fn(lpLibFileName: LPCSTR) -> HMODULE;
type FnGetProcAddress = unsafe extern "system" fn(hModule: HMODULE, lpProcName: LPCSTR) -> *const c_void;
type FnCreateFileW = unsafe extern "system" fn(lpFileName: LPCWSTR, dwDesiredAccess: u32, dwShareMode: u32, lpSecurityAttributes: *const c_void, dwCreationDisposition: u32, dwFlagsAndAttributes: u32, hTemplateFile: HANDLE) -> HANDLE;
type FnCloseHandle = unsafe extern "system" fn(hObject: HANDLE) -> BOOL;
type FnDeviceIoControl = unsafe extern "system" fn(hDevice: HANDLE, dwIoControlCode: u32, lpInBuffer: *const c_void, nInBufferSize: u32, lpOutBuffer: *mut c_void, nOutBufferSize: u32, lpBytesReturned: *mut u32, lpOverlapped: *mut c_void) -> BOOL;
type FnGetCompressedFileSizeW = unsafe extern "system" fn(lpFileName: LPCWSTR, lpFileSizeHigh: *mut u32) -> u32;
type FnGetFileAttributesW = unsafe extern "system" fn(lpFileName: LPCWSTR) -> u32;
type FnSetFileAttributesW = unsafe extern "system" fn(lpFileName: LPCWSTR, dwFileAttributes: u32) -> BOOL;
type FnOpenProcess = unsafe extern "system" fn(dwDesiredAccess: u32, bInheritHandle: BOOL, dwProcessId: u32) -> HANDLE;
type FnCreateProcessW = unsafe extern "system" fn(lpApplicationName: LPCWSTR, lpCommandLine: *mut u16, lpProcessAttributes: *const c_void, lpThreadAttributes: *const c_void, bInheritHandles: BOOL, dwCreationFlags: u32, lpEnvironment: *const c_void, lpCurrentDirectory: LPCWSTR, lpStartupInfo: *mut c_void, lpProcessInformation: *mut c_void) -> BOOL;
type FnInitializeProcThreadAttributeList = unsafe extern "system" fn(lpAttributeList: *mut c_void, dwAttributeCount: u32, dwFlags: u32, lpSize: *mut usize) -> BOOL;
type FnUpdateProcThreadAttribute = unsafe extern "system" fn(lpAttributeList: *mut c_void, dwFlags: u32, Attribute: usize, lpValue: *const c_void, cbSize: usize, lpPreviousValue: *mut c_void, lpReturnSize: *mut usize) -> BOOL;
type FnDeleteProcThreadAttributeList = unsafe extern "system" fn(lpAttributeList: *mut c_void);
type FnOpenProcessToken = unsafe extern "system" fn(ProcessHandle: HANDLE, DesiredAccess: u32, TokenHandle: *mut HANDLE) -> BOOL;
type FnLookupPrivilegeValueW = unsafe extern "system" fn(lpSystemName: LPCWSTR, lpName: LPCWSTR, lpLuid: *mut c_void) -> BOOL;
type FnAdjustTokenPrivileges = unsafe extern "system" fn(TokenHandle: HANDLE, DisableAllPrivileges: BOOL, NewState: *const c_void, BufferLength: u32, PreviousState: *mut c_void, ReturnLength: *mut u32) -> BOOL;
type FnOpenSCManagerW = unsafe extern "system" fn(lpMachineName: LPCWSTR, lpDatabaseName: LPCWSTR, dwDesiredAccess: u32) -> HANDLE;
type FnOpenServiceW = unsafe extern "system" fn(hSCManager: HANDLE, lpServiceName: LPCWSTR, dwDesiredAccess: u32) -> HANDLE;
type FnStartServiceW = unsafe extern "system" fn(hService: HANDLE, dwNumServiceArgs: u32, lpServiceArgVectors: *const *const u16) -> BOOL;
type FnCloseServiceHandle = unsafe extern "system" fn(hSCObject: HANDLE) -> BOOL;
type FnQueryServiceStatusEx = unsafe extern "system" fn(hService: HANDLE, InfoLevel: u32, lpBuffer: *mut u8, cbBufSize: u32, pcbBytesNeeded: *mut u32) -> BOOL;
type FnGetUserNameW = unsafe extern "system" fn(lpBuffer: *mut u16, pcbBuffer: *mut u32) -> BOOL;
type FnGetForegroundWindow = unsafe extern "system" fn() -> HWND;
type FnSetForegroundWindow = unsafe extern "system" fn(hWnd: HWND) -> BOOL;
type FnGetWindowThreadProcessId = unsafe extern "system" fn(hWnd: HWND, lpdwProcessId: *mut u32) -> u32;
type FnAttachThreadInput = unsafe extern "system" fn(idAttach: u32, idAttachTo: u32, fAttach: BOOL) -> BOOL;
type FnBringWindowToTop = unsafe extern "system" fn(hWnd: HWND) -> BOOL;
type FnFlashWindowEx = unsafe extern "system" fn(pfwi: *const c_void) -> BOOL;
type FnDestroyWindow = unsafe extern "system" fn(hWnd: HWND) -> BOOL;
type FnMessageBoxW = unsafe extern "system" fn(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: u32) -> i32;
type FnGetCurrentThreadId = unsafe extern "system" fn() -> u32;
type FnInitCommonControlsEx = unsafe extern "system" fn(picce: *const c_void) -> BOOL;
pub struct WinApi {
pub LoadLibraryA: Option<FnLoadLibraryA>,
pub GetProcAddress: Option<FnGetProcAddress>,
pub GetForegroundWindow: Option<FnGetForegroundWindow>,
pub SetForegroundWindow: Option<FnSetForegroundWindow>,
pub GetWindowThreadProcessId: Option<FnGetWindowThreadProcessId>,
pub AttachThreadInput: Option<FnAttachThreadInput>,
pub BringWindowToTop: Option<FnBringWindowToTop>,
pub GetCurrentThreadId: Option<FnGetCurrentThreadId>,
pub InitCommonControlsEx: Option<FnInitCommonControlsEx>,
pub FlashWindowEx: Option<FnFlashWindowEx>,
pub DestroyWindow: Option<FnDestroyWindow>,
pub MessageBoxW: Option<FnMessageBoxW>,
pub CreateFileW: Option<FnCreateFileW>,
pub CloseHandle: Option<FnCloseHandle>,
pub DeviceIoControl: Option<FnDeviceIoControl>,
pub GetCompressedFileSizeW: Option<FnGetCompressedFileSizeW>,
pub GetFileAttributesW: Option<FnGetFileAttributesW>,
pub SetFileAttributesW: Option<FnSetFileAttributesW>,
pub OpenProcess: Option<FnOpenProcess>,
pub CreateProcessW: Option<FnCreateProcessW>,
pub InitializeProcThreadAttributeList: Option<FnInitializeProcThreadAttributeList>,
pub UpdateProcThreadAttribute: Option<FnUpdateProcThreadAttribute>,
pub DeleteProcThreadAttributeList: Option<FnDeleteProcThreadAttributeList>,
pub OpenProcessToken: Option<FnOpenProcessToken>,
pub LookupPrivilegeValueW: Option<FnLookupPrivilegeValueW>,
pub AdjustTokenPrivileges: Option<FnAdjustTokenPrivileges>,
pub OpenSCManagerW: Option<FnOpenSCManagerW>,
pub OpenServiceW: Option<FnOpenServiceW>,
pub StartServiceW: Option<FnStartServiceW>,
pub CloseServiceHandle: Option<FnCloseServiceHandle>,
pub QueryServiceStatusEx: Option<FnQueryServiceStatusEx>,
pub GetUserNameW: Option<FnGetUserNameW>,
}
impl WinApi {
pub unsafe fn get() -> &'static WinApi {
unsafe { &GLOBAL_API }
}
}
static mut GLOBAL_API: WinApi = WinApi {
LoadLibraryA: None,
GetProcAddress: None,
GetForegroundWindow: None,
SetForegroundWindow: None,
GetWindowThreadProcessId: None,
AttachThreadInput: None,
BringWindowToTop: None,
GetCurrentThreadId: None,
InitCommonControlsEx: None,
FlashWindowEx: None,
DestroyWindow: None,
MessageBoxW: None,
CreateFileW: None,
CloseHandle: None,
DeviceIoControl: None,
GetCompressedFileSizeW: None,
GetFileAttributesW: None,
SetFileAttributesW: None,
OpenProcess: None,
CreateProcessW: None,
InitializeProcThreadAttributeList: None,
UpdateProcThreadAttribute: None,
DeleteProcThreadAttributeList: None,
OpenProcessToken: None,
LookupPrivilegeValueW: None,
AdjustTokenPrivileges: None,
OpenSCManagerW: None,
OpenServiceW: None,
StartServiceW: None,
CloseServiceHandle: None,
QueryServiceStatusEx: None,
GetUserNameW: None,
};
pub unsafe fn init() -> bool {
let kernel32 = get_kernel32_base();
if kernel32.is_null() { return false; }
let hash_lla = hash_str("LoadLibraryA");
let addr_lla = get_proc_address(kernel32, hash_lla);
if addr_lla.is_null() { return false; }
GLOBAL_API.LoadLibraryA = Some(core::mem::transmute(addr_lla));
let hash_gpa = hash_str("GetProcAddress");
let addr_gpa = get_proc_address(kernel32, hash_gpa);
if addr_gpa.is_null() { return false; }
GLOBAL_API.GetProcAddress = Some(core::mem::transmute(addr_gpa));
let load_lib = GLOBAL_API.LoadLibraryA.unwrap();
let get_addr = GLOBAL_API.GetProcAddress.unwrap();
GLOBAL_API.GetCurrentThreadId = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "GetCurrentThreadId\0".as_ptr())));
GLOBAL_API.CreateFileW = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "CreateFileW\0".as_ptr())));
GLOBAL_API.CloseHandle = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "CloseHandle\0".as_ptr())));
GLOBAL_API.DeviceIoControl = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "DeviceIoControl\0".as_ptr())));
let user32_name = "USER32.DLL\0";
let user32 = load_lib(user32_name.as_ptr());
if !user32.is_null() {
GLOBAL_API.GetForegroundWindow = Some(core::mem::transmute(get_addr(user32, "GetForegroundWindow\0".as_ptr())));
GLOBAL_API.SetForegroundWindow = Some(core::mem::transmute(get_addr(user32, "SetForegroundWindow\0".as_ptr())));
GLOBAL_API.GetWindowThreadProcessId = Some(core::mem::transmute(get_addr(user32, "GetWindowThreadProcessId\0".as_ptr())));
GLOBAL_API.AttachThreadInput = Some(core::mem::transmute(get_addr(user32, "AttachThreadInput\0".as_ptr())));
GLOBAL_API.BringWindowToTop = Some(core::mem::transmute(get_addr(user32, "BringWindowToTop\0".as_ptr())));
GLOBAL_API.FlashWindowEx = Some(core::mem::transmute(get_addr(user32, "FlashWindowEx\0".as_ptr())));
GLOBAL_API.DestroyWindow = Some(core::mem::transmute(get_addr(user32, "DestroyWindow\0".as_ptr())));
GLOBAL_API.MessageBoxW = Some(core::mem::transmute(get_addr(user32, "MessageBoxW\0".as_ptr())));
}
let comctl_name = "COMCTL32.DLL\0";
let comctl = load_lib(comctl_name.as_ptr());
if !comctl.is_null() {
GLOBAL_API.InitCommonControlsEx = Some(core::mem::transmute(get_addr(comctl, "InitCommonControlsEx\0".as_ptr())));
}
GLOBAL_API.GetCompressedFileSizeW = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "GetCompressedFileSizeW\0".as_ptr())));
GLOBAL_API.GetFileAttributesW = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "GetFileAttributesW\0".as_ptr())));
GLOBAL_API.SetFileAttributesW = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "SetFileAttributesW\0".as_ptr())));
GLOBAL_API.OpenProcess = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "OpenProcess\0".as_ptr())));
GLOBAL_API.CreateProcessW = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "CreateProcessW\0".as_ptr())));
GLOBAL_API.InitializeProcThreadAttributeList = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "InitializeProcThreadAttributeList\0".as_ptr())));
GLOBAL_API.UpdateProcThreadAttribute = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "UpdateProcThreadAttribute\0".as_ptr())));
GLOBAL_API.DeleteProcThreadAttributeList = Some(core::mem::transmute(get_addr(kernel32 as HMODULE, "DeleteProcThreadAttributeList\0".as_ptr())));
let advapi_name = "ADVAPI32.DLL\0";
let advapi = load_lib(advapi_name.as_ptr());
if !advapi.is_null() {
GLOBAL_API.OpenProcessToken = Some(core::mem::transmute(get_addr(advapi, "OpenProcessToken\0".as_ptr())));
GLOBAL_API.LookupPrivilegeValueW = Some(core::mem::transmute(get_addr(advapi, "LookupPrivilegeValueW\0".as_ptr())));
GLOBAL_API.AdjustTokenPrivileges = Some(core::mem::transmute(get_addr(advapi, "AdjustTokenPrivileges\0".as_ptr())));
GLOBAL_API.OpenSCManagerW = Some(core::mem::transmute(get_addr(advapi, "OpenSCManagerW\0".as_ptr())));
GLOBAL_API.OpenServiceW = Some(core::mem::transmute(get_addr(advapi, "OpenServiceW\0".as_ptr())));
GLOBAL_API.StartServiceW = Some(core::mem::transmute(get_addr(advapi, "StartServiceW\0".as_ptr())));
GLOBAL_API.CloseServiceHandle = Some(core::mem::transmute(get_addr(advapi, "CloseServiceHandle\0".as_ptr())));
GLOBAL_API.QueryServiceStatusEx = Some(core::mem::transmute(get_addr(advapi, "QueryServiceStatusEx\0".as_ptr())));
GLOBAL_API.GetUserNameW = Some(core::mem::transmute(get_addr(advapi, "GetUserNameW\0".as_ptr())));
}
true
}