我们首先从HWND、PID入手,这是我们经常要用到的两种“标志符”。
HWND:窗口句柄,当我们要向游戏窗口发送一个按键或输入一段文本时,它将非常有用。
PID:进程标志符,当我们要操作内存、截获和修改封包时,它将非常有用。
我们首先从内存读写开始:
1、根据窗口名获取HWND,根据HWND取得进程PID
2、获取数据地址,读写内存
步骤一:从窗口名获取HWND
工具:SPY++或VB编程乐园的密码查看器等可以查看指定窗口名,类信息的工具
使用API函数: FindWindow、GetWindowThreadProcessId
代码:
Public Function GetPid(lpClassName As String, lpWindowName As String) As Long
' 取得进程标识符
GetWindowThreadProcessId FindWindow(lpClassName, lpWindowName), GetPid
End Function
解释:
lpClassName为你取得的游戏窗口的类,如果是空的,那么这个值在调用时传入vbnullstring或&0
lpWindowName为取得的游戏窗口名称,一般不会为空
FindWindow(lpClassName, lpWindowName)的返回值就是对应窗口的HWND,将其作为GetWindowThreadProcessId的第一个参数,而GetWindowThreadProcessId的第二个参数是返回值,也就是我们要得到的PID,函数中直接用了GetPid(函数名)来接收返回值
调用:(以传颂之物DVD汉化版为例)
GamePid = GetPid("传颂之物DVD汉化版", "★传颂之物汉化版★ (全年龄) Version1.00")
这时,GamePid已经是游戏的PID值了。
第二步:打开进程,读写内存:
工具:SOFTICE+金山游侠
使用API函数:OpenProcess、ReadProcessMemory、WriteProcessMemory
代码:
'获取内存内容
Public Function GetData(ByVal lppid As Long, ByVal lpADDress As Long, Optional ByVal dtLen As Long = 4) As Long
Dim pHandle As Long ' 储存进程句柄
' 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, lppid)
' 在内存地址中读取数据
ReadProcessMemory pHandle, ByVal lpADDress, ByVal VarPtr(GetData), dtLen, 0&
' 关闭进程句柄
CloseHandle pHandle
End Function
'将修改内存
Public Function SetData(ByVal lppid As Long, ByVal lpDestAddr As Long, lpSrcAddr() As Byte, Optional ByVal dtLen As Long = 4) As Boolean
On Error GoTo mErr
Dim lBytesReadWrite As Long
Dim pHandle As Long ' 储存进程句柄
' 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, lppid)
WriteProcessMemory pHandle, ByVal lpDestAddr, ByVal VarPtr(lpSrcAddr(0)), dtLen, 0&
' 关闭进程句柄
CloseHandle pHandle
SetData = True
mErr:
End Function
解释:
参数意义同API函数
调用方法:
GetData函数:
hp = GetData(GamePid, &H163254)
读PID为GamePid的进程&H163254处的数据(四字节方式)
如果需要其他方式可以hp = GetData(GamePid, &H163254,2)(双字节方式)
SetData函数:
Dim HStr As String
HStr = Right$("00000000" & Hex(Text1.Text), 8)
Dim mBuff(3) As Byte '修改数值
mBuff(0) = "&H" & Mid(HStr, 7, 2)
mBuff(1) = "&H" & Mid(HStr, 5, 2)
mBuff(2) = "&H" & Mid(HStr, 3, 2)
mBuff(3) = "&H" & Mid(HStr, 1, 2)
SetData GamePid, &H163254, mBuff
将文本框TEXT1的内容转换为16进制写入数组,修改PID为GamePid进程的&H163254处开始的连续四个字节为mBuff数组内容。
当然,在进行读写操作之前,我们需要获取操作系统的允许——提升我们程序的权限(具体见代码)
这样,我们就完成了对一个游戏内存的读写,至于你究竟要读写哪个地址,写成什么,就得用金山游侠先查找到,然后用SOFTICE跟踪得到指向这个地址的指针并获取你要读写的地址了。(为什么这样做就不详细说了,不属于我要讨论的范畴)
以下是较为完整的代码,可以正常运行(你可以下载一个TSPY来跟踪一下看看下面代码是不是按照你的意愿去工作了)
'模块:
Option Explicit
'查找窗体写内存等
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SYNCHRONIZE = &H100000
Private Const SPECIFIC_RIGHTS_ALL = &HFFFF
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
Private Const PROCESS_VM_OPERATION = &H8&
Private Const PROCESS_VM_READ = &H10&
Private Const PROCESS_VM_WRITE = &H20&
'权限提升
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Const TOKEN_ASSIGN_PRIMARY = &H1
Private Const TOKEN_DUPLICATE = (&H2)
Private Const TOKEN_IMPERSONATE = (&H4)
Private Const TOKEN_QUERY = (&H8)
Private Const TOKEN_QUERY_SOURCE = (&H10)
Private Const TOKEN_ADJUST_PRIVILEGES = (&H20)
Private Const TOKEN_ADJUST_GROUPS = (&H40)
Private Const TOKEN_ADJUST_DEFAULT = (&H80)
Private Const TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or TOKEN_ASSIGN_PRIMARY Or _
TOKEN_DUPLICATE Or TOKEN_IMPERSONATE Or TOKEN_QUERY Or TOKEN_QUERY_SOURCE Or _
TOKEN_ADJUST_PRIVILEGES Or TOKEN_ADJUST_GROUPS Or TOKEN_ADJUST_DEFAULT)
Private Const SE_PRIVILEGE_ENABLED = &H2
Private Const ANYSIZE_ARRAY = 1
Private Type LUID
lowpart As Long
highpart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
pLuid As LUID
Attributes As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type
'提升权限为高
Public Function ToKen() As Boolean
Dim hdlProcessHandle As Long
Dim hdlTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpNewButIgnored As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long
Dim lP As Long
hdlProcessHandle = GetCurrentProcess()
lP = OpenProcessToken(hdlProcessHandle, TOKEN_ALL_ACCESS, hdlTokenHandle)
lP = LookupPrivilegeValue("", "SeDebugPrivilege", tmpLuid)
tkp.PrivilegeCount = 1
tkp.Privileges(0).pLuid = tmpLuid
tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
lP = AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded)
ToKen = lP
End Function
'获取内存内容
Public Function GetData(ByVal lppid As Long, ByVal lpADDress As Long, Optional ByVal dtLen As Long = 4) As Long
Dim pHandle As Long ' 储存进程句柄
' 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, lppid)
' 在内存地址中读取数据
ReadProcessMemory pHandle, ByVal lpADDress, ByVal VarPtr(GetData), dtLen, 0&
' 关闭进程句柄
CloseHandle pHandle
End Function
'将修改内存
Public Function SetData(ByVal lppid As Long, ByVal lpDestAddr As Long, lpSrcAddr() As Byte, Optional ByVal dtLen As Long = 4) As Boolean
On Error GoTo mErr
Dim lBytesReadWrite As Long
Dim pHandle As Long ' 储存进程句柄
' 使用进程标识符取得进程句柄
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, lppid)
WriteProcessMemory pHandle, ByVal lpDestAddr, ByVal VarPtr(lpSrcAddr(0)), dtLen, 0&
' 关闭进程句柄
CloseHandle pHandle
SetData = True
mErr:
End Function
Public Function GetPid(lpClassName As String, lpWindowName As String) As Long
' 取得进程标识符
GetWindowThreadProcessId FindWindow(lpClassName, lpWindowName), GetPid
End Function
'窗体(请另存为.FRM文件)
VERSION 5.00
Begin VB.Form Form1
AutoRedraw = -1 'True
BorderStyle = 3 'Fixed Dialog
Caption = "★传颂之物修改器 VB DEMO"
ClientHeight = 1305
ClientLeft = 45
ClientTop = 330
ClientWidth = 2670
LinkTopic = "侠义道补药"
MaxButton = 0 'False
MinButton = 0 'False
ScaleHeight = 1305
ScaleWidth = 2670
ShowInTaskbar = 0 'False
StartUpPosition = 3 '窗口缺省
Begin VB.CommandButton Command1
Caption = "解除"
Height = 375
Left = 1440
TabIndex = 4
Top = 840
Width = 975
End
Begin VB.TextBox Text1
Height = 270
Left = 1080
TabIndex = 2
Text = "13"
Top = 0
Width = 1575
End
Begin VB.Timer Timer1
Interval = 300
Left = 1440
Top = 960
End
Begin VB.CommandButton Command2
Caption = "锁定"
Height = 375
Left = 120
TabIndex = 0
Top = 840
Width = 975
End
Begin VB.Label Label2
Height = 255
Left = 1440
TabIndex = 5
Top = 360
Width = 1215
End
Begin VB.Label Label4
Height = 255
Left = 0
TabIndex = 3
Top = 360
Width = 1215
End
Begin VB.Label Label1
Caption = "能力数值:"
Height = 255
Left = 0
TabIndex = 1
Top = 0
Width = 1095
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'请保留作者信息:
'ZCSOR于06-6-24开发
'E-MAIL:[email protected]
'属性点
'163254
'1632F4
Option Explicit
Dim hp As Long
Dim mp As Long
Dim xp As Long
Dim GamePid As Long ' 储存进程标识符( Process Id )
Private Sub Command1_Click()
Timer1.Enabled = False
End Sub
Private Sub Command2_Click()
GamePid = GetPid("传颂之物DVD汉化版", "★传颂之物汉化版★ (全年龄) Version1.00")
If GamePid = 0 Then
MsgBox "游戏未启动", 48
Exit Sub
End If
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
Private Sub Form_Load()
MsgBox " 适用于:★传颂之物汉化版★ (全年龄) Version1.00" & vbCrLf & "因正在进一步修改,所以暂不公开代码。有问题请联系我。" & vbCrLf & "作者:ZCSOR E-MAIL:[email protected]", vbOKOnly, "爱翔广宇揽东日之傲骨梅花 飞入梦境待晓时其清水芙蓉"
ToKen
Timer1.Enabled = False
Me.Left = 0: Me.Top = 0
End Sub
Private Sub Timer1_Timer()
GetHPMP
SetHPMP
'Me.Caption = GetMemorySize(GamePid) / 1024
End Sub
Sub GetHPMP()
hp = GetData(GamePid, &H163254)
Label4.Caption = "现在点数:" & hp
mp = GetData(GamePid, &H1632F4)
Label2.Caption = "现在点数:" & mp
End Sub
Sub SetHPMP()
Dim HStr As String
HStr = Right$("00000000" & Hex(Text1.Text), 8)
Dim mBuff(3) As Byte '修改数值
mBuff(0) = "&H" & Mid(HStr, 7, 2)
mBuff(1) = "&H" & Mid(HStr, 5, 2)
mBuff(2) = "&H" & Mid(HStr, 3, 2)
mBuff(3) = "&H" & Mid(HStr, 1, 2)
SetData GamePid, &H163254, mBuff
SetData GamePid, &H1632F4, mBuff
End Sub
最后说明一点,如果你有这个游戏的话,运行这个修改器修改是不会成功的:(因为我们要读写的能力点数值位置不是固定位置,所以说,需要用SOFTICE进行调试。
今天回来更新一下,对所有使用第一个版本传颂之物修改器的朋友表示道歉!以上针对传颂之物的代码实际不可用,如需要可用的代码可去下载区-代码-GAME下载。如对代码有任何疑问,可以联系我:E-MAIL:[email protected]