├── .gitignore ├── README.md ├── demo.jpg ├── messagebox-eat-hook ├── Cargo.toml └── src │ └── lib.rs ├── messagebox-iat-hook ├── Cargo.toml └── src │ └── lib.rs └── messagebox-inline-hook ├── Cargo.toml └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | 4 | Cargo.lock 5 | target 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Screenshot 2 | 3 | ![messageboxw-hook](demo.jpg) 4 | -------------------------------------------------------------------------------- /demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurexav/hook-in-rust/50ea5a3cc66f4a304cbdd777e7f54fbbc2d0c687/demo.jpg -------------------------------------------------------------------------------- /messagebox-eat-hook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "messagebox-eat-hook" 3 | version = "0.1.0" 4 | authors = ["Xavier Lau "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | crate-type = ["dylib"] 11 | path = "src/lib.rs" 12 | 13 | [dependencies] 14 | winapi = { version = "*", features = ["errhandlingapi", "libloaderapi", "memoryapi", "psapi", "processthreadsapi", "windef", "winnt", "winuser"] } 15 | -------------------------------------------------------------------------------- /messagebox-eat-hook/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate winapi; 2 | 3 | use std::ptr::null_mut; 4 | use winapi::shared::{ 5 | minwindef::LPVOID, 6 | ntdef::LPCWSTR, 7 | windef::HWND, 8 | }; 9 | 10 | type MessageBoxWHook = *const unsafe extern "system" fn(HWND, LPCWSTR, LPCWSTR, u32) -> i32; 11 | 12 | static mut MESSAGE_BOX_W_HOOK_ADDRESS: u64 = 0; 13 | 14 | unsafe fn clear_last_error() { 15 | use winapi::um::errhandlingapi::SetLastError; 16 | SetLastError(0); 17 | } 18 | 19 | unsafe fn show_last_error() { 20 | use winapi::um::{ 21 | errhandlingapi::GetLastError, 22 | winuser::{MB_OK, MessageBoxA}, 23 | }; 24 | 25 | let e = GetLastError(); 26 | let e = format!("{}\0", e.to_string()); 27 | MessageBoxA(null_mut(), e.as_ptr() as _, "\0".as_ptr() as _, MB_OK); 28 | } 29 | 30 | unsafe extern "system" fn hook_message_box_w(h_wnd: HWND, _: LPCWSTR, _: LPCWSTR, u_type: u32) -> i32 { 31 | (*(&MESSAGE_BOX_W_HOOK_ADDRESS as *const _ as MessageBoxWHook))( 32 | h_wnd, 33 | "Ops hooked by Xavier!\0".encode_utf16().collect::>().as_ptr(), 34 | "Ops hooked by Xavier!\0".encode_utf16().collect::>().as_ptr(), 35 | u_type, 36 | ) 37 | } 38 | 39 | unsafe fn detour(module_name: *const i8, old_func_offset: u64, new_func_address: u64) -> u64 { 40 | use std::mem::size_of; 41 | use winapi::um::{ 42 | libloaderapi::GetModuleHandleA, 43 | memoryapi::VirtualProtect, 44 | processthreadsapi::GetCurrentProcess, 45 | psapi::{MODULEINFO, GetModuleInformation}, 46 | winnt::{PAGE_EXECUTE_READWRITE, PIMAGE_DOS_HEADER, PIMAGE_EXPORT_DIRECTORY, PIMAGE_NT_HEADERS}, 47 | winuser::{MB_OK, MessageBoxA}, 48 | }; 49 | 50 | let module_handle = GetModuleHandleA(module_name); 51 | let module_address = module_handle as u64; 52 | let mut module_info = MODULEINFO { 53 | lpBaseOfDll: null_mut(), 54 | SizeOfImage: 0, 55 | EntryPoint: null_mut(), 56 | }; 57 | GetModuleInformation(GetCurrentProcess(), module_handle, &mut module_info as _, size_of::() as _); 58 | let p_dos_header = module_address as PIMAGE_DOS_HEADER; 59 | let p_nt_headers = (module_address + (*p_dos_header).e_lfanew as u64) as PIMAGE_NT_HEADERS; 60 | let p_image_export_directory = (module_address + (*p_nt_headers).OptionalHeader.DataDirectory[0].VirtualAddress as u64) as PIMAGE_EXPORT_DIRECTORY; 61 | 62 | let p_address_of_name_ordinals = (module_address + (*p_image_export_directory).AddressOfNameOrdinals as u64) as *const u16; 63 | // let p_address_of_names = (module_address + (*p_image_export_directory).AddressOfNames as u64) as *const u32; 64 | let p_address_of_functions = (module_address + (*p_image_export_directory).AddressOfFunctions as u64) as *const u32; 65 | 66 | for i in 0..(*p_image_export_directory).NumberOfNames as isize { 67 | let ordinal = *p_address_of_name_ordinals.offset(i) as isize; 68 | // let name = (module_address + *(p_address_of_names.offset(i)) as u64) as *const i8; 69 | let p_func_offset = p_address_of_functions.offset(ordinal); 70 | let func_offset = *p_func_offset as u64; 71 | 72 | // MessageBoxA(null_mut(), name, "\0".as_ptr() as _, MB_OK); 73 | if old_func_offset == func_offset { 74 | // MessageBoxA(null_mut(), name, "\0".as_ptr() as _, MB_OK); 75 | 76 | if new_func_address > module_address { 77 | let mut old_protection = 0u32; 78 | VirtualProtect(module_address as _, module_info.SizeOfImage as _, PAGE_EXECUTE_READWRITE, &mut old_protection as _); 79 | *(p_func_offset as *mut u32) = (new_func_address - module_address) as _; 80 | VirtualProtect(module_address as _, module_info.SizeOfImage as _, PAGE_EXECUTE_READWRITE, &mut old_protection as _); 81 | 82 | return module_address + func_offset; 83 | } else { 84 | let s = format!( 85 | "\ 86 | new_func_address: {}\n\ 87 | old_func_address: {}\n\ 88 | module_address: {}\n\ 89 | new_func_offset: {}\n\ 90 | old_func_offset: {}\0", 91 | new_func_address, 92 | old_func_offset + module_address, 93 | module_address, 94 | new_func_address - module_address, 95 | old_func_offset 96 | ); 97 | MessageBoxA(null_mut(), s.as_ptr() as _, "\0".as_ptr() as _, MB_OK); 98 | 99 | break; 100 | } 101 | } 102 | } 103 | 104 | 0 105 | } 106 | 107 | unsafe fn test_message_box_w_hook() -> i32 { 108 | use winapi::um::{ 109 | libloaderapi::{GetModuleHandleA, GetProcAddress}, 110 | winuser::MB_OK, 111 | }; 112 | 113 | (*(&GetProcAddress(GetModuleHandleA("USER32.dll\0".as_ptr() as _), "MessageBoxW\0".as_ptr() as _) as *const _ as MessageBoxWHook))( 114 | null_mut(), 115 | "Test!\0".encode_utf16().collect::>().as_ptr(), 116 | "Test!\0".encode_utf16().collect::>().as_ptr(), 117 | MB_OK, 118 | ) 119 | } 120 | 121 | unsafe extern "system" fn init_hook(_: LPVOID) -> u32 { 122 | MESSAGE_BOX_W_HOOK_ADDRESS = detour("USER32.dll\0".as_ptr() as _, 0x72AD0, hook_message_box_w as _); 123 | test_message_box_w_hook(); 124 | 125 | 0 126 | } 127 | 128 | #[no_mangle] 129 | #[allow(non_snake_case)] 130 | pub extern "system" fn DllMain(_: winapi::shared::minwindef::HINSTANCE, reason: u32, _: LPVOID) -> i32 { 131 | use winapi::um::processthreadsapi::CreateThread; 132 | 133 | match reason { 134 | 1 => unsafe { CreateThread(null_mut(), 0, Some(init_hook), null_mut(), 0, null_mut()); } 135 | 0 => (), 136 | _ => (), 137 | } 138 | 139 | 1 140 | } 141 | -------------------------------------------------------------------------------- /messagebox-iat-hook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "messagebox-iat-hook" 3 | version = "0.1.0" 4 | authors = ["Xavier Lau "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | crate-type = ["dylib"] 11 | path = "src/lib.rs" 12 | 13 | [dependencies] 14 | libc = "*" 15 | winapi = { version = "*", features = ["errhandlingapi", "libloaderapi", "memoryapi", "processthreadsapi", "windef", "winnt", "winuser"] } 16 | -------------------------------------------------------------------------------- /messagebox-iat-hook/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate libc; 2 | extern crate winapi; 3 | 4 | use std::ptr::{null, null_mut}; 5 | use winapi::shared::{ 6 | minwindef::LPVOID, 7 | ntdef::LPCWSTR, 8 | windef::HWND, 9 | }; 10 | 11 | type MessageBoxWHook = *const unsafe extern "system" fn(HWND, LPCWSTR, LPCWSTR, u32) -> i32; 12 | 13 | static mut MESSAGE_BOX_W_HOOK_ADDRESS: u64 = 0; 14 | 15 | unsafe fn clear_last_error() { 16 | use winapi::um::errhandlingapi::SetLastError; 17 | SetLastError(0); 18 | } 19 | 20 | unsafe fn show_last_error() { 21 | use winapi::um::{ 22 | errhandlingapi::GetLastError, 23 | winuser::{MB_OK, MessageBoxA}, 24 | }; 25 | 26 | let e = GetLastError(); 27 | let e = format!("{}\0", e.to_string()); 28 | MessageBoxA(null_mut(), e.as_ptr() as _, "\0".as_ptr() as _, MB_OK); 29 | } 30 | 31 | unsafe extern "system" fn hook_message_box_w(h_wnd: HWND, _: LPCWSTR, _: LPCWSTR, u_type: u32) -> i32 { 32 | (*(&MESSAGE_BOX_W_HOOK_ADDRESS as *const _ as MessageBoxWHook))( 33 | h_wnd, 34 | "Ops hooked by Xavier!\0".encode_utf16().collect::>().as_ptr(), 35 | "Ops hooked by Xavier!\0".encode_utf16().collect::>().as_ptr(), 36 | u_type, 37 | ) 38 | } 39 | 40 | unsafe fn detour(module_name: *const i8, old_func_offset: u64, new_func_address: u64) -> u64 { 41 | use std::mem::size_of; 42 | use libc::strcmp; 43 | use winapi::{ 44 | um::{ 45 | libloaderapi::GetModuleHandleA, 46 | memoryapi::VirtualProtect, 47 | winnt::{PAGE_EXECUTE_READWRITE, PIMAGE_DOS_HEADER, PIMAGE_IMPORT_DESCRIPTOR, PIMAGE_NT_HEADERS}, 48 | winuser::{MB_OK, MessageBoxA}, 49 | }, 50 | }; 51 | 52 | let module_address = GetModuleHandleA(module_name) as u64; 53 | let old_func_address = module_address + old_func_offset; 54 | 55 | let image_base = GetModuleHandleA(null()) as u64; 56 | let p_dos_header = image_base as PIMAGE_DOS_HEADER; 57 | let p_nt_headers = (image_base + (*p_dos_header).e_lfanew as u64) as PIMAGE_NT_HEADERS; 58 | let mut p_import_descriptor = (image_base + (*p_nt_headers).OptionalHeader.DataDirectory[1].VirtualAddress as u64) as PIMAGE_IMPORT_DESCRIPTOR; 59 | 60 | while (*p_import_descriptor).FirstThunk != 0 { 61 | // MessageBoxA(null_mut(), (image_base + (*p_import_descriptor).Name as u64) as _, "\0".as_ptr() as _, MB_OK); 62 | if strcmp(module_name, (image_base + (*p_import_descriptor).Name as u64) as *const i8) != 0 { 63 | p_import_descriptor = p_import_descriptor.offset(1); 64 | continue; 65 | } 66 | MessageBoxA(null_mut(), (image_base + (*p_import_descriptor).Name as u64) as _, "\0".as_ptr() as _, MB_OK); 67 | 68 | let mut p_func = (image_base + (*p_import_descriptor).FirstThunk as u64) as *mut u64; 69 | for i in 0.. { 70 | if p_func.is_null() { return 0; } 71 | 72 | // MessageBoxA(null_mut(), (image_base + (*((image_base + *(*p_import_descriptor).u.OriginalFirstThunk() as u64) as *const u64).offset(i)) + 2) as _, "\0".as_ptr() as _, MB_OK); 73 | if old_func_address == *p_func { 74 | MessageBoxA(null_mut(), (image_base + (*((image_base + *(*p_import_descriptor).u.OriginalFirstThunk() as u64) as *const u64).offset(i)) + 2) as _, "\0".as_ptr() as _, MB_OK); 75 | 76 | let mut old_protection = 0u32; 77 | VirtualProtect(p_func as _, size_of::(), PAGE_EXECUTE_READWRITE, &mut old_protection as _); 78 | *p_func = new_func_address; 79 | VirtualProtect(p_func as _, size_of::(), old_protection, &mut old_protection as _); 80 | 81 | return old_func_address; 82 | } 83 | 84 | p_func = p_func.offset(1); 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | 0 91 | } 92 | 93 | unsafe extern "system" fn init_hook(_: LPVOID) -> u32 { 94 | MESSAGE_BOX_W_HOOK_ADDRESS = detour("USER32.dll\0".as_ptr() as _, 0x72AD0, hook_message_box_w as _); 95 | 96 | 0 97 | } 98 | 99 | #[no_mangle] 100 | #[allow(non_snake_case)] 101 | pub extern "system" fn DllMain(_: winapi::shared::minwindef::HINSTANCE, reason: u32, _: LPVOID) -> i32 { 102 | use winapi::um::processthreadsapi::CreateThread; 103 | 104 | match reason { 105 | 1 => unsafe { CreateThread(null_mut(), 0, Some(init_hook), null_mut(), 0, null_mut()); } 106 | 0 => (), 107 | _ => (), 108 | } 109 | 110 | 1 111 | } 112 | -------------------------------------------------------------------------------- /messagebox-inline-hook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "messagebox-inline-hook" 3 | version = "0.1.0" 4 | authors = ["Xavier Lau "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | crate-type = ["dylib"] 11 | path = "src/lib.rs" 12 | 13 | [dependencies] 14 | detour = "0.7.0" 15 | winapi = { version = "*", features = ["errhandlingapi", "libloaderapi", "processthreadsapi", "winuser"] } 16 | -------------------------------------------------------------------------------- /messagebox-inline-hook/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate detour; 3 | extern crate winapi; 4 | 5 | use std::ptr::null_mut; 6 | use winapi::shared::{ 7 | minwindef::LPVOID, 8 | ntdef::LPCWSTR, 9 | windef::HWND, 10 | }; 11 | 12 | static_detour! { 13 | static MessageBoxWHook: unsafe extern "system" fn(HWND, LPCWSTR, LPCWSTR, u32) -> i32; 14 | } 15 | 16 | type MessageBoxW = unsafe extern "system" fn(HWND, LPCWSTR, LPCWSTR, u32) -> i32; 17 | 18 | unsafe fn clear_last_error() { 19 | use winapi::um::errhandlingapi::SetLastError; 20 | SetLastError(0); 21 | } 22 | 23 | unsafe fn show_last_error() { 24 | use winapi::um::{ 25 | errhandlingapi::GetLastError, 26 | winuser::{MB_OK, MessageBoxA}, 27 | }; 28 | 29 | let e = GetLastError(); 30 | let e = format!("{}\0", e.to_string()); 31 | MessageBoxA(null_mut(), e.as_ptr() as _, "\0".as_ptr() as _, MB_OK); 32 | } 33 | 34 | fn hook_message_box_w(h_wnd: HWND, _: LPCWSTR, _: LPCWSTR, u_type: u32) -> i32 { 35 | unsafe { 36 | MessageBoxWHook.call( 37 | h_wnd, 38 | "Ops hooked by detour-rs!\0".encode_utf16().collect::>().as_ptr(), 39 | "Ops hooked by detour-rs!\0".encode_utf16().collect::>().as_ptr(), 40 | u_type, 41 | ) 42 | } 43 | } 44 | 45 | unsafe fn detour_message_box_w() { 46 | use winapi::um::libloaderapi::GetModuleHandleA; 47 | 48 | let module_address = GetModuleHandleA("USER32.dll\0".as_ptr() as _) as u64; 49 | 50 | let message_box_w_address = module_address + 0x72AD0; 51 | let message_box_w = *(&message_box_w_address as *const _ as *const MessageBoxW); 52 | let message_box_w_hook = MessageBoxWHook.initialize(message_box_w, hook_message_box_w).unwrap(); 53 | message_box_w_hook.enable().unwrap(); 54 | } 55 | 56 | unsafe extern "system" fn init_hook(_: LPVOID) -> u32 { 57 | detour_message_box_w(); 58 | 59 | 0 60 | } 61 | 62 | #[no_mangle] 63 | #[allow(non_snake_case)] 64 | pub extern "system" fn DllMain(_: winapi::shared::minwindef::HINSTANCE, reason: u32, _: LPVOID) -> i32 { 65 | use winapi::um::processthreadsapi::CreateThread; 66 | 67 | match reason { 68 | 1 => unsafe { CreateThread(null_mut(), 0, Some(init_hook), null_mut(), 0, null_mut()); } 69 | 0 => (), 70 | _ => (), 71 | } 72 | 73 | 1 74 | } 75 | --------------------------------------------------------------------------------