原帖内容
蛇夫座

2009-12-8 20:28
OD动态分析调试实例 -- 瓦崗(WaGan.wa)绝招伤害计算修改

OD动态分析调试实例 -- 瓦崗(WaGan.wa)绝招伤害计算修改

分析篇: (以修改绝招伤害计算为主线进行OLLYICE 动态分析调试的一个完整过程, 相信对新手有一定帮助)
       首先猜想绝招伤害计算是对物理攻击重新计算又或者是对物理攻击伤害值进行加成
       参考周瑜的《曹操传exe部分函数功能》, 获取函数功能和入口信息
       0043BC4B      ; 获取ECX武将对08栈武将的物理伤害, 10栈为是否实际值, 是则考虑是否命中和随机数
                     ; 这个函数最值得注意
       用OLLYICE打开WaGan.wa 文件, (文件类型下拉框中选择: 任何文件(*.*) )
       在反汇编窗口 CTRL + G, 在[输入要跟随的表达式]对话框中输入: 0043BC4B
       光标停在0043BC4B 一行, 信息提示面板显示:
       本地调用自 00405EB4, 00438ABF, 00438EB8, 004406AB
       现在要调试游戏, 要去到调用这个函数的地方下断, 再运行游戏看游戏有没有停下来
       由于《瓦崗》是双进程所以对其调试要有点技巧, 按CTRL+ F2 重新开始
       先对入口点设置断点:
       004817E0 >  $  55    push    ebp
       改为:
       004817E0 >     CC    int3
       保存文件
       然后设置OLLYICE为实时调试器, 点菜单的[选项] ==> [实时调试器设置] ==> [设置OLLYICE为实时调试器]
        ==> [附加前无需确认] ==> [完成]。
       双击《瓦崗山異聞録.exe》调试器将自动捕获陷阱
       光标停在入口点:   004817E0 >    CC       int3
       双击int3 所在栏目弹出[汇编于此处: 004817E0]对话框中输入: push ebp       ; 还原入口处的指令
       现在就可以实时断点、单步、修改寄存器、看数据窗、看堆栈窗等操作, 可以开始调试了!!
       首先读取进度进入到战场上(当时存档中的关卡是[救难临潼山 - 楂树岗之战 - (第 3回合)])
       将反汇编窗口的滚动条拖到最顶
       CTRL + F, 在[查找命令]对话框中输入: CALL 0043BC4B
       光标停在:    00405EB4 . E8 925D0300   call    0043BC4B    一行按F2 下断点
       由于先前观察共有四处调用, 再CTRL + F 回车
       光标停在:    00438ABF |. E8 87310000   call    0043BC4B    一行按F2 下断点
       同样CTRL + F 回车于
       00438EB8  |.  E8 8E2D0000   |call    0043BC4B
       004406AB   .  E8 9BB5FFFF   call    0043BC4B
       两处下断点, 直到显示: 条目未找到
       ALT + B 弹出[断点窗口]可以管理断点, 现如下:
       Breakpoints
       地址       模块       激活          反汇编               注释
       00405EB4   WaGan      始终          call    0043BC4B
       00438ABF   WaGan      始终          call    0043BC4B
       00438EB8   WaGan      始终          call    0043BC4B
       004406AB   WaGan      始终          call    0043BC4B

       F9 运行游戏, 移动<管毅>接近敌人点[攻击], (当时存档中的敌人为[周治])
       游戏停在:    004406AB . E8 9BB5FFFF   call    0043BC4B
       但问题出来了, 现在不管点战场那里不能响应, 为什么?
       只能取消那一行的断点了, 在004406AB 一行按F2, 现按F9 运行游戏, 这时光标可以自由移动和点击了
       发现没有, 当光标移动到攻击范围内的敌将身上(当时存档中的敌人为<周治>), 会显示红色一段的伤害值
       看来上面的问题答案就是: 显示伤害值之前调用 0043BC4B函数来计算了
       左键点击敌人, 这时光标停在:    00405EB4 . E8 925D0300   call    0043BC4B
       再按F9 运行游戏, 我方武将对敌方武将产生攻击动作了
       奇怪游戏这时又停在:    00405EB4 . E8 925D0300   call    0043BC4B
       继续按F9 运行游戏, 这时敌方武将对我方武将产生攻击动作了
       就此看来00405EB4 处就是[攻击]伤害的关键了
       在反汇编窗口 CTRL + G, 在[输入要跟随的表达式]对话框中输入: 00405EB4
       00405E78 . 8B4D F4           mov     ecx, dword ptr [ebp-C]
       00405E7B . 33D2              xor     edx, edx
       00405E7D . 8A51 01           mov     dl, byte ptr [ecx+1]
       00405E80 . 8BCA              mov     ecx, edx
       00405E82 . 6BC9 24           imul    ecx, ecx, 24
       00405E85 . 81C1 502C4B00     add     ecx, 004B2C50
       00405E8B . E8 E0970500       call    0045F670
       00405E90 . 6BC0 48           imul    eax, eax, 48
       00405E93 . 05 0000D600       add     eax, 0D60000
       00405E98 . 8945 F8           mov     dword ptr [ebp-8], eax
       00405E9B . 33C0              xor     eax, eax
       00405E9D . 3B05 042E4900     cmp     eax, dword ptr [492E04]
       00405EA3 . 1BC9              sbb     ecx, ecx
       00405EA5 . F7D9              neg     ecx
       00405EA7 . 51                push    ecx
       00405EA8 . 6A 01             push    1
       00405EAA . 8B55 F8           mov     edx, dword ptr [ebp-8]
       00405EAD . 52                push    edx
       00405EAE . 8B45 F4           mov     eax, dword ptr [ebp-C]
       00405EB1 . 8B48 0C           mov     ecx, dword ptr [eax+C]
       00405EB4 . E8 925D0300       call    0043BC4B                    
                                                            ; 获取ECX武将对08栈武将的物理伤害
       00405EB9 . 8B4D FC           mov     ecx, dword ptr [ebp-4]
       00405EBC . 81E1 FF000000     and     ecx, 0FF
       00405EC2 . 8B55 F4           mov     edx, dword ptr [ebp-C]
       00405EC5 . 89848A 84000000   mov     dword ptr [edx+ecx*4+84], eax    ; 保存物理伤害值

       读取游戏进度, 移动<管毅>接近敌人点[攻击], (当时存档中的敌人为<周治>)
       光标停在:    00405EB4 . E8 925D0300       call    0043BC4B
       按F8 单步步过call指令, 执行到:    00405EB9 . 8B4D FC       mov   ecx, dword ptr [ebp-4]
       看寄存器窗:
       EAX  0000001E            ; 函数(0043BC4 的返回值, 等于十进制: 30 (注:  1)
       注:  1. 可以OLLYICE界面下方[Command]命令行输入: 0000001E
            回车后显示:  HEX: 1E  -  DEC: 30  -  ASCII:

       接着F9 运行游戏, 我方武将对敌方武将产生攻击动作了, 打出30 点的伤害
       这时游戏再一次暂停在:    00405EB4 . E8 925D0300   call    0043BC4B
       同样按F8 单步步过call指令, 执行到:    00405EB9 . 8B4D FC       mov   ecx, dword ptr [ebp-4]
       看寄存器窗:
       EAX  00000021            ; 函数(0043BC4 的返回值, 等于十进制: 33
       接着F9 运行游戏, 敌方武将对我方武将产生攻击动作了, 打出33 点的伤害

       再看看反汇编指令:
       00405EB4 . E8 925D0300       call    0043BC4B
       00405EB9 . 8B4D FC           mov     ecx, dword ptr [ebp-4]
       00405EBC . 81E1 FF000000     and     ecx, 0FF
       00405EC2 . 8B55 F4           mov     edx, dword ptr [ebp-C]
       00405EC5 . 89848A 84000000   mov     dword ptr [edx+ecx*4+84], eax    ; 保存物理攻击伤害值
       哈哈, 现在已经知道物理攻击伤害值存放在那里了
       再一次读取游戏进度, 移动<管毅>接近敌人点[绝招], (当时存档中的敌人为<周治>)
       光标停在:    00405EB4 . E8 925D0300       call    0043BC4B
       还是刚才的位置, 看来绝招伤害计算与物理伤害计算有关
       按F8 单步步过call指令, 执行到:    00405EB9 . 8B4D FC       mov   ecx, dword ptr [ebp-4]
       看寄存器窗:
       EAX  0000001F            ; 函数(0043BC4 的返回值, 等于十进制: 31
       接着F9 运行游戏, <管毅>对敌方武将放出[苍龙过阵枪], 打出37 点的伤害
       看来是对物理攻击伤害值进行加成计算了

       好, 按ALT + B打开[断点窗口]删除所有断点, 并将光标停在:
       00405EC5 . 89848A 84000000     mov   dword ptr [edx+ecx*4+84], eax
       这一行, 按F2下断点, 移动<管毅>接近敌人点[绝招], (当时存档中的敌人为<周治>)

       光标停在:    00405EC5 . 89848A 84000000     mov   dword ptr [edx+ecx*4+84], eax
       看寄存器窗:
       EAX   0000001E
       ECX   00000000
       EDX   004927F0   WaGan.004927F0
       EBX   00000000
       ESP   0022FD60
       EBP   0022FD7C
       ESI   00242360
       EDI   FFFFFFFF
       EIP   00405EC5   WaGan.00405EC5
       现在要算一下表达式:  edx+ecx*4+84 的结果是多少
       OLLYICE界面下方[Command]命令行输入: 004927F0+00000000*4+84
       回车后显示:  HEX: 492874  -  DEC: 4794484  -  ASCII: I(t
       点数据窗, CTRL + G 在[输入要在数据窗口中跟随的表达式]对话框中输入: 492874
       00492874  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
       全部是0, 是未初始化数据?? 暂时不知道
       按F7 单步步入下一条指令, 光标停在:    00405ECC . 8B45 FC      mov   eax, dword ptr [ebp-4]
       点数据窗, CTRL + G 在[输入要在数据窗口中跟随的表达式]对话框中输入: 492874
       00492874  1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ...............
       注意前四字节的值改变为:  1E 00 00 00; 由于是机器码实质为: 00 00 00 1E, 等于十进制: 30
       由于猜测是对物理攻击伤害值进行加成计算, 这样我们可以试着在00492874 处设置内存写入断点
       (注:  2)

       注:  2. 可以对数据或代码设置内存访问断点、内存写入断点, 还可以设置硬件断点, 但硬件断点最多
            只可以设置四个(想详细了解建议看书或者看使用说明)

       点数据窗的1E位置, 右键 ==> 断点 ==> 内存写入(W)
       F9 运行游戏, 游戏停在:    00405F5F  89848A 84000000    mov  dword ptr [edx+ecx*4+84], eax
       看反汇编代码:
       00405F38  8B55 FC             mov   edx, dword ptr [ebp-4]
       00405F3B  81E2 FF000000       and   edx, 0FF
       00405F41  8B45 F4             mov   eax, dword ptr [ebp-C]
       00405F44  8B8490 84000000     mov   eax, dword ptr [eax+edx*4+84] ; 刚才存放物理伤害的地方
       00405F4B  6BC0 03             imul  eax, eax, 3                   ; 取出物伤*3后存入EAX
       00405F4E  99                  cdq                                 ; EAX符号扩展至EDX
       00405F4F  2BC2                sub   eax, edx                      ; EDX貌似总为0
       00405F51  D1F8                sar   eax, 1                        ; 算术右移1位, 符号位不变
       00405F53  8B4D FC             mov   ecx, dword ptr [ebp-4]
       00405F56  81E1 FF000000       and   ecx, 0FF
       00405F5C  8B55 F4             mov   edx, dword ptr [ebp-C]
       00405F5F  89848A 84000000     mov   dword ptr [edx+ecx*4+84], eax ; 将加成后的物伤保存回原位
       按F7 单步步入下一条指令, 光标停在:    00405F66   8B45 F4     mov  eax, dword ptr [ebp-C]
       看数据窗:
       00492874  2D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  $...............
       等于十进制:  45
       F9继续运行游戏, <管毅>对敌方武将放出[苍龙过阵枪], 打出45 点的伤害
       点数据窗的2D位置, 右键 ==> 断点 ==> 删除内存断点(M)
       总结:  原绝招伤害 = 物理攻击伤害 * 3 / 2
              要修改绝招伤害, 只要修改00405F4B 处开始的指令即可





       现在我想修改绝招伤害计算使之与双方武力相关, 并且重新定义计算方法
       首先就要获取双方武力
       参考周瑜的《曹操传exe部分函数功能》, 获取函数功能和入口信息
       0040709A      ; 获取ECX武将的武、统、智、敏、运, 并乘2,跟据08栈值0~4
                     ; 这个函数最值得注意
       按ALT + B打开[断点窗口]删除所有断点
       点反汇编窗口, CTRL + G, 在[输入要跟随的表达式]对话框中输入: 0040709A
       这时光标停在:    0040709A  /$  55      push    ebp
       信息面板提示:    本地调用自   0041DE40, 0041DE80, 0041DEC0, 0041DF00, 0041DF40
       点反汇编窗口, CTRL + G, 在[输入要跟随的表达式]对话框中输入: 0041DE40
       这时光标停在:    0041DE40 |. E8 5592FEFF    call  0040709A
       这里是一个函数内镶调用:
       0041DE30 /$  55            push    ebp
       0041DE31 |.  8BEC          mov     ebp, esp
       0041DE33 |.  51            push    ecx
       0041DE34 |.  894D FC       mov     [local.1], ecx
       0041DE37 |.  8B45 08       mov     eax, [arg.1]
       0041DE3A |.  50            push    eax                ; 0C栈是什么, 接下来会分析
       0041DE3B |.  6A 00         push    0                  ; 跟据解释, 08栈为0时则获取武力值
       0041DE3D |.  8B4D FC       mov     ecx, [local.1]     ; ECX输入参数是什么, 接下来会分析
       0041DE40 |.  E8 5592FEFF   call    0040709A           ; 当时我没看到周瑜的这个函数, 搞到
                                                             ; 从SetDlgItemInt 这个API开始跟踪..
       0041DE45 |.  8BE5          mov     esp, ebp
       0041DE47 |.  5D            pop     ebp
       0041DE48 \.  C2 0400       retn    4

       下断点于:    0041DE40 一行, 再按F9运行游戏
       在战场武将<管毅>上点鼠标右键时, 游戏暂停下来, 再按F7单步步入
       执行到:    0040709B |. 8BEC      mov   ebp, esp
       看堆栈:
       0022FCC8  /0022FCDC    ; EBP      原EBP值
       0022FCCC  |0041DE45    ; EBP+4    CALL 指令返回地址, 返回到 WaGan.0041DE45
       0022FCD0  |00000000    ; EBP+8    获取武力值
       0022FCD4  |00000001    ; EBP+0CH

       再看寄存器窗:
       ECX   00D60000         ; 传入参数, 暂时不知是什么, 貌似为指针或者基地址
       点数据窗, CTRL + G 在[输入要在数据窗口中跟随的表达式]对话框中输入: 00D60000
       00D60000   00 10 00 00 00 00 00 00 B9 DC D2 E3 00 00 00 00    .......管毅....
       00D60010   00 3B 00 47 00 44 00 3B 00 3D 00 00 88 00 00 00    .;.G.D.;.=..?..
       00D60020   2A 2A 31 2D 2A 2B 00 02 00 00 00 00 06 3B 17 01    **1-*+.....;
       00D60030   2F 26 02 13 FF FF FF B9 DC D2 E3 00 00 00 00 00    /&

用户名时间功绩理由
赵辉 2009-12-8 22:39 +60 教程帖奖励




当前时区 GMT+8, 现在时间是 2025-2-15 08:01
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.013238 second(s), 6 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP