本帖最后由 yiyiyicz 于 2014-6-17 09:54 编辑
【VB读写内存-2】
下面我们要开始写在计时器窗口中显示我们名字的代码了。首先我们使用 FindWindow函数取得目标窗口的句柄。把这个返回值保存在一个变量中,并检查它的值是否出错来确保计时器程序正在运行。(FindWindow函数出错时返回0) Dim hwnd As Long
hwnd = FindWindow(vbNullString, "Calculator")
If (hwnd = 0) Then
MsgBox "Window not found!"
Exit Sub
End If
注意在这里我们传递了一个 Null 值给 FindWindow 函数,而不是 ClassName。因此任何名为 Calculator的窗口都符合条件。如果知道计算器程序窗口的 ClassName,你可以传给它,但这不是必须的。 现在使用得到的窗口句柄来取得进程标识符( ProcessId )。注意 pid 是作为参数传递给函数的,而不是被赋以函数返回值。
Dim pid As Long
GetWindowThreadProcessId hwnd, pid
再利用变量pid得到计算器程序的进程句柄。再次检查函数的返回值,如果是非法数据则退出程序。 Dim pHandle As Long
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
If (pHandle = 0) Then
MsgBox "Couldn’t get a process handle!"
Exit Sub
End If
在我们的修改器中 WriteProcessMemory 函数是最重要的部分,而且非常容易出错。不妨让我们再仔细讨论一下它的参数。 WriteProcessMemory (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As) hProcess 是目标进程的句柄,从上面的 OpenProcess 函数中取得的。 lpBaseAddress 是在计算器程序的虚拟内存中将要被修改的地址,也就是使用内存搜索程序找到的那个地址。(在我的程序里是&H40B181)lpBuffer 是将要写如上述地址的数据,可以是一个数值、数组、字符串或其他任何数据类型。 nSize 是希望写入 lpBaseAddress 的字节数。这个位置应该与你的数据类型相符。如果写入的是一个长整数( long),这里应该是4。如果写入的是一个字符串,那么这里应该是字符串的长度。 lpNumberOfBytesWritten 是函数执行返回后,写入目标地址的实际字节数。它能被用来确认函数实际的执行情况。 把我们的数据放到函数中,得到 WriteProcessMemory pHandle, &H40B181, "Beans", 5, 0&。我把0传递到lpNumberOfBytesWritten 位置是因为不需要检查两次实际写入的字节数。 最后通过传递进程句柄给 CloseHandle() 函数来关闭由 OpenProcess 打开的句柄。 CloseHandle hProcess 现在将所有的代码输入我们的编辑器中。双击按钮,显示它的代码编辑窗口。代码应该加到名为 btnPasteName 的 Click事件中。(不必输入注释)
Private Sub btnPasteName_Click()
’ 声明一些需要的变量
Dim hwnd As Long ’ 储存 FindWindow 函数返回的句柄
Dim pid As Long ’ 储存进程标识符( Process Id )
Dim pHandle As Long ’ 储存进程句柄
’ 首先取得目标窗口的句柄
hwnd = FindWindow(vbNullString, "Calculator")
If (hwnd = 0) Then
MsgBox "Window not found!"
Exit Sub
End If
’ 取得进程标识符
GetWindowThreadProcessId hwnd, pid
’ 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
If (pHandle = 0) Then
MsgBox "Couldn’t get a process handle!"
Exit Sub
End If
’ 在内存地址中写入名字
WriteProcessMemory pHandle, &H40B181, "Beans", 5, 0&
’ 关闭进程句柄
CloseHandle hProcess
End Sub 完毕。现在单击按钮将使计算器窗口文本变为我们键如的名字。(可能需要最小化计算器程序,再还原,以便程序更新显示)
下面将给我们的修改器增加一个新功能。我们将检测计算器程序的窗口显示数据,并在修改器中显示。双击计时器,显示它的代码编辑窗口,然后输入以下代码:
Private Sub ReadTimer_Timer()
’ 声明变量
Dim hwnd As Long ’ 储存 FindWindow 函数返回的句柄
Dim pid As Long ’ 储存进程标识符
Dim pHandle As Long ’ 储存进程句柄
Dim str As String * 20 ’ 存储显示文本
’ 取得目标窗口的句柄
hwnd = FindWindow(vbNullString, "Calculator")
If (hwnd = 0) Then Exit Sub
’ 取得进程标识符
GetWindowThreadProcessId hwnd, pid
’ 取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
If (pHandle = 0) Then Exit Sub
’ 读取内存数据
ReadProcessMemory pHandle, &H40B181, str, 20, 0&
’ 在文本框显示
txtDisplay = str
’ 关闭进程句柄
CloseHandle hProcess
End Sub 在这里出现的新东西是 ReadProcessMemory 函数。从 &H40B181 地址中读出的数据被存入变量 str 中,然后显示在名为txtDisplay 的文本框中
22222222222222222222222222222222222222222222222222222222222
Private Declare Sub WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpDestBuff As Long, ByVal lpPatchBuff As Long, ByVal CodeSizeLen As Long, ByVal lpNumByWrite As Long)
Dim lpBuff(5) As Byte
lpBuff(0) = &HE9 '这里开始写你的补丁机器码
lpBuff(1) = &HC9
lpBuff(2) = &H60
lpBuff(3) = &H32
lpBuff(4) = 0
WriteProcessMemory hProcess, &H006b1dd2, VarPtr(lpBuff(0)),5,0
|