Page 1 of 3

intercept API

Posted: Thu Jun 24, 2010 5:44 am
by registrymechanic22
Hi all

Code: Select all

Procedure.s PutDirektorii(PutPapka); #CSIDL_SYSTEM
Put$=Space(#MAX_PATH):SHGetSpecialFolderLocation_(0,PutPapka,@Raz)
SHGetPathFromIDList_(Raz, @Put$):ProcedureReturn Trim(Put$)
EndProcedure

Procedure HookedProcedure(a,b)
; newmessagebox:
; Debug a
; Debug b
; Debug c
; Debug d
MessageRequester("!!!!", "+++++++++++++++++++++++")
ProcedureReturn
EndProcedure

Procedure Hook(process,library$,function$,HookedProcAddr)
   dwAddr=GetProcAddress_(GetModuleHandle_(library$),function$)
   Debug dwaddr
   ReadProcessMemory_(process,dwAddr,@Backup(0),6,@readbytes)
   Dim a.b(6) : a(0)=$68 : a(5)=$C3 : dwCalc=HookedProcAddr-dwAddr-5
   CopyMemory(@dwCalc,@a(1),4)
;    VirtualProtect_(dwAddr,8,#PAGE_EXECUTE_READWRITE,@oldP) 
   WriteProcessMemory_(process,dwAddr,@a(0),6,@written)
EndProcedure

Procedure OpenWindow_Window_0()
Protected res=0
  If OpenWindow(0, 100, 100, 145, 260, "HookMe", #PB_Window_SystemMenu)
    ButtonGadget(1, 40,  60,  60, 25, "Delete")
    ButtonGadget(2, 40,  20,  60, 25, "Create")
    ButtonGadget(3, 40,  100,  60, 25, "MSB")
    StringGadget(4, 40,  140, 60, 25, Str(GetCurrentProcessId_()), #PB_String_ReadOnly)
    ButtonGadget(5, 40,  180,  60, 25, "inject")
    ButtonGadget(6, 40,  220,  60, 25, "Hook")
    res=1
  EndIf
ProcedureReturn res
EndProcedure

  If OpenWindow_Window_0()
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_Gadget
          EventGadget = EventGadget()
          Select EventGadget
            Case 1 : f$="c:\test.txt" : DeleteFile_(f$)
            Case 2 : f$="c:\test.txt" : CreateFile(0,f$) : WriteString(0,"hi") : CloseFile(0) 
            Case 3 : MessageBox_(0," О  п  а .            ","В н и м а н и е !", #MB_ICONHAND)  
;             Case 5 : InjectDll("scan.dll")  
            Case 6
                    hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, Val(GetGadgetText(4)))
                    Hook(hProcess,"kernel32.dll","DeleteFileA",@HookedProcedure())
          EndSelect
      EndSelect
    Until Event=#PB_Event_CloseWindow
  EndIf
End
program crashes... :(
What am I doing wrong?
Correctly find the address of the procedure, why it does not work??

Thanks for your help in advance!

Re: intercept API

Posted: Fri Jun 25, 2010 12:11 am
by Jihugen
Interesting/fun piece of code.
What seems to be wrong for me:
- You were using $68 (PUSH). I think you intended to use $E9 (CALL). ;)
- Remove the all parameter from HookedProcedure() (I think you're not pushing any parameter on the stack with your patch).
If you want to intercept the parameters given to DeleteFileA(), it's probably more complicated.

The code below is working (replace those 2 procedures in your code).

Code: Select all

Procedure HookedProcedure()                   ; <--- No parameter here
MessageRequester("!!!!", "+++++++++++++++++++++++")
ProcedureReturn
EndProcedure

Procedure Hook(process,library$,function$,HookedProcAddr)
   dwAddr=GetProcAddress_(GetModuleHandle_(library$),function$)
   Debug dwaddr
   Debug Hex(PeekL(dwaddr))
   ReadProcessMemory_(process,dwAddr,@Backup(0),6,@readbytes)
   Dim a.b(5) : a(0)=$E8 : a(5)=$c3 : dwCalc=HookedProcAddr-dwAddr-5    ; <--- fixed line
   CopyMemory(@dwCalc,@a(1),4)
   WriteProcessMemory_(process,dwAddr,@a(0),6,@written)
 EndProcedure

Re: intercept API

Posted: Fri Jun 25, 2010 5:07 am
by registrymechanic22
Jihugen wrote:
Hi.
Thank you.

How then can intercept the parameters given to DeleteFileA(?) ?


Yours sincerely.

Re: intercept API

Posted: Fri Jun 25, 2010 7:38 am
by registrymechanic22
alternatively can use this:

Code: Select all

Global Dim Backup(0)

Global buf1.s
Global buf11,buf2,buf3.s,buf4.s,buf5

Procedure.s PutDirektorii(PutPapka); #CSIDL_SYSTEM
Put$=Space(#MAX_PATH):SHGetSpecialFolderLocation_(0,PutPapka,@Raz)
SHGetPathFromIDList_(Raz, @Put$):ProcedureReturn Trim(Put$)
EndProcedure

Procedure HookedProcedure1()

 ! mov eax,[esp+8] 
 ! mov dword[v_buf1],eax

Debug "DeleteFile_("+Chr($22)+buf1+Chr($22)+")"

EndProcedure
Procedure HookedProcedure2()

 ! mov eax,[esp+8] 
 ! mov dword[v_buf2],eax
 ! mov eax,[esp+12] 
 ! mov dword[v_buf3],eax
 ! mov eax,[esp+16] 
 ! mov dword[v_buf4],eax
 ! mov eax,[esp+20] 
 ! mov dword[v_buf5],eax

Debug "MessageBox("+Str(buf2)+", "+Chr($22)+buf3+Chr($22)+", "+Chr($22)+buf4+Chr($22)+", "+Str(buf5)+")"

EndProcedure

Procedure Hook(process,library$,function$,HookedProcAddr)
   dwAddr=GetProcAddress_(GetModuleHandle_(library$),function$)
   ReadProcessMemory_(process,dwAddr,@Backup(0),6,@readbytes)
   Dim a.b(5) : a(0)=$E8 : a(5)=$c3 : dwCalc=HookedProcAddr-dwAddr-5    ; <--- fixed line
   CopyMemory(@dwCalc,@a(1),4)
   WriteProcessMemory_(process,dwAddr,@a(0),6,@written)
EndProcedure
Procedure OpenWindow_Window_0()
Protected res=0
  If OpenWindow(0, 100, 100, 145, 260, "HookMe", #PB_Window_SystemMenu)
    ButtonGadget(1, 40,  60,  60, 25, "Delete")
    ButtonGadget(2, 40,  20,  60, 25, "Create")
    ButtonGadget(3, 40,  100,  60, 25, "MSB")
    StringGadget(4, 40,  140, 60, 25, Str(GetCurrentProcessId_()), #PB_String_ReadOnly)
    ButtonGadget(5, 40,  180,  60, 25, "inject")
    ButtonGadget(6, 40,  220,  60, 25, "Hook")
    res=1
  EndIf
ProcedureReturn res
EndProcedure

  If OpenWindow_Window_0()
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_Gadget
          EventGadget = EventGadget()
          Select EventGadget
            Case 1 : f$="c:\test1.txt" : DeleteFile_(f$)
            Case 2 : f$="c:\test.txt" : CreateFile(0,f$) : WriteString(0,"hi") : CloseFile(0) 
            Case 3 : MessageBox_(0," О  п  а .            ","В н и м а н и е !", #MB_ICONHAND)  
;             Case 5 : InjectDll("scan.dll")  
            Case 6
                    hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, Val(GetGadgetText(4)))
                    Hook(hProcess,"kernel32.dll","DeleteFileA",@HookedProcedure1())
                    Hook(hProcess,"user32.dll","MessageBoxA",@HookedProcedure2())
          EndSelect
      EndSelect
    Until Event=#PB_Event_CloseWindow
  EndIf
End
BUT, I do not want to use ASM... :(
than can replace these inserts from ASM?? :?:

Re: intercept API

Posted: Fri Jun 25, 2010 12:50 pm
by Jihugen
registrymechanic22 wrote:BUT, I do not want to use ASM... :(
than can replace these inserts from ASM?? :?:
I don't know if there is another feasible way (but well, I'm far from an expert in this field :? ).
Why not use ASM?
In this case it seems actually pertinent, no?

Re: intercept API

Posted: Fri Jun 25, 2010 1:23 pm
by registrymechanic22
I do not know ASM? I can not work with him .... :oops:

in HookedProcedure () to add to intercept functions, its treatment, and return it to either suspend or continue.

.. Sorry for my english... :oops:

Code: Select all

Procedure UnHook(library$,function$)
  dwAddr=GetProcAddress_(GetModuleHandle_(library$),function$)
  WriteProcessMemory_(GetCurrentProcess_(),dwAddr,@Backup(0),6,@written)
EndProcedure

Procedure HookedProcedure1()

! mov eax,[esp+8]
! mov dword[v_buf1],eax

UnHook("kernel32.dll","DeleteFileA")
DeleteFile_(buf2) ; or stop!
Hook("kernel32.dll","DeleteFileA",@NewDeleteFile())
EndProcedure
I think there's a lot extra, and how to make beautiful, myself can not understand

Re: intercept API

Posted: Fri Jun 25, 2010 6:16 pm
by Thorium
If you hook API functions you can just put the parameter in the hook procedure as normal parameters. No assembler needed, if it's StdCall.

Re: intercept API

Posted: Fri Jun 25, 2010 8:32 pm
by SFSxOI
Whats the whole thing look like? I lost track between the asm conversions and the replacement procedures as to what exactly you were trying to accomplish. And whats 'backup' look like?

Re: intercept API

Posted: Fri Jun 25, 2010 9:23 pm
by registrymechanic22
Prompt please example (code), to correct my mistake?
I do not know how to implement it.... :(

Fhanks in advance.


PS:
********* executable EXE *********

Code: Select all

Procedure.s PutDirektorii(PutPapka)
; PutPapka=#CSIDL_SYSTEMX86
Put$=Space(#MAX_PATH):SHGetSpecialFolderLocation_(0,PutPapka,@Raz)
SHGetPathFromIDList_(Raz, @Put$):ProcedureReturn Trim(Put$)
EndProcedure

Procedure InjectDll(NameDll.s)
   hProcess=OpenProcess_(#PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_READ | #PROCESS_VM_WRITE,0,Val(GetGadgetText(4)))
   LL=GetProcAddress_(GetModuleHandle_(PutDirektorii(#CSIDL_SYSTEM)+"\kernel32.dll"),"LoadLibraryA")
   VA=VirtualAllocEx_(hProcess,0,12,#MEM_RESERVE | #MEM_COMMIT,#PAGE_READWRITE)
   WriteProcessMemory_(hProcess,VA,NameDll.s,12,0)
   CreateRemoteThread_(hProcess,0,0,LL,VA,0,0)
   CloseHandle_(hProcess)
EndProcedure

Procedure OpenWindow_Window_0()
Protected res=0
  If OpenWindow(0, 100, 100, 145, 260, "HookMe", #PB_Window_SystemMenu)
    ButtonGadget(1, 40,  60,  60, 25, "Delete")
    ButtonGadget(2, 40,  20,  60, 25, "Create")
    ButtonGadget(3, 40,  100,  60, 25, "MSB")
    StringGadget(4, 40,  140, 60, 25, Str(GetCurrentProcessId_()), #PB_String_ReadOnly)
    ButtonGadget(5, 40,  180,  60, 25, "inject")
    ButtonGadget(6, 40,  220,  60, 25, "Hook")
    res=1
  EndIf
ProcedureReturn res
EndProcedure

  If OpenWindow_Window_0()
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_Gadget
          EventGadget = EventGadget()
          Select EventGadget
            Case 1 : f$="c:\test.txt" : DeleteFile_(f$)
            Case 2 : f$="c:\test.txt" : CreateFile(0,f$) : WriteString(0,"hi") : CloseFile(0) 
            Case 3 : MessageBox_(0," О  п  а .            ","В н и м а н и е !", #MB_ICONHAND)  
            Case 5 : InjectDll("scan.dll")  
            Case 6
;                     hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, 1448)
;                     Hook(hProcess,"kernel32.dll","DeleteFileA",@HookedProcedure1())
;                     Hook(hProcess,"user32.dll","MessageBoxA",@HookedProcedure2())
          EndSelect
      EndSelect
    Until Event=#PB_Event_CloseWindow
  EndIf
End
********* DLL *********

Code: Select all

Global Dim Backup(0)

Global oldP

Global buf1.s,buf2.s,buf3.s,buf4.s,buf5.s,buf6.s

Declare NewDeleteFile() 

Procedure EnableDebugPrivilege()
If OpenProcessToken_(GetCurrentProcess_(),#TOKEN_ADJUST_PRIVILEGES|#TOKEN_QUERY,@hToken)
tp.TOKEN_PRIVILEGES : tp\PrivilegeCount=1
If LookupPrivilegeValue_(#Null,"SeDebugPrivilege",tp\Privileges[0]\Luid)
tp\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
If AdjustTokenPrivileges_(hToken,#False,@tp,SizeOf(tp),#Null,#Null)
EndIf : EndIf : EndIf
EndProcedure
EnableDebugPrivilege()


Procedure.s PutDirektorii(PutPapka)
Protected Put.s
PutPapka=#CSIDL_SYSTEMX86
Put.s=Space(#MAX_PATH):SHGetSpecialFolderLocation_(0,PutPapka,@Raz)
SHGetPathFromIDList_(Raz, @Put):ProcedureReturn Trim(Put)
EndProcedure

Procedure Hook(library$,function$,HookedProcAddr)
Protected dwAddr, old
Protected process = OpenProcess_(#PROCESS_ALL_ACCESS, 0, GetCurrentProcessId_())
old=GetModuleHandle_(library$)
dwAddr=GetProcAddress_(old,function$)
ReadProcessMemory_(process,dwAddr,@Backup(0),6,@readbytes)
Dim a.b(5) : a(0)=$E8 : a(5)=$c3 : dwCalc=HookedProcAddr-dwAddr-5    ; <--- fixed line
CopyMemory(@dwCalc,@a(1),4)
WriteProcessMemory_(process,dwAddr,@a(0),6,@written)
EndProcedure

Procedure UnHook(library$,function$)
  dwAddr=GetProcAddress_(GetModuleHandle_(library$),function$)
  WriteProcessMemory_(GetCurrentProcess_(),dwAddr,@Backup(0),6,@written)
EndProcedure


ProcedureDLL AttachProcess(Instance) 

Hook("kernel32.dll","DeleteFileA",@NewDeleteFile())

EndProcedure 

; *******************************************************
; user32.dll


Procedure NewMessageBox() 

         ! mov eax,[esp+4] 
         ! mov dword[v_buf1],eax         ;hwnd 
         ! mov eax,[esp+8] 
         ! mov dword[v_buf2],eax      ;text 
         ! mov eax,[esp+12] 
         ! mov dword[v_buf3],eax      ;caption 
         ! mov eax,[esp+16] 
         ! mov dword[v_buf4],eax         ;type 
          
         OpenFile(1,"qqqqq.txt") 
         FileSeek(1,Lof(1)) 
         WriteStringN(1, "MessageBox("+Str(v_buf1)+", "+Chr($22)+buf2+Chr($22)+", "+Chr($22)+buf3+Chr($22)+", "+Str(v_buf4)+")" ) 
         CloseFile(1) 
         
; call_newmessagebox=delta_newmessagebox+NewUser32 
; ! jmp dword[v_call_newmessagebox] 
EndProcedure 



; *******************************************************
; kernel32.dll

Procedure NewDeleteFile() 

;          ! mov eax,[esp+4] 
;          ! mov dword[v_buf1],eax         ;name 
         ! mov eax,[esp+8] 
         ! mov dword[v_buf2],eax         ;name 


         OpenFile(1,"qqqqq.txt") 
         FileSeek(1,Lof(1)) 
         WriteStringN(1, buf2) 
         CloseFile(1) 
; MessageRequester("",buf2)

; call_newdeletefile =delta_newdeletefile+NewKernel32 
; ! jmp dword[v_call_newdeletefile] 

UnHook("kernel32.dll","DeleteFileA")
; DeleteFile_(buf2)
OpenLibrary(1,"kernel32.dll")
CallFunction(1, "DeleteFileA", buf2)
CloseLibrary(1)
Hook("kernel32.dll","DeleteFileA",@NewDeleteFile())
EndProcedure

; *******************************************************
; !jmp @F
; !MP10 ;3 по счету
; !MP12 ;4
; !@@:
; *******************************************************
; *******************************************************
???

Re: intercept API

Posted: Fri Jun 25, 2010 9:28 pm
by Thorium
SFSxOI wrote:Whats the whole thing look like? I lost track between the asm conversions and the replacement procedures as to what exactly you were trying to accomplish. And whats 'backup' look like?
'backup' is the original code fragment he is overwriting. It's needed if he wants to call the original procedure and to uninstall the hook. However it's not good in his code. He just uses a length of 6 byte for the backup, which can lead to a crash if the procedure don't starts with the code he is expecting. If the instructions are longer or shorter and not match the 6 byte border he will not be able to call the original procedure without uninstalling his hook. The normal solution to that is using a simple disassembler engine to get the length of the instructions.

Re: intercept API

Posted: Fri Jun 25, 2010 9:33 pm
by Thorium

Code: Select all

Procedure NewMessageBox(hwnd.i, text.s, caption.s, type.i)

         OpenFile(1,"qqqqq.txt")
         FileSeek(1,Lof(1))
         WriteStringN(1, "MessageBox("+Str(v_buf1)+", "+Chr($22)+buf2+Chr($22)+", "+Chr($22)+buf3+Chr($22)+", "+Str(v_buf4)+")" )
         CloseFile(1)
         
; call_newmessagebox=delta_newmessagebox+NewUser32
; ! jmp dword[v_call_newmessagebox]
EndProcedure 
Not tested but thats what i mean with the parameters.

Re: intercept API

Posted: Sat Jun 26, 2010 2:32 am
by SFSxOI
Thorium wrote:
SFSxOI wrote:Whats the whole thing look like? I lost track between the asm conversions and the replacement procedures as to what exactly you were trying to accomplish. And whats 'backup' look like?
'backup' is the original code fragment he is overwriting. It's needed if he wants to call the original procedure and to uninstall the hook. However it's not good in his code. He just uses a length of 6 byte for the backup, which can lead to a crash if the procedure don't starts with the code he is expecting. If the instructions are longer or shorter and not match the 6 byte border he will not be able to call the original procedure without uninstalling his hook. The normal solution to that is using a simple disassembler engine to get the length of the instructions.

Ahhhh...ok, got it. Thanks

But why even use ASM to begin with, what he wants to do is just StdCall isn't it ?

Re: intercept API

Posted: Sat Jun 26, 2010 3:12 am
by Jihugen
SFSxOI wrote:But why even use ASM to begin with, what he wants to do is just StdCall isn't it ?
The goal was to write a Call to HookedProcedure() directly at the beginning of the DeleteFileA function, so that each call to DeleteFileA will be forwarded to HookedProcedure.
It's fast, dirty and fun... There is probably other (and better) ways.

Thorium wrote:However it's not good in his code. He just uses a length of 6 byte for the backup, which can lead to a crash if the procedure don't starts with the code he is expecting. If the instructions are longer or shorter and not match the 6 byte border he will not be able to call the original procedure without uninstalling his hook. The normal solution to that is using a simple disassembler engine to get the length of the instructions.
Sorry, Thorium, but I don't understand what you mean here.
For me, 6 bytes is enough for the backup, and it seems clear that calling the original procedure without uninstalling the hook is impossible. What did I get wrong?

Re: intercept API

Posted: Sat Jun 26, 2010 7:48 am
by registrymechanic22
Thorium wrote:

Code: Select all

Procedure NewMessageBox(hwnd.i, text.s, caption.s, type.i)
......................
EndProcedure 
Not tested but thats what i mean with the parameters.
... Tried, not working, the program crashes :?

Re: intercept API

Posted: Sat Jun 26, 2010 8:27 am
by Thorium
Calling the original procedure without uninstalling the hook is not only possible, its a normal thing. It's not that hard. You just need to copy the correct number of bytes on hook installation. The code you will write to the procedure is likely 5 byte. What you need to do is copy the complete instructions that you overwrite. There can be some shorter instructions or one bigger. But you cant expect them to allways end at byte 6. You need a intact code fragment not a cutted instruction. Therefor you need to get the length of the intructions you overwrite to copy them intact. Thats easy with the Error Lib of PB.
Once you have that intact code fragment you may need to fix it. For example if there is a jump in it you have to recalculate the destination, because its saved relative to the instruction. Then you write a jmp to the end of the copied code that jumps right after your patched code in the original procedure. Now you just need to call the copied code to Call the original procedure.
Most people skip the part of fixing instructions because its very unlikely that there is a jump in the first 5 byte.

I hope thats better understandable, sorry english is not my nativ language.