API hooking

Share your advanced PureBasic knowledge/code with the community.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Hmm, not a bad idea... But I would use it for PureAV 8) . Lemme search for PureFan's posts, maybe i can find some info about it...
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post by newbie »

Great info Rings ;)

About the driver, you will need to do it in C++ with the MS SDK I guess, and hook native API. Far less easy than PB :?
- Registered PB user -

Using PB 4.00
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Nope, it's too hard... Yes, i tried with VC++ express + Windows SDK + Windows DDK, but it takes to much space and it's very hard to build something good. So the better option is to use this code and patch all running processes... I don't see an alternative here unless a very experienced C coder will help us make a good driver. And that's hard. We'd better stick with this code until we find something better.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
uweb
User
User
Posts: 98
Joined: Wed Mar 15, 2006 9:40 am
Location: Germany

Post by uweb »

May this will help. I found it but i am not able to use it.
http://www.codeproject.com/system/kernelspying.asp
http://www.codeproject.com/system/api_spying_hack.asp

I am also not abel to use your good work for my purpose :

Code: Select all

;Translated  from C to Pure by Siegfried Rings, 2006 

;API Hooking example for PureBasic 4 
;(c) Sigfried Rings and Inf0Byt3 
;Version 0.1 
;>------------------------------------------------------------ 

;License: Freeware but with some limits: By using this library you agree 
;NOT use it for creating malware, viruses, spyware, worms or rootkits 
;or any program of this kind. If you do this I will find you, I'll kick your sorry ass, 
;and cut your arms off so you can't code such crap in the future ;) 
;Now get back to coding! 

#module = "kernel32" 
#proc = "FindNextFileA" 

; ############################################################################
; you should have a file with the extension ".wf" in c:\ to see any difference
; ############################################################################

Procedure SearchDisk(path.s)
  Count = 0
  url.s = path + "*"
  Static searchData.WIN32_FIND_DATA 
  hFind = FindFirstFile_(url.s,@searchData) 
  If hFind <> #INVALID_HANDLE_VALUE 
    Repeat
      Count+1
    Until FindNextFile_(hFind, @searchData)= #False
    FindClose_(handle)
  EndIf
  Debug Count
EndProcedure

Procedure Test () 
    StandardFile$ = "C:\" 
    Pattern$ = "Text (*.txt)|*.txt;*.bat|*.pb|Alle Dateien (*.*)|*.*" 
    Pattern = 2 
    File$ = OpenFileRequester("Bitte Datei auswählen", StandardFile$, Pattern$, Pattern) 
EndProcedure 

Global Dim Backup.b(5) 

