Skip to main content

data/
lib.rs

1//! Shared Windows FFI types, constants, and the [`lc!`] string macro.
2//!
3//! You normally get this through `dyncvoke::data`. `HANDLE`,
4//! `OBJECT_ATTRIBUTES`, `UNICODE_STRING`, PE metadata, and NT access-mask
5//! constants live here. [`lc!`] expands to an obfuscated
6//! `alloc::string::String`.
7
8// dyncvoke - Data Types
9// @5mukx
10
11#![no_std]
12#![cfg_attr(docsrs, feature(doc_cfg))]
13extern crate alloc;
14
15#[cfg(not(windows))]
16compile_error!("dyncvoke-data is Windows-only");
17
18use alloc::{collections::BTreeMap, string::String, vec::Vec};
19use core::ffi::c_void;
20
21pub use obfstr;
22
23/// Compile-time obfuscated string. Expands to `alloc::string::String`.
24#[macro_export]
25macro_rules! lc {
26    ($s:literal) => {
27        $crate::obfstr::obfstring!($s)
28    };
29}
30use windows_sys::Win32::Foundation::BOOL;
31use windows_sys::Win32::Graphics::Printing::{DOC_INFO_1A, PRINTER_DEFAULTSA};
32use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
33use windows_sys::Win32::System::Diagnostics::Debug::{EXCEPTION_RECORD, IMAGE_DATA_DIRECTORY, IMAGE_OPTIONAL_HEADER32, IMAGE_SECTION_HEADER, MINIDUMP_CALLBACK_INFORMATION, MINIDUMP_EXCEPTION_INFORMATION, MINIDUMP_USER_STREAM_INFORMATION};
34use windows_sys::Win32::System::Diagnostics::ToolHelp::THREADENTRY32;
35use windows_sys::Win32::System::Memory::MEMORY_BASIC_INFORMATION;
36use windows_sys::Win32::System::SystemInformation::SYSTEM_INFO;
37use windows_sys::Win32::System::Threading::{PROCESS_INFORMATION, STARTUPINFOW};
38use windows_sys::Win32::System::WindowsProgramming::CLIENT_ID;
39use windows_sys::Win32::System::IO::{IO_STATUS_BLOCK, OVERLAPPED};
40
41pub type HANDLE = *mut c_void;
42pub type HINSTANCE = *mut c_void;
43
44/// Trim a PE section name (`IMAGE_SECTION_HEADER.Name`) to the bytes before
45/// the first NUL. Names are 8-byte padded, not UTF-8 strings.
46pub fn section_ascii_name(name: &[u8; 8]) -> &[u8] {
47    match name.iter().position(|&b| b == 0) {
48        Some(i) => &name[..i],
49        None => name,
50    }
51}
52#[repr(C)]
53#[allow(non_snake_case)]
54#[derive(Default)]
55pub struct UNICODE_STRING {
56    pub Length: u16,
57    pub MaximumLength: u16,
58    pub Buffer: *mut u16,
59}
60
61#[repr(C)]
62#[allow(non_snake_case)]
63#[derive(Clone, Copy)]
64pub struct OBJECT_ATTRIBUTES {
65    pub Length: u32,
66    pub RootDirectory: HANDLE,
67    pub ObjectName: *mut UNICODE_STRING,
68    pub Attributes: u32,
69    pub SecurityDescriptor: *mut c_void,
70    pub SecurityQualityOfService: *mut c_void,
71}
72
73impl Default for OBJECT_ATTRIBUTES {
74    fn default() -> Self {
75        unsafe { core::mem::zeroed() }
76    }
77}
78
79#[repr(C)]
80#[allow(non_snake_case)]
81#[derive(Clone, Copy, Default)]
82pub struct LARGE_INTEGER {
83    pub QuadPart: i64,
84}
85
86pub type PVOID = *mut c_void;
87pub type DWORD = u32;
88pub type EAT = BTreeMap<usize,String>;
89pub type EntryPoint = extern "system" fn (HINSTANCE, u32, *mut c_void) -> BOOL;
90pub type QueryInterface = unsafe extern "system" fn (*mut c_void, *const GUID, *mut *mut c_void) -> u32;
91pub type AddRef = unsafe extern "system" fn(*mut c_void) -> u32;
92pub type Release = unsafe extern "system" fn(*mut c_void) -> u32;
93pub type ImpersonateLoggedOnUser = unsafe extern "system" fn (HANDLE) -> bool;
94pub type RevertToSelf = unsafe extern "system" fn () -> bool;
95pub type LoadLibraryA = unsafe extern "system" fn (*mut u8) -> usize;
96pub type FreeLibrary = unsafe extern "system" fn (HINSTANCE) -> BOOL;
97pub type CreateToolhelp32Snapshot = unsafe extern "system" fn (u32, u32) -> HANDLE;
98pub type Thread32First = unsafe extern "system" fn (HANDLE, *mut THREADENTRY32) -> bool;
99pub type Thread32Next = unsafe extern "system" fn (HANDLE, *mut THREADENTRY32) -> bool;
100pub type PostThreadMessageA = unsafe extern "system" fn (u32, u32, usize, isize) -> bool;
101pub type OpenProcess = unsafe extern "system" fn (u32, i32, u32) -> HANDLE;
102pub type OpenThread = unsafe extern "system" fn (u32, i32, u32) -> HANDLE;
103pub type OpenPrintA = unsafe extern "system" fn (*mut u8, *mut HANDLE, *mut PRINTER_DEFAULTSA) -> BOOL;
104pub type StartDocPrinterA = unsafe extern "system" fn (HANDLE, u32, *mut DOC_INFO_1A) -> u32;
105pub type GetDefaultPrinterA = unsafe extern "system" fn (*mut u8, *mut u32) -> BOOL;
106pub type EnumProcesses = unsafe extern "system" fn (*mut u32, u32, *mut u32) -> bool;
107pub type EnumProcessModules = unsafe extern "system" fn (HANDLE, *mut usize, u32, *mut u32) -> bool;
108pub type SetPriorityClass = unsafe extern "system" fn (HANDLE, u32) -> bool;
109pub type SetThreadPriority = unsafe extern "system" fn (HANDLE, u32) -> bool;
110pub type QueueUserWorkItem = unsafe extern "system" fn (*mut c_void, *mut c_void, u32) -> bool;
111pub type InitializeProcThreadAttributeList = unsafe extern "system" fn (PVOID, u32, u32, *mut usize) -> BOOL;
112pub type UpdateProcThreadAttribute = unsafe extern "system" fn (PVOID, u32, usize, *const c_void, usize, PVOID, *const usize) -> BOOL;
113pub type QueryFullProcessImageNameW = unsafe extern "system" fn (HANDLE, u32, *mut u16, *mut u32) -> i32;
114pub type MiniDumpWriteDump = unsafe extern "system" fn (HANDLE, u32, HANDLE, u32, *mut MINIDUMP_EXCEPTION_INFORMATION,
115    *mut MINIDUMP_USER_STREAM_INFORMATION, *mut MINIDUMP_CALLBACK_INFORMATION) -> i32;
116pub type GetOverlappedResult = unsafe extern "system" fn (HANDLE, *mut OVERLAPPED, *mut u32, bool) -> BOOL;
117pub type CreateFileA = unsafe extern "system" fn (*mut u8, u32, u32, *const SECURITY_ATTRIBUTES, u32, u32, HANDLE) -> HANDLE;
118pub type CreateFileW = unsafe extern "system" fn (*const u16, u32, u32, *const SECURITY_ATTRIBUTES, u32, u32, HANDLE) -> HANDLE;
119pub type ReadFile = unsafe extern "system" fn (HANDLE, PVOID, u32, *mut u32, *mut OVERLAPPED) -> i32;
120pub type CreateTransaction = unsafe extern "system" fn (*mut SECURITY_ATTRIBUTES, *mut GUID, u32, u32, u32, u32, *mut u16) -> HANDLE;
121pub type CreateFileTransactedA = unsafe extern "system" fn (*mut u8, u32, u32, *const SECURITY_ATTRIBUTES, u32, u32, HANDLE,
122    HANDLE, *const u32, PVOID) -> HANDLE;
123pub type CreateProcessWithLogon = unsafe extern "system" fn (*const u16, *const u16, *const u16, u32, *const u16, *mut u16, u32, *const c_void, *const u16, *const STARTUPINFOW, *mut PROCESS_INFORMATION) -> BOOL;
124pub type RollbackTransaction = unsafe extern "system" fn (HANDLE) -> BOOL;
125pub type GetFileSize = unsafe extern "system" fn (HANDLE, *mut u32) -> u32;
126pub type CreateFileMapping = unsafe extern "system" fn (HANDLE, *const SECURITY_ATTRIBUTES, u32, u32, u32, *mut u8) -> HANDLE;
127pub type MapViewOfFile = unsafe extern "system" fn (HANDLE, u32, u32, u32, usize) -> PVOID;
128pub type UnmapViewOfFile = unsafe extern "system" fn (PVOID) -> BOOL;
129pub type ConvertThreadToFiber = unsafe extern "system" fn (PVOID) -> PVOID;
130pub type CreateFiber = unsafe extern "system" fn (usize, PVOID, PVOID) -> PVOID;
131pub type SwitchToFiber = unsafe extern "system" fn (PVOID);
132pub type GetLastError = unsafe extern "system" fn () -> u32;
133pub type CloseHandle = unsafe extern "system" fn (HANDLE) -> i32;
134pub type VirtualFree = unsafe extern "system" fn (PVOID, usize, u32) -> bool;
135pub type LocalAlloc = unsafe extern "system" fn (u32, usize) -> PVOID;
136pub type TlsAlloc = unsafe extern "system" fn () -> u32;
137pub type TlsGetValue = unsafe extern "system" fn (u32) -> PVOID;
138pub type TlsSetValue = unsafe extern "system" fn (u32, PVOID) -> bool;
139pub type GetModuleHandleExA = unsafe extern "system" fn (i32,*const u8,*mut usize) -> bool;
140pub type GetModuleBaseNameW = unsafe extern "system" fn (HANDLE, usize, *mut u16, u32) -> u32;
141pub type GetModuleFileNameExW = unsafe extern "system" fn (HANDLE, usize, *mut u16, u32) -> u32;
142pub type GetSystemInfo = unsafe extern "system" fn (*mut SYSTEM_INFO);
143pub type VirtualQueryEx = unsafe extern "system" fn (HANDLE, *const c_void, *mut MEMORY_BASIC_INFORMATION, usize) -> usize;
144pub type LptopLevelExceptionFilter = usize;
145pub type AddVectoredExceptionHandler = unsafe extern "system" fn (first: u32, handle: usize) -> PVOID;
146pub type SetUnhandledExceptionFilter = unsafe extern "system" fn (filter: LptopLevelExceptionFilter) -> LptopLevelExceptionFilter;
147pub type BCryptOpenAlgorithmProvider = unsafe extern "system" fn (*mut HANDLE, *const u16, *const u16, u32) -> i32;
148pub type BCryptGetProperty = unsafe extern "system" fn (HANDLE, *const u16, *mut u8, u32, *mut u32, u32) -> i32;
149pub type BCryptSetProperty = unsafe extern "system" fn (HANDLE, *const u16, *mut u8, u32, u32) -> i32;
150pub type BCryptGenerateSymmetricKey = unsafe extern "system" fn (HANDLE,*mut HANDLE, *mut u8, u32, *mut u8, u32, u32) -> i32;
151pub type BCryptEncrypt = unsafe extern "system" fn (HANDLE, *mut u8, u32, PVOID, *mut u8, u32, *mut u8, u32, *mut u32, u32) -> i32;
152pub type BCryptDestroyKey = unsafe extern "system" fn (HANDLE) -> i32;
153pub type BCryptDecrypt = unsafe extern "system" fn (HANDLE, *mut u8, u32, PVOID, *mut u8, u32, *mut u8, u32, *mut u32, u32) -> i32;
154pub type BCryptCloseAlgorithmProvider  = unsafe extern "system" fn (HANDLE, u32) -> i32;
155pub type CryptSignHashW = unsafe extern "system" fn (usize, u32, *mut u16, u32, *mut u8, *mut u32) -> bool;
156pub type CreateEventW = unsafe extern "system" fn (*const SECURITY_ATTRIBUTES, i32, i32, *const u16) -> HANDLE;
157#[repr(C)]
158#[allow(non_camel_case_types, non_snake_case)]
159pub struct ANSI_STRING {
160    pub Length: u16,
161    pub MaximumLength: u16,
162    pub Buffer: *const u8,
163}
164
165pub type LdrGetProcedureAddress = unsafe extern "system" fn (PVOID, *const ANSI_STRING, u32, *mut PVOID) -> i32;
166pub type NtCreateTransaction = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, *mut GUID, HANDLE, u32, u32, u32, *mut LARGE_INTEGER, *mut UNICODE_STRING) -> i32;
167pub type NtWriteVirtualMemory = unsafe extern "system" fn (HANDLE, PVOID, PVOID, usize, *mut usize) -> i32;
168pub type NtProtectVirtualMemory = unsafe extern "system" fn (HANDLE, *mut PVOID, *mut usize, u32, *mut u32) -> i32;
169pub type NtAllocateVirtualMemory = unsafe extern "system" fn (HANDLE, *mut PVOID, usize, *mut usize, u32, u32) -> i32;
170pub type NtQueryInformationProcess = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, *mut u32) -> i32;
171pub type NtQuerySystemInformation = unsafe extern "system" fn (u32, PVOID, u32, *mut u32) -> i32;
172pub type NtQueryInformationThread = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, *mut u32) -> i32;
173pub type NtQueryInformationFile = unsafe extern "system" fn (HANDLE, *mut IO_STATUS_BLOCK, PVOID, u32, u32) -> i32;
174pub type NtDuplicateObject = unsafe extern "system" fn (HANDLE, HANDLE, HANDLE, *mut HANDLE, u32, u32, u32) -> i32;
175pub type NtQueryObject = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, *mut u32) -> i32;
176pub type NtCreateUserProcess = unsafe extern "system" fn (*mut HANDLE, *mut HANDLE,u32, u32, *mut OBJECT_ATTRIBUTES,*mut OBJECT_ATTRIBUTES, u32, u32, PVOID, *mut PsCreateInfo, *mut PsAttributeList) -> i32;
177pub type NtOpenFile = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, *mut IO_STATUS_BLOCK, u32, u32) -> i32;
178pub type NtCreateSection = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, *mut LARGE_INTEGER, u32, u32, HANDLE) -> i32;
179pub type NtMapViewOfSection = unsafe extern "system" fn (HANDLE, HANDLE, *mut PVOID, usize, usize, *mut LARGE_INTEGER, *mut usize, u32, u32, u32) -> i32;
180pub type NtOpenProcess = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, *mut ClientId) -> i32;
181pub type NtCreateThreadEx = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, HANDLE, PVOID, PVOID, u32, usize, usize, usize, *mut PsAttributeList) -> i32;
182pub type NtReadVirtualMemory = unsafe extern "system" fn (HANDLE, PVOID, PVOID, usize, *mut usize) -> i32;
183pub type NtRemoveProcessDebug = unsafe extern "system" fn (HANDLE, HANDLE) -> i32;
184pub type NtWaitForDebugEvent = unsafe extern "system" fn (HANDLE, u8, *mut LARGE_INTEGER, PVOID) -> i32;
185pub type NtTerminateProcess = unsafe extern "system" fn (HANDLE, i32) -> i32;
186pub type NtOpenKey = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES) -> i32;
187pub type NtSaveKey = unsafe extern "system" fn (HANDLE, HANDLE) -> i32;
188pub type NtOpenProcessToken = unsafe extern "system" fn (HANDLE, u32, *mut HANDLE) -> i32;
189pub type NtDuplicateToken = unsafe extern "system" fn (HANDLE, u32, *mut OBJECT_ATTRIBUTES, bool, u32, *mut HANDLE) -> i32;
190pub type NtCreateKey = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, u32, *mut UNICODE_STRING, u32, *mut u32) -> i32;
191pub type NtSetValueKey = unsafe extern "system" fn (HANDLE, *const UNICODE_STRING, u32, u32, *const c_void, u32) -> i32;
192pub type RtlAdjustPrivilege = unsafe extern "system" fn (u32, u8, u8, *mut u8) -> i32;
193pub type RtlInitUnicodeString = unsafe extern "system" fn (*mut UNICODE_STRING, *const u16) -> () ;
194pub type RtlZeroMemory = unsafe extern "system" fn (PVOID, usize) -> ();
195pub type RtlQueueWorkItem = unsafe extern "system" fn (usize, PVOID, u32) -> i32;
196pub type RtlAddFunctionTable = unsafe extern "system" fn (usize, i32, usize) -> bool;
197pub type NtCommitTransaction = unsafe extern "system" fn (HANDLE, bool) -> i32;
198
199pub const JMP_RBX: u16 = 9215;
200pub const ADD_RSP: u32 = 1489273672;// add rsp,0x58 -> up to 11 parameters
201
202pub const TLS_OUT_OF_INDEXES: u32 = 0xFFFFFFFF;
203
204pub const UNW_FLAG_EHANDLER: u8 = 0x1;
205pub const UNW_FLAG_UHANDLER: u8 = 0x2;
206pub const UNW_FLAG_CHAININFO: u8 = 0x4;
207
208// COFF Relocation constants
209pub const IMAGE_REL_AMD64_ABSOLUTE: u16 = 0x0000;
210pub const IMAGE_REL_AMD64_ADDR64: u16 = 0x0001;
211pub const IMAGE_REL_AMD64_ADDR32: u16 = 0x0002;
212pub const IMAGE_REL_AMD64_ADDR32NB: u16 = 0x0003;
213pub const IMAGE_REL_AMD64_REL32: u16 = 0x0004;
214
215pub const DLL_PROCESS_DETACH: u32 = 0;
216pub const DLL_PROCESS_ATTACH: u32 = 1;
217pub const DLL_THREAD_ATTACH: u32 = 2;
218pub const DLL_THREAD_DETACH: u32 = 3;
219
220pub const PAGE_NOACCESS: u32 = 0x1;
221pub const PAGE_READONLY: u32 = 0x2;
222pub const PAGE_READWRITE: u32 = 0x4;
223pub const PAGE_WRITECOPY: u32 = 0x8;
224pub const PAGE_EXECUTE: u32 = 0x10;
225pub const PAGE_EXECUTE_READ: u32 = 0x20;
226pub const PAGE_EXECUTE_READWRITE: u32 = 0x40;
227pub const PAGE_EXECUTE_WRITECOPY: u32 = 0x80;
228
229pub const MEM_COMMIT: u32 = 0x1000;
230pub const MEM_RESERVE: u32 = 0x2000;
231
232pub const SECTION_MEM_READ: u32 = 0x40000000;
233pub const SECTION_MEM_WRITE: u32 = 0x80000000;
234pub const SECTION_MEM_EXECUTE: u32 = 0x20000000;
235
236// Access mask
237pub const GENERIC_READ: u32 = 0x80000000;
238pub const GENERIC_WRITE: u32 = 0x40000000;
239pub const GENERIC_EXECUTE: u32 = 0x20000000;
240pub const GENERIC_ALL: u32 = 0x10000000;
241pub const SECTION_ALL_ACCESS: u32 = 0x10000000;
242pub const PROCESS_QUERY_LIMITED_INFORMATION: u32 = 0x1000;
243pub const THREAD_ALL_ACCESS: u32 =  0x000F0000 |  0x00100000 | 0xFFFF;
244
245//File share flags
246pub const FILE_SHARE_NONE: u32 = 0x0;
247pub const FILE_SHARE_READ: u32 = 0x1;
248pub const FILE_SHARE_WRITE: u32 = 0x2;
249pub const FILE_SHARE_DELETE: u32 = 0x4;
250
251//File access flags
252pub const DELETE: u32 = 0x10000;
253pub const FILE_READ_DATA: u32 = 0x1;
254pub const FILE_READ_ATTRIBUTES: u32 = 0x80;
255pub const FILE_READ_EA: u32 = 0x8;
256pub const READ_CONTROL: u32 = 0x20000;
257pub const FILE_WRITE_DATA: u32 = 0x2;
258pub const FILE_WRITE_ATTRIBUTES: u32 = 0x100;
259pub const FILE_WRITE_EA: u32 = 0x10;
260pub const FILE_APPEND_DATA: u32 = 0x4;
261pub const WRITE_DAC: u32 = 0x40000;
262pub const WRITE_OWNER: u32 = 0x80000;
263pub const SYNCHRONIZE: u32 = 0x100000;
264pub const FILE_EXECUTE: u32 = 0x20;
265
266// File open flags
267pub const FILE_SYNCHRONOUS_IO_NONALERT: u32 = 0x20;
268pub const FILE_NON_DIRECTORY_FILE: u32 = 0x40;
269
270pub const SEC_IMAGE: u32 = 0x1000000;
271
272pub const MAX_PATH: u32 = 260;
273
274#[derive(Clone)]
275#[repr(C)]
276pub struct PeMetadata {
277    pub pe: u32,
278    pub is_32_bit: bool,
279    pub image_file_header: ImageFileHeader,
280    pub opt_header_32: IMAGE_OPTIONAL_HEADER32,
281    pub opt_header_64: ImageOptionalHeader64,
282    pub sections: Vec<IMAGE_SECTION_HEADER>
283}
284
285impl Default for PeMetadata {
286    fn default() -> PeMetadata {
287        unsafe {
288            PeMetadata {
289                pe: u32::default(),
290                is_32_bit: false,
291                image_file_header: ImageFileHeader::default(),
292                opt_header_32: core::mem::zeroed(),
293                opt_header_64: core::mem::zeroed(),
294                sections: Vec::default(),
295            }
296        }
297    }
298}
299
300#[derive(Clone)]
301#[repr(C)]
302pub struct CoffMetadata {
303    pub image_file_header: ImageFileHeader,
304    pub sections: Vec<IMAGE_SECTION_HEADER>,
305    pub sections_order: BTreeMap<u32,Vec<u16>>,
306    pub sections_mapped_addresses: BTreeMap<u16,usize>,
307    pub symbols: Vec<CoffSymbol>,
308    pub imports: BTreeMap<String,usize>
309}
310
311impl Default for CoffMetadata {
312    fn default() -> CoffMetadata {
313        CoffMetadata {
314            image_file_header: ImageFileHeader::default(),
315            sections: Vec::default(),
316            sections_order: BTreeMap::default(),
317            sections_mapped_addresses: BTreeMap::default(),
318            symbols: Vec::default(),
319            imports: BTreeMap::default()
320        }
321    }
322}
323
324#[derive(Clone, Copy)]
325#[repr(C)]
326pub struct AuxSymbolEntry {
327    pub aux_symbol_entry: [u8;18]
328}
329
330impl Default for AuxSymbolEntry {
331    fn default() -> AuxSymbolEntry {
332        AuxSymbolEntry {
333            aux_symbol_entry: [0u8;18]
334        }
335    }
336}
337
338#[derive(Clone)]
339#[repr(C)]
340pub struct CoffSymbol {
341    pub name_str: String,
342    pub symbol_offset: u32, // offset in strings table in case that the symbol's name is bigger than 8 bytes
343    pub value: u32,
344    pub section_number: u16,
345    pub symbol_type: u16,
346    pub storage_class: u8,
347    pub aux_symbols: u8,
348    pub aux_symbol_entries: Vec<AuxSymbolEntry>
349}
350
351impl Default for CoffSymbol {
352    fn default() -> CoffSymbol {
353        CoffSymbol {
354            name_str:  String::default(),
355            symbol_offset: u32::default(),
356            value: u32::default(),
357            section_number: u16::default(),
358            symbol_type: u16::default(),
359            storage_class: u8::default(),
360            aux_symbols: u8::default(),
361            aux_symbol_entries: Vec::default()
362        }
363    }
364}
365
366#[repr(C)]
367pub struct PeManualMap {
368    pub decoy_module: String,
369    pub base_address: usize,
370    pub pe_info: PeMetadata,
371}
372
373#[repr(C)]
374#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
375pub struct ApiSetNamespace {
376    pub unused: [u8;12],
377    pub count: i32, // offset 0x0C
378    pub entry_offset: i32, // offset 0x10
379}
380
381#[repr(C)]
382#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
383pub struct ApiSetNamespaceEntry {
384    pub unused1: [u8;4],
385    pub name_offset: i32, // offset 0x04
386    pub name_length: i32, // offset 0x08
387    pub unused2: [u8;4],
388    pub value_offset: i32, // offset 0x10
389    pub value_length: i32, // offset 0x14
390}
391
392#[repr(C)]
393#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
394pub struct ApiSetValueEntry {
395    pub flags: i32, // offset 0x00
396    pub name_offset: i32, // offset 0x04
397    pub name_count: i32, // offset 0x08
398    pub value_offset: i32, // offset 0x0C
399    pub value_count: i32, // offset 0x10
400}
401
402#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
403#[repr(C)]
404pub struct ImageFileHeader {
405    pub machine: u16,
406    pub number_of_sections: u16,
407    pub time_data_stamp: u32,
408    pub pointer_to_symbol_table: u32,
409    pub number_of_symbols: u32,
410    pub size_of_optional_header: u16,
411    pub characteristics: u16,
412}
413
414#[derive(Copy, Clone)]
415#[repr(C)] // required to keep fields order, otherwise Rust may change that order randomly
416pub struct ImageOptionalHeader64 {
417        pub magic: u16,
418        pub major_linker_version: u8,
419        pub minor_linker_version: u8,
420        pub size_of_code: u32,
421        pub size_of_initialized_data: u32,
422        pub size_of_unitialized_data: u32,
423        pub address_of_entry_point: u32,
424        pub base_of_code: u32,
425        pub image_base: u64,
426        pub section_alignment: u32,
427        pub file_alignment: u32,
428        pub major_operating_system_version: u16,
429        pub minor_operating_system_version: u16,
430        pub major_image_version: u16,
431        pub minor_image_version: u16,
432        pub major_subsystem_version: u16,
433        pub minor_subsystem_version: u16,
434        pub win32_version_value: u32,
435        pub size_of_image: u32,
436        pub size_of_headers: u32,
437        pub checksum: u32,
438        pub subsystem: u16,
439        pub dll_characteristics: u16,
440        pub size_of_stack_reserve: u64,
441        pub size_of_stack_commit: u64,
442        pub size_of_heap_reserve: u64,
443        pub size_of_heap_commit: u64,
444        pub loader_flags: u32,
445        pub number_of_rva_and_sizes: u32,
446        pub datas_directory: [IMAGE_DATA_DIRECTORY; 16],
447}
448
449#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
450#[repr(C)]
451pub struct GUID
452{
453    pub data1: u32,
454    pub data2: u16,
455    pub data3: u16,
456    pub data4: [u8; 8],
457}
458
459#[repr(C)]
460pub struct SystemHandleInformation {
461    pub number_of_handles: u32,
462    pub handles: Vec<SystemHandleTableEntryInfo>,
463}
464
465#[repr(C)]
466pub struct SystemHandleTableEntryInfo {
467    pub process_id: u16,
468    pub creator_back_trace_index: u16,
469    pub object_type_index: u8,
470    pub handle_attributes: u8,
471    pub handle_value: u16,
472    pub object: PVOID,
473    pub granted_access: u32,
474}
475
476#[repr(C)]
477#[derive(Clone, Copy)]
478pub struct ClientId {
479    pub unique_process: HANDLE,
480    pub unique_thread: HANDLE,
481}
482
483impl Default for ClientId {
484    fn default() -> Self {
485        unsafe { core::mem::zeroed() }
486    }
487}
488
489pub struct NtAllocateVirtualMemoryArgs
490{
491    pub handle: HANDLE,
492    pub base_address: *mut PVOID
493}
494
495pub struct NtOpenProcessArgs
496{
497   pub handle: *mut HANDLE,
498   pub access: u32,
499   pub attributes: *mut OBJECT_ATTRIBUTES,
500   pub client_id: *mut ClientId
501}
502
503pub struct NtProtectVirtualMemoryArgs
504{
505    pub handle: HANDLE,
506    pub base_address: *mut PVOID,
507    pub size: *mut usize,
508    pub protection: u32
509}
510
511pub struct NtWriteVirtualMemoryArgs
512{
513    pub handle: HANDLE,
514    pub base_address: PVOID,
515    pub buffer: PVOID,
516    pub size: usize
517}
518
519pub struct NtCreateThreadExArgs
520{
521    pub thread: *mut HANDLE,
522    pub access: u32,
523    pub attributes: *mut OBJECT_ATTRIBUTES,
524    pub process: HANDLE
525}
526
527#[repr(C)]
528#[allow(non_snake_case)]
529pub struct CONTEXT {
530
531    pub P1Home: u64,
532    pub P2Home: u64,
533    pub P3Home: u64,
534    pub P4Home: u64,
535    pub P5Home: u64,
536    pub P6Home: u64,
537    pub ContextFlags: u32,
538    pub MxCsr: u32,
539    pub SegCs: u16,
540    pub SegDs: u16,
541    pub SegEs: u16,
542    pub SegFs: u16,
543    pub SegGs: u16,
544    pub SegSs: u16,
545    pub EFlags: u32,
546    pub Dr0: u64,
547    pub Dr1: u64,
548    pub Dr2: u64,
549    pub Dr3: u64,
550    pub Dr6: u64,
551    pub Dr7: u64,
552    pub Rax: u64,
553    pub Rcx: u64,
554    pub Rdx: u64,
555    pub Rbx: u64,
556    pub Rsp: u64,
557    pub Rbp: u64,
558    pub Rsi: u64,
559    pub Rdi: u64,
560    pub R8: u64,
561    pub R9: u64,
562    pub R10: u64,
563    pub R11: u64,
564    pub R12: u64,
565    pub R13: u64,
566    pub R14: u64,
567    pub R15: u64,
568    pub Rip: u64,
569    // XMM_SAVE_AREA32 is 512 bytes (winnt.h). Fields above Rip are the only
570    // ones the VEH handler touches; keep the rest layout-correct anyway.
571    pub Anonymous: [u8; 512],
572    pub VectorRegister: [u8; 16 * 26],
573    pub VectorControl: u64,
574    pub DebugControl: u64,
575    pub LastBranchToRip: u64,
576    pub LastBranchFromRip: u64,
577    pub LastExceptionToRip: u64,
578    pub LastExceptionFromRip: u64,
579}
580
581impl Default for CONTEXT
582{
583    fn default() -> CONTEXT {
584        CONTEXT {
585            P1Home: 0,
586            P2Home: 0,
587            P3Home: 0,
588            P4Home: 0,
589            P5Home: 0,
590            P6Home: 0,
591            ContextFlags: 0,
592            MxCsr: 0,
593            SegCs: 0,
594            SegDs: 0,
595            SegEs: 0,
596            SegFs: 0,
597            SegGs: 0,
598            SegSs: 0,
599            EFlags: 0,
600            Dr0: 0,
601            Dr1: 0,
602            Dr2: 0,
603            Dr3: 0,
604            Dr6: 0,
605            Dr7: 0,
606            Rax: 0,
607            Rcx: 0,
608            Rdx: 0,
609            Rbx: 0,
610            Rsp: 0,
611            Rbp: 0,
612            Rsi: 0,
613            Rdi: 0,
614            R8: 0,
615            R9: 0,
616            R10: 0,
617            R11: 0,
618            R12: 0,
619            R13: 0,
620            R14: 0,
621            R15: 0,
622            Rip: 0,
623            Anonymous: [0; 512],
624            VectorRegister: [0; 16 * 26],
625            VectorControl: 0,
626            DebugControl: 0,
627            LastBranchToRip: 0,
628            LastBranchFromRip: 0,
629            LastExceptionToRip: 0,
630            LastExceptionFromRip: 0
631        }
632    }
633}
634
635#[repr(C)]
636pub struct ExceptionPointers {
637    pub exception_record: *mut EXCEPTION_RECORD,
638    pub context_record: *mut CONTEXT,
639}
640
641#[repr(C)]
642pub struct PsAttributeList {
643    pub size: u32,
644    pub unk1: u32,
645    pub unk2: u32,
646    pub unk3: *mut u32,
647    pub unk4: u32,
648    pub unk5: u32,
649    pub unk6: u32,
650    pub unk7: *mut u32,
651    pub unk8: u32,
652
653}
654
655pub enum ExceptionHandleFunction
656{
657    NtOpenProcess,
658    NtAllocateVirtualMemory,
659    NtWriteVirtualMemory,
660    NtProtectVirtualMemory,
661    NtCreateThreadEx
662}
663
664#[repr(C)]
665#[derive(Copy, Clone, Default)]
666pub struct RuntimeFunction {
667    pub begin_addr: u32,
668    pub end_addr: u32,
669    pub unwind_addr: u32
670}
671
672#[repr(C)]
673pub struct PsCreateInfo {
674    pub size: usize,
675    pub unused: [u8;80],
676}
677
678#[repr(C)]
679pub struct PsAttribute {
680    pub attribute: usize,
681    pub size: usize,
682    pub union: PsAttributeU,
683    pub return_length: *mut usize,
684}
685
686#[repr(C)]
687pub union PsAttributeU {
688    pub value: usize,
689    pub value_ptr: PVOID,
690}
691
692
693#[derive(Clone,Copy,Default)]
694#[repr(C)]
695pub struct PsCreateInfoInitState{
696    pub init_flags: u32,
697    pub additional_file_access: u32,
698}
699
700#[derive(Clone,Copy)]
701#[repr(C)]
702pub struct PsCreateInfoUSuccessSate {
703    pub output_flags: u32,
704    pub file_handle: HANDLE,
705    pub section_handle: HANDLE,
706    pub user_process_parameters_native: u64,
707    pub user_process_parameters_wow64: u32,
708    pub current_parameter_flags: u32,
709    pub peb_address_native: u64,
710    pub peb_address_wow64: u32,
711    pub manifest_address: u64,
712    pub manifest_size: u32,
713}
714
715#[derive(Clone,Copy)]
716#[repr(C)]
717pub union PsCreateInfoU {
718    pub init_state: PsCreateInfoInitState,
719    pub file_handle: HANDLE,
720    pub dll_characteristics: u16,
721    pub ifeokey: HANDLE,
722    pub success_state: PsCreateInfoUSuccessSate,
723}
724
725#[repr(C)]
726pub struct FileProcessIdsUsingFileInformation {
727    pub number_of_process_ids_in_list: u32,
728    pub process_id_list: [usize;1],
729}
730
731#[repr(C)]
732pub struct ThreadBasicInformation {
733    pub exit_status: i32,
734    pub teb_base_address: PVOID,
735    pub client_id: CLIENT_ID,
736    pub affinity_mask: usize,
737    pub priority: i32,
738    pub base_priority: i32,
739
740}
741
742#[cfg(test)]
743extern crate std;
744
745#[cfg(test)]
746mod tests {
747    use super::*;
748    use core::ptr;
749
750    #[test]
751    fn test_unicode_string_default() {
752        let us = UNICODE_STRING::default();
753        assert_eq!(us.Length, 0);
754        assert_eq!(us.MaximumLength, 0);
755        assert!(us.Buffer.is_null());
756    }
757
758    #[test]
759    fn test_unicode_string_creation() {
760        let us = UNICODE_STRING {
761            Length: 10,
762            MaximumLength: 12,
763            Buffer: ptr::null_mut(),
764        };
765        assert_eq!(us.Length, 10);
766        assert_eq!(us.MaximumLength, 12);
767    }
768
769    #[test]
770    fn test_object_attributes_default() {
771        let oa = OBJECT_ATTRIBUTES::default();
772        assert_eq!(oa.Length, 0);
773        assert!(oa.RootDirectory.is_null());
774        assert!(oa.ObjectName.is_null());
775        assert_eq!(oa.Attributes, 0);
776    }
777
778    #[test]
779    fn test_large_integer_default() {
780        let li = LARGE_INTEGER::default();
781        assert_eq!(li.QuadPart, 0);
782    }
783
784    #[test]
785    fn test_large_integer_creation() {
786        let li = LARGE_INTEGER { QuadPart: 12345 };
787        assert_eq!(li.QuadPart, 12345);
788    }
789
790    #[test]
791    fn test_dll_constants() {
792        assert_eq!(DLL_PROCESS_DETACH, 0);
793        assert_eq!(DLL_PROCESS_ATTACH, 1);
794        assert_eq!(DLL_THREAD_ATTACH, 2);
795        assert_eq!(DLL_THREAD_DETACH, 3);
796    }
797
798    #[test]
799    fn test_page_constants() {
800        assert_eq!(PAGE_NOACCESS, 0x1);
801        assert_eq!(PAGE_READONLY, 0x2);
802        assert_eq!(PAGE_READWRITE, 0x4);
803        assert_eq!(PAGE_WRITECOPY, 0x8);
804        assert_eq!(PAGE_EXECUTE, 0x10);
805        assert_eq!(PAGE_EXECUTE_READ, 0x20);
806        assert_eq!(PAGE_EXECUTE_READWRITE, 0x40);
807        assert_eq!(PAGE_EXECUTE_WRITECOPY, 0x80);
808    }
809
810    #[test]
811    fn test_memory_constants() {
812        assert_eq!(MEM_COMMIT, 0x1000);
813        assert_eq!(MEM_RESERVE, 0x2000);
814    }
815
816    #[test]
817    fn test_section_constants() {
818        assert_eq!(SECTION_MEM_READ, 0x40000000);
819        assert_eq!(SECTION_MEM_WRITE, 0x80000000);
820        assert_eq!(SECTION_MEM_EXECUTE, 0x20000000);
821    }
822
823    #[test]
824    fn test_access_constants() {
825        assert_eq!(GENERIC_READ, 0x80000000);
826        assert_eq!(GENERIC_WRITE, 0x40000000);
827        assert_eq!(GENERIC_EXECUTE, 0x20000000);
828        assert_eq!(GENERIC_ALL, 0x10000000);
829    }
830
831    #[test]
832    fn test_file_share_constants() {
833        assert_eq!(FILE_SHARE_NONE, 0x0);
834        assert_eq!(FILE_SHARE_READ, 0x1);
835        assert_eq!(FILE_SHARE_WRITE, 0x2);
836        assert_eq!(FILE_SHARE_DELETE, 0x4);
837    }
838
839    #[test]
840    fn test_file_access_constants() {
841        assert_eq!(DELETE, 0x10000);
842        assert_eq!(FILE_READ_DATA, 0x1);
843        assert_eq!(FILE_READ_ATTRIBUTES, 0x80);
844        assert_eq!(FILE_READ_EA, 0x8);
845        assert_eq!(READ_CONTROL, 0x20000);
846        assert_eq!(FILE_WRITE_DATA, 0x2);
847        assert_eq!(FILE_WRITE_ATTRIBUTES, 0x100);
848        assert_eq!(FILE_WRITE_EA, 0x10);
849        assert_eq!(FILE_APPEND_DATA, 0x4);
850    }
851
852    #[test]
853    fn test_file_open_constants() {
854        assert_eq!(FILE_SYNCHRONOUS_IO_NONALERT, 0x20);
855        assert_eq!(FILE_NON_DIRECTORY_FILE, 0x40);
856    }
857
858    #[test]
859    fn test_other_constants() {
860        assert_eq!(SEC_IMAGE, 0x1000000);
861        assert_eq!(MAX_PATH, 260);
862        assert_eq!(TLS_OUT_OF_INDEXES, 0xFFFFFFFF);
863    }
864
865    #[test]
866    fn test_unw_flags() {
867        assert_eq!(UNW_FLAG_EHANDLER, 0x1);
868        assert_eq!(UNW_FLAG_UHANDLER, 0x2);
869        assert_eq!(UNW_FLAG_CHAININFO, 0x4);
870    }
871
872    #[test]
873    fn test_coff_relocation_constants() {
874        assert_eq!(IMAGE_REL_AMD64_ABSOLUTE, 0x0000);
875        assert_eq!(IMAGE_REL_AMD64_ADDR64, 0x0001);
876        assert_eq!(IMAGE_REL_AMD64_ADDR32, 0x0002);
877        assert_eq!(IMAGE_REL_AMD64_ADDR32NB, 0x0003);
878        assert_eq!(IMAGE_REL_AMD64_REL32, 0x0004);
879    }
880
881    #[test]
882    fn test_pe_metadata_default() {
883        let pe = PeMetadata::default();
884        assert_eq!(pe.pe, 0);
885        assert!(!pe.is_32_bit);
886    }
887
888    #[test]
889    fn test_coff_metadata_default() {
890        let coff = CoffMetadata::default();
891        assert_eq!(coff.image_file_header.machine, 0);
892        assert!(coff.sections.is_empty());
893        assert!(coff.imports.is_empty());
894    }
895
896    #[test]
897    fn test_image_file_header_default() {
898        let header = ImageFileHeader::default();
899        assert_eq!(header.machine, 0);
900        assert_eq!(header.number_of_sections, 0);
901        assert_eq!(header.time_data_stamp, 0);
902    }
903
904    #[test]
905    fn test_client_id_default() {
906        let cid = ClientId::default();
907        assert!(cid.unique_process.is_null());
908        assert!(cid.unique_thread.is_null());
909    }
910
911    #[test]
912    fn test_api_set_namespace_default() {
913        let ns = ApiSetNamespace::default();
914        assert_eq!(ns.count, 0);
915        assert_eq!(ns.entry_offset, 0);
916    }
917
918    #[test]
919    fn test_api_set_namespace_entry_default() {
920        let entry = ApiSetNamespaceEntry::default();
921        assert_eq!(entry.name_offset, 0);
922        assert_eq!(entry.name_length, 0);
923        assert_eq!(entry.value_offset, 0);
924        assert_eq!(entry.value_length, 0);
925    }
926
927    #[test]
928    fn test_api_set_value_entry_default() {
929        let entry = ApiSetValueEntry::default();
930        assert_eq!(entry.flags, 0);
931        assert_eq!(entry.name_offset, 0);
932        assert_eq!(entry.name_count, 0);
933        assert_eq!(entry.value_offset, 0);
934        assert_eq!(entry.value_count, 0);
935    }
936
937    #[test]
938    fn test_context_default() {
939        let ctx = CONTEXT::default();
940        assert_eq!(ctx.P1Home, 0);
941        assert_eq!(ctx.Rax, 0);
942        assert_eq!(ctx.Rsp, 0);
943        assert_eq!(ctx.Rip, 0);
944    }
945
946    #[test]
947    fn test_guid_default() {
948        let guid = GUID::default();
949        assert_eq!(guid.data1, 0);
950        assert_eq!(guid.data2, 0);
951        assert_eq!(guid.data3, 0);
952    }
953
954    #[test]
955    fn test_runtime_function_default() {
956        let rf = RuntimeFunction::default();
957        assert_eq!(rf.begin_addr, 0);
958        assert_eq!(rf.end_addr, 0);
959        assert_eq!(rf.unwind_addr, 0);
960    }
961
962    #[test]
963    fn test_handle_type() {
964        let null_handle: HANDLE = ptr::null_mut();
965        assert!(null_handle.is_null());
966    }
967
968    #[test]
969    fn test_hinstance_type() {
970        let null_hinstance: HINSTANCE = ptr::null_mut();
971        assert!(null_hinstance.is_null());
972    }
973}