It is currently Mon Dec 09, 2019 6:32 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 36 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: API Hook Engine Module (Windows)
PostPosted: Tue Feb 02, 2016 3:41 am 
Offline
Enthusiast
Enthusiast

Joined: Mon Dec 24, 2007 4:15 pm
Posts: 203
Location: Iran
hi, i create this Hook Engine for educational purposes and use it in some of my projects so now share it maybe come in handy for someone.

i try to optimize it to work on X64 & X86 Windows apps and also with Unicode switch on.

Version 1.0
  • Initial

Update 1.1
  • Added InjectDLL for inject a DLL to another process (Injector must be same as Target process both must be X86 or X64)

Update 1.2
  • Added EjectDLL method for unload a DLL from target process
  • Added CallRemoteFunction method to call a proc from a DLL in target process (just one parameter can be passed to Remote Function)
  • Improved Injector, Now X64 Injector can inject in x64 & x86 target but x86 injector just can inject to x86 target.

API_HookEngine.pbi
Code:
; ====================================================================================================
; Title:        API_HookEngine Module
; Description:  With this module you can hook procedures and api in windows
; Author:       Peyman
; Version:      1.0 (02 FEB 2016) initial version
;               1.1 (07 FEB 2016) added Inject DLL
;               1.2 (11 FEB 2016) improved injector, added Eject DLL & CallRemoteFunction with parrameter
; Platform:     Windows (X64 And X86) Unicode And Ansi
; License:      Free But Any improvements to be shared with the community.
; ====================================================================================================

