首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

遠端執行緒呼叫 API 實作:RunRemoteAPI 類別完整解析

     編輯:關於.NET

架構概述

繼承 RunRemoteASMCode 基類,實現遠端進程 API 呼叫。核心技術點:

  1. 構造遠端呼叫機器碼與參數堆疊。
  2. 線性搜尋目標進程模組導出表,解析 API 入口位址(效能較低,可改用雜湊表優化)。

關鍵實作細節

  • E8 CALL 相對位址計算:目標位址 - (下一指令位址)。
  • 參數封送:除整數外皆以指標形式傳遞,使用位元組陣列。
  • 參數逆序入堆:符合 `__stdcall`/`__cdecl` 呼叫慣例。
  • 泛型結構轉位元組陣列:Param<T>.GetBytes() 利用 Marshal.StructureToPtr,未測試,建議手動轉換。
  • 記憶體頁屬性修改:VirtualProtectEx 配合 PAGE_EXECUTE_READWRITE,預留後續代碼注入使用。

核心代碼結構 (VB.NET)

Public Class RunRemoteAPI : Inherits RunRemoteASMCode
    ' 導出函數資訊結構
    Protected Structure avExportOrImports
        Dim LibName As String
        Dim ExportsIndex As Integer
        Dim Name As String
        Dim ExportsRVA As Integer
        Dim FunctionRVA As Integer
    End Structure

    ' 依名稱呼叫遠端 API
    Function CallRemoteAPIByName(DllName, FuncName, Wait, ParamArray FuncParams() As mFuncParam) As Integer
        ' 1. 列舉模組取得 Dll 基址
        ' 2. 解析導出表取得 FunctionRVA
        ' 3. 構造 ASM:逆序 PUSH 參數 → E8 CALL → C3 RET → CC INT3
        ' 4. 執行遠端執行緒並取得返回值
    End Function

    ' 讀取 ByRef 參數返回值
    Public Function RemoteBytesFromIndex(index) As Byte()
        ' 從記錄的資料區位址 ReadProcessMemory
    End Function

    ' 解析 PE 導出表 (線性搜尋)
    Public Function GetExports(pHandle, ModuleBaseAddress) As avExportOrImports()
        ' 遍歷 IMAGE_EXPORT_DIRECTORY:AddressOfFunctions/Names/NameOrdinals
    End Function
End Class

' 參數封裝
Public Class mFuncParam
    Public Obj As Byte()
    Public Ptr As Boolean
    Sub New(val As Integer) : Obj = BitConverter.GetBytes(val) : Ptr = False : End Sub
    Sub New(bytes As Byte()) : Obj = bytes.Clone() : Ptr = True : End Sub
End Class

' 結構轉位元組陣列 (泛型)
Public Class Param(Of T)
    Shared Function GetBytes(val As T) As Byte()
        Dim size = Marshal.SizeOf(val)
        Dim ptr = Marshal.AllocHGlobal(size)
        Marshal.StructureToPtr(val, ptr, True)
        Marshal.Copy(ptr, ret, 0, size)
        Marshal.FreeHGlobal(ptr)
        Return ret
    End Function
End Class

使用範例

範例 1:LoadLibrary 注入 DLL

api = New RunRemoteAPI(PID)
Dim pathBytes = Encoding.Unicode.GetBytes("G:\HOOKRECV\Debug\HOOKRECV.dll")
Dim hMod = api.CallRemoteAPIByName("kernel32", "LoadLibraryW", True, New mFuncParam(pathBytes))
TextBox3.Text = Hex(hMod)  ' 返回模組句柄

範例 2:GetWindowTextW 讀取視窗標題

mapi = New RunRemoteAPI(Shell("notepad.exe"))
Dim buf(1023) As Byte
mapi.CallRemoteAPIByName("user32.dll", "GetWindowTextW", True, _
    New mFuncParam(Me.Handle.ToInt32), _
    New mFuncParam(buf), _
    New mFuncParam(buf.Length))
Dim title = Encoding.Unicode.GetString(mapi.RemoteBytesFromIndex(1))
MessageBox.Show(title)
mapi.RotateProcess.Kill()

注意:GetWindowTextA ANSI 版在 .NET 環境常失敗,因字串編碼不匹配,請使用 Wide 版 W 後綴。

權限提升:SeDebugPrivilege

遠端進程操作需啟用 SeDebugPrivilege:

Public Class SeDebugPrivilege
    ' P/Invoke: OpenProcessToken, LookupPrivilegeValue, AdjustTokenPrivileges
    Public Function ToKenPrivileges() As Boolean
        ' 啟用 SE_PRIVILEGE_ENABLED
    End Function
End Class

' Form_Load 啟用
Dim SeDebug As New SeDebugPrivilege
If Not SeDebug.ToKenPrivileges() Then MsgBox("提升權限失敗")

已知限制與改進方向

  • 導出表線性搜尋 O(n),大型 DLL 明顯延遲 → 改用 Dictionary 快取。
  • 參數封送僅支援基本型別與位元組陣列,複雜結構需手動編碼。
  • 多核心環境下 WriteProcessMemory 緩存一致性問題,建議單一連續代碼段「一條龍」服務。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved