您好
我正在使用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,值不会改变
SOLUTION:
<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&)
答案 0 :(得分:2)
当您调用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中,您需要执行其他操作。有两个步骤:
SetLastError = True
标记P / Invoke签名,这会导致CLR自动调用GetLastError
并保存其值。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
,文档说明的意思是:
嗯,不是很有帮助......我希望你能得到更好的东西。 C'est la vie 。只完成了ReadProcessMemory或WriteProcessMemory请求的一部分。
你将需要一些额外的知识来解决这个问题。在文档中再次给出了提示。任何时候它说参数是“指针”(用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()
),因为它指定了要写入地址空间的数据。
答案 1 :(得分:1)
如果函数失败,则返回 值为0(零)。扩展 错误信息,调用GetLastError。 如果请求,该函数将失败 写操作跨越一个区域 无法进入的过程。
我建议你按照说法去找出失败的原因。
说到这一点之后,失败的原因似乎是您尝试写入的地址2000不是该过程中的有效地址。
lpBuffer
参数是一个指针,您将整数值2000作为该参数传递。因此,这被解释并且是存储器地址。我怀疑你确实打算传递data
的地址。