给初学者:用VB写外挂 ———— 从窗口到PID,进而读写内存

我们首先从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]

你可能感兴趣的:(外挂技术)