You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB读取内存地址时输出异常,如何正确传入目标地址?

问题:VB.NET中ReadProcessMemory传入内存地址导致输出乱码的问题

我编写了如下VB代码来读取GeometryDash进程的内存:

Imports System.Runtime.InteropServices
Imports System.Text
Public Class Form1
    Const PROCESS_WM_READ As Integer = &H10
    <DllImport("kernel32.dll")>
    Public Shared Function OpenProcess(dwDesiredAccess As Integer, bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
    End Function
    <DllImport("kernel32.dll")>
    Public Shared Function ReadProcessMemory(hProcess As Integer, lpBaseAddress As Integer, lpBuffer As Byte(), dwSize As Integer, ByRef lpNumberOfBytesRead As Integer) As Boolean
    End Function
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim notepadProcess As Process = Process.GetProcessesByName("GeometryDash")(0)
        Dim processHandle As IntPtr = OpenProcess(PROCESS_WM_READ, False, notepadProcess.Id)
        Dim bytesRead As Integer = 0
        Dim buffer As Byte() = New Byte(23) {}
        'The address in this line is hard-coded. Use whatever is appropriate for your situation.
        ReadProcessMemory(CInt(processHandle), 117317672, buffer, buffer.Length, bytesRead)
        MsgBox(Encoding.Unicode.GetString(buffer))
    End Sub
End Class

运行后输出2-3个奇怪的日文字符,其中传入的地址“117317672”是十六进制地址“06FE2028”的十进制形式。我认为问题出在地址的传入方式上,请问该如何正确传入内存地址?


回答

你遇到的核心问题是内存地址的类型不匹配,再加上编码和函数签名的小问题,咱们一步步来解决:

1. 先修正ReadProcessMemory的函数签名

你的DllImport声明有两个关键错误:

  • hProcess应该是IntPtr类型,而不是Integer——进程句柄是指针类型,64位系统下用Integer会直接截断数据,导致句柄无效
  • lpBaseAddress也得是IntPtr类型,32位和64位进程的内存地址宽度不一样,用IntPtr能完美兼容两种架构

另外建议加上SetLastError:=True,这样后续可以通过Marshal.GetLastWin32Error()获取系统错误码,调试起来方便很多。修正后的声明:

<DllImport("kernel32.dll", SetLastError:=True)>
Public Shared Function ReadProcessMemory(
    hProcess As IntPtr,
    lpBaseAddress As IntPtr,
    lpBuffer As Byte(),
    dwSize As Integer,
    ByRef lpNumberOfBytesRead As Integer
) As Boolean
End Function

2. 正确传入内存地址

你手动把十六进制转十进制再传的方式容易出错,尤其是地址长度超过Integer范围的时候。直接用VB的十六进制字面量(前缀&H)初始化IntPtr就好:

' 直接用你的十六进制地址初始化,不用转十进制
Dim targetAddress As IntPtr = New IntPtr(&H06FE2028)

如果你的地址是字符串形式,也可以用IntPtr.Parse指定十六进制格式来处理:

Dim targetAddress As IntPtr = IntPtr.Parse("06FE2028", Globalization.NumberStyles.HexNumber)

之后调用ReadProcessMemory时,直接传入这个targetAddress就行,不用再做类型转换。

3. 验证编码和读取长度

乱码也可能是编码不匹配导致的——你现在用Encoding.Unicode.GetString(buffer),但要确认目标内存里的数据确实是UTF-16编码。如果是ASCII或UTF-8,用Unicode解码肯定会出乱码。

可以同时尝试几种编码来测试,找到正确的那一个:

Dim unicodeResult As String = Encoding.Unicode.GetString(buffer, 0, bytesRead)
Dim utf8Result As String = Encoding.UTF8.GetString(buffer, 0, bytesRead)
Dim asciiResult As String = Encoding.ASCII.GetString(buffer, 0, bytesRead)

另外注意读取时只用实际读到的字节数(bytesRead)来解码,不要用整个buffer的长度,避免末尾的空字节干扰。

4. 加上调试检查

每次调用ReadProcessMemory后,先检查返回值是否为True,如果失败就获取错误码,能快速定位权限不足、地址无效这类问题:

Dim readSuccess As Boolean = ReadProcessMemory(processHandle, targetAddress, buffer, buffer.Length, bytesRead)
If Not readSuccess Then
    Dim errorCode As Integer = Marshal.GetLastWin32Error()
    MsgBox($"读取失败,错误码:{errorCode}")
End If

修正后的完整代码示例

Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Diagnostics
Imports System.Globalization

Public Class Form1
    Const PROCESS_VM_READ As Integer = &H10
    <DllImport("kernel32.dll")>
    Public Shared Function OpenProcess(dwDesiredAccess As Integer, bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
    End Function

    <DllImport("kernel32.dll", SetLastError:=True)>
    Public Shared Function ReadProcessMemory(
        hProcess As IntPtr,
        lpBaseAddress As IntPtr,
        lpBuffer As Byte(),
        dwSize As Integer,
        ByRef lpNumberOfBytesRead As Integer
    ) As Boolean
    End Function

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            Dim gdProcess As Process = Process.GetProcessesByName("GeometryDash")(0)
            Dim processHandle As IntPtr = OpenProcess(PROCESS_VM_READ, False, gdProcess.Id)

            If processHandle = IntPtr.Zero Then
                MsgBox("无法打开进程,可能是权限不足或进程未运行")
                Return
            End If

            Dim bytesRead As Integer = 0
            Dim buffer As Byte() = New Byte(23) {}
            ' 正确初始化目标内存地址
            Dim targetAddress As IntPtr = New IntPtr(&H06FE2028)

            Dim readSuccess As Boolean = ReadProcessMemory(processHandle, targetAddress, buffer, buffer.Length, bytesRead)

            If Not readSuccess Then
                Dim errorCode As Integer = Marshal.GetLastWin32Error()
                MsgBox($"读取内存失败,错误码:{errorCode}")
            Else
                ' 尝试多种编码,找到正确结果
                Dim unicodeResult As String = Encoding.Unicode.GetString(buffer, 0, bytesRead)
                Dim utf8Result As String = Encoding.UTF8.GetString(buffer, 0, bytesRead)
                Dim asciiResult As String = Encoding.ASCII.GetString(buffer, 0, bytesRead)

                MsgBox($"Unicode结果:{unicodeResult}{vbCrLf}UTF8结果:{utf8Result}{vbCrLf}ASCII结果:{asciiResult}")
            End If
        Catch ex As Exception
            MsgBox($"发生异常:{ex.Message}")
        End Try
    End Sub
End Class

内容的提问来源于stack exchange,提问作者NexusEyes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:12:32