游戏数据的捕捉(郁金香学习笔记)

来源:互联网 发布:郭靖黄蓉爱情知乎 编辑:程序博客网 时间:2024/04/30 15:02

目录:

1.得到角色对象属性

2.得到吃药的CALL

3.得到快捷键CALL

4.得到选中怪物的ID地址

5.得到怪物列表

6.得到怪物属性

7.得到显示血条CALL

8.得到普通攻击CALL

9.得到捡物品CALL

10.得到背包列表地址

11.得到喊话CALL

12.坐标相关信息

13.得到综合内存信息

14.得到买卖物品CALL

15.关于OD调试多线程的问题

16.游戏多开实现

17.辅助编程注意事项

最近学习郁金香视频 写下学习笔记以便以后查询.

 
1.得到角色对象属性
角色属性是一个对象,通过生命值的变化 得到生命值地址 查看附近的内存得到其他属性
 角色对象基地址 02EE5B98
02EE5BE8    角色名字
02EE5C68    生命地址    dword
+4        内功        dword
+8        愤怒值        dword 千分比
+C        生命上限    dword    
+10        内功上限    dword
+14        3E8        
+18        经验值        2dword
+20        下一级经验值    2dword
+28        0A
+2C        历练        dword
+30        心        dword
+34        气        dword
+38        体        dword
+3C        魂        dword
+40        0
+44        0
+48        攻击        dword
+4C        防御        dword
+50        命中        dword
+54        回避        dword
+58        武功命中    dword?
+5C        武功防御    dword?
+60        0
+64        金钱
+68        0    

2.得到吃药的CALL
通过数量定位 小量金创药数量地址 2F8DAE24
CE监测访问数量的代码得到
//吃药call地址
push 0        //物品栏ID
push 1        //数量
push 0
call    00757700
提取特征码 A1648110038B8498040400008BB0B80200000BB0BC0200007433

3.得到快捷键CALL
用快捷键吃药 吃药call是在快捷键call中的 跟踪往上一层来到快捷键call
F1-F10快捷键
0065BF07    50              push    eax                    //0-9
0065BF0E    E8 BD65FFFF     call    00652520
提取特征码为 741F83BCB104040000000F84F40900008B84B10404000083784800 便于更新程序的时候好定位
        
4.得到选中怪物的ID地址
选中不同的怪物有不同的ID来定位
可以通过CE来监控 变化的值 未变化的值
得到选中怪物ID所在地址 [312DF1C]+1478

5.得到怪物列表
通过监测 改写选中怪物ID的代码 可以看到一个值填充了 选中ID
004AF442    8981 78140000   mov     dword ptr [ecx+0x1478], eax      ; 指定选中怪的ID
跟踪上下文可以发现
004AF470 - 8B 0C 85 20DF1203     - mov ecx,[eax*4+0312DF20]
eax是怪物ID 也是数组ID 这个数组一般就是怪物列表地址了

6.得到怪物属性
通过怪物列表得到怪物对象 选中不同怪物 以及打死怪物 怪物距离的不同 得到怪物属性
怪物列表地址
0312DF20
{
    + ID*4 怪物对象地址
    {
        +0    怪物各种功能的函数指针列表
        +8    类型 怪2E
        +C    ID/数组下标
        +31C    角色离怪物的距离
        +320    怪物的名字
        +37C    怪物复活过程
        +380    怪物生死状态 0为生 1为死
        +1018    怪物坐标X
        +1020    怪物坐标Y
    }
}

其中的怪物生死状态 可以通过CE来锁定选中的怪ID 打死后它会自动刷出 这样便于观察怪物对象内存中的各种属性
有些属性是浮点型 比如坐标 距离 所以用OD观察数据时要用相应的数据类型来观察

7.得到显示血条CALL
手动改写选中怪物ID时 发现没有鼠标选中时的血条 跟踪选中怪的ID代码
发现在之前有一个call 经测试是显示血条的call

选中怪显示血条call 使用条件最好是没有选中怪 要不然出现多个怪显示血条
  mov     esi, 0x2B1EBE18
  mov     eax, dword ptr [esi]
  mov     edx, dword ptr [eax+0x4]
  push    0                  //这个push以后经过了一个跳转猜到下一个push的 很容易漏掉    
  push    0x1
  push    0x44F
  mov     ecx, esi
  call    edx
  mov     eax, dword ptr [esi+0xC]
  mov     ecx, dword ptr [0x312DF1C]
  mov     dword ptr [ecx+0x1478], eax
提取特征码 83C410EB108B068B50046A01684F0400008BCEFFD2

8.得到普通攻击CALL
监测 访问选中怪物ID的代码 在按下攻击以后出现的代码 这个代码一般是在普通攻击call中的
逐一测试发现 普通攻击call
0064DA3F    8B0D 1CDF1203   mov     ecx, dword ptr [0x312DF1C]
0064DA45    E8 D689E5FF     call    004A6470
提取特征码 8B88D802000080B9E9290000000F8408020000578BBE7814000039BE9014000075218B8694140000
其中通过普通攻击发现 选中怪物的对象的地址 [312DF1C]


9.得到捡物品CALL
通过丢物品 捡物品发现鼠标选中的对象ID都放在 [312DF1C]+1478 地址里的,怪物 NPC 物品都是通用的
捡丢物品 监测 访问此地址 可以得到一条捡物品call内部的代码 从而得到捡物品call 这种方法比较难跟踪

另一个方法是 因为普攻 和捡物属于同一类 动作 大部分程序员会把它们放到一个case里边
如:
  switch(动作号)
  {
    case 普攻ID:{调用普攻call}
    case 捡物ID:{相应的call}
    case 打坐ID:{相应的call}
    case 走跑ID:{相应的call}
    case 逃脱ID:{相应的call}
    case 组队ID:{相应的call}
    case 交易ID:{相应的call}
    ...
    ...
    default:
  }
恰好前边得到了普攻call的调用地方 用IDA视图查看很轻松可以得到其他几个call
分别是
跑走: 0064DA51                 call    sub_64CE10
运气: 0064DA71                 call    sub_64CEA0
普攻: 0064DA95            call    sub_4A6470
捡物: 0064DAB9                 call    sub_4A66C0
其他以此类推...

在跟踪call的参数得到 代码
0076CBB4    8B0D FC2FEA00   mov     ecx, dword ptr [0xEA2FFC]
0076CBBA    8B89 74020000   mov     ecx, dword ptr [ecx+0x274]

最终call完整调用参数如下:
A.
mov ecx, dword ptr [0xEA2FFC]
mov ecx, dword ptr [ecx+0x274]
call 64CDC0

B.运气call
mov ecx, dword ptr [0xEA2FFC]
mov ecx, dword ptr [ecx+0x274]
call    64CEA0            
以此类推...

10.得到背包列表地址
背包数据结构一般为:
物品背包数组(基址1)
 +4 物品对象1
 +8 物品对象2
   +??
   +?? 物品数量
   +?? 物品名称
   +?? 功能说明
每个物品格 对应一个对象 这些对象是连续的数组

从人参数量下手 得到数量地址 监控访问地址的代码 人参所在物品栏的临时基址
0DD97468,搜索此地址得到几个代码 分别监控访问,鼠标移动人参换不同的物品格,可以得到代码:
0076B9D1 - 3B 3D 64811003        - cmp edi,[03108164]
0076B9D7 - 75 2A                 - jne 0076BA03
0076B9D9 - 8B 84 B7 04040000     - mov eax,[edi+esi*4+00000404]
很明显[edi+esi*4+00000404]这个是关键 edi的值可能背包基地址但是发现其值是19eBA4C0 也是一个临时地址往上看代码
发现cmp edi,[03108164] 可以推测[03108164]就是存放每次游戏背包基地址的地方了

综合上边发现 OD观察内存得到:
物品栏基地址 [03108164]
     +404 装备物品第一格基地址 0DD97468(临时)
        +5C  物品名字
    +AC  使用级别
    +F1  说明
        +23C 数量
    +26c 防御
    +290 背包数组下标
    +30C 耐久度
     +408 第二格
     ...
     ...
     +?? 如果这格没有物品 则为0

11.得到喊话CALL
喊话功能call寻找过程:
通过在喊话对话框中输入不同的字符串 得到2个地址 分别在CE中改写这2个地址
发现地址A改写后马上更新到喊话对话框中了 但是发送对话显示的是地址B的内容
追踪到B CE监控访问该地址代码 得到一个MEMSET函数内的代码 CE查看访问时 ECX的值
OD下条件断点 断下后放回上一层 用IDA查看地址 结合视图查看 反复跟踪得到喊话call
esi=[312E7E0]=0E278010
00447A9E    8B06            mov     eax, dword ptr [esi]
00447AA0    8B50 04         mov     edx, dword ptr [eax+0x4]
00447AA3    57              push    edi        //0xD
00447AA4    53              push    ebx        //0xD
00447AA5    68 ED030000     push    0x3ED
00447AAA    8BCE            mov     ecx, esi
00447AAC    FFD2            call    edx
具体访问代码:

mov     esi, dword ptr [312E7E0]
mov    edi,0xd
mov    ebx,0xd
mov     eax, dword ptr [esi]      
mov     edx, dword ptr [eax+0x4]  
push    edi              
push    ebx                
push    0x3ED                     
mov     ecx, esi                  
call    edx                       
函数特征码 8B068B5004575368ED0300008BCEFFD2


内容基地址寻找过程:
监控地址B访问代码
mov     cl, [eax]
以此往上跟踪可以得到
mov     ebx, dword_E73D1C
lea     edi, [ebx+13Ch]
mov     eax, edi
由此可得到 喊话基地址为 [0E73D1C]+13c
        
        
12.坐标相关信息
需要注意的是3D游戏中 坐标是由X Y Z 其中z是高 如果瞬间转移的时候不注意Z很有可能就会移动到
山体里边或湖水里边 或 地下 或天上 这个时候系统是会监测到的 所以会还原到一个正确的位置
Z坐标的计算 可以一般是以上往下计算的 所以Z都是负数 负得越多海拔越低 负得少海拔高,
想象一下就是把整个3D实地模型放到一个箱子里了 箱子的上顶角就是坐标的0点

 通过CE观察鼠标坐标得到
坐标对象基地址 0312DF1C 其中还存放了鼠标选怪ID
+0x1614 当前角色X坐标
+0x1618 当前角色Z坐标
+0x161C 当前角色Y坐标  或者0012762C
+0x15D8 鼠标点击坐标X  或者00E9AB50
+0x15DC    鼠标点击坐标Z
+0x15E0 鼠标点击坐标Y  或者00E9AB58
这组鼠标地址 主要是用来计算发送数据
另外一组组要是画面跑动使用
[[312DF1C]+2C94]+280 当前X    //修改后直接跳到相应的坐标 只是本地 服务器数据未变
[[312DF1C]+2C94]+284 当前Z
[[312DF1C]+2C94]+288 当前Y
[312DF1C]+147C 目标X
[312DF1C]+1480 目标Z
[312DF1C]+1484 目标Y
后边还发现一组用于跑动需要
直接通过鼠标改变来跟踪跑步函数比较困难 所以通过动静的状态来判断
CE搜索后得到比较多 通过改写目标地址 然后状态来判断角色移动没 来最终发现
以下2个开关
[312DF1C]+1494 开关1 1
[312DF1C]+1498 开关2 1
但是发现不是每次画面人物都能移动的 观察得到人物摆poss时 开关2会变成1 动作完成后变为0
这个时候在修改 目标地址 及开关就可以移动 推测摆poss 不光是好看 应该有数据更新重置功能
跟踪开关2改写的代码 来到了摆poss的代码处 发现每次改写时 还会改写一个地方 且这个地方很临近
经CE测试得到
[312DF1C]+149C 开关3 为0时更改坐标开关12可以移动
现在可以自由移动 但是发现走的是直线 和平时移动不太一样 这样势必会撞墙 应该有代码判断是否有障碍 定位判断障碍的函数
用CE修改目标地址 让主角跑起来 监测X或Y写入 当撞墙时 X或Y有一个值就不会变了 这时候查看写入代码
地址004B1693 如果遇到墙 执行不到这个地址 地址前边应该有校正 IDA视图浏览很快定位到有3个流程
但是都是 54CEC0 函数的返回值 从而推断 54CEC0 函数是判断障碍物的函数有,进入函数发现有4个返回值
分别是 0 1 2 3 OD断点检测 正常时返回的是1 快速验证 修改函数代码正常返回0时就返回1 再用CE修改
目标地址进行跑动 这下就可以穿越一切了
上边的一切都是画面变动 服务器数据并没有发生变化 定位发送坐标数据的函数
由于鼠标函数比较复杂 且游戏本身有土灵符可以瞬移 这样省去了 鼠标函数调用 但是有发送数据的函数
CE监测 鼠标坐标 使用土灵符 可以得到函数 495AD0 下断函数 发现鼠标点击时也有调用此函数 应该就是
数据发送函数了 但是使用道具和鼠标点击参数不一样 综合一下写入 完整的角色移动call

mov esi, dword ptr [312DF1C]
//设置目标地址
mov dword ptr [esi+147C],44C70000
mov dword ptr [esi+1480],0xC3B621EF
mov dword ptr [esi+1484],4465C000
mov dword ptr [esi+1494],1
mov dword ptr [esi+1498],1
mov dword ptr [esi+149C],0
//发送数据到服务器
mov dword ptr [esi+15D8],44C70000
mov dword ptr [esi+15DC],0xC3B621EF
mov dword ptr [esi+15E0],4465C000
mov edx,dword ptr [esi+15D8]
mov ecx,dword ptr [esi+15DC]
push 2
sub esp, 0c
mov eax, esp
mov [eax], edx
mov edx,[esi+15E0]
mov [eax+4],ecx
mov ecx,esi
mov [eax+8],edx
call 495AD0

13.得到综合内存信息
通过丢物品后 走远点击物品然后点击其他地方来取消捡物品 可以得到选择物品ID和怪物是同一个
观察物品内存块情况 得到
0312DF20
{
    + ID*4 物品对象地址
    {
        +8    类型 33
        +C    ID/数组下标
        +64    物品的距离
        +94    物品的名字
        +198    物品坐标X
        +19C    物品坐标Z
        +1A0    物品坐标Y
    }
}

人物角色内存情况
0312DF20
{
    + ID*4 人物对象地址
    {
        +8    类型 2E
        +C    ID/数组下标
        +18    人物名字
        +1D00    人物等级
        +147C    人物坐标X
        +1480    人物坐标Z
        +1484    人物坐标Y
    }
}

14.得到买卖物品CALL
通过执行买卖动作 用OD监视得到买卖物品的数据包信息
可以多次检查不同数据来观察
0012A48C  00 00 92 00 80 00 02 00 00 00 19 41 68 F3 68 CA  //92 80 02为常量
0012A49C  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 32 1B  //01数量 32为计数ID
0012A4AC  02 00 00 00 00 00 17 39 C2 90 23 A2 E8 0C 68 CA  //物品类型
0012A4BC  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 01 0C  //01数量 0C是背包下标
0012A4CC  00 00 01 00 6C F3 00 00 00 00 00 00 00 00 00 00  
0012A4DC  00 00 00 00 00 00 00 00 00 00 00 00 00 F3 00 00  
0012A4EC  00 00 00 00 00 00 00 00 68 F3 00 00 00 00 00 00
0012A4FC  00 00 00 00 00 00 00 45 65 F3 00 00 00 00 27 44  
0012A50C  62 F3 26 42 62 F3 00 00 00 00 00 00 00 00 00 00

