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
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
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
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
Just another question.
It's surely more careful to make a copy of the DLL before, no ??
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
Just another question.
It's surely more careful to make a copy of the DLL before, no ??
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
This subject is really interesting, but like sometime KCC play with the fire, and try code without understand
In fact, KCC want always playing with the big, but sometime he thinks a little bit before
Cool !!!! , only in memory, this story of DLL injecting it's really very GREAT
Thanks again at xorc1zt and you, and have a good day