本页主题: [原创][VB]内存修改器教程 打印 | 加为IE收藏 | 复制链接 | 收藏主题 | 上一主题 | 下一主题

lms7888
介就素人生啊
级别: 论坛版主


精华: 0
发帖: 117
威望: 10 点
金钱: 2240 胜利币
贡献值: 0 点
在线时间:32(小时)
注册时间:2007-05-19
最后登录:2008-10-12

 [原创][VB]内存修改器教程

0
管理提醒:
本帖被 superttl 执行置顶操作(2007-12-25)
阅读本文需要一定的汇编基础知识和OD使用经验.另外,对VB也要有一定的了解.
前几天论坛的一个朋友给我发短信,说"高手教教我",呵呵,我不是高手,我也是从一无所知过来的.我只不过是早学了一段时间.如果你能拿出时间来学习的话,你一定会更棒的!好了.言归正传.
下面我们以英雄无敌3 3.1 中文版来说明.
工具:OD,VB6.0 SP6,GM8,SPY++

首先,开始游戏,进入游戏后,发现英雄名字是"克里斯丁",好了切换到GM8,搜索该英雄的名字.
[attachment=449079]
搜索出5个地址
[attachment=449080]
经过试验,第二个地址是英雄名字存放的地方.
[attachment=449081]
[attachment=449082] 
看,改了以后,英雄的名字变了.成了"舅里斯丁"了.汗.
[attachment=449083]

然后,记下刚才我们修改的地址打开OD,选"文件"-"附加",附加英雄无敌3的程序
[ [attachment=449084]
附加完成后,在数据栏中,点右键,选"转到",输入刚才我们记下的那个地址,输入正确的话,应该能看到下面的图画.

[attachment=449085]
然后,用鼠标选中这一段数据,点右键,选内存断点-内存访问断点.然后,回到游戏中,双击英雄头像.程序被断下了.在如图的位置.

[attachment=449086]
这只是一个模块.我们要知道是哪里调用他,地址是哪来的.OD中,按Ctrl+F9,执行到返回.我们看到如图.

[attachment=449087]
程序停在我用红线标的地方.我们往上找,到了我用鼠标选中的那一行里,我们知道了,在地址8261D8中存放的数据+23就是英雄名字的地址.一试,果然如此.

汗,上班到点了,先写到这.晚上下班后,接着写第二节...欢迎大家继续收看.
本帖最近评分记录:
  • 金钱:+200(superttl) 支持教程
  • 写修改器还是用VB吧.用.Net来写修改器有种高射炮打蚊子的感觉...
    顶端 Posted: 2007-12-24 12:50 | [楼 主]
    lms7888
    介就素人生啊
    级别: 论坛版主


    精华: 0
    发帖: 117
    威望: 10 点
    金钱: 2240 胜利币
    贡献值: 0 点
    在线时间:32(小时)
    注册时间:2007-05-19
    最后登录:2008-10-12

     

    第二节开课啦。。。

    在上一节中,我们知道了当打开英雄状态窗口时,8261D8中存放的数值再+23(十六进制,以下一样),就是英雄名字的首字符位置,什么,你不知道是怎么来的,我汗,朋友,作修改器不是请客吃饭,在这种关键时刻,你必须得一行一行代码的看,别的不说,你必须要知道关键位置是从哪里读取的。
    大家可以在57A25F的位置按下F2下断,然后回来游戏,打开英雄状态窗口,断下后,按F7跟着程序走,你就会明白啦。一般来说,在CALL之前PUSH入栈的数据都是关键数据。如果您还是不懂,………………建议您去看一下汇编基础再回来。
    下面,我们就要用修改器来实现这一功能。因为在游戏中,英雄姓名首字符位置与英雄其它的属性相隔的位置是固定的。比如四围啦。宝物啦,军队,魔法什么的。位置相隔都是一定的。
    我们来打个比方吧。比如英雄的攻击力与姓名首字符的距离是1F。我们打开VB6,新建一个标准EXE,在窗体上新建一个CommandButton,其Caption为“读取”新建一个TextBox,其Text为空。如图。


    [attachment=449181]

    然后开始写代码啦。。在窗体的通用部分声明以下API
    Option Explicit
    '1.查找窗口
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    '2.取得进程ID
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    '3.打开进程
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    '4.把数值写入内存
    Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
    '5.从内存中读取数值
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
    '6.关闭打开的线程句柄
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    '7.一个操作内存的权力常数
    Private Const PROCESS_ALL_ACCESS = &H1F0FFF
    '以上7个项目可以从API浏览器中复制,,但可能会有一点不同,,建议复制上面的代码

    '8.一个保存游戏进程ID的变量
    Public hProcess As Long
    '9我们刚才找到的基础地址
    Const BaseAddr = &H8261D8

    然后打开SPY++,查看游戏窗口的名称:魔法门之英雄无敌III  3.1 Jul 18 2000 13:48:09

    再接着上边写以下函数:
    Function FindGame() As Boolean
    Dim PID As Long, Gamehwnd As Long
    FindGame = False
    Gamehwnd = FindWindow(VbNullString, "魔法门之英雄无敌III  3.1 Jul 18 2000 13:48:09") '查找游戏的句柄
    If (Gamehwnd = 0) Then Exit Function '如果找不到(例如游戏未运行)就退出函数
    GetWindowThreadProcessId Gamehwnd, PID '取得进程ID
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, PID) '以全部权力打开进程
    If (hProcess = 0) Then Exit Function '打开进程失败
    FindGame = True '成功!!
    End Function

    然后在FORM1的LOAD事件中写如下代码:
    If Not FindGame Then
    MsgBox "请先运行游戏,并双击英雄,打开英雄信息窗口!", vbCritical
    Command1.Enable = False
    Text1.Enable=False
    Exit sub
    End If
    以上意思就是说如果找不到游戏进程,就给出提示,并且使命令按键和文本编辑框不可用。

    然后双击“读取”在CLICK事件中写以下代码:
    Dim MyAddr&
    ReadProcessMemory hProcess, BaseAddr, MyAddr, 4, 0
    MyAddr = MyAddr + &H23
    这样,我们就完成了程序中读取英雄姓名首字节的工作。在MYADDR中存放的就是英雄名字首字节。
    接着,我们就是要读取英雄的攻击力,并在TEXTBOX中显示出来。
    Dim I as Byte ‘因为攻击力最大是100,所以我们就用BYTE类型来表示。
    ReadProcessMemory hProcess, MyAddr + &H1F, I, 1, 0 '读取攻击力
    Text1.Text = i
    这样我们就完成了攻击力的读取并显示在窗体上。
    如果我们要保存呢,我们可以再新建一个CommandButton,并命名为“保存”
    在其CLICK事件中这么写
    Dim I as Byte
    I = Text1.Text
    WriteProcessMemory hProcess, MyAddr + &H1F, I, 1, 0
    这样,就完成了写入,当然,这只是最简单的一个示例,如果大家自己在写修改器时,一定要把一些情况考虑全面,比如错误处理,限制输入,数据长度等等。这些大家去百度一下就会找到很好的源代码,我就不浪费大家时间了。希望大家看过后,能对您有一些小启发。
    写修改器还是用VB吧.用.Net来写修改器有种高射炮打蚊子的感觉...
    顶端 Posted: 2007-12-25 09:16 | 1 楼
    lms7888
    介就素人生啊
    级别: 论坛版主


    精华: 0
    发帖: 117
    威望: 10 点
    金钱: 2240 胜利币
    贡献值: 0 点
    在线时间:32(小时)
    注册时间:2007-05-19
    最后登录:2008-10-12

     

    是的,当打开英雄状态窗口时,在8261D8中的数值 +23就是英雄名字的位置.
    写修改器还是用VB吧.用.Net来写修改器有种高射炮打蚊子的感觉...
    顶端 Posted: 2007-12-27 19:27 | 2 楼
    帖子浏览记录 版块浏览记录
    胜利之歌超级论坛 » PC修改专区


    浙ICP备05022506号
    Total 1.308933(s) query 6, Time now is:10-13 14:55, Gzip enabled
    Powered by PHPWind v6.3.2 Certificate Code © 2003-08 PHPWind.com Corporation