0012A48C  00 00 92 00 80 00 02 00 00 00 00 00 00 00 94 CA  ..?€........斒
0012A49C  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 36 1B  ?...........6
0012A4AC  02 00 00 00 00 00 F7 57 2F D0 AE A8 E8 0C 94 CA  .....鱓/挟ㄨ.斒
0012A4BC  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 01 00  ?............
0012A4CC  00 14 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ..............
0012A4DC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0012A4EC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


6C6EB130 >00 00 92 00 80 00 02 00 00 00 00 00 00 00 94 CA  ..?€........斒
6C6EB140  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 36 1B  ?...........6
6C6EB150  02 00 00 00 00 00 F7 57 2F D0 AE A8 E8 0C 94 CA  .....鱓/挟ㄨ.斒
6C6EB160  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 01 00  ?............
6C6EB170  00 14 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ..............
6C6EB180  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
6C6EB190  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
6C6EB1A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
6C6EB1B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


3233FDC0  00 00 92 00 80 00 02 00 00 00 00 00 00 00 94 CA  ..?€........斒
3233FDD0  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 36 1B  ?...........6
3233FDE0  02 00 00 00 00 00 F7 57 2F D0 AE A8 E8 0C 94 CA  .....鱓/挟ㄨ.斒
3233FDF0  9A 3B 00 00 00 00 01 00 00 00 00 00 00 00 01 00  ?............
3233FE00  00 14 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ..............


出售物品数据包结构
struct
{
    +0    const0            word    00        
    +2    const1            word    92        
    +4    const2            word    80        
    +6    const3            dword    2
    +A    ??            dword   可以为0
    +E    物品对象+4C        dword    物品ID
    +12    物品对象+50        dword
    +16    数量 23c        dword
    +1A    ??            dword   可以为0
    +1E    角色属性[0x2EE5CCC]    dword
    +22    角色属性[0x2EE5CD0]    dword
    +26    物品对象+54        dword
    +2A    物品对象+58        dword
    +2E    物品对象+4c        dword
    +32    物品对象+50        dword
    +36    数量 23c        dword    
    +3A    物品对象+240        dword
    +3E    物品对象+1F2        byte
    +3F    背包下标 290        byte
    +40    物品对象+238        byte
    +41    物品对象+244        byte
    +42    物品对象+AC        byte
    +43    物品对象+A4        byte
        6C F3 00 00 00 00 00 00 00 00 00 00  
        00 00 00 00 00 00 00 00 00 00 00 00 00 F3 00 00  
        00 00 00 00 00 00 00 00 68 F3 00 00 00 00 00 00  
        00 00 00 00 00 00 00 45 65 F3 00 00 00 00 27 44  
        62 F3 26 42 62 F3 00 00 00 00 00 00 00 00 00 00
}
提取特征码 8D853CFFFFFF50B840E94700FFD0


以此类推得到 买物品CALL的数据包 打开NPC买卖对话框CALL的数据包 从而完成自动买卖物品


15.关于OD调试多线程的问题
OD调试多线程会出现这样的问题
"OllyICE无法再断点(可能无效)地址 读取寄存器及更新EIP
通常纠正后继续试不可能的 然后 您可以在自己承担风险的情况下
恢复及继续"
解决方法参照 http://blog.csdn.net/whatday/article/details/9059281

16.游戏多开实现
此游戏多开会有提示框 OD载入去除 发现还是不行 网上搜索发现是client文件夹冲突 想想也是第一个客户端一个文件嘛
复制client文件夹命名为其他名字 复制launcher.exe修改其中路径 多开OK了

17.辅助编程注意事项
 1.由于牵涉到内存 所以每个内存读之前 先尝试是否有效 可以使用 IsBadReadPtr 函数
 2.各种对象属性最好基于指针 因为数据都是动态变化的 只有在使用前来取得数据还是最正确的数据

 3.怪物对象ID不会变 但是对象基地址有可能变 所以应时候ID找对象基地址



原创粉丝点击