Page 2 of 2

Re: Hot Patching hook (32bits)

Posted: Mon Sep 05, 2011 4:55 pm
by Kwai chang caine
Excuse me, but this super subject give to me an idea :idea:

Believe you it's possible to modify the behaviour of the OLE32.dll, with this great code ????

Re: Hot Patching hook (32bits)

Posted: Thu Oct 17, 2019 2:13 am
by Opcode
Updated, as today even syscalls are hot-patchable.

Code: Select all

; Hot Patch Hooking

; --------------------------------------------------
;   Place Hook
;   $E9, $xx, $xx, $xx, $xx, $EB, $F9
; --------------------------------------------------

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

; --------------------------------------------------
;   Remove Hook
;   $CC, $CC, $CC, $CC, $CC, $8B, $FF
; --------------------------------------------------

Procedure RemoveHook(TargetFuncAddress.l)
  
  Protected.l Protection
  
  VirtualProtect_(TargetFuncAddress - 5, 7, #PAGE_EXECUTE_READWRITE, @Protection)
  
  PokeB(TargetFuncAddress - 5, $CC)
  PokeB(TargetFuncAddress - 4, $CC)
  PokeB(TargetFuncAddress - 3, $CC)
  PokeB(TargetFuncAddress - 2, $CC)
  PokeB(TargetFuncAddress - 1, $CC)
  PokeB(TargetFuncAddress + 0, $8B)
  PokeB(TargetFuncAddress + 1, $FF)
  
  VirtualProtect_(TargetFuncAddress - 5, 7, Protection, @Protection)
  
EndProcedure

; --------------------------------------------------
;   Check If Function Is Hot Patchable
; --------------------------------------------------

Procedure.b IsHotPatchable(TargetFuncAddress.l)
  
  Protected.q EntryPoint = PeekQ(TargetFuncAddress - 5)
  
  If FindString(Hex(EntryPoint), "FF8BCCCCCCCCCC", 3)
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
  
EndProcedure
Example:

Code: Select all

XIncludeFile "HotPatch.pbi"

Prototype.l ProtoMessageBox(hWnd.l, *lpText, *lpCaption, uType.l = 0)

Global CocoaMessageBox.ProtoMessageBox

; Hooked MessageBoxW
Procedure MsgBoxProxy(hWnd.l, *lpText, *lpCaption, uType.l = 0)
  
  Debug "MessageBoxW => " + "Title: " + PeekS(*lpCaption) + " Body: " + PeekS(*lpText)
  CocoaMessageBox(hWnd, *lpText, *lpCaption, uType)
  
EndProcedure

; Main
If OpenLibrary(0, "User32.dll")
  
  Address.l = GetFunction(0, "MessageBoxW")
  
  If IsHotPatchable(Address)
    CocoaMessageBox = Address + 2
    HotPatchHook(Address, @MsgBoxProxy())
    
    CallFunction(0, "MessageBoxW", 0, @"Body", @"Title", 0)
    CallFunction(0, "MessageBoxW", 0, @"bbbb", @"aaaa", 0)
    CallFunction(0, "MessageBoxW", 0, @"2222", @"1111", 0)
    
    RemoveHook(Address)
    CallFunction(0, "MessageBoxW", 0, @"dddd", @"cccc", 0)
  EndIf
EndIf

Re: Hot Patching hook (32bits)

Posted: Thu Oct 17, 2019 8:37 am
by BarryG
SFSxOI wrote: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?
Maybe it could stop false positives with virus-checkers? I will have to check this out.

Re: Hot Patching hook (32bits)

Posted: Thu Oct 17, 2019 8:54 am
by Mijikai
BarryG wrote:
SFSxOI wrote: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?
Maybe it could stop false positives with virus-checkers? I will have to check this out.
This is often used to update a running program or to add in some logging functionality (statistics).
Hooks are also often used in the game modding scene or program automation.

With some minor changes the method shown here can be used to hook code without the need of pre existing 'spaces'.

Hooking itself will more likely increase false positives as it is also used in malware.

Re: Hot Patching hook (32bits)

Posted: Thu Oct 17, 2019 11:49 am
by chi
@Opcode: IsHotPatchable() always returns 0 on my rig with Win7 x64 PB5.71(x86+x64) and WinXP x86 (VM) PB5.70(x86). Any ideas why?

Re: Hot Patching hook (32bits)

Posted: Sat Oct 19, 2019 11:02 pm
by Opcode
BarryG wrote:
SFSxOI wrote: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?
Maybe it could stop false positives with virus-checkers? I will have to check this out.
From my personal experience, the best way to reduce false positives with PB compiled binary is to make sure you include version info (some antivirus scanners will flag it simply because it lacks version info) and then packing the binary with UPX (scrambles and masks signatures that antivirus scanners have flag otherwise). If I do neither, I'll get like 13/69 on VirusTotal. If I do both, depending on the code base I'm comping I can even achieve 0/69. I've noticed even just version info strings themselves can upset virus scanners. So you have to be creative and do a little trial and error.
chi wrote:@Opcode: IsHotPatchable() always returns 0 on my rig with Win7 x64 PB5.71(x86+x64) and WinXP x86 (VM) PB5.70(x86). Any ideas why?
I changed NOP to INT3 since on Windows 10 Pro x64 it wouldn't work (what's read on my machine shows "FF8BCCCCCCCCCC" instead of "FF8B9090909090").