Procedure.l MyHook ( FindFileHandle.l, *FindFileData.WIN32_FIND_DATA)
  SetLastError_(#ERROR_NO_MORE_FILES)
  ProcedureReturn 0
EndProcedure
  
Procedure.l Hook(Libname.s,FuncName.s,NewFunctionAddress) 
  dwAddr =GetProcAddress_(GetModuleHandle_(LibName), FuncName) 
  OriginalAdress=dwAddr 
  Result=ReadProcessMemory_(GetCurrentProcess_(), dwAddr, @Backup(0), 6, @readbytes) ;save old Bytes 
  Dim a.b(6) 
  a(0)=$e9 
  a(5)=$C3 
  dwCalc = NewFunctionAddress - dwAddr - 5;   //((to)-(from)-5) 
  CopyMemory(@dwCalc,@a(1),4) 
  Result = WriteProcessMemory_(GetCurrentProcess_(), dwAddr, @a(0), 6, @written); 
  Debug "Result : "+Str(Result)
EndProcedure 
  
Procedure UnHook(Libname.s,FuncName.s) 
  dwAddr = GetProcAddress_(GetModuleHandle_(LibName), FuncName) 
  Result= WriteProcessMemory_(GetCurrentProcess_(), dwAddr, @Backup(0), 6, @written); 
EndProcedure 
  
Test () 
SearchDisk("C:\")
Hook(#module, #proc, @MyHook()); 
Test () 
SearchDisk("C:\")
UnHook(#module, #proc)
Where is my failure ?
Is OpenFileRequester not a part of my app-process ?
Please pardon my English, my native tongue is German.
sazuker
New User
New User
Posts: 9
Joined: Thu Jun 05, 2008 6:48 pm

Post by sazuker »

the problem on this hook is that you need to hook and un hook the function everytime you need to use the original procedure

ex.

Code: Select all

procedure myfunction(a,b,c,d)
	procedurereturn thisfunction(a,b,c,d) 
	;THIS RUNS ON AN INFINITE LOOP
	;since calling thisfunction would jmp again to myfunction then to thisfunction...
endprocedure

HookFunction(thisfunction, myfunction)
as a FIX

Code: Select all

procedure myfunction(a,b,c,d)
	UnHookFunction(thisfunction, myfunction) ;unhook first so that we can use thisfunction() without looping back
	result = thisfunction(a,b,c,d) 
	HookFunction(thisfunction, myfunction)
	procedurereturn result
endprocedure

HookFunction(thisfunction, myfunction)
But this is not efficient since everytime the program uses the function you need to hook/unhook read/write memory

As a solution I found this asm code but I dont know how to translate it to PB
what does it do is that it hooks the function and then returns the relocated address of the original function
so you can do 1 time hook and just pass the parameters to the original function

so you will just do

Code: Select all

myoriginalfunction =0
procedure myfunction(a,b,c,d)
	procedurereturn CallFunctionFast(myoriginalfunction, a,b,c,d) 
endprocedure

myoriginalfunction = HookFunction(thisfunction, myfunction)

Code: Select all

; ProcInstallHook proc uses ebx edi esi hookProc:DWORD, targetProc:DWORD, patchLen:DWORD
; 	
; 	mov esi, patchLen
; 	mov edi, targetProc
; 	
; 	mov eax, esi
; 	add eax, 5
; 	invoke Alloc, eax
; 	mov ebx, eax
; 	
; 	; copy the to-be-emulated bytes from targetProc to detour's beginning
; 	invoke MemCopy, edi, eax, esi
; 	
; 	; make the target writable
; 	invoke VirtualProtect, edi, 5, PAGE_EXECUTE_READWRITE, ADDR targetProc
; 	
; 	; replace the bytes with a jmp to the hook
; 	mov eax, hookProc
; 	sub eax, edi
; 	sub eax, 5
; 	mov BYTE PTR [edi], 0E9h
; 	mov [edi + 1], eax
; 	
; 	; set protections back to old ones to avoid complications
; 	invoke VirtualProtect, edi, 5, targetProc, ADDR targetProc
; 	
; 	; put a jmp to the targetProc at the end of detour
; 	sub edi, ebx
; 	add esi, ebx
; 	sub edi, 5
; 	mov BYTE PTR [esi], 0E9h
; 	mov [esi + 1], edi
; 	
; 	Return ebx
; 	
; ProcInstallHook endp 
Can anyone do help translate this wonderful piece of code?
thx
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

They prefer if you post a request one time in one forum.

cheers
User avatar
pdwyer
Addict
Addict
Posts: 2813
Joined: Tue May 08, 2007 1:27 pm
Location: Chiba, Japan

Post by pdwyer »

Can you hook a process running under different credentials? or, if your process is not running as an administrator can you hook a process that is? (I would hope not I guess...)
Paul Dwyer

“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
User avatar
DoubleDutch
Addict
Addict
Posts: 3220
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Post by DoubleDutch »

If you create the system hooking code in a DLL, then call the hooking "start" from your user app it will hook system system wide.
(If no anti-virus code stops you).
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

pdwyer wrote:Can you hook a process running under different credentials? or, if your process is not running as an administrator can you hook a process that is? (I would hope not I guess...)
I believe you can so long as you have equal or higher credentials than that process. I know this is very restrictive on Vista. I don't know how loose these rules are on other Windows operating systems.
superadnim
Enthusiast
Enthusiast
Posts: 480
Joined: Thu Jul 27, 2006 4:06 am

Post by superadnim »

I tried to port it but I messed up, I think at the last portions where I got "register loss" since I'm not very good with assembly



Code: Select all

Procedure.l ProcInstallHook (hookProc.l, targetProc.l, patchLen.l)  ; detouring hook.
  
   Memory = AllocateMemory(patchLen+5)
   
   ; copy the to-be-emulated bytes from targetProc to detour's beginning 
   CopyMemory(targetProc, Memory, patchLen)
   
   ; make the target writable 
   VirtualProtect_(targetProc, 5, #PAGE_EXECUTE_READWRITE, @protection)
   
   ; replace the bytes with a jmp to the hook 
   PokeB(targetProc, $0E9)
   PokeL(targetProc + SizeOf(BYTE), ((hookProc - targetProc) - 5) )
   
   ; set protections back to old ones to avoid complications 
   VirtualProtect_( targetProc, 5, protection, @protection )
   
   targetProc - Memory 
   patchLen 	+ Memory
   targetProc - 5
   
   ; put a jmp to the targetProc at the end of detour 
   PokeB(Memory, $0E9)
   PokeL(Memory + SizeOf(BYTE), targetProc)
   
   ProcedureReturn Memory 
    
EndProcedure ; ProcInstallHook


Global myoriginalfunction = 0 


Procedure myfunction(hWnd, Title$, Text$, Flags=#Null) 
	a:
	Beep_(1000,100) : Debug "BEEP!"
	ProcedureReturn CallFunctionFast(myoriginalfunction, hWnd, Title$, Text$, Flags)
	b:
EndProcedure 

Declare MessageBox(hWnd, Title$, Text$, Flags=#Null )

Import "user32.lib"
	MessageBox(hWnd, Title$, Text$, Flags=#Null ) As "_MessageBoxA"
EndImport

myoriginalfunction = ProcInstallHook( @MessageBox(), @myfunction(), ?b-?a)

MessageBox(0, "world", "hello")
;myfunction(0,"world", "hello")

I assumed the size it requires is of the new function (else I don't know how to get the original function's size...!)

But it never beeps in my example, and if you swap the procedure pointers it does beep but in an endless loop (no detouring at all).

Perhaps someone could spot my mistake (I assume its on the bottom part of the code). I understand the idea behind this, I don't understand the "how" exactly.

:lol: should I bash the keyboard and give up?
:?
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

DoubleDutch wrote:If you create the system hooking code in a DLL, then call the hooking "start" from your user app it will hook system system wide.
(If no anti-virus code stops you).
I'm not sure if I understand what you mean, but I had no luck using a dll here. Can you maybe show some example?
I like logic, hence I dislike humans but love computers.
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Re: API hooking

Post by Blankname »

newbie wrote:Interesting piece of code, thanks for sharing ;)
But I do not understand at all this snippet :

Code: Select all

Dim a.b(6)
a(0)=$e9
a(5)=$C3
What are these values ? Where do they come from ?
Basically you backup the current real API address, and then you overwrite it with your custom procedure address, I don't see the need of these values.

Code: Select all

Dim a.b(6)
a(0)=$e9 ;JMP
a(5)=$C3 ;RET
It backs up existing API bytes, and makes the function jump to your own procedure. From there you can do whatever you want with the information that is sent in the API call. When its done, it just writes the original bytes back to restore the original function.
Post Reply