Darky - PureBasic API Hooking Library

Share your advanced PureBasic knowledge/code with the community.
Darky
New User
New User
Posts: 3
Joined: Wed Aug 18, 2010 3:22 am

Darky - PureBasic API Hooking Library

Post by Darky »

detour_lib.pbi

Code: Select all

Structure Hook_Data
  OriBytes.b[6]
  NewBytes.b[6]
  ProcAddr.l
EndStructure

#CURRENT_LIB_VERSION = "1.0"
#CURRENT_LIB_NAME = "Darky - PureBasic API Hooking Library"

Global Dim Hooks.Hook_Data(0)
Global bFirstTime.b = #True

Procedure.i Setup_Hook(Libname.s, FuncName.s, RedFunAddr.l)
If bFirstTime = #False
  ReDim Hooks(ArraySize(Hooks()) + 1)
EndIf
bFirstTime = #False
  
dwAddr = GetProcAddress_(GetModuleHandle_(LibName), FuncName) ;Get the Function Memory Address
OriginalAdress = dwAddr
Hooks(ArraySize(Hooks()))\ProcAddr = dwAddr ;This for Fast Unhooking

If OriginalAdress > 0
  ;Save the old api Bytes
  If ReadProcessMemory_(-1, dwAddr, @Hooks(ArraySize(Hooks()))\OriBytes[0], 6, 0)
    
    Dim a.b(6)
    a(0)=$e9 ;JMP
    a(5)=$C3 ;RET
    
    dwCalc = RedFunAddr - dwAddr - 5; 

    CopyMemory(@dwCalc, @a(1), 4)
    
    ;Save the New Bytes
    CopyMemory(@a(0), @Hooks(ArraySize(Hooks()))\NewBytes[0], 6)
    ;Get ready for new hook
    
    If WriteProcessMemory_(-1, dwAddr, @a(0), 6, 0)
      ProcedureReturn ArraySize(Hooks())
    EndIf
  EndIf
EndIf
   
ProcedureReturn - 1 ;Bad didn't work
EndProcedure

Procedure.b Fast_ReHook(hookIndex.i)
  ProcedureReturn WriteProcessMemory_(-1, Hooks(hookIndex)\ProcAddr, @Hooks(hookIndex)\NewBytes[0], 6, 0)
EndProcedure

Procedure.b ReHook(hookIndex.i, LibName.s, FuncName.s)
  dwAddr = GetProcAddress_(GetModuleHandle_(LibName), FuncName) ;Get the Memory Address
  ProcedureReturn WriteProcessMemory_(-1, dwAddr, @Hooks(hookIndex)\NewBytes[0], 6, 0)
EndProcedure

Procedure.b Fast_UnHook(hookIndex.i)
  ProcedureReturn WriteProcessMemory_(-1, Hooks(hookIndex)\ProcAddr, @Hooks(hookIndex)\OriBytes[0], 6, 0)
EndProcedure

Procedure.b UnHook(hookIndex.i, LibName.s, FuncName.s)
  dwAddr = GetProcAddress_(GetModuleHandle_(LibName), FuncName) ;Get the Memory Address
  ProcedureReturn WriteProcessMemory_(-1, dwAddr, @Hooks(hookIndex)\OriBytes[0], 6, 0) ;Restore Old Bytes
EndProcedure 
Example:

Code: Select all

Procedure.l RedMsgboxA(hWnd.i, lpText.s, lpCaption.s, uType.i)
  Fast_UnHook(0)
  MessageBox_(0, "Hooked" ,"me", 0)
  Fast_ReHook(0)
  ProcedureReturn 1
EndProcedure

Debug Setup_Hook("User32.dll", "MessageBoxA", @RedMsgboxA())
MessageBox_(0, "123", "456", 0) 
Note: Setup_Hook returns the current hook index.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Re: Darky - PureBasic API Hooking Library

Post by Rescator »

