vb 2008 WriteProcessMemory() 返回 0
你好 我正在使用 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&)
hello
i'm using vb 2008
here is part of my code:
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&)
But, the WriteProcessMemory() returns 0, and value don't change
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&)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当你调用Windows API函数时,你必须自己实现错误检查代码。当出现问题时,它们不会像标准 .NET Framework 函数那样抛出异常。
所需的具体错误检查因功能而异。 (像这样的不一致正是 .NET 使用异常的原因。)检查文档至关重要。
WriteProcessMemory
的工作方式是相当常见。返回值为BOOL
(Win32 库将其视为布尔值的整数,其中 0 = FALSE,1 = TRUE)。如果函数失败,返回值为 0 (FALSE)。如果成功,返回值为 1 (TRUE):当然,有趣的部分是我们被告知必须调用 GetLastError 函数才能确定函数失败的原因。其中一部分是正确的。 您仅调用
GetLastError
当您编写非托管 C++ 代码时。在.NET 中,您需要做其他事情。有两个步骤:SetLastError = True
标记 P/Invoke 签名,这会导致 CLR 自动调用GetLastError
并保存其值。Marshal.GetLastWin32Error
检索该值。因此,要调试它,您需要像这样重新编写代码(使用标准 P/Invoke 语法,而不是 VB.NET 特有的更有限的
Declare
关键字):知道错误代码后,您可以在系统错误列表中查找它代码看看它的意思。
结果错误是编号 299,
ERROR_PARTIAL_COPY
,文档说的意思是:嗯,不是很有帮助...我希望你能得到更好的东西。 这就是生活。
您将必须具备一些额外的知识才能解决该问题。文档中再次给出了提示。任何时候它说参数是“指针”(在C++语法中用星号
*
表示),这意味着在VB.NET中,需要传递它作为参考,而不是作为值。要指定将某些内容作为引用传递,请使用ByRef
关键字。当然,要按值传递,您需要指定默认的ByVal
关键字。另外,请注意,当文档说某物是句柄或地址时,您应该在VB.NET中将其声明为
IntPtr
类型,而不是整数。IntPtr
很特殊,因为它的大小会发生变化,具体取决于底层操作系统是 32 位还是 64 位(与整数不同,整数是固定大小的,无论您在什么平台上运行) )。尽管这不会立即导致问题,但在编译 64 位代码时会导致兼容性问题。所以事实证明你的声明实际上是错误的。像这样重新声明:
您可能还认为第三个参数(
lpBuffer
)应该是一个字节数组(Byte()
),因为它指定要写入的数据到地址空间。When you're calling Windows API functions, you have to implement the error-checking code yourself. They won't throw exceptions when something goes wrong like the standard .NET Framework functions.
The specific error checks required vary depending on the function. (Inconsistency like this is precisely why .NET uses exceptions instead.) Checking the documentation is essential.
WriteProcessMemory
works in a way that is fairly common. The return value is aBOOL
(an integer that the Win32 libraries treat as a Boolean, where 0 = FALSE and 1 = TRUE). If the function fails, the return value is 0 (FALSE). If it's successful, the return value is 1 (TRUE):The interesting part there, of course, is that we're told that we must call the
GetLastError
function in order to determine why the function failed. Part of that is true. You only callGetLastError
when you're writing unmanaged C++ code. In .NET, you need to do something else. There are two steps:SetLastError = True
, which causes the CLR to automatically callGetLastError
and save its value.Marshal.GetLastWin32Error
to retrieve that value.So, to debug it, you'll need to re-write your code like this (using the standard P/Invoke syntax, rather than the more limited
Declare
keyword that is unique to VB.NET):Once you know the error code, you can look it up in the list of System Error Codes to see what it means.
Turns out the error is number 299,
ERROR_PARTIAL_COPY
, which the documentation says just means:Hmm, not very helpful... I was hoping you'd get something better. C'est la vie.
You're going to have to have a little bit of additional knowledge to solve that problem. A hint is given, once again, in the documentation. Any time it says that a parameter is a "pointer" (indicated in C++ syntax with an asterisk
*
), that means that in VB.NET, it needs to be passed as a reference, rather than as a value. To specify that something is passed as a reference, use theByRef
keyword. To pass by value, of course, you specify the defaultByVal
keyword.Additionally, note that when the documentation says something is a handle or an address, you should declare it in VB.NET as an
IntPtr
type, rather than as an integer.IntPtr
is special because its size changes, depending on whether the underlying operating system is 32-bit or 64-bit (unlike an integer, which is a fixed size, no matter what platform you're running on). Even though this is not causing your immediate problem, it will cause compatibility problems when you compile the code for 64-bit.So it turns out that your declaration is actually wrong. Redeclare it like this:
You might also consider that the third parameter (
lpBuffer
) should be an array of bytes (Byte()
), because it specifies the data to be written to the address space.文档指出:
我建议您按照它的说明进行操作,找出失败的原因。
指出这一点后,失败的原因似乎是您尝试写入的地址 2000 在该过程中不是有效地址。
lpBuffer
参数是一个指针,您将整数值 2000 作为该参数传递。因此,这被解释为内存地址。我怀疑您实际上打算传递data
的地址。The documentation states:
I recommend you do what it says to find out why this has failed.
Having made that point, it seems likely that the cause of the failure is that the address 2000, which you are attempting to write to, is not a valid address in that process.
The
lpBuffer
parameter is a pointer and you are passing the integer value 2000 as that parameter. This is therefore interpreted and being a memory address. I suspect you actually intended to pass the address ofdata
.