【问题标题】:vb 2008 WriteProcessMemory() returns 0VB 2008 WriteProcessMemory() 返回 0
【发布时间】:2011-05-14 10:59:42
【问题描述】:

你好 我正在使用vb 2008 这是我的代码的一部分:

Private Declare Function WriteProcessMemory Lib "kernel32" Alias "WriteProcessMemory" ( _
      ByVal hProcess As Integer, _
      ByVal lpBaseAddress As Integer, _
      ByVal lpBuffer As Integer, _
      ByVal nSize As Integer, _
      ByVal lpNumberOfBytesWritten As Integer _
   ) As Integer

    Dim proc() As Process = Process.GetProcessesByName("process")
    If proc.Length = 0 Then Console.WriteLine("Process Not Found") : Exit Sub
    Dim p = proc(0)
    Dim pH As Integer = OpenProcess(PROCESS_ALL_ACCESS, 0, p.Id)
    Dim address As Integer
    address = &H98544
    Dim memory As IntPtr
    Call ReadProcessMemory(pH, address, memory, 4, 0)
    Console.WriteLine(memory.ToString)
    Dim data As Integer = 2000
    Call WriteProcessMemory(pH, address, data, Len(data), 0&)

但是,WriteProcessMemory() 返回 0,值不变

解决方案:

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function WriteProcessMemory( _
                                      ByVal hProcess As IntPtr, _
                                      ByVal lpBaseAddress As IntPtr, _
                                      ByVal lpBuffer As Byte(), _
                                      ByVal nSize As UInt32, _
                                      ByRef lpNumberOfBytesWritten As UInt32 _
                                      ) As Boolean
End Function

        Dim proc() As Process = Process.GetProcessesByName("process")
        If proc.Length = 0 Then Console.WriteLine("Process Not Found") : Exit Sub
        Dim p = proc(0)
        Dim pH As Integer = OpenProcess(PROCESS_ALL_ACCESS, 0, p.Id)
        Dim address As Integer
        address = &H98544
        Dim memory As IntPtr
        Call ReadProcessMemory(pH, address, memory, 4, 0)
        Console.WriteLine(memory.ToString)
        Dim data() As Byte = BitConverter.GetBytes(2000)
        Call WriteProcessMemory(pH, address, data, 4, 0&)

【问题讨论】:

  • 提前抱歉 - 这本身不是一个答案,但可能更多的是一个提示。我自己也开始使用这个函数,我怀疑我们遇到的问题与令牌权限有关。

标签: .net windows vb.net winapi process


【解决方案1】:

当您调用 Windows API 函数时,您必须自己实现错误检查代码。当标准 .NET Framework 函数出现问题时,它们不会引发异常。

所需的特定错误检查因功能而异。 (这种不一致正是 .NET 使用异常的原因。)检查文档是必不可少的。

WriteProcessMemory 以一种相当常见的方式工作。返回值为BOOL(Win32 库将其视为布尔值的整数,其中 0 = FALSE 和 1 = TRUE)。如果函数失败,则返回值为 0 (FALSE)。如果成功,则返回值为 1 (TRUE):

如果函数成功,则返回值非零。

如果函数失败,则返回值为 0(零)。要获取更多错误信息,请致电GetLastError。如果请求的写入操作进入进程中不可访问的区域,则该函数将失败。

当然,有趣的部分是我们被告知必须调用GetLastError 函数才能确定为什么函数失败。部分是真的。 You only call GetLastError when you're writing unmanaged C++ code。在 .NET 中,您需要做其他事情。有两个步骤:

  1. 使用SetLastError = True 标记P/Invoke 签名,这会导致CLR 自动调用GetLastError 并保存其值。
  2. 调用 Marshal.GetLastWin32Error 以检索该值。

因此,要调试它,您需要像这样重写代码(使用标准 P/Invoke 语法,而不是 VB.NET 独有的更有限的 Declare 关键字):

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function WriteProcessMemory(
                                           ByVal hProcess As Integer, _
                                           ByVal lpBaseAddress As Integer, _
                                           ByVal lpBuffer As Integer, _
                                           ByVal nSize As Integer, _
                                           ByVal lpNumberOfBytesWritten As Integer _
                                          ) As Integer
End Function

Dim proc() As Process = Process.GetProcessesByName("process")
If proc.Length = 0 Then Console.WriteLine("Process Not Found") : Exit Sub
Dim p = proc(0)
Dim pH As Integer = OpenProcess(PROCESS_ALL_ACCESS, 0, p.Id)
Dim address As Integer
address = &H98544
Dim memory As IntPtr
Call ReadProcessMemory(pH, address, memory, 4, 0)
Console.WriteLine(memory.ToString)
Dim data As Integer = 2000
If WriteProcessMemory(pH, address, data, Len(data), 0&) = 0 Then
   ' The function failed, so find out what the error was
   MessageBox.Show("WriteProcessMemory failed with error " & Marshal.GetLastWin32Error)
End If

知道错误代码后,您可以在list of System Error Codes 中查找它以了解其含义。


原来错误是数字 299,ERROR_PARTIAL_COPY,文档中说的只是意味着:

仅完成了 ReadProcessMemory 或 WriteProcessMemory 请求的一部分。

嗯,不是很有帮助...我希望你能得到更好的东西。 C'est la vie.

您必须具备一些额外的知识才能解决该问题。文档中再次给出了提示。任何时候它说参数是一个“指针”(用星号*表示的C++语法),这意味着在VB.NET中,它需要作为一个传递参考,而不是作为一个值。要指定某些内容作为引用传递,请使用 ByRef 关键字。当然,要按值传递,您需要指定默认的 ByVal 关键字。

另外,请注意,当文档说某事是 句柄地址 时,您应该在 VB.NET 中将其声明为 IntPtr type,而不是一个整数。 IntPtr 很特别,因为它的大小会发生变化,具体取决于底层操作系统是 32 位还是 64 位(与整数不同,整数是固定大小的,无论您在什么平台上运行)。即使这不会导致您立即出现问题,但当您编译 64 位代码时,它导致兼容性问题。

所以事实证明你的声明实际上是错误的。像这样重新声明它:

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function WriteProcessMemory(
                                           ByVal hProcess As IntPtr, _
                                           ByVal lpBaseAddress As IntPtr, _
                                           ByVal lpBuffer As Integer, _
                                           ByVal nSize As Integer, _
                                           ByRef lpNumberOfBytesWritten As Integer _
                                          ) As Integer
End Function

您可能还认为第三个参数(lpBuffer)应该是一个字节数组(Byte()),因为它指定了要写入地址空间的数据。

【讨论】:

  • 它显示“299”错误(系统错误代码(0-499)),但仍然无法理解问题出在哪里。
  • @John: 299 is ERROR_PARTIAL_COPY: ReadProcessMemory 或 WriteProcessMemory 请求仅完成了一部分。事实证明这不是很有帮助。我以为它会告诉你更好的事情。让我用修复来编辑我的答案。
  • 我用解决方案更新了我的问题,感谢您的帮助
【解决方案2】:

documentation 声明:

如果函数失败,返回 值为 0(零)。得到扩展 错误信息,调用GetLastError。 如果请求,该功能将失败 写操作跨入一个区域 无法访问的进程。

我建议您按照它所说的去做,找出失败的原因。

已经说明了这一点,失败的原因似乎是您尝试写入的地址 2000 在该过程中不是有效地址。

lpBuffer 参数是一个指针,您将整数值 2000 作为该参数传递。因此,这被解释为内存地址。我怀疑你实际上打算传递data 的地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多