Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

API Inline Hook Example

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • API Inline Hook Example

    HookApi.Inc:
    Code:
    #If Not %Def(%WINAPI)
        #Include "win32api.inc"
    #EndIf
    #Include "LDasm.Inc"
    %PAGE_SIZE = 4096
    
    Function HookAPI(ByRef module As Asciiz, ByRef api As Asciiz, ByVal lpcallbackFunc As Dword,ByRef nextHook As Dword,Opt ByVal pSize As Dword) As Long
        Local DLLModule As Dword,FuncAddr As Dword,tOldPoint As Dword
        DLLModule = LoadLibrary(module)
        FuncAddr = GetProcAddress(DLLModule, api)
        If IsFalse(pSize) Then pSize = SizeOfHook(FuncAddr)
        If IsTrue(VirtualProtect(ByVal FuncAddr, pSize, %PAGE_READWRITE, tOldPoint)) Then
            '----------------------------------------------------------------------
            nextHook = VirtualAlloc(ByVal %NULL,%PAGE_SIZE, %MEM_COMMIT,%PAGE_READWRITE)
            CopyMemory (ByVal nextHook,ByVal FuncAddr,pSize)
            Poke Byte,nextHook+pSize,&HE9
            Poke Dword,nextHook+pSize+1,FuncAddr-nextHook-5
            Poke Dword,nextHook+pSize+5,FuncAddr
            '----------------------------------------------------------------------
            Poke Byte,FuncAddr,&HE9
            Poke Dword,FuncAddr+1,lpcallbackFunc-FuncAddr-5        FlushInstructionCache(GetCurrentProcess, ByVal FuncAddr, pSize)
            VirtualProtect(ByVal FuncAddr, pSize, tOldPoint, tOldPoint)
            Function = %TRUE
        End If
    End Function
    
    Function UnHookAPI(ByRef nextHook As Dword, Opt ByVal pSize As Dword) As Long
        Local lOldAddrs As Dword,tOldPoint As Dword
        If IsFalse(pSize) Then pSize = SizeOfHook(nextHook)
        If nextHook Then
            If Peek(Byte,nextHook+pSize) = &HE9 Then
                lOldAddrs = Peek(Dword,nextHook+pSize+5)
                VirtualProtect(ByVal lOldAddrs, pSize, %PAGE_READWRITE, tOldPoint)
                CopyMemory (ByVal lOldAddrs,ByVal nextHook,pSize)
                FlushInstructionCache(GetCurrentProcess, ByVal lOldAddrs, pSize)
                VirtualProtect(ByVal lOldAddrs, pSize, tOldPoint, tOldPoint)
                If VirtualFree(ByVal nextHook, %NULL, %MEM_RELEASE) Then
                    nextHook = %NULL
                    Function = %TRUE
                End If
            End If
        End If
    End Function
    LDasm.Inc:
    Code:
    'Opcode Length Disassembler.
    'Coded by GPcH
    'Email: [email protected]
    'Icq: 1195723
    'Original version Coded By Ms-Rem ( [email protected] ) ICQ 286370715
    'Modified For PowerBASIC By 4n85
    
    %OP_NONE = &H0
    %OP_MODRM = &H1
    %OP_DATA_I8 = &H2
    %OP_DATA_I16 = &H4
    %OP_DATA_I32 = &H8
    %OP_DATA_PRE66_67 = &H10
    %OP_WORD = &H20
    %OP_REL32 = &H40
    
    Global InitializeFlags As Long
    
    Sub DisasmInitialize()
        Dim OpcodeFlags(&H0 To &HFF) As Global Byte
        Dim OpcodeFlagsExt(&H0 To &HFF) As Global Byte
        Array Assign OpcodeFlags() = %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, _
        %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, _
        %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, _
        %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_PRE66_67, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_DATA_PRE66_67, %OP_MODRM Or %OP_DATA_PRE66_67, %OP_DATA_I8, %OP_MODRM Or %OP_DATA_I8, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, _
        %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM Or %OP_DATA_PRE66_67, _
        %OP_MODRM Or %OP_DATA_I8, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_DATA_I32 Or %OP_DATA_I16, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_DATA_I8, %OP_DATA_PRE66_67, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, _
        %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_DATA_PRE66_67, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM Or %OP_DATA_I8, %OP_DATA_I16, %OP_NONE, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM Or %OP_DATA_PRE66_67, %OP_DATA_I8 Or %OP_DATA_I16, %OP_NONE, %OP_DATA_I16, %OP_NONE, %OP_NONE, %OP_DATA_I8, %OP_NONE, %OP_NONE, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_DATA_I8, %OP_DATA_I8, %OP_NONE, %OP_NONE, %OP_WORD, %OP_WORD, %OP_WORD, _
        %OP_WORD, %OP_WORD, %OP_WORD, %OP_WORD, %OP_WORD, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, _
        %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_I8, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_I16 Or %OP_DATA_I32, %OP_DATA_I8, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM Or %OP_REL32
    
        Array Assign OpcodeFlagsExt() = %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_NONE, _
        %OP_MODRM Or %OP_DATA_I8, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, _
        %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, _
        %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, _
        %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_DATA_PRE66_67 Or %OP_REL32, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_MODRM, %OP_MODRM Or %OP_DATA_I8, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_MODRM, _
        %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, _
        %OP_NONE, %OP_NONE, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_MODRM, _
        %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_NONE, _
        %OP_MODRM, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_NONE, _
        %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_NONE, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE, %OP_MODRM, %OP_MODRM, %OP_MODRM, %OP_NONE
    
    End Sub
    
    'Получение полного размера машинной комманды по указателю на нее
    Function SizeOfCode(ByVal Code As Byte Ptr,Opt ByRef pOpcode As Byte) As Long
        If InitializeFlags = 0 Then DisasmInitialize : InitializeFlags = 1
        Local PFX66 As Long, PFX67 As Long, SibPresent As Long
        Local OffsetSize As Byte, iAdd As Byte, iMod As Byte, iRM As Byte, cPtr As Byte Ptr, Flags As Byte
    
        OffsetSize = 0
        PFX66 = 0
        PFX67 = 0
        cPtr = Code
        'определяем размер преффиксов
        While ((@cPtr = &H2E) Or (@cPtr = &H3E) Or (@cPtr = &H36) Or (@cPtr = &H26) Or (@cPtr = &H64) Or (@cPtr = &H65) Or (@cPtr = &HF0) Or (@cPtr = &HF2) Or (@cPtr = &HF3) Or (@cPtr = &H66) Or (@cPtr = _
    &H67))
          If (@cPtr = &H66) Then PFX66 = 1
          If (@cPtr = &H67) Then PFX67 = 1
          Incr cPtr
          If (cPtr > 16) Then SizeOfCode = 0: Exit Function
        Wend
        If VarPtr(pOpcode) Then pOpcode = @cPtr
        'определяем размер опкода и получаем флаги
        If (@cPtr = &HF) Then
          Incr cPtr
          Flags = OpcodeFlagsExt(@cPtr)
        Else
          Flags = OpcodeFlags(@cPtr)
        End If
        Incr cPtr
        If (Flags And %OP_WORD) Then cPtr = cPtr + 1
        'обрабатываем MOD r/m
        If (Flags And %OP_MODRM) Then
          iMod = Int(@cPtr / (2 ^ 6))
          iRM = @cPtr And 7
          Incr cPtr
          'обрабатываем SIB и Offset
          SibPresent = (Not PFX67) And (iRM = 4)
          Select Case iMod
            Case 0:
              If (PFX67 And (iRM = 6)) Then OffsetSize = 2
              If ((Not PFX67) And (iRM = 5)) Then OffsetSize = 4
            Case 1: OffsetSize = 1
            Case 2: If (PFX67) Then OffsetSize = 2 Else OffsetSize = 4
            Case 3: SibPresent = 0
          End Select
          If (SibPresent) Then
            If (((@cPtr And 7) = 5) And ((Not iMod) Or (iMod = 2))) Then OffsetSize = 4
            Incr cPtr
          End If
          cPtr = cPtr + OffsetSize
        End If
        'обрабатываем IMM значения
        If (Flags And %OP_DATA_I8) Then Incr cPtr
        If (Flags And %OP_DATA_I16) Then cPtr = cPtr + 2
        If (Flags And %OP_DATA_I32) Then cPtr = cPtr + 4
        If (PFX66) Then iAdd = 2 Else iAdd = 4
        If (Flags And %OP_DATA_PRE66_67) Then cPtr = cPtr + iAdd
        Function = cPtr - Code
    End Function
    
    'Получение размера функции по указател на нее (размер до первой комманды RET)
    Function SizeOfProc(ByVal Proc As Dword) As Long
        Local Length As Long, pOpcode As Byte, Result As Long
        Do
            Length = SizeOfCode(Proc, pOpcode)
            Result = Result + Length
            If ((Length = 1) And (pOpcode = &HC3)) Then Exit Do
            Proc = Proc + Length
        Loop While (Length)
        Function = Result
    End Function
    
    'Get Hook Api number of bytes required for preservation
    Function SizeOfHook(ByVal Proc As Dword) As Long
        Local Length As Long, pOpcode As Byte, Result As Long
        Do
            Length = SizeOfCode(Proc, pOpcode)
            Result = Result + Length
            Proc = Proc + Length
        Loop While (Result < 5 And Length)
        Function = Result
    End Function
    
    'определение того, имеет ли комманда rel32 offset
    Function IsRelativeCmd(ByVal pOpcode As Byte) As Byte
        If InitializeFlags = 0 Then DisasmInitialize : InitializeFlags = 1
        Local Flags As Byte
        If (pOpcode = &HF) Then Flags = OpcodeFlagsExt(pOpcode + 1) Else Flags = OpcodeFlags(pOpcode)
        Function = (Flags And %OP_REL32)
    End Function
    Example1:
    test.bas
    Code:
    #Compile Exe
    #Dim All
    #Include "Win32Api.Inc"
    #Include "HookApi.Inc"
    
    Global MessageBoxNextHook As Dword
    
    Function MyMessageBox(ByVal hwnd As Dword, lpText As Asciiz, lpCaption As Asciiz, ByVal wType As Dword) As Long
        Local result As Long
        Call Dword MessageBoxNextHook Using MessageBox(ByVal hwnd, lpText,ByCopy lpCaption & " --> By Hook", ByVal wType) To result
        Function = result
    End Function
    
    Function PBMain() As Long
        Call HookAPI("user32.dll", "MessageBoxA" , CodePtr(MyMessageBox), MessageBoxNextHook)
        MsgBox "test Hook"
        Call UnHookApi(MessageBoxNextHook)
        MsgBox "test UnHook"
    End Function
    Example2:
    ProcessAPI.bas
    Code:
    #Compile Exe
    #Dim All
    #Include "win32api.inc"
    #Include "HookApi.Inc"
    Global WinExecNextHook As Dword
    
    Function MyWinExecHook(cmdLine As Asciiz, ByVal showCmd As Long) As Long
        Local result As Long
        If MessageBox(0, cmdLine, "Execute?", %MB_YESNO Or %MB_ICONQUESTION) = %IDYES Then
            Call Dword WinExecNextHook Using WinExec(cmdLine, showCmd) To result
            Function = result
        Else
            Function = %ERROR_ACCESS_DENIED
        End If
    End Function
    
    Function PBMain()
        Call HookAPI("kernel32.dll", "WinExec", CodePtr(MyWinExecHook), WinExecNextHook)
        Call WinExec("notepad.exe", %SW_SHOWNORMAL)
        Call UnhookAPI(WinExecNextHook)
    End Function
Working...
X