rainstormmaster的blog
rainstormmaster的blog

        一个远程调用api函数的模块,今天整理资料时发现的,忘记从哪里找到的了,不过感觉它应该有用,就把它贴出来了
Option Explicit

Public Enum ARG_FLAG
   arg_Value
   arg_Pointer
End Enum

Public Type API_DATA
   lpData       As Long      'Pointer to data or real data
   dwDataLength As Long      'Data length
   argType      As ARG_FLAG  'ByVal or ByRef?
   bOut         As Boolean   'Is this argument [OUT]?
End Type

Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CreateRemoteThread Lib "kernel32.dll" (ByVal hProcess As Long, ByVal lpThreadAttributes As Long, ByVal dwStackSize As Long, lpStartAddress As Long, ByVal lpParameter As Long, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
Private Declare Function GetExitCodeThread Lib "kernel32.dll" (ByVal hThread As Long, lpExitCode As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cBytes As Long)
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long

Public Const INFINITE = -1&
Private Const MEM_COMMIT = &H1000
Private Const MEM_RESERVE = &H2000
Private Const MEM_RELEASE = &H8000
Private Const PAGE_READWRITE = &H4&

'Variables to store main kernel functions addresses
Dim hKernel           As Long
Dim lpGetModuleHandle As Long
Dim lpLoadLibrary     As Long
Dim lpFreeLibrary     As Long
Dim lpGetProcAddress  As Long
Dim bKernelInit       As Boolean

Dim abAsm() As Byte 'buffer for assembly code
Dim lCP As Long     'used to keep track of latest byte added to code

Public Function CallAPIRemote(ByVal hProcess As Long, ByVal LibName As String, _
                             ByVal FuncName As String, ByVal nParams As Long, _
                             data() As API_DATA, _
                             Optional ByVal dwTimeOut As Long = INFINITE) As Long
  
   Dim hLib As Long, fnAddress As Long
   Dim bNeedUnload As Boolean
   Dim locData(1) As API_DATA
     
   hLib = GetModuleHandleRemote(hProcess, LibName)
   If hLib = 0 Then
      hLib = LoadLibraryRemote(hProcess, LibName)
      If hLib = 0 Then Exit Function
      bNeedUnload = True
   End If
  
   fnAddress = GetProcAddressRemote(hProcess, hLib, FuncName)
   If fnAddress Then
      CallAPIRemote = CallFunctionRemote(hProcess, fnAddress, nParams, data, dwTimeOut)
   End If
   If bNeedUnload Then Call FreeLibraryRemote(hProcess, hLib)
End Function

'Main function which do the job
Private Function CallFunctionRemote(ByVal hProcess As Long, ByVal func_addr As Long, _
                                    ByVal nParams As Long, data() As API_DATA, _
                                    Optional ByVal dwTimeOut As Long = INFINITE) As Long
   Dim hThread As Long, ThreadId As Long
   Dim addr As Long, ret As Long, h As Long, i As Long
   Dim codeStart As Long
   Dim param_addr() As Long
  
   If nParams = 0 Then
      CallFunctionRemote = CallFunctionRemoteOneParam(hProcess, func_addr, 0, 0, 0, 0)
   ElseIf nParams = 1 Then
      CallFunctionRemote = CallFunctionRemoteOneParam(hProcess, func_addr, 1, _
                           data(0).lpData, data(0).dwDataLength, data(0).argType, _
                           data(0).bOut)
   End If
  
   ReDim abAsm(50 + 6 * nParams)
   ReDim param_addr(nParams - 1)
   lCP = 0
   addr = VirtualAllocEx(ByVal hProcess, ByVal 0&, ByVal UBound(abAsm) + 1, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
  
   codeStart = GetAlignedCodeStart(addr)
   lCP = codeStart - addr
   For i = 0 To lCP - 1
       abAsm(i) = &HCC
   Next
   PrepareStack 1 'remove ThreadFunc lpParam
   Dim s As String
   s = "MessageBoxA" & Chr(0)
   For i = nParams To 1 Step -1
       AddByteToCode &H68 'push wwxxyyzz
       If data(i - 1).argType = arg_Value Then
          If data(i - 1).dwDataLength > 4 Then
             MsgBox "Arguments passing as Value should not exeed 4 bytes (long)", vbCritical
             GoTo CleanUp
          End If
          AddLongToCode data(i - 1).lpData
       Else
          param_addr(i - 1) = VirtualAllocEx(ByVal hProcess, ByVal 0&, _
                              ByVal data(i - 1).dwDataLength, MEM_RESERVE Or MEM_COMMIT, _
                              PAGE_READWRITE)
          If param_addr(i - 1) = 0 Then GoTo CleanUp
          If WriteProcessMemory(hProcess, ByVal param_addr(i - 1), ByVal data(i - 1).lpData, _
                               data(i - 1).dwDataLength, ret) = 0 Then GoTo CleanUp
          AddLongToCode param_addr(i - 1)
       End If
   Next
   AddCallToCode func_addr, addr + VarPtr(abAsm(lCP)) - VarPtr(abAsm(0))
   AddByteToCode &HC3
   AddByteToCode &HCC
   If WriteProcessMemory(hProcess, ByVal addr, abAsm(0), UBound(abAsm) + 1, ret) = 0 Then GoTo CleanUp
   hThread = CreateRemoteThread(hProcess, 0, 0, ByVal codeStart, data(0).lpData, 0&, ThreadId)
   If hThread Then
      ret = WaitForSingleObject(hThread, dwTimeOut)
      If ret = 0 Then ret = GetExitCodeThread(hThread, h)
   End If
   CallFunctionRemote = h
   For i = 0 To nParams - 1
       If param_addr(i) <> 0 Then
          If data(i).bOut Then
             ReadProcessMemory hProcess, ByVal param_addr(i), ByVal data(i).lpData, data(i).dwDataLength, ret
          End If
       End If
   Next i
CleanUp:
   VirtualFreeEx hProcess, ByVal addr, 0, MEM_RELEASE
   For i = 0 To nParams - 1
       If param_addr(i) <> 0 Then VirtualFreeEx hProcess, ByVal param_addr(i), 0, MEM_RELEASE
   Next i
End Function

Private Function CallFunctionRemoteOneParam(ByVal hProcess As Long, ByVal func_addr As Long, _
                                    ByVal nParams As Long, ByVal lngVal As Long, _
                                    ByVal dwSize As Long, ByVal argType As ARG_FLAG, _
                                    Optional ByVal bReturn As Boolean) As Long
   Dim hThread As Long, ThreadId As Long
   Dim addr As Long, ret As Long, h As Long, i As Long
   Dim lngTemp As Long
   If nParams = 0 Then
      bReturn = False
   Else
      If argType = arg_Pointer Then
          addr = VirtualAllocEx(ByVal hProcess, ByVal 0&, ByVal dwSize, _
                                MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
          If addr = 0 Then Exit Function
          Call WriteProcessMemory(hProcess, ByVal addr, ByVal lngVal, dwSize, ret)
          lngTemp = addr
      Else
          lngTemp = lngVal
      End If
   End If
   hThread = CreateRemoteThread(hProcess, 0, 0, ByVal func_addr, lngTemp, 0&, ThreadId)
   If hThread Then
      ret = WaitForSingleObject(hThread, 1000)
      If ret = 0 Then ret = GetExitCodeThread(hThread, h)
      CallFunctionRemoteOneParam = h
      CloseHandle hThread
   End If
   If bReturn Then
      If addr <> 0 Then
         ReadProcessMemory hProcess, ByVal addr, ByVal lngVal, dwSize, ret
         VirtualFreeEx hProcess, ByVal addr, 0, MEM_RELEASE
      End If
   End If
End Function

Public Function GetModuleHandleRemote(ByVal hProcess As Long, ByVal LibName As String) As Long
   If Not InitKernel Then Exit Function
   If GetModuleHandle(LibName) = hKernel Then
      GetModuleHandleRemote = hKernel
      Exit Function
   End If

   Dim hThread As Long, ThreadId As Long
   Dim addr As Long, ret As Long, h As Long
   addr = VirtualAllocEx(ByVal hProcess, ByVal 0&, ByVal Len(LibName) + 1, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
   If addr = 0 Then Exit Function
   If WriteProcessMemory(hProcess, ByVal addr, ByVal LibName, Len(LibName), ret) Then
      hThread = CreateRemoteThread(hProcess, 0, 0, ByVal lpGetModuleHandle, addr, 0&, ThreadId)
      If hThread Then
         ret = WaitForSingleObject(hThread, 500)
         If ret = 0 Then ret = GetExitCodeThread(hThread, h)
      End If
   End If
   VirtualFreeEx hProcess, ByVal addr, 0, MEM_RELEASE
   CloseHandle hThread
   GetModuleHandleRemote = h
End Function

Public Function LoadLibraryRemote(ByVal hProcess As Long, ByVal LibName As String) As Long
   If Not InitKernel Then Exit Function
   If GetModuleHandle(LibName) = hKernel Then
      LoadLibraryRemote = hKernel
      Exit Function
   End If
  
   Dim hThread As Long, ThreadId As Long
   Dim addr As Long, ret As Long, h As Long
   addr = VirtualAllocEx(ByVal hProcess, ByVal 0&, ByVal Len(LibName) + 1, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
   If addr = 0 Then Exit Function
   If WriteProcessMemory(hProcess, ByVal addr, ByVal LibName, Len(LibName), ret) Then
      hThread = CreateRemoteThread(hProcess, 0, 0, ByVal lpLoadLibrary, addr, 0&, ThreadId)
      If hThread Then
         ret = WaitForSingleObject(hThread, 500)
         If ret = 0 Then ret = GetExitCodeThread(hThread, h)
      End If
   End If
   LoadLibraryRemote = h
End Function

Public Function GetProcAddressRemote(ByVal hProcess As Long, ByVal hLib As Long, ByVal fnName As String) As Long
   If Not InitKernel Then Exit Function
  
   If hLib = hKernel Then
      GetProcAddressRemote = GetProcAddress(hKernel, fnName)
      Exit Function
   End If
   Dim localData(1) As API_DATA
   Dim abName() As Byte
   With localData(0)
      .lpData = hLib
      .dwDataLength = 4
      .argType = arg_Value
   End With
   fnName = fnName & Chr(0)
   abName = StrConv(fnName, vbFromUnicode)
   With localData(1)
      .lpData = VarPtr(abName(0))
      .dwDataLength = UBound(abName) + 1
      .argType = arg_Pointer
   End With
   GetProcAddressRemote = CallFunctionRemote(hProcess, lpGetProcAddress, 2, localData)
End Function

Public Function FreeLibraryRemote(ByVal hProcess As Long, ByVal hLib As Long) As Long
   If Not InitKernel Then Exit Function
   If hLib = hKernel Then
      FreeLibraryRemote = True
      Exit Function
   End If
  
   Dim hThread As Long, ThreadId As Long, h As Long, ret As Long
   hThread = CreateRemoteThread(hProcess, 0, 0, ByVal lpFreeLibrary, hLib, 0&, ThreadId)
   If hThread Then
      ret = WaitForSingleObject(hThread, 500)
      If ret = 0 Then ret = GetExitCodeThread(hThread, h)
   End If
   CloseHandle hThread
   FreeLibraryRemote = h
End Function

'============Private routines to prepare asm (op)code===========
Private Sub AddCallToCode(ByVal dwAddress As Long, ByVal BaseAddr As Long)
    AddByteToCode &HE8
    AddLongToCode dwAddress - BaseAddr - 5
End Sub

Private Sub AddLongToCode(ByVal lng As Long)
    Dim i As Integer
    Dim byt(3) As Byte
    CopyMemory byt(0), lng, 4
    For i = 0 To 3
        AddByteToCode byt(i)
    Next
End Sub

Private Sub AddByteToCode(ByVal byt As Byte)
    abAsm(lCP) = byt
    lCP = lCP + 1
End Sub

Private Function GetAlignedCodeStart(ByVal dwAddress As Long) As Long
    GetAlignedCodeStart = dwAddress + (15 - (dwAddress - 1) Mod 16)
    If (15 - (dwAddress - 1) Mod 16) = 0 Then GetAlignedCodeStart = GetAlignedCodeStart + 16
End Function

Private Sub PrepareStack(ByVal numParamsToRemove As Long)
    If numParamsToRemove = 0 Then Exit Sub
    Dim i As Long
    AddByteToCode &H58     'pop eax -  pop return address
    For i = 1 To numParamsToRemove
        AddByteToCode &H59 'pop ecx -  kill param
    Next i
    AddByteToCode &H50     'push eax - put return address back
End Sub

Private Sub ClearStack(ByVal nParams As Long)
   Dim i As Long
   For i = 1 To nParams
       AddByteToCode &H59  'pop ecx - remove params from stack
   Next
End Sub

'==========Get main kernel32 functions addresses=========
Private Function InitKernel() As Boolean
   If bKernelInit Then
      InitKernel = True
      Exit Function
   End If
   hKernel = GetModuleHandle("kernel32")
   If hKernel = 0 Then Exit Function
   lpGetProcAddress = GetProcAddress(hKernel, "GetProcAddress")
   lpGetModuleHandle = GetProcAddress(hKernel, "GetModuleHandleA")
   lpLoadLibrary = GetProcAddress(hKernel, "LoadLibraryA")
   lpFreeLibrary = GetProcAddress(hKernel, "FreeLibrary")
   InitKernel = True
   bKernelInit = True
End Function


 

posted on 2006-01-26 14:28  学剑学诗两不成  阅读(1628)  评论(6编辑  收藏  举报