DeclareModule API_HookEngine
  Declare.i Hook(*OldFunctionAddress, *NewFunctionAddress)
  Declare.i UnHook(*hook_ptr)
  Declare.i ProcAddress(ModuleName$, ProcName$)
  Declare.i InjectDLL(PID, DLL$)
  Declare.b EjectDLL(PID, DLL$, *_Module = #Null)
  Declare.i CallRemoteFunction(PID, *Func, Proc2Call$, WaitForReturn.b = #False, *retValue = #Null, *Parameter = #Null, nSize = #Null)
EndDeclareModule


Module API_HookEngine 
  EnableExplicit
 
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    #INJECTOR_IS_64 = #True
  CompilerElse
    #INJECTOR_IS_64 = #False
  CompilerEndIf
 
 
  Structure opcode
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      mov.u
    CompilerElse
      mov.a
    CompilerEndIf
    addr.i
    push.a
    ret.a
  EndStructure
 
 
  Structure hookstruct
    addr.i
    hook.opcode
    orig.a[SizeOf(opcode)]
  EndStructure
 
 
  CompilerIf #PB_Compiler_Unicode
    Import "kernel32.lib"
      GetProcAddress(hModule, lpProcName.p-ascii)
    EndImport
  CompilerElse
    Import "kernel32.lib"
      GetProcAddress(hModule, lpProcName.s)
    EndImport
  CompilerEndIf
 

  Import ""
    GetNativeSystemInfo(*info)
  EndImport
 
 
  Procedure.i ProcAddress(ModuleName$, ProcName$)
    Protected moduleH.i
   
    moduleH = GetModuleHandle_(ModuleName$)
    If moduleH = #Null
      moduleH = LoadLibrary_(ModuleName$)
      If moduleH = #Null
        ProcedureReturn #Null
      EndIf
    EndIf
   
    ProcedureReturn GetProcAddress(moduleH, ProcName$)
  EndProcedure


  Procedure Hook(*OldFunctionAddress, *NewFunctionAddress)
    Protected *hook_ptr.hookstruct
   
    If Not *OldFunctionAddress
      ProcedureReturn #Null
    EndIf
   
    *hook_ptr = AllocateMemory(SizeOf(hookstruct))
    *hook_ptr\addr = *OldFunctionAddress
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      *hook_ptr\hook\mov = $B848
    CompilerElse
      *hook_ptr\hook\mov = $B8
    CompilerEndIf
    *hook_ptr\hook\addr = *NewFunctionAddress
    *hook_ptr\hook\push = $50
    *hook_ptr\hook\ret = $C3
     
    CopyMemory(*OldFunctionAddress, @*hook_ptr\orig, SizeOf(opcode))
    If Not WriteProcessMemory_(GetCurrentProcess_(), *OldFunctionAddress, @*hook_ptr\hook, SizeOf(opcode), #Null)
      FreeMemory(*hook_ptr)
      ProcedureReturn #Null
    Else
      ProcedureReturn *hook_ptr
    EndIf
  EndProcedure
 

  Procedure.i UnHook(*hook_ptr.hookstruct)
    Protected retValue.i
   
    If *hook_ptr
      If *hook_ptr\addr
        If WriteProcessMemory_(GetCurrentProcess_(), *hook_ptr\addr, @*hook_ptr\orig, SizeOf(opcode), #Null)
          retValue = *hook_ptr\addr
          FreeMemory(*hook_ptr)
          ProcedureReturn retValue
        EndIf
      EndIf
    EndIf
   
    ProcedureReturn #Null
  EndProcedure
 
 
  Procedure Is64Process(PID); is the Process is 64;
    Protected *IsWow64Process, retvalue, hProcess
    Protected Info.SYSTEM_INFO, is_64 = #False
   
    GetNativeSystemInfo(Info)
    If info\wProcessorArchitecture = 9 ; is a X64 os   
      *IsWow64Process = ProcAddress("kernel32.dll", "IsWow64Process")
      If *IsWow64Process
        hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION, #False, PID)
        If hProcess
          CallFunctionFast(*IsWow64Process, hProcess, @retvalue)
          CloseHandle_(hProcess)
          If retvalue = #False
            is_64 = #True
          EndIf
        EndIf
      EndIf
    EndIf
   
    ProcedureReturn is_64
  EndProcedure
 
 
  Procedure TraverseRemoteModules(PID, _Module$)
    Protected modules.MODULEENTRY32
    Protected snapshot, m_ok, modBaseAddr
     
    snapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE | #TH32CS_SNAPMODULE32, PID)
    If snapshot
      modules\dwSize = SizeOf(MODULEENTRY32)
      m_ok = Module32First_(snapshot, modules)
      While m_ok
        If FindString(PeekS(@modules\szModule), _Module$, 1, #PB_String_NoCase)
          modBaseAddr = modules\modBaseAddr
          Break
        EndIf
        m_ok = Module32Next_(snapshot, modules)
      Wend
      CloseHandle_(snapshot) 
    EndIf
   
    ProcedureReturn modBaseAddr
  EndProcedure
 
 
  Procedure TraverseRemoteProcs(PID, _Module$, ProcName$, *_Module = #Null)
    Protected hProcess, modBaseAddr, retValue = #Null
    Protected index, index2, TempChar.a, TempFunctionName.s
    Protected DosHeader.IMAGE_DOS_HEADER
    Protected Signature.l
    Protected FileHeader.IMAGE_FILE_HEADER
    Protected Is64Bit.b
    Protected OptHeader64.IMAGE_OPTIONAL_HEADER64
    Protected OptHeader32.IMAGE_OPTIONAL_HEADER32
    Protected ExportDirectory.IMAGE_DATA_DIRECTORY
    Protected ExportTable.IMAGE_EXPORT_DIRECTORY
    Protected Dim ExportFunctionTable.l(0)
    Protected Dim ExportNameTable.l(0)
    Protected Dim ExportOrdinalTable.w(0)
     
     hProcess = OpenProcess_(#PROCESS_VM_READ, #False, PID)
     If hProcess
       If *_Module
         modBaseAddr = *_Module
       Else
         modBaseAddr = TraverseRemoteModules(PID, _Module$)
       EndIf
     
      If Not modBaseAddr
        Goto TRM_END
      EndIf
     
       If ReadProcessMemory_(hProcess, modBaseAddr, @DosHeader, SizeOf(IMAGE_DOS_HEADER), #Null) And DosHeader\e_magic <> $5A4D
         Goto TRM_END
       EndIf
       
       If ReadProcessMemory_(hProcess, modBaseAddr + DosHeader\e_lfanew, @Signature, SizeOf(Signature), #Null) And Signature <> $4550
         Goto TRM_END
       EndIf
       
       If Not ReadProcessMemory_(hProcess, modBaseAddr + DosHeader\e_lfanew + SizeOf(Signature), @FileHeader, SizeOf(IMAGE_FILE_HEADER), #Null)
        Goto TRM_END
      EndIf
     
       If FileHeader\SizeOfOptionalHeader = SizeOf(IMAGE_OPTIONAL_HEADER64)
          Is64Bit = #True
       ElseIf FileHeader\SizeOfOptionalHeader = SizeOf(IMAGE_OPTIONAL_HEADER32)
          Is64Bit = #False
       Else
         Goto TRM_END
       EndIf
       
       If Is64Bit
          If ReadProcessMemory_(hProcess, modBaseAddr + DosHeader\e_lfanew + SizeOf(Signature) + SizeOf(IMAGE_FILE_HEADER),  @OptHeader64, FileHeader\SizeOfOptionalHeader, #Null) And OptHeader64\Magic <> $020B
            Goto TRM_END
          EndIf
       Else
          If ReadProcessMemory_(hProcess, modBaseAddr + DosHeader\e_lfanew + SizeOf(Signature) + SizeOf(IMAGE_FILE_HEADER), @OptHeader32, FileHeader\SizeOfOptionalHeader, #Null) And OptHeader32\Magic <> $010B
            Goto TRM_END
          EndIf
        EndIf
        
       If Is64Bit And OptHeader64\NumberOfRvaAndSizes >= #IMAGE_DIRECTORY_ENTRY_EXPORT + 1
          ExportDirectory\VirtualAddress = OptHeader64\DataDirectory[#IMAGE_DIRECTORY_ENTRY_EXPORT]\VirtualAddress
          ExportDirectory\Size = OptHeader64\DataDirectory[#IMAGE_DIRECTORY_ENTRY_EXPORT]\Size
       ElseIf OptHeader32\NumberOfRvaAndSizes >= #IMAGE_DIRECTORY_ENTRY_EXPORT + 1
          ExportDirectory\VirtualAddress = OptHeader32\DataDirectory[#IMAGE_DIRECTORY_ENTRY_EXPORT]\VirtualAddress
          ExportDirectory\Size = OptHeader32\DataDirectory[#IMAGE_DIRECTORY_ENTRY_EXPORT]\Size
       Else
         Goto TRM_END
       EndIf
       
       If Not ReadProcessMemory_(hProcess, modBaseAddr + ExportDirectory\VirtualAddress, @ExportTable, SizeOf(IMAGE_EXPORT_DIRECTORY), #Null)
         Goto TRM_END
       EndIf
      
       ReDim ExportFunctionTable(ExportTable\NumberOfFunctions)
       ReDim ExportNameTable(ExportTable\NumberOfNames)
       ReDim ExportOrdinalTable.w(ExportTable\NumberOfNames)
       
       If Not ReadProcessMemory_(hProcess, modBaseAddr + ExportTable\AddressOfFunctions,   @ExportFunctionTable(), ExportTable\NumberOfFunctions * SizeOf(Long), #Null)
         Goto TRM_END
       EndIf
     
       If Not ReadProcessMemory_(hProcess, modBaseAddr + ExportTable\AddressOfNames, @ExportNameTable(), ExportTable\NumberOfNames * SizeOf(Long), #Null)
         Goto TRM_END
       EndIf
     
       If Not ReadProcessMemory_(hProcess, modBaseAddr + ExportTable\AddressOfNameOrdinals, @ExportOrdinalTable(), ExportTable\NumberOfNames * SizeOf(Word), #Null)
         Goto TRM_END
       EndIf
 
       For index = 0 To ExportTable\NumberOfNames - 1
         TempFunctionName = ""
         index2 = 0
   
         Repeat
           If Not ReadProcessMemory_(hProcess, modBaseAddr + ExportNameTable(index) + index2, @TempChar, SizeOf(TempChar), #Null)
             Break 2
          EndIf
   
             If TempChar = #Null
               Break
             Else
               TempFunctionName + Chr(TempChar)
             EndIf
             
             index2 + 1
          ForEver
       
         If TempFunctionName = ProcName$
           retValue = modBaseAddr + ExportFunctionTable(ExportOrdinalTable(index))
           Break
         EndIf
      Next
     
      TRM_END:
      CloseHandle_(hProcess)
      FreeArray(ExportFunctionTable())
      FreeArray(ExportNameTable())
      FreeArray(ExportOrdinalTable())
    EndIf
   
    ProcedureReturn retValue
  EndProcedure
 
 
  Procedure InjectDLL(PID.i, DLL$)
    Protected address, ThreadHandle, BufferSize, *buffer
    Protected ProcessHandle.i, retvalue = #Null, *dll_unicode
    Protected is_target_64.b = #False
   
    If FileSize(Dll$) > 0
      is_target_64 = Is64Process(PID)
      If #INJECTOR_IS_64 = is_target_64
        address = ProcAddress("kernel32.dll", "LoadLibraryW")
      ElseIf #INJECTOR_IS_64
        address = TraverseRemoteProcs(PID, "kernel32.dll", "LoadLibraryW")
      Else
        Debug "X86 Injector --> X64 Target not Supported yet!!"
        ProcedureReturn #Null
      EndIf
     
      ProcessHandle = OpenProcess_(#PROCESS_CREATE_THREAD | #PROCESS_QUERY_INFORMATION | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE | #PROCESS_VM_READ, #False, PID)
      If ProcessHandle
        BufferSize = Len(Dll$) * 2 + 1
        *dll_unicode = AllocateMemory(BufferSize)
        PokeS(*dll_unicode, Dll$, -1, #PB_Unicode)
        *buffer = VirtualAllocEx_(ProcessHandle, #Null, BufferSize, #MEM_COMMIT, #PAGE_READWRITE)
        If *buffer
          WriteProcessMemory_(ProcessHandle, *buffer, *dll_unicode, BufferSize, #Null)
          ThreadHandle = CreateRemoteThread_(ProcessHandle, #Null, #Null, address, *buffer, #Null, #Null)
          If ThreadHandle
            WaitForSingleObject_(ThreadHandle, #INFINITE)
            CloseHandle_(ThreadHandle)
            retvalue = TraverseRemoteModules(PID, GetFilePart(Dll$))
          EndIf
          VirtualFreeEx_(ProcessHandle, *buffer, #Null, #MEM_RELEASE)         
        EndIf
        CloseHandle_(ProcessHandle)
        FreeMemory(*dll_unicode)
      EndIf
    EndIf
   
    ProcedureReturn retvalue
  EndProcedure
 
 
  Procedure.b EjectDLL(PID, DLL$, *_Module = #Null)
    Protected address, ThreadHandle
    Protected ProcessHandle, retvalue = #False
    Protected is_target_64.b = #False
   
    If FileSize(Dll$) > 0 Or *_Module
      is_target_64 = Is64Process(PID)
      If #INJECTOR_IS_64 = is_target_64
        address = ProcAddress("kernel32.dll", "FreeLibrary")
      ElseIf #INJECTOR_IS_64
        address = TraverseRemoteProcs(PID, "kernel32.dll", "FreeLibrary")
      Else
        Debug "X86 Ejector --> X64 Target not Supported yet!!"
        ProcedureReturn #False
      EndIf
     
      If Not *_Module
        *_Module = TraverseRemoteModules(PID, GetFilePart(DLL$))
        If Not *_Module
          ProcedureReturn #False
        EndIf
      EndIf
     
      ProcessHandle = OpenProcess_(#PROCESS_CREATE_THREAD | #PROCESS_QUERY_INFORMATION | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE | #PROCESS_VM_READ, #False, PID)
      If ProcessHandle
        ThreadHandle = CreateRemoteThread_(ProcessHandle, #Null, #Null, address, *_Module, #Null, #Null)
        If ThreadHandle
          WaitForSingleObject_(ThreadHandle, #INFINITE)
          CloseHandle_(ThreadHandle)
          retvalue = #True
        EndIf
        CloseHandle_(ProcessHandle)
      EndIf
    EndIf
   
    ProcedureReturn retvalue
  EndProcedure
 
 
  Procedure CallRemoteFunction(PID, *Func, Proc2Call$, WaitForReturn.b = #False, *retValue = #Null, *Parameter = #Null, nSize = #Null)
    Protected ret, ProcessHandle, address, *buffer
    Protected ThreadHandle
   
    ProcessHandle = OpenProcess_(#PROCESS_CREATE_THREAD | #PROCESS_QUERY_INFORMATION | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE | #PROCESS_VM_READ, #False, PID)
   
    If ProcessHandle
      address = TraverseRemoteProcs(PID, "", Proc2Call$, *Func)
      If address
        *buffer = #Null
        If *Parameter And nSize
          *buffer = VirtualAllocEx_(ProcessHandle, #Null, nSize, #MEM_COMMIT, #PAGE_READWRITE)
          WriteProcessMemory_(ProcessHandle, *buffer, *Parameter, nSize, #Null)
        EndIf
             
        ThreadHandle = CreateRemoteThread_(ProcessHandle, #Null, #Null, address, *buffer, #Null, #Null)
        If ThreadHandle
          If WaitForReturn
            WaitForSingleObject_(ThreadHandle, #INFINITE)
            If *retValue
              GetExitCodeThread_(ProcessHandle, *retValue)
            EndIf
          EndIf
          CloseHandle_(ThreadHandle)
          ret = #True
        EndIf
       
        If *buffer
          VirtualFreeEx_(ProcessHandle, *buffer, #Null, #MEM_RELEASE)
        EndIf
        CloseHandle_(ProcessHandle)
      EndIf
    EndIf
   
    ProcedureReturn ret
  EndProcedure
 

EndModule



Simple Sample.pb:
Code:
; Simple Sample
IncludeFile "API_HookEngine.pbi"

EnableExplicit
Global *MessageBoxW, *MessageBoxA

UseModule API_HookEngine

Procedure My_MessageBoxW(hWnd, lpText$, lpCaption$, uType)
  Protected func.i
  Protected ret_value.i
 
  Debug "You Called MessageBoxW(" + hWnd + ", '" + lpText$ + "', '" + lpCaption$ + "', " + uType + ")"
 
  func = UnHook(*MessageBoxW)
  ret_value = MessageBox_(hWnd, lpText$, "Hooked Message", uType)
  *MessageBoxW = Hook(func, @My_MessageBoxW())
 
  ProcedureReturn ret_value
EndProcedure



Procedure My_MessageBoxA(hWnd, lpText$, lpCaption$, uType)
  Protected func.i
  Protected ret_value.i
 
  Debug "You Called MessageBoxA(" + hWnd + ", '" + lpText$ + "', '" + lpCaption$ + "', " + uType + ")"
 
  func = UnHook(*MessageBoxA)
  ret_value = MessageBox_(hWnd, lpText$, "Hooked Message", uType)
  *MessageBoxA = Hook(func, @My_MessageBoxA())
 
  ProcedureReturn ret_value
EndProcedure


*MessageBoxW = Hook(ProcAddress("user32.dll", "MessageBoxW"), @My_MessageBoxW())
*MessageBoxA = Hook(ProcAddress("user32.dll", "MessageBoxA"), @My_MessageBoxA())


MessageRequester("Test", "Hello World!!")

UnHook(*MessageBoxW)
UnHook(*MessageBoxA)

UnuseModule API_HookEngine

_________________
Sorry for my bad english.


Last edited by Peyman on Thu Feb 11, 2016 5:53 pm, edited 7 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Tue Feb 02, 2016 9:19 am 
Offline
Moderator
Moderator
User avatar

Joined: Thu Dec 31, 2009 11:05 pm
Posts: 1108
Location: Berlin (Germany)
Thank you for sharing. Image

_________________
ImageImageImageImage Image


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Tue Feb 02, 2016 9:36 am 
Offline
Addict
Addict

Joined: Sun Sep 07, 2008 12:45 pm
Posts: 4448
Location: Germany
Hi,

small hint:

Use
Code:
CompilerIf #PB_Compiler_IsMainFile
  :
  :
  :
CompilerEndIf


Than your small demo code can always be inside the file.

Bernd


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Tue Feb 02, 2016 11:46 am 
Offline
Enthusiast
Enthusiast

Joined: Mon Dec 24, 2007 4:15 pm
Posts: 203
Location: Iran
@RSBasic
your welcome, enjoy it. 8)

@infratec
very good point, thanks for hint. UPDATED.

_________________
Sorry for my bad english.


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Tue Feb 02, 2016 7:01 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4542
Location: Lyon - France
Works great
Thanks for sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Wed Feb 03, 2016 9:28 am 
Offline
Addict
Addict
User avatar

Joined: Mon Oct 26, 2015 2:55 am
Posts: 908
Location: UA
Looks great, but won't work on Windows 7 Ultimate x64 running with admin righs. I've tried both 32bit and 64.
- if app that set hook calls captured function, it works
- if another app calls while captured, it has no reaction

_________________
Dreamness

Like a copyleft notify: all the source code created by me and posted on Purebasic official forums is free to use and modification in all possible (and several impossible) ways for anyone, without asking my permission


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Wed Feb 03, 2016 12:04 pm 
Offline
Addict
Addict
User avatar

Joined: Sat Aug 15, 2009 6:59 pm
Posts: 1252
Lunasole wrote:
Looks great, but won't work on Windows 7 Ultimate x64 running with admin righs. I've tried both 32bit and 64.
- if app that set hook calls captured function, it works
- if another app calls while captured, it has no reaction

Thats how it works. It's hooked only in the process the code is running in.
If you want to hook API functions in other apps you have to inject the code into the process. Search for DLL injection on the forum.


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Wed Feb 03, 2016 10:22 pm 
Offline
Enthusiast
Enthusiast

Joined: Mon Dec 24, 2007 4:15 pm
Posts: 203
Location: Iran
@Kwai chang caine
your welcome.

@Lunasole
as Thorium said with this you just can hook your programs api calls.
for other processes you have 2 option:
1 - DLL Injection : you create a DLL with this hook on apis you want and inject it to a program (as Thorium said)
2 - use a system wide API hooking : its a interesting solution to create a kernel driver and after a process created that kernel driver automatically inject our DLL to that process.

i really like 2nd solution and maybe try to create it if PB members like it.

_________________
Sorry for my bad english.


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Thu Feb 04, 2016 4:31 am 
Offline
Addict
Addict
User avatar

Joined: Mon Oct 26, 2015 2:55 am
Posts: 908
Location: UA
Thanks for explanations, then it is all ok.

Peyman wrote:
1 - DLL Injection : you create a DLL with this hook on apis you want and inject it to a program (as Thorium said)
2 - use a system wide API hooking : its a interesting solution to create a kernel driver and after a process created that kernel driver automatically inject our DLL to that process.

i really like 2nd solution and maybe try to create it if PB members like it.


Sounds cool, I remember there was bare driver example, but nothing with such stuff.

_________________
Dreamness

Like a copyleft notify: all the source code created by me and posted on Purebasic official forums is free to use and modification in all possible (and several impossible) ways for anyone, without asking my permission


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Sun Feb 07, 2016 1:12 am 
Offline
Enthusiast
Enthusiast

Joined: Mon Dec 24, 2007 4:15 pm
Posts: 203
Location: Iran
hi update 1.1 with a simple dll injector, now working on a professional injector.


Update 1.1
  • Added InjectDLL for inject a DLL to another process (Injector must be same as Target process both must be X86 or X64)

here is a sample for injecting a dll to notepad and hook ShellAboutA/W Apis then every time you click on Help -> About Notepad see your MessageBox 8)

DLL :
Code:
IncludeFile "API_HookEngine.pbi"

UseModule API_HookEngine
EnableExplicit

Global *ShellAboutW
Global *ShellAboutA

Procedure My_ShellAboutW(hWnd, *szApp, *szOtherStuff, hIcon)
  Protected func.i
  Protected ret_value.i
 
  ;Show Our Message
  MessageRequester("About Notepad", "its a hooked Message." + #CRLF$ + "Ha ha ha ha")
 
 
  ;func = UnHook(*ShellAboutW)
  ;ret_value = CallFunctionFast(func, hWnd, *szApp, *szOtherStuff, hIcon)
  ;*ShellAboutW = Hook(func, @My_ShellAboutW())
 
  ProcedureReturn ret_value
EndProcedure



Procedure My_ShellAboutA(hWnd, *szApp, *szOtherStuff, hIcon)
  Protected func.i
  Protected ret_value.i
 
  ;Show Our Message
  MessageRequester("About Notepad", "its a hooked Message." + #CRLF$ + "Ha ha ha ha")
 
  ;func = UnHook(*ShellAboutA)
  ;ret_value = CallFunctionFast(func, hWnd, *szApp, *szOtherStuff, hIcon)
  ;*ShellAboutA = Hook(func, @My_ShellAboutA())
 
  ProcedureReturn ret_value
EndProcedure



ProcedureDLL AttachProcess(Instance)
  Protected name.s = Space(#MAX_PATH)
 
  *ShellAboutW = Hook(ProcAddress("Shell32.dll", "ShellAboutW"), @My_ShellAboutW())
  *ShellAboutA = Hook(ProcAddress("Shell32.dll", "ShellAboutA"), @My_ShellAboutA())
  GetModuleFileName_(#Null, @name, #MAX_PATH)
  OutputDebugString_("Im Loaded in " + GetFilePart(name))
  OutputDebugString_("ShellAboutW = " + Str(*ShellAboutW))
  OutputDebugString_("ShellAboutA = " + Str(*ShellAboutA))
EndProcedure


ProcedureDLL dummy()
 
EndProcedure

UnuseModule API_HookEngine



and the injector code :
Code:
IncludeFile "API_HookEngine.pbi"

UseModule API_HookEngine

program = RunProgram("notepad.exe", "", "", #PB_Program_Open)
If InjectDll(ProgramID(program), "D:\NotepadHook.dll") = #False
  Debug "Error Cant Inject DLL"
EndIf

UnuseModule API_HookEngine


change the path to created Dll, Injector and Target process must be same (X86 or X64).

_________________
Sorry for my bad english.


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Sun Feb 07, 2016 6:29 am 
Offline
Addict
Addict
User avatar

Joined: Mon Oct 26, 2015 2:55 am
Posts: 908
Location: UA
Thanks, very interesting examples. Long ago I wished to experiment with hooks and similar stuff to understand it better.

_________________
Dreamness

Like a copyleft notify: all the source code created by me and posted on Purebasic official forums is free to use and modification in all possible (and several impossible) ways for anyone, without asking my permission


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Wed Feb 10, 2016 4:13 am 
Offline
User
User

Joined: Wed Aug 06, 2008 8:21 am
Posts: 72
Image

_________________
PureBASIC v5.41 LTS , Windows v8.1 x64
Forget UNICODE - Keep it BASIC !


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Thu Feb 11, 2016 5:51 pm 
Offline
Enthusiast
Enthusiast

Joined: Mon Dec 24, 2007 4:15 pm
Posts: 203
Location: Iran
hi update 1.2 with a more professional and smarter DLL injector, and way to Eject loaded DLL, and a CallRemoteFunction!!
based on article in Microsoft for DllMain some tasks you should never perform them, like LoadLibrary, CreateProcess, ... (DllMain in purebasic are AttachThread, DetachThread, ....).
So for ex if we want to inject a dll to a process and that dll want to load a library this task can cause a deadlock or a crash (Base on article on msdn), so how we can achive this ? here CallRemoteFunction appears :D
we can create a Dll with some Export and write our tasks to them then inject it to target process and after injection calling that exports.

just one parameter can be passed to Remote procedures, so for more parameter you can use a structure, see below example.


Update 1.2
  • Added EjectDLL method for unload a DLL from target process
  • Added CallRemoteFunction method to call a proc from a DLL in target process (just one parameter can be passed to Remote Function)
  • Improved Injector, Now X64 Injector can inject in x64 & x86 target but x86 injector just can inject to x86 target.

DLL:
Code:
IncludeFile "API_HookEngine.pbi"

UseModule API_HookEngine
EnableExplicit

Global *ShellAboutW
Global *ShellAboutA

Structure Params
  ShowDebug.b
  uMsg.s{100}
EndStructure

Procedure My_ShellAboutW(hWnd, *szApp, *szOtherStuff, hIcon)
  Protected func.i
  Protected ret_value.i
 
  ;Show Our Message
  MessageRequester("About Notepad", "its a hooked Message." + #CRLF$ + "Ha ha ha ha", #MB_ICONINFORMATION)
 
 
  ;func = UnHook(*ShellAboutW)
  ;ret_value = CallFunctionFast(func, hWnd, *szApp, *szOtherStuff, hIcon)
  ;*ShellAboutW = Hook(func, @My_ShellAboutW())
 
  ProcedureReturn ret_value
EndProcedure



Procedure My_ShellAboutA(hWnd, *szApp, *szOtherStuff, hIcon)
  Protected func.i
  Protected ret_value.i
 
  ;Show Our Message
  MessageRequester("About Notepad", "its a hooked Message." + #CRLF$ + "Ha ha ha ha", #MB_ICONINFORMATION)
 
  ;func = UnHook(*ShellAboutA)
  ;ret_value = CallFunctionFast(func, hWnd, *szApp, *szOtherStuff, hIcon)
  ;*ShellAboutA = Hook(func, @My_ShellAboutA())
 
  ProcedureReturn ret_value
EndProcedure


ProcedureDLL _End()
  UnHook(*ShellAboutW)
  UnHook(*ShellAboutA)
EndProcedure


ProcedureDLL Start(*Parameters.Params)
  Protected name.s = Space(#MAX_PATH)
 
  *ShellAboutW = Hook(ProcAddress("Shell32.dll", "ShellAboutW"), @My_ShellAboutW())
  *ShellAboutA = Hook(ProcAddress("Shell32.dll", "ShellAboutA"), @My_ShellAboutA())
  If *Parameters\ShowDebug
    GetModuleFileName_(#Null, @name, #MAX_PATH)
    OutputDebugString_("Im Loaded in " + GetFilePart(name))
    OutputDebugString_("ShellAboutW = " + Str(*ShellAboutW))
    OutputDebugString_("ShellAboutA = " + Str(*ShellAboutA)) 
  EndIf
  MessageRequester("Message From Injector", *Parameters\uMsg)
 
EndProcedure


Injector :
Code:
IncludeFile "API_HookEngine.pbi"

UseModule API_HookEngine

Structure Params
  ShowDebug.b
  uMsg.s{100}
EndStructure

Define program = RunProgram("notepad.exe", "", "", #PB_Program_Open)
Define *func
Define DLL$ = "D:\NotepadHook.dll"
Define Parameters.Params
Parameters\ShowDebug = #False
Parameters\uMsg = "WOW OMG Message Passing!!"


If OpenWindow(0, 0, 0, 240, 90, "DLL Injection Sample", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  ButtonGadget(0, 40, 30, 60, 30, "Inject")
  ButtonGadget(1, 130, 30, 60, 30, "Eject")
 
  Repeat
    Event = WaitWindowEvent()
     
    Select Event
     
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 0
            *func = InjectDll(ProgramID(program), DLL$)
            If *func
              Debug "DLL Injected Sucessfuly"
              Delay(1000)
              If CallRemoteFunction(ProgramID(program), *func, "Start", #True, #Null, @Parameters, SizeOf(Parameters))
                Debug "Start Procedure Called"
                MessageRequester("", "Now Check Help -> About Notepad", #MB_ICONINFORMATION)
              Else
                Debug "Cannot Call Start Procedure"
              EndIf
            Else
              Debug "Error in Injecting DLL to program"
            EndIf
           
          Case 1
            If *func
              If CallRemoteFunction(ProgramID(program), *func, "_End", #True)
                Debug "_End Procedure Called"
                If EjectDLL(ProgramID(program), "", *func)
                  Debug "DLL Ejected Sucessfuly"
                  *func = #Null
                  MessageRequester("", "Another time Check Help -> About Notepad", #MB_ICONINFORMATION)
                Else
                  Debug "Error in Ejecting DLL from program"
                EndIf
              Else
                Debug "Cannot Call _End Procedure"
              EndIf
            Else
              Debug "First inject DLL to program"
            EndIf
           
        EndSelect
       
    EndSelect
  Until Event = #PB_Event_CloseWindow
 
EndIf

If ProgramRunning(program)
  KillProgram(program)
EndIf

_________________
Sorry for my bad english.


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Mon Feb 15, 2016 10:28 am 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4542
Location: Lyon - France
For me that not works on v5.40 and W7 :|
Quote:
Error in Injecting DLL to program

Perhaps a problem to translate something in french ?

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: API Hook Engine Module (Windows)
PostPosted: Mon Feb 15, 2016 12:32 pm 
Offline
User
User
User avatar

Joined: Wed Mar 15, 2006 9:40 am
Posts: 98
Location: Germany
for 64 Bit :
Code:
Define program = RunProgram("C:\Windows\SysWOW64\notepad.exe", "", "", #PB_Program_Open)

_________________
Please pardon my English, my native tongue is German.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 36 posts ]  Go to page 1, 2, 3  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye