摘要:在实际计算机游戏的过程中,常会遇到资源不足的问题。为了解决游戏中的资源不足的问题,我用VB设计了这个小程序。里面用到了一些常用的API函数,希望它能给我们在处理类似问题时提供一个可行的依据。
关键词:API函数,内存指针,变量
Keywords: API Functions, Memory Pointers, Variables
本程序的原理是找到游戏资源相应的内存地址,对其进行操作。但实际游戏中的内存地址是变动的,给修改带来了一定的困难。本程序中使用CPU指令跟踪,用空指令取代原有的游子指令序列,实现了对游戏资源的无限修改。以下是程序模块的声明:
Option Explicit '本模块实现了对内存的操作
Option Base 1
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Const PROCESS_ALL_ACCESS As Long = &H
Public pHwnd As Long
Public processID As Long '进程名称
Public pHandle As Long
Public MemoryData(2) As Long
Public MemoryBackup(2) As Long
有了模块的支持,以下是程序内存修改函数代码:
Public Function MemRevise(ByVal pAddress As Long, ByRef MemData() As Long, ByVal ElementNum As Long, Optional ByVal nSize As Long) As Boolean '内存修改函数,成功返回真
MemRevise = False
pHwnd = FindWindow(vbNullString, "Brood War")
GetWindowThreadProcessId pHwnd, processID
If processID = 0 Then MsgBox "星际争霸未运行。", vbExclamation + vbOKOnly: Exit Function
pHandle = OpenProcess(PROCESS_ALL_ACCESS, False, processID)
WriteProcessMemory pHandle, ByVal pAddress, ByVal VarPtr(MemData(ElementNum)), IIf(nSize = 0, 1, nSize), 0&
CloseHandle pHandle: MemRevise = True '成功改写内存
End Function
有了内存修改函数作为基础,以下为对应的分类内存锁定函数:
Public Function MemLock(ByVal GameVersion$)
Select Case GameVersion
Case "1.08b"
MemRevise &H4020DD, MemoryData, 1
MemRevise &H4020DE, MemoryData, 2
MemRevise &H4020EB, MemoryData, 1
MemRevise &H4020EC, MemoryData, 2
Case "
MemRevise &H402B03, MemoryData, 1
MemRevise &H402B04, MemoryData, 2
MemRevise &H402B17, MemoryData, 1
MemRevise &H402B18, MemoryData, 2
Case "1.14"
MemRevise &H466EB0, MemoryData, 1
MemRevise &H466EB0, MemoryData, 2
MemRevise &H4542E4, MemoryData, 1
MemRevise &H4542E5, MemoryData, 2
Case "1.15"
MemRevise &H4676D0, MemoryData, 1
MemRevise &H4676D1, MemoryData, 2
MemRevise &H454B14, MemoryData, 1
MemRevise &H454B15, MemoryData, 2
End Select
End Function
以下为分类内存解锁函数:
Public Function MemRelease(ByVal GameVersion$)
Select Case GameVersion
Case "1.08b"
MemRevise &H4020DD, MemoryBackup, 1
MemRevise &H4020DE, MemoryBackup, 2
MemRevise &H4020EB, MemoryBackup, 1
MemRevise &H4020EC, MemoryBackup, 2
Case "
MemRevise &H402B03, MemoryBackup, 1
MemRevise &H402B04, MemoryBackup, 2
MemRevise &H402B17, MemoryBackup, 1
MemRevise &H402B18, MemoryBackup, 2
Case "1.14"
MemRevise &H466EB0, MemoryBackup, 1
MemRevise &H466EB1, MemoryBackup, 2
MemRevise &H4542E4, MemoryBackup, 1
MemRevise &H4542E5, MemoryBackup, 2
Case "1.15"
MemRevise &H4676D0, MemoryBackup, 1
MemRevise &H4676D1, MemoryBackup, 2
MemRevise &H454B14, MemoryBackup, 1
MemRevise &H454B15, MemoryBackup, 2
End Select
End Function
最后,为窗体加上初始化代码(主要是控件数组的初始化),整个程序就完成了。
'本程序实现了星际争霸修改器的功能,作为论文例程使用
Option Explicit
Option Base 1
Private Sub Command1_Click(Index As Integer)
Select Case Index
Case 1
Dim i%
For i = 1 To 4
If Form1.Option1(i).Value = True Then MemLock Form1.Option1(i).Caption: Exit Sub
Next i
If i = 5 Then MsgBox "请先选择游戏版本!", vbExclamation + vbOKOnly: Exit Sub
Case 2
Dim j%
For j = 1 To 4
If Form1.Option1(i).Value = True Then MemRelease Form1.Option1(j).Caption: Exit Sub
Next j
If j = 5 Then MsgBox "请先选择游戏版本!", vbExclamation + vbOKOnly
Case 3
End
End Select
End Sub
Private Sub Command2_Click()
MemLock "
End Sub
Private Sub Form_Load() '初始化窗体
Form1.Font = "Tahoma"
Form1.Frame1.Caption = "星际争霸版本(&V)"
Form1.Frame1.Font = "Tahoma"
Form1.ScaleHeight = 32
Form1.ScaleWidth = 48
Form1.Frame1.Move 2, 2, 30, 28
Form1.Option1(0).Visible = False
Dim i%
For i = 1 To 4 '框架中的元素不受窗体ScaleWidth属性的制约
Load Form1.Option1(i)
Form1.Option1(i).Move 120, 240 + 400 * (i - 1), 2535, 375
Form1.Option1(i).Visible = True
Form1.Option1(i).Font = "Tahoma"
Next i
Form1.Option1(1).Caption = "1.08b"
Form1.Option1(2).Caption = "
Form1.Option1(3).Caption = "1.14"
Form1.Option1(4).Caption = "1.15"
Form1.Command1(0).Visible = False
For i = 1 To 3
Load Form1.Command1(i)
Form1.Command1(i).Move 34, 4 + 8 * (i - 1), 12, 6
Form1.Command1(i).Visible = True
Form1.Command1(i).Font = "Tahoma"
Next i
Form1.Command1(1).Caption = "&Lock!"
Form1.Command1(2).Caption = "&Unlock!"
Form1.Command1(3).Caption = "E&xit"
MemoryData(2) = &H90
MemoryData(1) = &H90
MemoryBackup(1) = &H2B
MemoryBackup(2) = &HD1
End Sub
后记
本程序的核心思想是对内存指针的跟踪,内存变量的变换是不定的,但反映其变换依据的指针却是一定的。通过对指针的指针的跟踪,我们实现了星际争霸资源无限修改器的功能。为今后类似问题的实现提供了可行的理论依据。
参考文献
[1],张艳,新编Visual Basic程序设计,徐州:中国矿业大学出版社,2006
[2],张基温,张伟,C++程序开发习题与例题,北京:清华大学出版社,2003