You could try going back to using NOP.

Code: Select all

If FindString(Hex(EntryPoint), "FF8B9090909090", 3)
If that's the case you'll need to update the unhook function as well.

Code: Select all

  PokeB(TargetFuncAddress - 5, $90)
  PokeB(TargetFuncAddress - 4, $90)
  PokeB(TargetFuncAddress - 3, $90)
  PokeB(TargetFuncAddress - 2, $90)
  PokeB(TargetFuncAddress - 1, $90)
  PokeB(TargetFuncAddress + 0, $8B)
  PokeB(TargetFuncAddress + 1, $FF)

Re: Hot Patching hook (32bits)

Posted: Sun Oct 20, 2019 3:47 pm
by chi
@Opcode: Thanks, with "FF8B9090909090" I got it working on PB x86, but on PB x64 Hex(EntryPoint) returns "EC83489090909090". I think it's because the user32.dll doesn't load from "C:\Windows\System32\user32.dll" but from "C:\Windows\winsxs\amd64_microsoft-windows-user32_31bf3856ad364e35_6.1.7601.24524_none_2bdcf8519d2214ea\user32.dll" instead. Seems like MS patched the HotPatching feature?! The dll now contains "90 90 90 90 90 90 90 90 90 48 83 EC" instead of "90 90 90 90 90 8B FF"...

Re: Hot Patching hook (32bits)

Posted: Mon Oct 21, 2019 1:02 am
by Opcode
chi wrote:@Opcode: Thanks, with "FF8B9090909090" I got it working on PB x86, but on PB x64 Hex(EntryPoint) returns "EC83489090909090". I think it's because the user32.dll doesn't load from "C:\Windows\System32\user32.dll" but from "C:\Windows\winsxs\amd64_microsoft-windows-user32_31bf3856ad364e35_6.1.7601.24524_none_2bdcf8519d2214ea\user32.dll" instead. Seems like MS patched the HotPatching feature?! The dll now contains "90 90 90 90 90 90 90 90 90 48 83 EC" instead of "90 90 90 90 90 8B FF"...
It seems there's a lot of variance between builds of Windows in regards to if they use NOP or INT3. I will stick to the inline method of hooking (using a trampoline) as it still works flawlessly.

I posted updated code in this topic if you're interested: viewtopic.php?p=543517#p543517

Re: Hot Patching hook (32bits)

Posted: Mon Oct 21, 2019 5:45 am
by chi
Opcode wrote:
chi wrote:@Opcode: Thanks, with "FF8B9090909090" I got it working on PB x86, but on PB x64 Hex(EntryPoint) returns "EC83489090909090". I think it's because the user32.dll doesn't load from "C:\Windows\System32\user32.dll" but from "C:\Windows\winsxs\amd64_microsoft-windows-user32_31bf3856ad364e35_6.1.7601.24524_none_2bdcf8519d2214ea\user32.dll" instead. Seems like MS patched the HotPatching feature?! The dll now contains "90 90 90 90 90 90 90 90 90 48 83 EC" instead of "90 90 90 90 90 8B FF"...
It seems there's a lot of variance between builds of Windows in regards to if they use NOP or INT3. I will stick to the inline method of hooking (using a trampoline) as it still works flawlessly.

I posted updated code in this topic if you're interested: viewtopic.php?p=543517#p543517
Thanks, going to check it out...

I was using Peyman's API_HookEngine Module for some time, but eventually switched to MinHook because it's much more reliable and has some unique features.

Re: Hot Patching hook (32bits)

Posted: Mon Oct 21, 2019 7:01 am
by Mijikai
chi wrote:@Opcode: Thanks, with "FF8B9090909090" I got it working on PB x86, but on PB x64 Hex(EntryPoint) returns "EC83489090909090". I think it's because the user32.dll doesn't load from "C:\Windows\System32\user32.dll" but from "C:\Windows\winsxs\amd64_microsoft-windows-user32_31bf3856ad364e35_6.1.7601.24524_none_2bdcf8519d2214ea\user32.dll" instead. Seems like MS patched the HotPatching feature?! The dll now contains "90 90 90 90 90 90 90 90 90 48 83 EC" instead of "90 90 90 90 90 8B FF"...
The easiest solution for a multiplatfom scenario is to hook the IAT instead of the function itself.