├── LICENSE ├── MinHook_133_bin ├── LICENSE.txt ├── bin │ ├── MinHook.gcc.x86.dll │ ├── MinHook.x64.dll │ ├── MinHook.x64.lib │ ├── MinHook.x86.dll │ └── MinHook.x86.lib └── include │ └── MinHook.h ├── README.md └── gominhook.go /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /MinHook_133_bin/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MinHook - The Minimalistic API Hooking Library for x64/x86 2 | Copyright (C) 2009-2017 Tsuda Kageyu. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | ================================================================================ 28 | Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov. 29 | ================================================================================ 30 | Hacker Disassembler Engine 32 C 31 | Copyright (c) 2008-2009, Vyacheslav Patkov. 32 | All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions 36 | are met: 37 | 38 | 1. Redistributions of source code must retain the above copyright 39 | notice, this list of conditions and the following disclaimer. 40 | 2. Redistributions in binary form must reproduce the above copyright 41 | notice, this list of conditions and the following disclaimer in the 42 | documentation and/or other materials provided with the distribution. 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 45 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 48 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 49 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 50 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 51 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 52 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 53 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 54 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 | 56 | ------------------------------------------------------------------------------- 57 | Hacker Disassembler Engine 64 C 58 | Copyright (c) 2008-2009, Vyacheslav Patkov. 59 | All rights reserved. 60 | 61 | Redistribution and use in source and binary forms, with or without 62 | modification, are permitted provided that the following conditions 63 | are met: 64 | 65 | 1. Redistributions of source code must retain the above copyright 66 | notice, this list of conditions and the following disclaimer. 67 | 2. Redistributions in binary form must reproduce the above copyright 68 | notice, this list of conditions and the following disclaimer in the 69 | documentation and/or other materials provided with the distribution. 70 | 71 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 72 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 73 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 74 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 75 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 76 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 77 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 78 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 79 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 80 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 81 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 82 | -------------------------------------------------------------------------------- /MinHook_133_bin/bin/MinHook.gcc.x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NaniteFactory/gominhook/9e6cf28c511f90ac2dad38abe8959103716e015e/MinHook_133_bin/bin/MinHook.gcc.x86.dll -------------------------------------------------------------------------------- /MinHook_133_bin/bin/MinHook.x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NaniteFactory/gominhook/9e6cf28c511f90ac2dad38abe8959103716e015e/MinHook_133_bin/bin/MinHook.x64.dll -------------------------------------------------------------------------------- /MinHook_133_bin/bin/MinHook.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NaniteFactory/gominhook/9e6cf28c511f90ac2dad38abe8959103716e015e/MinHook_133_bin/bin/MinHook.x64.lib -------------------------------------------------------------------------------- /MinHook_133_bin/bin/MinHook.x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NaniteFactory/gominhook/9e6cf28c511f90ac2dad38abe8959103716e015e/MinHook_133_bin/bin/MinHook.x86.dll -------------------------------------------------------------------------------- /MinHook_133_bin/bin/MinHook.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NaniteFactory/gominhook/9e6cf28c511f90ac2dad38abe8959103716e015e/MinHook_133_bin/bin/MinHook.x86.lib -------------------------------------------------------------------------------- /MinHook_133_bin/include/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gominhook 2 | 3 | `gominhook` is a Golang wrapper of [minhook](https://github.com/TsudaKageyu/minhook). 4 | 5 | This stuff heavily relies on `cgo`. 6 | 7 | - - - 8 | 9 | ### Installation 10 | 11 | 1. Install `gominhook`. 12 | 13 | `go get -v github.com/nanitefactory/gominhook` 14 | 15 | 2. Get `Minhook` library. 16 | 17 | --- 18 | 19 | **For x64 users:** 20 | 21 | Have `MinHook.x64.dll` with your project. 22 | 23 | You can get it from either of these sites: 24 | 25 | - [gominhook/MinHook_133_bin/bin/MinHook.x64.dll](./MinHook_133_bin/bin) 26 | 27 | - https://github.com/TsudaKageyu/minhook/releases 28 | 29 | --- 30 | 31 | **For x86 users:** 32 | 33 | You need `MinHook.gcc.x86.dll`. 34 | 35 | - [gominhook/MinHook_133_bin/bin/MinHook.gcc.x86.dll](./MinHook_133_bin/bin) 36 | 37 | --- 38 | 39 | 3. That's it! 40 | 41 | `import "github.com/nanitefactory/gominhook"` 42 | 43 | - - - 44 | 45 | ### Exports 46 | 47 | Here is a list of all supported functions & data by `gominhook`, 48 | 49 | ```Go 50 | func gominhook.Initialize() error 51 | func gominhook.Uninitialize() error 52 | ``` 53 | 54 | ```Go 55 | func gominhook.CreateHook(pTarget, pDetour, ppOriginal uintptr) error 56 | func gominhook.CreateHookAPI(strModule, strProcName string, pDetour, ppOriginal uintptr) error 57 | func gominhook.CreateHookAPIEx(strModule, strProcName string, pDetour, ppOriginal, ppTarget uintptr) error 58 | ``` 59 | 60 | ```Go 61 | func gominhook.RemoveHook(pTarget uintptr) error 62 | func gominhook.EnableHook(pTarget uintptr) error 63 | func gominhook.DisableHook(pTarget uintptr) error 64 | ``` 65 | 66 | ```Go 67 | func gominhook.QueueEnableHook(pTarget uintptr) error 68 | func gominhook.QueueDisableHook(pTarget uintptr) error 69 | func gominhook.ApplyQueued() error 70 | ``` 71 | 72 | ```Go 73 | const gominhook.AllHooks = NULL 74 | const gominhook.NULL = 0 75 | ``` 76 | 77 | which is straightforward & effective enough. xD 78 | 79 | - - - 80 | 81 | ### Samples 82 | 83 | - https://github.com/NaniteFactory/hookwin10calc 84 | - https://gist.github.com/NaniteFactory/181ac6be5ac13c200612677f17e3f352 85 | 86 | This example below tries to hook `user32.MessageBoxW`. 87 | 88 | ```Go 89 | package main 90 | 91 | import ( 92 | "fmt" 93 | "log" 94 | "syscall" 95 | "unsafe" 96 | 97 | "github.com/nanitefactory/gominhook" 98 | ) 99 | 100 | /* 101 | #include 102 | 103 | // Put C prototypes here 104 | 105 | // Delegate type for calling original MessageBoxW. 106 | typedef int (WINAPI *MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT); 107 | 108 | // (!) This way you can connect/convert a go function to a c function. 109 | int MessageBoxWOverrideHellYeah(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType); 110 | */ 111 | import "C" 112 | 113 | // Pointer for calling original MessageBoxW. 114 | var fpMessageBoxW C.MESSAGEBOXW 115 | 116 | // (!) This way you can connect/convert a go function to a c function. 117 | //export MessageBoxWOverrideHellYeah 118 | func MessageBoxWOverrideHellYeah(hWnd C.HWND, lpText C.LPCWSTR, lpCaption C.LPCWSTR, uType C.UINT) C.int { 119 | fmt.Println(" - MessageBoxW Override") 120 | foo() 121 | ret, _, _ := syscall.Syscall6( 122 | uintptr(unsafe.Pointer(fpMessageBoxW)), 123 | 4, 124 | uintptr(unsafe.Pointer(hWnd)), 125 | uintptr(unsafe.Pointer(lpText)), 126 | uintptr(unsafe.Pointer(lpCaption)), 127 | uintptr(uint(uType)), 128 | 0, 0, 129 | ) 130 | return C.int(ret) 131 | } 132 | 133 | func foo() { 134 | fmt.Println(" - I'm so hooked now.") 135 | } 136 | 137 | func main() { 138 | // Initialize minhook 139 | err := gominhook.Initialize() 140 | if err != nil { 141 | log.Fatalln(err) 142 | } 143 | defer gominhook.Uninitialize() 144 | 145 | // Get procedure user32.MessageBoxW 146 | procedure := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW") 147 | fmt.Println("-- not hooked yet") 148 | procedure.Call( 149 | 0, 150 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello1"))), 151 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("World1"))), 152 | 1, 153 | ) 154 | fmt.Println(fmt.Sprintf("0x%X", procedure.Addr()), fmt.Sprintf("0x%X", &fpMessageBoxW), fmt.Sprintf("0x%X", fpMessageBoxW)) 155 | fmt.Println() 156 | 157 | // Create a hook for MessageBoxW. 158 | err = gominhook.CreateHook(procedure.Addr(), uintptr(C.MessageBoxWOverrideHellYeah), uintptr(unsafe.Pointer(&fpMessageBoxW))) 159 | if err != nil { 160 | log.Fatalln(err) 161 | } 162 | 163 | // Enable the hook for MessageBoxW. 164 | err = gominhook.EnableHook(gominhook.AllHooks) 165 | if err != nil { 166 | log.Fatalln(err) 167 | } 168 | 169 | // Calling our hooked procedure user32.MessageBoxW. 170 | fmt.Println("-- after hook") 171 | procedure.Call( 172 | 0, 173 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello2"))), 174 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("World2"))), 175 | 1, 176 | ) 177 | fmt.Println(fmt.Sprintf("0x%X", procedure.Addr()), fmt.Sprintf("0x%X", &fpMessageBoxW), fmt.Sprintf("0x%X", fpMessageBoxW)) 178 | fmt.Println() 179 | 180 | // Disable the hook for MessageBoxW. 181 | err = gominhook.DisableHook(gominhook.AllHooks) 182 | if err != nil { 183 | log.Fatalln(err) 184 | } 185 | 186 | // Calling our unhooked procedure user32.MessageBoxW. 187 | fmt.Println("-- after unhook") 188 | procedure.Call( 189 | 0, 190 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello3"))), 191 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("World3"))), 192 | 1, 193 | ) 194 | fmt.Println(fmt.Sprintf("0x%X", procedure.Addr()), fmt.Sprintf("0x%X", &fpMessageBoxW), fmt.Sprintf("0x%X", fpMessageBoxW)) 195 | fmt.Println() 196 | } 197 | 198 | /* This outputs... 199 | 200 | -- not hooked yet 201 | 0x7FFE6CA4EE10 0x578180 0x0 202 | 203 | -- after hook 204 | - MessageBoxW Override 205 | - I'm so hooked now. 206 | 0x7FFE6CA4EE10 0x578180 0x& 207 | 208 | -- after unhook 209 | 0x7FFE6CA4EE10 0x578180 0x& 210 | 211 | */ 212 | ``` 213 | 214 | - - - 215 | 216 | ### More information 217 | 218 | See `minhook` ref for C/C++ users. 219 | - https://github.com/TsudaKageyu/minhook 220 | - https://github.com/TsudaKageyu/minhook/blob/master/include/MinHook.h 221 | - https://github.com/TsudaKageyu/minhook/wiki 222 | - https://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra 223 | 224 | - - - 225 | -------------------------------------------------------------------------------- /gominhook.go: -------------------------------------------------------------------------------- 1 | package gominhook 2 | 3 | import ( 4 | "errors" 5 | "syscall" 6 | "unsafe" 7 | ) 8 | 9 | /* 10 | #cgo CFLAGS: -I${SRCDIR}/MinHook_133_bin/include 11 | #cgo amd64 LDFLAGS: -L${SRCDIR}/MinHook_133_bin/bin -lMinHook.x64 12 | #cgo 386 LDFLAGS: -L${SRCDIR}/MinHook_133_bin/bin -lMinHook.gcc.x86 13 | #include "MinHook.h" 14 | */ 15 | import "C" 16 | 17 | // Status for MH_STATUS 18 | // MinHook Error Codes. 19 | type _Status int 20 | 21 | // const for enum STAUS 22 | // MinHook Error Codes. 23 | const ( 24 | _Unknown _Status = C.MH_UNKNOWN // -1 // Unknown error. Should not be returned. 25 | _OK _Status = C.MH_OK // 0 // Successful. 26 | _ErrorAlreadyInitialized _Status = C.MH_ERROR_ALREADY_INITIALIZED // 1 // MinHook is already initialized. 27 | _ErrorNotInitialized _Status = C.MH_ERROR_NOT_INITIALIZED // 2 // MinHook is not initialized yet, or already uninitialized. 28 | _ErrorAlreadyCreated _Status = C.MH_ERROR_ALREADY_CREATED // 3 // The hook for the specified target function is already created. 29 | _ErrorNotCreated _Status = C.MH_ERROR_NOT_CREATED // 4 // The hook for the specified target function is not created yet. 30 | _ErrorEnabled _Status = C.MH_ERROR_ENABLED // 5 // The hook for the specified target function is already enabled. 31 | _ErrorDisabled _Status = C.MH_ERROR_DISABLED // 6 // The hook for the specified target function is not enabled yet, or already disabled. 32 | _ErrorNotExecutable _Status = C.MH_ERROR_NOT_EXECUTABLE // 7 // The specified pointer is invalid. It points the address of non-allocated and/or non-executable region. 33 | _ErrorUnsupportedFunction _Status = C.MH_ERROR_UNSUPPORTED_FUNCTION // 8 // The specified target function cannot be hooked. 34 | _ErrorMemoryAlloc _Status = C.MH_ERROR_MEMORY_ALLOC // 9 // Failed to allocate memory. 35 | _ErrorMemoryProtect _Status = C.MH_ERROR_MEMORY_PROTECT // 10 // Failed to change the memory protection. 36 | _ErrorModuleNotFound _Status = C.MH_ERROR_MODULE_NOT_FOUND // 11 // The specified module is not loaded. 37 | _ErrorFunctionNotFound _Status = C.MH_ERROR_FUNCTION_NOT_FOUND // 12 // The specified function is not found. 38 | ) 39 | 40 | // ToError () for const char * WINAPI MH_StatusToString(MH_STATUS status); 41 | // MH_StatusToString() - Translates the MH_STATUS to its name as a string. 42 | // ------------------------------------------------------------------------ 43 | // _Status#ToError() - Converts 'MinHook Error Codes' to 'Golang error'. 44 | func (minhookStatus _Status) ToError() error { 45 | var errMsg string 46 | switch minhookStatus { 47 | case _Unknown: 48 | errMsg = "MH_UNKNOWN" 49 | case _OK: 50 | return nil 51 | case _ErrorAlreadyInitialized: 52 | errMsg = "MH_ERROR_ALREADY_INITIALIZED" 53 | case _ErrorNotInitialized: 54 | errMsg = "MH_ERROR_NOT_INITIALIZED" 55 | case _ErrorAlreadyCreated: 56 | errMsg = "MH_ERROR_ALREADY_CREATED" 57 | case _ErrorNotCreated: 58 | errMsg = "MH_ERROR_NOT_CREATED" 59 | case _ErrorEnabled: 60 | errMsg = "MH_ERROR_ENABLED" 61 | case _ErrorDisabled: 62 | errMsg = "MH_ERROR_DISABLED" 63 | case _ErrorNotExecutable: 64 | errMsg = "MH_ERROR_NOT_EXECUTABLE" 65 | case _ErrorUnsupportedFunction: 66 | errMsg = "MH_ERROR_UNSUPPORTED_FUNCTION" 67 | case _ErrorMemoryAlloc: 68 | errMsg = "MH_ERROR_MEMORY_ALLOC" 69 | case _ErrorMemoryProtect: 70 | errMsg = "MH_ERROR_MEMORY_PROTECT" 71 | case _ErrorModuleNotFound: 72 | errMsg = "MH_ERROR_MODULE_NOT_FOUND" 73 | case _ErrorFunctionNotFound: 74 | errMsg = "MH_ERROR_FUNCTION_NOT_FOUND" 75 | } 76 | return errors.New(errMsg) 77 | } 78 | 79 | // AllHooks for #define MH_ALL_HOOKS NULL 80 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, MH_QueueEnableHook or MH_QueueDisableHook. 81 | const AllHooks = NULL 82 | 83 | // NULL = 0x00000000 84 | const NULL = 0 85 | 86 | // Initialize () for MH_STATUS WINAPI MH_Initialize(VOID) 87 | // Initialize the MinHook library. You must call this function EXACTLY ONCE at the beginning of your program. 88 | func Initialize() (err error) { 89 | ret, _, _ := syscall.Syscall(uintptr(C.MH_Initialize), 0, 0, 0, 0) 90 | return _Status(ret).ToError() 91 | } 92 | 93 | // Uninitialize () for MH_STATUS WINAPI MH_Uninitialize(VOID) 94 | // Uninitialize the MinHook library. You must call this function EXACTLY ONCE at the end of your program. 95 | func Uninitialize() (err error) { 96 | ret, _, _ := syscall.Syscall(uintptr(C.MH_Uninitialize), 0, 0, 0, 0) 97 | return _Status(ret).ToError() 98 | } 99 | 100 | // CreateHook () for MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 101 | // Creates a Hook for the specified target function, in disabled state. 102 | // Parameters: 103 | // pTarget [in] A pointer to the target function, which will be 104 | // overridden by the detour function. 105 | // pDetour [in] A pointer to the detour function, which will override 106 | // the target function. 107 | // ppOriginal [out] A pointer to the trampoline function, which will be 108 | // used to call the original target function. 109 | // This parameter can be NULL. 110 | func CreateHook(pTarget, pDetour, ppOriginal uintptr) (err error) { 111 | ret, _, _ := syscall.Syscall(uintptr(C.MH_CreateHook), 3, pTarget, pDetour, ppOriginal) 112 | return _Status(ret).ToError() 113 | } 114 | 115 | // CreateHookAPI () for MH_STATUS WINAPI MH_CreateHookApi(LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 116 | // Creates a Hook for the specified API function, in disabled state. 117 | // Parameters: 118 | // pszModule [in] A pointer to the loaded module name which contains the 119 | // target function. 120 | // pszTarget [in] A pointer to the target function name, which will be 121 | // overridden by the detour function. 122 | // pDetour [in] A pointer to the detour function, which will override 123 | // the target function. 124 | // ppOriginal [out] A pointer to the trampoline function, which will be 125 | // used to call the original target function. 126 | // This parameter can be NULL. 127 | // ------------------------------------------------------------------------ 128 | // strModule: Module name in Go's string. Replace of pszModule. 129 | // strProcName: Procedure (target function) name in Go's string. Replace of pszTarget. 130 | func CreateHookAPI(strModule, strProcName string, pDetour, ppOriginal uintptr) (err error) { 131 | ret, _, _ := syscall.Syscall6( 132 | uintptr(C.MH_CreateHookApi), 133 | 4, 134 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(strModule))), 135 | uintptr(unsafe.Pointer(C.CString(strProcName))), 136 | pDetour, 137 | ppOriginal, 138 | 0, 0, 139 | ) 140 | return _Status(ret).ToError() 141 | } 142 | 143 | // CreateHookAPIEx () for MH_STATUS WINAPI MH_CreateHookApiEx(LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 144 | // Creates a Hook for the specified API function, in disabled state. 145 | // Parameters: 146 | // pszModule [in] A pointer to the loaded module name which contains the 147 | // target function. 148 | // pszTarget [in] A pointer to the target function name, which will be 149 | // overridden by the detour function. 150 | // pDetour [in] A pointer to the detour function, which will override 151 | // the target function. 152 | // ppOriginal [out] A pointer to the trampoline function, which will be 153 | // used to call the original target function. 154 | // This parameter can be NULL. 155 | // ppTarget [out] A pointer to the target function, which will be used 156 | // with other functions. 157 | // This parameter can be NULL. 158 | // ------------------------------------------------------------------------ 159 | // strModule: Module name in Go's string. Replace of pszModule. 160 | // strProcName: Procedure (target function) name in Go's string. Replace of pszTarget. 161 | func CreateHookAPIEx(strModule, strProcName string, pDetour, ppOriginal, ppTarget uintptr) (err error) { 162 | ret, _, _ := syscall.Syscall6( 163 | uintptr(C.MH_CreateHookApiEx), 164 | 5, 165 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(strModule))), 166 | uintptr(unsafe.Pointer(C.CString(strProcName))), 167 | pDetour, 168 | ppOriginal, 169 | ppTarget, 170 | 0, 171 | ) 172 | return _Status(ret).ToError() 173 | } 174 | 175 | // RemoveHook () for MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 176 | // Removes an already created hook. 177 | // Parameters: 178 | // pTarget [in] A pointer to the target function. 179 | func RemoveHook(pTarget uintptr) (err error) { 180 | ret, _, _ := syscall.Syscall(uintptr(C.MH_RemoveHook), 1, pTarget, 0, 0) 181 | return _Status(ret).ToError() 182 | } 183 | 184 | // EnableHook () for MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 185 | // Enables an already created hook. 186 | // Parameters: 187 | // pTarget [in] A pointer to the target function. 188 | // If this parameter is MH_ALL_HOOKS, all created hooks are 189 | // enabled in one go. 190 | // ------------------------------------------------------------------------ 191 | // gominhook.AllHooks is equivalent to MH_ALL_HOOKS. 192 | // gominhook.AllHooks can be used as an argument to this function to enable all created hooks. 193 | func EnableHook(pTarget uintptr) (err error) { 194 | ret, _, _ := syscall.Syscall(uintptr(C.MH_EnableHook), 1, pTarget, 0, 0) 195 | return _Status(ret).ToError() 196 | } 197 | 198 | // DisableHook () for MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 199 | // Disables an already created hook. 200 | // Parameters: 201 | // pTarget [in] A pointer to the target function. 202 | // If this parameter is MH_ALL_HOOKS, all created hooks are 203 | // disabled in one go. 204 | // ------------------------------------------------------------------------ 205 | // gominhook.AllHooks is equivalent to MH_ALL_HOOKS. 206 | // gominhook.AllHooks can be used as an argument to this function to disable all created hooks. 207 | func DisableHook(pTarget uintptr) (err error) { 208 | ret, _, _ := syscall.Syscall(uintptr(C.MH_DisableHook), 1, pTarget, 0, 0) 209 | return _Status(ret).ToError() 210 | } 211 | 212 | // QueueEnableHook () for MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 213 | // Queues to enable an already created hook. 214 | // Parameters: 215 | // pTarget [in] A pointer to the target function. 216 | // If this parameter is MH_ALL_HOOKS, all created hooks are 217 | // queued to be enabled. 218 | // ------------------------------------------------------------------------ 219 | // gominhook.AllHooks is equivalent to MH_ALL_HOOKS. 220 | // gominhook.AllHooks can be used as an argument to this function to queue all created hooks to be enabled. 221 | func QueueEnableHook(pTarget uintptr) (err error) { 222 | ret, _, _ := syscall.Syscall(uintptr(C.MH_QueueEnableHook), 1, pTarget, 0, 0) 223 | return _Status(ret).ToError() 224 | } 225 | 226 | // QueueDisableHook () for MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 227 | // Queues to disable an already created hook. 228 | // Parameters: 229 | // pTarget [in] A pointer to the target function. 230 | // If this parameter is MH_ALL_HOOKS, all created hooks are 231 | // queued to be disabled. 232 | // ------------------------------------------------------------------------ 233 | // gominhook.AllHooks is equivalent to MH_ALL_HOOKS. 234 | // gominhook.AllHooks can be used as an argument to this function to queue all created hooks to be disabled. 235 | func QueueDisableHook(pTarget uintptr) (err error) { 236 | ret, _, _ := syscall.Syscall(uintptr(C.MH_QueueDisableHook), 1, pTarget, 0, 0) 237 | return _Status(ret).ToError() 238 | } 239 | 240 | // ApplyQueued () for MH_STATUS WINAPI MH_ApplyQueued(VOID); 241 | // Applies all queued changes in one go. 242 | func ApplyQueued() (err error) { 243 | ret, _, _ := syscall.Syscall(uintptr(C.MH_ApplyQueued), 0, 0, 0, 0) 244 | return _Status(ret).ToError() 245 | } 246 | --------------------------------------------------------------------------------