原作者的话:
"对不起,我想这是不可能的,因为VB是一个如此简单的编程语音。"如果有人这么告诉你,别去理他。我可以肯定告诉你,对于制作修改器这种简单的程序,VB完全可以胜任。
然而,有个问题必须首先考虑:使用VB编写的修改器需要VB的执行库才能执行。如果考虑到有些使用者(实际上可能是大部分使用者)没有执行库,那么在最后制作的ZIP压缩档中就必须包含这些庞大的档。在下面的教程里我将制作一个修改器,如果为它再制作一个安装程序,那么整个修改器的体积将超过1M B。其中包括一个很好的安装和反安装程序,但大部分还是VB40032.D LL这个档。
除了以上这点,使用VB制作修改器是非常简单的。一旦制作了多次后,你会发现能很快地制作出一个修改器。而且使用VB制作的修改器能够毫无困难地解决游戏执行时的动态内存分配问题,因此即使是最新的游戏,也可以使用VB制作修改器。在本教程中将不涉及动态内存分配,因为虽然简单,但仍然属于一个高级的选项。
一些背景知识
不象C语音,VB不会自动包括普通的API函数的声明,因此我们必须把他们加入我们的项目文件。在几乎所有的修改器中会使用到6个主要的函数,讨论如下:1. Fin dWind ow(Cl assNa me, W indow Title) - F indWi ndow返回符合指定的类
名( Clas sName )和窗口名( Wi ndowT itle)的窗口句柄。对我们来说,可以让
Cla ssNam e 为空( Null ),只给出游戏的Windo wTitl e。
函数应该这样声明:
Decl are F uncti on Fi ndWin dow L ib "u ser32" Ali as "F indWi ndowA"
(By Val l pClas sName As S tring, ByV al lp Windo wName As S tring) AsLong
2.GetWi ndowT hread Proce ssId(Windo wHand le, P roces sId)- 在这里我们
把F indWi ndow
函数中得到的句柄作为参数,来获得进程标识符(Proce ssId)。
声明如下:
Dec lareFunct ion G etWin dowTh readP roces sId L ib "u ser32" (By Val h wnd A s Lon g, lp dwPro cessI d AsLong) As L ong
3. O penPr ocess(Desi redAc cess, Inhe rit,Proce ssId) -
这个函数将返回一个我们目标进程的句柄,可以用来对目标进行读写操作。Desir edAcc ess参数的值决定了句柄对进程的存取权利,对我们来说,要使用
PROC ESS_A LL_AC CESS(完全存取权限)。I nheri t 应该总是Fals e。 Pr ocess Id 是从GetW indow Threa dProc essId函数中取得的。
Decl are F uncti on Op enPro cessLib "kerne l32"(ByVa l dwD esire dAcce ss As Long, ByV al bI nheri tHand le As Long, ByV al dw Proce ssIdAs Lo ng) A s Lon g
4. Clo seHan dle(P roces sHand le) -每一个打开的句柄必须呼叫这个函数来关闭。D eclar e Fun ction Clos eHand le Li b "ke rnel32" (B yValhObje ct As Long) AsLong
5.Write Proce ssMem ory(P roces sHand le, A ddres s, va lue,Sizeo fvalu e,
Byte sWrit ten)- 把指定的值 va lue 写入由 Ad dress指定的目标地址。
Dec lareFunct ion W riteP roces sMemo ry Li b "ke rnel32" (B yValhProc ess A s Lon g,
By Val l pBase Addre ss As Any, ByVa l lpB uffer As A ny, B yValnSize As L ong,
lpNum berOf Bytes Writt en As Long) AsLong
6.ReadP roces sMemo ry(Pr ocess Handl e, Ad dress, val ue, S izeof value,
Bytes Writt en) -把 Ad dress指定的目标地址的值存入 va lue 位置的变量中。
De clare Func tionWrite Proce ssMem ory L ib "k ernel32" (ByVal hPro cessAs
Lo ng, B yVallpBas eAddr ess A s Any, ByV al lp Buffe r AsAny,ByVal nSiz e AsLong, lpNu mberO fByte sWrit ten A s Lon g) As Long
这些函数一环扣一环,缺一不可。更详细的内容可以参考VB的帮助档。
一个简单的修改器范例
如何使上面介绍的这些函数一起工作,制作出我们需要的修改器呢?下面是一个为Windo ws的计算器程序制作修改器的例子。这个修改器将读出计算器窗口中显示的数值,并在点击一个按钮后在计算器窗口中显示我们的名字。
首先我们需要到计算器显示窗口中显示值的地址。本教程不是关于如何进行内存搜索,因而我将只作简单的说明:
- 在计算器窗口中输入123456
- 使用你喜欢的任何一种内存地址搜索程序寻字符串123456
- 使用另一个值重复上面的过程直到只返回1个地址
那是制作我们的修改器需要的唯一一个地址。在我的计算器程序里这个地址是40B181 hex, 4239745dec。用你到的地址替代在下面的代码里使用的这个地址。现在让我们开始设计修改器的接口:
-在VB中新建一个项目,加入一个文本框(Textb ox )、一个按钮和一个定时器( tim er
)。文本框用来显示从计算器窗口取得的字符串,按钮用来把我们的名字传到计算器窗口
-把窗体(form)的标题( Capt ion )内容设为Calcu lator Trai ner
- 把文本框改名为 txtD ispla y 并清除 Text内容
- 把定时器改名为 Read Timer并把间隔( int erval )设为500
- 把按钮的标题改为 Disp lay N ame,按钮的名字改为 btn Paste Name
在这个修改器中我们将使用所有6个函数,R eadPr ocess Memor y、
Wri tePro cessM emory、Open Proce ss、Ge tWind owThr eadPr ocess Id、Fi ndWin dow 和Clos eHand le。在项目中插入一个新的模块,增加下列代码。(下面的一些行自动换行了,在你的模块中每一句必须在一行里,或使用延长符_)
De clare Func tionFindW indow Lib"user32" A lias"Find Windo wA" (ByVal
l pClas sName As S tring, ByV al lp Windo wName As S tring) AsLong
Dec lareFunct ion G etWin dowTh readP roces sId L ib "u ser32" (By Val h wnd A s
Long, lpdw Proce ssIdAs Lo ng) A s Lon g
D eclar e Fun ction Open Proce ss Li b "ke rnel32" (B yValdwDes iredA ccess As
Lon g, By Val b Inher itHan dle A s Lon g, By Val d wProc essId As L ong)As Lo ng
Decla re Fu nctio n Wri tePro cessM emory Lib"kern el32" (ByV al hP roces s As
Lo ng, B yVallpBas eAddr ess A s Any, ByV al lp Buffe r AsAny,ByVal nSiz e As
Lo ng, l pNumb erOfB ytesW ritte n AsLong) As L ong
Decl are F uncti on Re adPro cessM emory Lib"kern el32" (ByV al hP roces s AsLong,
B yVallpBas eAddr ess A s Any, ByV al lp Buffe r AsAny,ByVal nSiz e AsLong,
l pNumb erOfB ytesW ritte n AsLong) As L ong
Decl are F uncti on Cl oseHa ndleLib "kerne l32"(ByVa l hOb jectAs Lo ng) A s Lon g
下面我们要开始写在定时器窗口中显示我们名字的代码了。首先我们使用
FindW indow函数取得目标窗口的句柄。把这个返回值保存在一个变量中,并检查它的值是否出错来确保定时器程序正在执行。(Find Windo w函数出错时返回0)
Di m hwn d AsLong
hwn d = F indWi ndow(vbNul lStri ng, "Calcu lator")
If (h wnd = 0) T hen
MsgB ox "W indow notfound!"
ExitSub
EndIf
注意在这里我们传递了一个 Null值给F indWi ndow函数,而不是 Cla ssNam e。因此任何名为C alcul ator的窗口都符合条件。如果知道计算器程序窗口的
vb计算器代码大全Clas sName,你可以传给它,但这不是必须的。
现在使用得到的窗口句柄来取得进程标识符( Pr ocess Id )。注意 pi d 是作为参数传递给函数的,而不是被赋以函数返回值。
D im pi d AsLong
Get Windo wThre adPro cessI d hwn d, pi d
再利用变量pid得到计算器程序的进程句柄。再次检查函数的返回值,如果是非法数据则退出程序。
Dim p Handl e AsLong
pHa ndle= Ope nProc ess(P ROCES S_ALL_ACCE SS, F alse, pid)
If (pHa ndle= 0)Then
Msg Box "Could n’t g et aproce ss ha ndle!"
E xit S ub
End I f
在我们的修改器中 Writ eProc essMe mory函数是最重要的部分,而且非常容易出错。不妨让我们再仔细讨论一下它的参数。
W riteP roces sMemo ry (B yValhProc ess A s Lon g, By Val l pBase Addre ss As Any,
B yVallpBuf fer A s Any, ByV al nS ize A s Lon g, lp Numbe rOfBy tesWr itten As)
hProc ess 是目标进程的句柄,从上面的 Op enPro cess函数中取得的。
lp BaseA ddres s 是在计算器程序的虚拟内存中将要被修改的地址,也就是使用内存搜索程序到的那个地址(在我的程序里是&H40B181)。lpBuf fer 是将要写入上述地址的数据,可以是一个数值、数组、字符串或其它任何数据类型。
nSi ze 是希望写入l pBase Addre ss 的字节数。这个位置应该与你的数据类型相符。如果写入的是一个长整数( lon g),这里应该是4。如果写入的是一个字符串,那么这里应该是字符串的长度。
l pNumb erOfB ytesW ritte n 是函数执行返回后,写入目标地址的实际字节数。它能被用来确认函数实际的执行情况。
把我们的数据放到函数中,得到 Wri tePro cessM emory pHan dle,&H40B181,"Bean s", 5, 0&。我把0传递到lpNu mberO fByte sWrit ten 位置是因为不需要检查两次实际写入的字节数。
最后通过传递进程句柄给 Cl oseHa ndle() 函数来关闭由O penPr ocess打开的句柄。
Close Handl e hPr ocess
现在将所有的代码输入我们的编辑器中。双击按钮,显示它的代码编辑窗口。代码应该加到名为b tnPas teNam e 的C lick事件中。(不必输入注释)
P rivat e Sub btnP asteN ame_C lick()
'声明一些需要的变量
Di m hwn d AsLong' 储存FindW indow函数返回的句柄
Dimpid A s Lon g ' 储存进程标识符( Pr ocess Id )
Di m pHa ndleAs Lo ng '储存进程句柄
'首先取得目标窗口的句柄
hwnd= Fin dWind ow(vb NullS tring, "Ca lcula tor")
If (hwn d = 0) The n
M sgBox "Win dow n ot fo und!"
Ex it Su b
E nd If
'取得进程标识符
GetWi ndowT hread Proce ssIdhwnd, pid
' 使用进程标识符取得进程句柄
pHand le =OpenP roces s(PRO CESS_ALL_A CCESS, Fal se, p id)
If (pHand le =0) Th en
MsgBo x "Co uldn’t get a pr ocess hand le!"
Exi t Sub
En d If
' 在内存地址中写入名字
Wri tePro cessM emory pHan dle,&H40B181,"Bean s", 5, 0&
' 关闭进程句柄
Cl oseHa ndlehProc ess
EndSub
完毕。现在单击按钮将使计算器窗口文本变为我们键如的名字。(可能需要最小化计算器程序,再还原,以便程序更新显示)
下面将给我们的修改器增加一个新功能。我们将检测计算器程序的窗口显示数据,并在修改器中显示。双击定时器,显示它的代码编辑窗口,然后输入以下代码:
Priva te Su b Rea dTime r_Tim er()
' 声明变数
DimhwndAs Lo ng '储存 Fi ndWin dow 函数返回的句柄
D im pi d AsLong' 储存进程标识符
Dim pHan dle A s Lon g ' 储存进程句柄
Di m str As S tring * 20 ' 存储显示文本
' 取得目标窗口的句柄
hwnd = Fi ndWin dow(v bNull Strin g, "C alcul ator")
I f (hw nd =0) Th en Ex it Su b
'取得进程标识符
GetW indow Threa dProc essId hwnd, pid
'取得进程句柄
p Handl e = O penPr ocess(PROC ESS_A LL_AC CESS, Fals e, pi d)
If (p Handl e = 0) The n Exi t Sub
'读取内存数据
R eadPr ocess Memor y pHa ndle, &H40B181, str, 20,0&
' 在文本框显示
txtD ispla y = s tr
' 关闭进程句柄
Clos eHand le hP roces s
E nd Su b
在这里出现的新东西是 Re adPro cessM emory函数。从 &H40B181地址中读出的数据被存入变量s tr 中,然后显示在名为txt Displ ay 的文本框中。
本教程中所讲的是非常简单的东西,主要是想起抛砖引玉的目的。最重要的是不断学习,不断实践,了解其它的API并在修改器中使用。练习越多,就会觉得越容易。
好的话帮忙顶一下,谢谢!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论