首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >vb 2008 WriteProcessMemory()返回0

vb 2008 WriteProcessMemory()返回0
EN

Stack Overflow用户
提问于 2011-05-14 10:59:42
回答 2查看 1.7K关注 0票数 1

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

代码语言:javascript
运行
复制
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,并且值不改变

解决方案:

代码语言:javascript
运行
复制
<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&)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-14 11:16:59

当您调用Windows函数时,必须自己实现错误检查代码。当出现诸如标准.NET框架函数之类的错误时,它们不会抛出异常。

所需的特定错误检查取决于函数的不同。(这正是.NET使用异常的原因。)检查文档是非常重要的。

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

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

当然,有趣的是,我们被告知我们必须调用GetLastError函数,以确定函数失败的原因。部分是真的。当您编写非托管C++代码时。在.NET中,您需要做一些其他的事情。有两个步骤:

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

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

代码语言:javascript
运行
复制
<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

一旦您知道了错误代码,就可以在系统错误码列表中查找它,以了解它的含义。

结果,错误是299号,ERROR_PARTIAL_COPY,文档中说这意味着:

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

嗯,没什么用.我希望你能得到更好的东西。拉维先生。

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

此外,请注意,当文档显示某物是句柄或地址时,您应该在VB.NET中将其声明为类型,而不是整数。IntPtr之所以特殊,是因为它的大小会发生变化,这取决于底层操作系统是32位还是64位(与整数不同,它是固定大小的,无论您在哪个平台上运行)。尽管这并不会导致直接的问题,但当您为64位编译代码时,它将导致兼容性问题。

所以事实证明你的声明是错误的。请重新声明如下:

代码语言:javascript
运行
复制
<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()),因为它指定要写入地址空间的数据。

票数 2
EN

Stack Overflow用户

发布于 2011-05-14 11:13:08

文档指出:

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

我建议你照它说的去找出失败的原因。

指出这一点后,失败的原因似乎很可能是您试图写入的地址2000在此过程中不是有效的地址。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6001371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档