Same issues as the other hook post.

This only works for the Ascii calls, not the Unicode "W" calls.

Secondly this only works within the current process, starting a second process while the first is running and the second behaves just like normal, no hooking shown.

Thirdly, it's a good thing it doesn't work on other processes etc. Because in the example you forgot to restore the original.
Not only that but the unhook routines, seem odd, for some reason they re-read the proc address instead of simply using the ProcAddr in the array.
And there really should be a unhook all that one could call at the end of the program.


Then again, since this only works in the current process it's just simpler to use a macro anyway. *laughs*

The way hooks are easily done is making a dll, putting that dll in the program folder. Obviously that dll need to replace/pass through ALL functions of the original dll.
The other way is a Loader (or injector).
A third would be a Trainer but not really intended for this kind of hooking.

The proper way to do this is a Debugger hook, and it must be running as admin and it must have write to process privileges etc. (I'm sure some of the folks around here knows how to properly do this stuff?)

But I wouldn't be surprised if your code works as intended on Win 9x though.
Darky
New User
New User
Posts: 3
Joined: Wed Aug 18, 2010 3:22 am

Re: Darky - PureBasic API Hooking Library

Post by Darky »

This only works for the Ascii calls, not the Unicode "W" calls.
Unicode calls work fine for me.
Thirdly, it's a good thing it doesn't work on other processes etc. Because in the example you forgot to restore the original.
I do restore the original bytes by using the Fast_UnHook or the UnHook Procedure:
Procedure.l RedMsgboxA(hWnd.i, lpText.s, lpCaption.s, uType.i)
Fast_UnHook(0)
MessageBox_(0, "Hooked" ,"me", 0)
Fast_ReHook(0)
ProcedureReturn 1
EndProcedure
Then again, since this only works in the current process it's just simpler to use a macro anyway. *laughs*
The way hooks are easily done is making a dll, putting that dll in the program folder. Obviously that dll need to replace/pass through ALL functions of the original dll.
This code is to be used inside an dll not out.
But I wouldn't be surprised if your code works as intended on Win 9x though.
Working at 100% on Windows Xp/Vista/7 - 32bit.
Thorium
Addict
Addict
Posts: 1271
Joined: Sat Aug 15, 2009 6:59 pm

Re: Darky - PureBasic API Hooking Library

Post by Thorium »

Darky wrote: Working at 100% on Windows Xp/Vista/7 - 32bit.
It doesnt work at 100%.
Same problem than the other inline hook example: It misses a disassembler to verify code integrity. It will lead to crashes if used on functions that start with instructions that dont align to the 5 or 6 byte border. Which is very uncommen in WinAPI, only a few functions like DbgBreakPoint are that way. But it's actualy common in none WinAPI DLLs.
registrymechanic22
Enthusiast
Enthusiast
Posts: 176
Joined: Sun Jun 28, 2009 7:07 pm
Location: RUS

Re: Darky - PureBasic API Hooking Library

Post by registrymechanic22 »

Darky wrote:
does not work on Win_64 :(
what to do to fix this?
Thorium
Addict
Addict
Posts: 1271
Joined: Sat Aug 15, 2009 6:59 pm

Re: Darky - PureBasic API Hooking Library

Post by Thorium »

registrymechanic22 wrote:
Darky wrote:
does not work on Win_64 :(
what to do to fix this?
Use integer as addresses. I am not sure if the assembler instructions have to be changed, since jmp is relativ it should also work on x64.
DarkDragon
Addict
Addict
Posts: 2228
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: Darky - PureBasic API Hooking Library

Post by DarkDragon »

Rescator wrote:Then again, since this only works in the current process it's just simpler to use a macro anyway. *laughs*
This doesn't work in all cases. Just look at the old v2synth libraries. There you had to hook a directshow audio routine behind the lib to render the v2 music to a file. This can't be done with PB macros. :wink:
bye,
Daniel
Post Reply