Updated 5.7X as a module. Removed
OpenProcess so it will only work for the current process that it's running in (you can re-add it if needed).
Detour.pbiCode:
DeclareModule CHook
Import "Kernel32.lib"
GetProcAddress_(hModule.l, lpProcName.p-ascii) As "_GetProcAddress@8"
EndImport
Declare.b InlineHook(LibraryName.s, LibraryFunction.s, NewFunction.l, OldFunction.l)
Declare.b InlineUnhook(LibraryName.s, LibraryFunction.s, NewFunction.l, OldFunction.l)
EndDeclareModule
Module CHook
; --------------------------------------------------
; Install Hook
; --------------------------------------------------
Procedure.b InlineHook(LibraryName.s, LibraryFunction.s, NewFunction.l, OldFunction.l)
Protected.l OldAddr, NewAddr, RetAddr, CodeAddress, OldProtection
OldAddr = GetProcAddress_(GetModuleHandle_(LibraryName), LibraryFunction)
NewAddr = NewFunction
RetAddr = OldAddr + 5
CodeAddress = VirtualAllocEx_(GetCurrentProcess_(), #Null, 10, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
If CodeAddress = #Null
ProcedureReturn #False
EndIf
VirtualProtect_(OldAddr, 5, #PAGE_EXECUTE_READWRITE, @OldProtection)
; Trampoline
CopyMemory(OldAddr, CodeAddress, 5)
PokeB(CodeAddress + 5, $E9)
PokeL(CodeAddress + 6, RetAddr - (CodeAddress + 10))
; JMP To Detour Function
PokeB(OldAddr + 0, $E9)
PokeL(OldAddr + 1, ((NewAddr - OldAddr) - 5))
VirtualProtect_(OldAddr, 5, OldProtection, @OldProtection)
; Update Prototype Pointer To Point To Trampoline
PokeL(OldFunction, CodeAddress)
ProcedureReturn #True
EndProcedure
; --------------------------------------------------
; Remove Hook
; --------------------------------------------------
Procedure.b InlineUnhook(LibraryName.s, LibraryFunction.s, NewFunction.l, OldFunction.l)
Protected.l OldAddr, CodeAddress, OldProtection
OldAddr = GetProcAddress_(GetModuleHandle_(LibraryName), LibraryFunction)
CodeAddress = PeekL(OldFunction)
If CodeAddress = #Null
ProcedureReturn #False
EndIf
; Restore Bytes Of Original Function
VirtualProtect_(OldAddr, 5, #PAGE_EXECUTE_READWRITE, @OldProtection)
CopyMemory(CodeAddress, OldAddr, 5)
VirtualProtect_(OldAddr, 5, OldProtection, @OldProtection)
; Free Trampoline
FillMemory(CodeAddress, 10, 0)
VirtualFreeEx_(GetCurrentProcess_(), CodeAddress, 0, #MEM_RELEASE)
; Update Prototype Pointer To Point To Hook Function
PokeL(OldFunction, NewFunction)
ProcedureReturn #True
EndProcedure
EndModule
Example.pbCode:
XIncludeFile "Detour.pbi"
Prototype.l RealMessageBoxW(hWnd.l, lpText.s, lpCaption.s, uType.l)
Global o_MessageBoxW.RealMessageBoxW
Procedure.l MyMessageBoxW(hWnd.l, lpText.s, lpCaption.s, uType.l)
ProcedureReturn o_MessageBoxW(hWnd, "MessageBoxW Is Now Hooked!", lpCaption, uType)
EndProcedure
CHook::InlineHook("User32.dll", "MessageBoxW", @MyMessageBoxW(), @o_MessageBoxW)
MessageRequester("Demo", "This Is Test A!")
CHook::InlineUnhook("User32.dll", "MessageBoxW", @MyMessageBoxW(), @o_MessageBoxW)
MessageRequester("Demo", "This Is Test B!")