Page 1 of 2

Hot Patching hook (32bits)

Posted: Thu Sep 01, 2011 8:37 pm
by xorc1zt
Since Windows XP, Most of the windows APIs are compiled with the hotpatch command who make inline hook more proper (no more trampolines).

Code: Select all

; hot patching hook
; xorc1zt

Procedure HotPatchHook(TargetFuncAddress.l, ProxyFuncAddress.l)
  ;E9 XX XX XX XX EB F9 
  Protection.w
  JumpOffset.l = ( ProxyFuncAddress - ( TargetFuncAddress-5 ) )-5
  VirtualProtect_(TargetFuncAddress-5, 7, #PAGE_EXECUTE_READWRITE, @Protection)
  PokeA( TargetFuncAddress-5, $E9 ) ;Far Jump
  PokeL( TargetFuncAddress-4, JumpOffset )
  PokeA( TargetFuncAddress,   $EB ) ;Short Jump
  PokeA( TargetFuncAddress+1, $F9 ) ; -5
  VirtualProtect_(TargetFuncAddress-5, 7, Protection, @Protection )
EndProcedure

Procedure RemoveHook(TargetFuncAddress.l)
  ;90 90 90 90 90 8B FF
  Protection.w
  VirtualProtect_(TargetFuncAddress-5, 7, #PAGE_EXECUTE_READWRITE, @Protection)
  PokeA( TargetFuncAddress-5, $90 )
  PokeA( TargetFuncAddress-4, $90 )
  PokeA( TargetFuncAddress-3, $90 )
  PokeA( TargetFuncAddress-2, $90 )
  PokeA( TargetFuncAddress-1, $90 )
  PokeA( TargetFuncAddress,   $8B )
  PokeA( TargetFuncAddress+1, $FF )
  VirtualProtect_(TargetFuncAddress-5, 7, Protection, @Protection )
EndProcedure
Example: hooking MessageBoxA

Code: Select all

Prototype.l ProtoMessageBox(Window.l, Body$, Title$, Flags.l = 0)
Global CocoaMessageBox.ProtoMessageBox

Procedure MsgBoxProxy(Window.l, Body$, Title$, Flags.l = 0)
  Debug "MessageBoxA: "+Str(Window)+", "+Body$+", "+Title$+", "+Str(Flags)
  CocoaMessageBox(Window, Body$, Title$, Flags)
EndProcedure

OpenLibrary(0, "User32.dll")
address.l = GetFunction(0, "MessageBoxA")
CocoaMessageBox = address+2
HotPatchHook(address,@MsgBoxProxy())
CallFunction(0,"MessageBoxA", 0, @"Body", @"Title", 0)
CallFunction(0,"MessageBoxA", 0, @"aaaa", @"bbbb", 0)
CallFunction(0,"MessageBoxA", 0, @"1111", @"2222", 0)
RemoveHook(address)
CallFunction(0,"MessageBoxA", 0, @"cccc", @"dddd", 0)
edit : use this to check if a function is hot patchable or not

Code: Select all

Procedure.b IsHotPatchable(TargetFuncAddress.l)
  op.q = PeekQ(TargetFuncAddress-5)
  If FindString(Hex(op), "FF8B9090909090", 3)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Re: Hot Patching hook (32bits)

Posted: Thu Sep 01, 2011 9:24 pm
by luis
Weird in a nice way thanks !

So this can be useful to replace all the calls to a specific Windows api with your code ?

Didn't know about this thing. :)

I suppose this works only for the patching process, right ?

Re: Hot Patching hook (32bits)

Posted: Thu Sep 01, 2011 10:55 pm
by xorc1zt
luis wrote:I suppose this works only for the patching process, right ?
Yes, system wide hook must be done at kernel level with a driver

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 11:42 am
by SFSxOI
It is nice in a weird sort of way, but I don't know about a replacement for a call to the API. I mean, if you still need to declair a prototype of some sort and still call the API then why not just call the API in the first place instead of adding additional code that in the end does the same thing?

But... it is interesting. Thanks for the tip. :)

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 4:26 pm
by xorc1zt
with api hooking you can do what you want into every process where you inject your code.

example with ShellAboutW (many apps use this function for the about box)

Code: Select all

; Proxy DLL
; xorc1zt

Prototype.l ProtoShellAbout(hWnd.l, szApp.s, szOtherStuff.s, hIcon.l)
Global oShellAbout.ProtoShellAbout
Global ShellAboutAddress.l


Procedure ShellAboutProxy(hWnd.l, szApp.s, szOtherStuff.s, hIcon.l)
  szApp = "**** xorc1zt ****"
  szOtherStuff = "Hello from proxy.dll"
  oShellAbout(hWnd, szApp, szOtherStuff, hIcon)
EndProcedure

Procedure HotPatchHook(TargetFuncAddress.l, ProxyFuncAddress.l)
  ;E9 XX XX XX XX EB F9
  Protection.w
  JumpOffset.l = ( ProxyFuncAddress - ( TargetFuncAddress-5 ) )-5
  VirtualProtect_(TargetFuncAddress-5, 7, #PAGE_EXECUTE_READWRITE, @Protection)
  PokeA( TargetFuncAddress-5, $E9 ) ;Far Jump
  PokeL( TargetFuncAddress-4, JumpOffset )
  PokeA( TargetFuncAddress,   $EB ) ;Short Jump
  PokeA( TargetFuncAddress+1, $F9 ) ; -5
  VirtualProtect_(TargetFuncAddress-5, 7, Protection, @Protection )
EndProcedure

Procedure RemoveHook(TargetFuncAddress.l)
  ;90 90 90 90 90 8B FF
  Protection.w
  VirtualProtect_(TargetFuncAddress-5, 7, #PAGE_EXECUTE_READWRITE, @Protection)
  PokeA( TargetFuncAddress-5, $90 )
  PokeA( TargetFuncAddress-4, $90 )
  PokeA( TargetFuncAddress-3, $90 )
  PokeA( TargetFuncAddress-2, $90 )
  PokeA( TargetFuncAddress-1, $90 )
  PokeA( TargetFuncAddress,   $8B )
  PokeA( TargetFuncAddress+1, $FF )
  VirtualProtect_(TargetFuncAddress-5, 7, Protection, @Protection )
EndProcedure


ProcedureDLL AttachProcess(Instance)
  OpenLibrary(0, "Shell32.dll")
  
  CompilerIf #PB_Compiler_Unicode
    ShellAboutAddress = GetFunction(0, "ShellAboutW")
    oShellAbout = ShellAboutAddress+2
    HotPatchHook(ShellAboutAddress,@ShellAboutProxy())
  CompilerElse
    ShellAboutAddress = GetFunction(0, "ShellAboutA")
    oShellAbout = ShellAboutAddress+2
    HotPatchHook(ShellAboutAddress,@ShellAboutProxy())
  CompilerEndIf
EndProcedure
  
ProcedureDLL DetachProcess(Instance)
  RemoveHook(ShellAboutAddress)
EndProcedure
  
ProcedureDLL AttachThread(Instance) 
EndProcedure
  
ProcedureDLL DetachThread(Instance)
EndProcedure
this dll hook ShellAboutW (or ShellAboutA if ASCII mode)

Code: Select all

ShellAboutAddress = GetFunction(0, "ShellAboutW")
oShellAbout = ShellAboutAddress+2
HotPatchHook(ShellAboutAddress,@ShellAboutProxy())
Now, Every time the process call ShellAboutW, the call will be detoured to my function (ShellAboutProxy) who modify the arguments szApp and szOtherStuff

Code: Select all

Procedure ShellAboutProxy(hWnd.l, szApp.s, szOtherStuff.s, hIcon.l)
  szApp = "**** xorc1zt ****"
  szOtherStuff = "Hello from proxy.dll"
  oShellAbout(hWnd, szApp, szOtherStuff, hIcon)
EndProcedure
Try to inject this dll into notepad.exe and go to "?" then "About Notepad".

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 5:24 pm
by Kwai chang caine
That's look great, but i have not understand how use it :oops:

1/ I create a DLL with the first code
2/ I name it Inject.dll

So after where i put the DLL ???
How i call her ???

Can you give to me more explanation, please :cry:

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 6:34 pm
by luis
@Kwaï chang caïne

I suppose the easier way should be using a DLL injector.

http://warpzone.se/uniject.php

I never used it, it's the first I found, I suppose it should work.

Anyway search for "dll injection" and you will find a lot of info.

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 6:47 pm
by Kwai chang caine
Ok thanks LUIS 8)

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 10:07 pm
by SFSxOI
luis wrote:@Kwaï chang caïne

I suppose the easier way should be using a DLL injector.

http://warpzone.se/uniject.php

I never used it, it's the first I found, I suppose it should work.

Anyway search for "dll injection" and you will find a lot of info.
If you just wanted a .dll injector, here is one i've used for a long time for general .dll injection (and in a few games for testing :) )

Code: Select all

DisableDebugger

Prototype.i PFNCreateToolhelp32Snapshot(dwFlags.i, th32ProcessID.i) ;
Prototype.b PFNProcess32First(hSnapshot.i, *lppe.PROCESSENTRY32) ;
Prototype.b PFNProcess32Next(hSnapshot.i, *lppe.PROCESSENTRY32) ;

Procedure GetPidByName(p_name$) 
    Protected hDLL.i, process_name$ 
    Protected PEntry.PROCESSENTRY32, hTool32.i 
    Protected pCreateToolhelp32Snapshot.PFNCreateToolhelp32Snapshot 
    Protected pProcess32First.PFNProcess32First 
    Protected pProcess32Next.PFNProcess32Next 
    Protected pid.i 
    
    hDLL = OpenLibrary(#PB_Any,"kernel32.dll") 
    
    If hDLL 
        pCreateToolhelp32Snapshot = GetFunction(hDLL,"CreateToolhelp32Snapshot") 
        pProcess32First = GetFunction(hDLL,"Process32First") 
        pProcess32Next = GetFunction(hDLL,"Process32Next") 
    Else 
        ProcedureReturn 0 
    EndIf 
    
    PEntry\dwSize = SizeOf(PROCESSENTRY32) 
    hTool32 = pCreateToolhelp32Snapshot(#TH32CS_SNAPPROCESS, 0) 
    pProcess32First(hTool32, @PEntry) 
    process_name$ = Space(#MAX_PATH) 
    CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
    
    If  UCase(process_name$) = UCase(p_name$) 
        ProcedureReturn PEntry\th32ProcessID 
    EndIf 
    
    While pProcess32Next(hTool32, @PEntry) > 0 
        process_name$ = Space(#MAX_PATH) 
        CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
        
        If  UCase(process_name$) = UCase(p_name$) 
            ProcedureReturn PEntry\th32ProcessID 
        EndIf 
    
    Wend 
    
    CloseLibrary(hDLL) 
    
    ProcedureReturn 0 
EndProcedure

Procedure InjectLibA(dwProcessId.i, pszLibFile$) 
  hProcess.i 
  hThread.i 
  lzLibFileRemote.i 
  lSize.i 
  endSize.i 
  lsThreadRtn.i 
  
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId) 
  
  If hProcess = 0 : Goto ErrHandle : EndIf 
  lSize = 1 + Len(pszLibFile$) 
  endSize = lSize 
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE) 
  
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf 
  
  If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf 
  
  OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0) 
  
  If lsThreadRtn = 0 : Goto ErrHandle : EndIf 
  
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null) 
  
  If (hThread = 0) : Goto ErrHandle : EndIf 
  
  WaitForSingleObject_(hThread, #INFINITE) 
  
  If lzLibFileRemote<>0 
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Suceeded", 0)
    Else
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Failed !!!", 0)
  EndIf 
  End 
  
  ErrHandle: 
      CloseHandle_(hThread) 
      CloseHandle_(hProcess)
      MessageRequester("Inject Status", "Injection Failed !!!", 0) 
EndProcedure

dll_dir$ = GetCurrentDirectory() + "mydll.dll" ; dll is in dir with injector
Input_proc$ = "target_exe.exe"
val_pid.i = GetPidByName(Input_proc$)
Delay(10)
File_dll$ = dll_dir$
Delay(10)
InjectLibA(val_pid, dll_dir$)
The above code is from somewhere in the forum, can't remember who originated it or if it was a collective sum of methods and ideas from possibly here > http://www.purebasic.fr/english/viewtop ... 12&t=16676 - but if this code belongs to you please let me know so that I can credit it properly, and until then the credit goes to the original poster.

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 10:14 pm
by SFSxOI
I can see its use for other things, already got some ideas in mind so this is a nice addition to the arsenel of useful tricks and tips.

Does leaving this "detour" return what ever you used it on to its original 'before hook' state. Like the MS Detours use was able to do?

Re: Hot Patching hook (32bits)

Posted: Fri Sep 02, 2011 10:51 pm
by xorc1zt
another example is to hook CreateProcessW for a antivirus or prevent user to launch forbidden softwares.

speudo code

Code: Select all

Procedure MyCreateProcessW( lpApplicationName.s, ...)
	If FindString(lpApplicationName, "notepad.exe", 1)
		MessageRequester("Denied!", "You are not allowed to use notepad", #PB_MessageRequester_Ok)
		ProcedureReturn
	EndIf
	oCreateProcessW( lpApplicationName, ...	)
EndProcedure
SFSxOI wrote:I can see its use for other things, already got some ideas in mind so this is a nice addition to the arsenel of useful tricks and tips.

Does leaving this "detour" return what ever you used it on to its original 'before hook' state. Like the MS Detours use was able to do?
do you mean using ProcedureReturn originalfunc(...) ?

Like this

Code: Select all

Procedure MsgBoxProxy(Window.l, Body$, Title$, Flags.l = 0)
  ; stuff
  ProcedureReturn CocoaMessageBox(Window, Body$, Title$, Flags) ; return value of the original MessageBoxA
EndProcedure

Re: Hot Patching hook (32bits)

Posted: Sat Sep 03, 2011 12:19 am
by SFSxOI
@xorc1zt

Never mind, got it figured out now. My thoughts were confusing this with something else similar we use at work. Thanks for posting :)

Re: Hot Patching hook (32bits)

Posted: Sun Sep 04, 2011 6:59 pm
by Kwai chang caine
Thanks a lot SFSxOI 8)
Just another question.
It's surely more careful to make a copy of the DLL before, no ?? :D
In the case of it's impossible to return back :(

Re: Hot Patching hook (32bits)

Posted: Sun Sep 04, 2011 8:59 pm
by SFSxOI
Kwaï chang caïne wrote:Thanks a lot SFSxOI 8)
Just another question.
It's surely more careful to make a copy of the DLL before, no ?? :D
In the case of it's impossible to return back :(
It doesn't actually change the physical process file its self, it only does it in memory. The physical file is still intact in its original form and unchanged. Your injecting a .dll into a process in memory, and the code in the .dll you inject changes what ever is in memory of the process that your .dll was designed to affect. So there is nothing to worry about returning back to, when the process ends so does the injected .dll effect on the process and the original file of the process is unchanged.

It is possible to create a .dll to inject that does make changes to the physical process file, but unless you intentionally create or use such an injected .dll then there is nothing to worry about.

Re: Hot Patching hook (32bits)

Posted: Mon Sep 05, 2011 9:33 am
by Kwai chang caine
Thanks a lot SFSxOI for your good explanation 8)

This subject is really interesting, but like sometime KCC play with the fire, and try code without understand :oops:
Image
In fact, KCC want always playing with the big, but sometime he thinks a little bit before :mrgreen:

Cool !!!! , only in memory, this story of DLL injecting it's really very GREAT :shock:

Thanks again at xorc1zt and you, and have a good day 8)