-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.rs
105 lines (92 loc) · 4.77 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use core::arch::asm;
use windows_sys::Win32::UI::WindowsAndMessaging::MB_OK;
use windows_sys::Win32::Foundation::*;
use windows_sys::Win32::System::Threading::PEB;
use windows_sys::Win32::System::WindowsProgramming::LDR_DATA_TABLE_ENTRY;
use windows_sys::Win32::System::SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY};
use windows_sys::Win32::System::Diagnostics::Debug::{IMAGE_NT_HEADERS64, IMAGE_DATA_DIRECTORY};
use windows_sys::Win32::System::Kernel::LIST_ENTRY;
mod types;
#[inline]
#[cfg(target_pointer_width = "64")]
pub unsafe fn __readgsqword(offset: types::DWORD) -> types::DWORD64 {
let out: u64;
asm!(
"mov {}, gs:[{:e}]",
lateout(reg) out,
in(reg) offset,
options(nostack, pure, readonly),
);
out
}
fn get_module_base_addr(module_name: &str) -> HINSTANCE {
unsafe {
let peb_offset: *const u64 = __readgsqword(0x60) as *const u64;
let rf_peb: *const PEB = peb_offset as * const PEB;
let peb = *rf_peb;
let mut p_ldr_data_table_entry: *const LDR_DATA_TABLE_ENTRY = (*peb.Ldr).InMemoryOrderModuleList.Flink as *const LDR_DATA_TABLE_ENTRY;
let mut p_list_entry = &(*peb.Ldr).InMemoryOrderModuleList as *const LIST_ENTRY;
loop {
let buffer = std::slice::from_raw_parts(
(*p_ldr_data_table_entry).FullDllName.Buffer,
(*p_ldr_data_table_entry).FullDllName.Length as usize / 2);
let dll_name = String::from_utf16_lossy(buffer);
if dll_name.to_lowercase().starts_with(module_name) {
let module_base: HINSTANCE = (*p_ldr_data_table_entry).Reserved2[0] as HINSTANCE;
return module_base;
}
if p_list_entry == (*peb.Ldr).InMemoryOrderModuleList.Blink {
println!("Module not found!");
return 0;
}
p_list_entry = (*p_list_entry).Flink;
p_ldr_data_table_entry = (*p_list_entry).Flink as *const LDR_DATA_TABLE_ENTRY;
}
}
}
fn get_proc_addr(module_handle: HINSTANCE, function_name: &str) -> FARPROC {
let mut address_array: types::UINT_PTR;
let mut name_array: types::UINT_PTR;
let mut name_ordinals: types::UINT_PTR;
let nt_headers: *const IMAGE_NT_HEADERS64;
let data_directory: *const IMAGE_DATA_DIRECTORY;
let export_directory: *const IMAGE_EXPORT_DIRECTORY;
let dos_headers: *const IMAGE_DOS_HEADER;
unsafe {
dos_headers = module_handle as *const IMAGE_DOS_HEADER;
nt_headers = (module_handle as u64 + (*dos_headers).e_lfanew as u64) as *const IMAGE_NT_HEADERS64;
data_directory = (&(*nt_headers).OptionalHeader.DataDirectory[0]) as *const IMAGE_DATA_DIRECTORY;
export_directory = (module_handle as u64 + (*data_directory).VirtualAddress as u64) as *const IMAGE_EXPORT_DIRECTORY;
address_array = (module_handle as u64 + (*export_directory).AddressOfFunctions as u64) as types::UINT_PTR;
name_array = (module_handle as u64 + (*export_directory).AddressOfNames as u64) as types::UINT_PTR;
name_ordinals = (module_handle as u64 + (*export_directory).AddressOfNameOrdinals as u64) as types::UINT_PTR;
loop {
let name_offest: u32 = *(name_array as *const u32);
let current_function_name = std::ffi::CStr::from_ptr(
(module_handle as u64 + name_offest as u64) as *const i8
).to_str().unwrap();
if current_function_name == function_name {
address_array = address_array + (*(name_ordinals as *const u16) as u64 * (std::mem::size_of::<types::DWORD>() as u64));
let fun_addr: FARPROC = std::mem::transmute(module_handle as u64 + *(address_array as *const u32) as u64);
return fun_addr;
}
name_array = name_array + std::mem::size_of::<types::DWORD>() as u64;
name_ordinals = name_ordinals + std::mem::size_of::<u16>() as u64;
}
}
}
fn main() {
unsafe{
println!("[+] Getting base address of kernel32.dll");
let kernel32_base_address: HINSTANCE = get_module_base_addr("kernel32.dll");
println!("[+] Dynamically resolving LoadLibraryA");
let dn_load_library_a: types::LoadLibraryA = std::mem::transmute(get_proc_addr(kernel32_base_address, "LoadLibraryA"));
println!("[+] Load user32.dll");
dn_load_library_a("user32.dll\0".as_ptr());
println!("[+] Getting base address of user32.dll");
let user32_base_address: HINSTANCE = get_module_base_addr("user32.dll");
println!("[+] Dynamically resolve MessageBoxA");
let dn_message_box_a: types::MessageBoxA = std::mem::transmute(get_proc_addr(user32_base_address, "MessageBoxA"));
dn_message_box_a(0, "Resolved dynamically\0".as_ptr(), "MessageBoxA\0".as_ptr(), MB_OK);
}
}