Skip to content

Instantly share code, notes, and snippets.

@NaniteFactory
Last active May 12, 2022 20:09
Show Gist options
  • Save NaniteFactory/181ac6be5ac13c200612677f17e3f352 to your computer and use it in GitHub Desktop.
Save NaniteFactory/181ac6be5ac13c200612677f17e3f352 to your computer and use it in GitHub Desktop.
API hook in Golang.
package main
import (
"log"
"syscall"
"unsafe"
"github.com/nanitefactory/gominhook" // In order to use this package you need to have MinHook.x64.dll in your system.
)
//#include <windows.h>
//DWORD64 override(DWORD64 arg, DWORD64 arg2, DWORD64 arg3, DWORD64 arg4);
//DWORD64 foo(DWORD64 arg, DWORD64 arg2, DWORD64 arg3, DWORD64 arg4);
import "C"
// or... DWORD64 (*fpFoo)(DWORD64 arg, DWORD64 arg2, DWORD64 arg3, DWORD64 arg4);
var fpFoo *func(arg1, arg2, arg3, arg4 uintptr) (ret uintptr)
//export foo
func foo(arg1, arg2, arg3, arg4 uintptr) uintptr {
log.Println("hi", arg1, arg2, arg3, arg4)
return arg1 + arg2 + arg3 + arg4
}
//export override
func override(arg1, arg2, arg3, arg4 uintptr) (ret uintptr) {
log.Println("hooked", arg1, arg2, arg3, arg4)
ret, _, _ = syscall.Syscall6(
uintptr(unsafe.Pointer(fpFoo)),
4, 9, 9, 9, 9, 0, 0,
)
return ret
}
func main() {
log.Println("init")
gominhook.Initialize()
defer gominhook.Uninitialize()
log.Println("creat")
if err := gominhook.CreateHook(
uintptr(unsafe.Pointer(C.foo)),
uintptr(unsafe.Pointer(C.override)),
uintptr(unsafe.Pointer(&fpFoo)),
); err != nil {
log.Println(err)
}
log.Println("enable")
gominhook.EnableHook(gominhook.AllHooks)
log.Println("call foo")
log.Println(
syscall.Syscall6(
uintptr(unsafe.Pointer(C.foo)),
4, uintptr(0x1), uintptr(0x2), 3, 4, 0, 0,
),
)
}
package main
import (
"log"
"syscall"
"unsafe"
"github.com/nanitefactory/gominhook" // In order to use this package you need to have MinHook.x64.dll in your system.
)
//#include <windows.h>
//DWORD32 override(DWORD32 arg, DWORD32 arg2, DWORD32 arg3, DWORD32 arg4);
//DWORD32 foo(DWORD32 arg, DWORD32 arg2, DWORD32 arg3, DWORD32 arg4);
import "C"
// or... DWORD32 (*fpFoo)(DWORD32 arg, DWORD32 arg2, DWORD32 arg3, DWORD32 arg4);
var fpFoo *func(arg1, arg2, arg3, arg4 uintptr) (ret uintptr)
//export foo
func foo(arg1, arg2, arg3, arg4 uintptr) uintptr {
log.Println("hi", arg1, arg2, arg3, arg4)
return arg1 + arg2 + arg3 + arg4
}
//export override
func override(arg1, arg2, arg3, arg4 uintptr) (ret uintptr) {
log.Println("hooked", arg1, arg2, arg3, arg4)
ret, _, _ = syscall.Syscall6(
uintptr(unsafe.Pointer(fpFoo)),
4, 9, 9, 9, 9, 0, 0,
)
return ret
}
func main() {
log.Println("init")
gominhook.Initialize()
defer gominhook.Uninitialize()
log.Println("creat")
if err := gominhook.CreateHook(
uintptr(unsafe.Pointer(C.foo)),
uintptr(unsafe.Pointer(C.override)),
uintptr(unsafe.Pointer(&fpFoo)),
); err != nil {
log.Println(err)
}
log.Println("enable")
gominhook.EnableHook(gominhook.AllHooks)
log.Println("call foo")
log.Println(
syscall.Syscall6(
uintptr(unsafe.Pointer(C.foo)),
4, uintptr(0x1), uintptr(0x2), 3, 4, 0, 0,
),
)
}
package main
import (
"fmt"
"log"
"syscall"
"unsafe"
"github.com/nanitefactory/gominhook"
)
/*
#include <Windows.h>
// Put C prototypes here
// Delegate type for calling original MessageBoxW.
typedef int (WINAPI *MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT);
// (!) This way you can connect/convert a go function to a c function.
int MessageBoxWOverrideHellYeah(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
*/
import "C"
// Pointer for calling original MessageBoxW.
var fpMessageBoxW C.MESSAGEBOXW
// (!) This way you can connect/convert a go function to a c function.
//export MessageBoxWOverrideHellYeah
func MessageBoxWOverrideHellYeah(hWnd C.HWND, lpText C.LPCWSTR, lpCaption C.LPCWSTR, uType C.UINT) C.int {
fmt.Println(" - MessageBoxW Override")
foo()
ret, _, _ := syscall.Syscall6(
uintptr(unsafe.Pointer(fpMessageBoxW)),
4,
uintptr(unsafe.Pointer(hWnd)),
uintptr(unsafe.Pointer(lpText)),
uintptr(unsafe.Pointer(lpCaption)),
uintptr(uint(uType)),
0, 0,
)
return C.int(ret)
}
func foo() {
fmt.Println(" - I'm so hooked now.")
}
func main() {
// Initialize minhook
err := gominhook.Initialize()
if err != nil {
log.Fatalln(err)
}
defer gominhook.Uninitialize()
// Get procedure user32.MessageBoxW
procedure := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW")
fmt.Println("-- not hooked yet")
procedure.Call(
0,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello1"))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("World1"))),
1,
)
fmt.Println(fmt.Sprintf("0x%X", procedure.Addr()), fmt.Sprintf("0x%X", &fpMessageBoxW), fmt.Sprintf("0x%X", fpMessageBoxW))
fmt.Println()
// Create a hook for MessageBoxW.
err = gominhook.CreateHook(procedure.Addr(), uintptr(C.MessageBoxWOverrideHellYeah), uintptr(unsafe.Pointer(&fpMessageBoxW)))
if err != nil {
log.Fatalln(err)
}
// Enable the hook for MessageBoxW.
err = gominhook.EnableHook(gominhook.AllHooks)
if err != nil {
log.Fatalln(err)
}
// Calling our hooked procedure user32.MessageBoxW.
fmt.Println("-- after hook")
procedure.Call(
0,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello2"))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("World2"))),
1,
)
fmt.Println(fmt.Sprintf("0x%X", procedure.Addr()), fmt.Sprintf("0x%X", &fpMessageBoxW), fmt.Sprintf("0x%X", fpMessageBoxW))
fmt.Println()
// Disable the hook for MessageBoxW.
err = gominhook.DisableHook(gominhook.AllHooks)
if err != nil {
log.Fatalln(err)
}
// Calling our unhooked procedure user32.MessageBoxW.
fmt.Println("-- after unhook")
procedure.Call(
0,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello3"))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("World3"))),
1,
)
fmt.Println(fmt.Sprintf("0x%X", procedure.Addr()), fmt.Sprintf("0x%X", &fpMessageBoxW), fmt.Sprintf("0x%X", fpMessageBoxW))
fmt.Println()
}
/* This outputs...
-- not hooked yet
0x7FFE6CA4EE10 0x578180 0x0
-- after hook
- MessageBoxW Override
- I'm so hooked now.
0x7FFE6CA4EE10 0x578180 0x&
-- after unhook
0x7FFE6CA4EE10 0x578180 0x&
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment