zoukankan      html  css  js  c++  java
  • qq四国军旗2.1 beat03 builde017记牌器开发思路(二)

    接着前文《qq四国军旗2.1 beat03 builde017记牌器开发思路(一)》讲,暂时不讨论内存扫描和协议解析,先重点分析HOOK API。要HOOK API,就要找到API,API怎么找?上文已经找到了播放行进音乐的CALL,一个CALL可以理解为一个函数。那么走路的过程是同级调用,还是上级调用还是下级调用呢?

    先来解释下这个“级”的问题。先定义两个函数:
    void PlayMusic(){

          //这个编译完后,就是一个CALL,用来播放音乐的

    void DisplayMove(){

      //这个编译完后,就是一个移动的CALL

    所谓同级调用,那么就是

    bool FrameFunc(){

           PlayMusic();
           DisplayMove();

    而上级调用呢,就是在DisplayMove中调用了PlayMusic,下级调用就是PlayMusic调用DisplayMove。根据调试的步骤,同级的话,就在当前函数找;上级的话,就要返回,步出该函数;而下级就要切入进去。操作上不一样,所以这个很重要。OD里,如果是同级调用,那么就是按F8慢慢找;上级调用,就要CTRL+F9返回到上级函数;下级的话就要在PlayMusic CALL的地方按F7切入进去。当然,我们不知道是怎么调用的,可以用排除法,搞这个就是要有耐心,呵呵。

    首先是同级函数。

    00411540  /$  8B4424 04     MOV EAX,DWORD PTR SS:[ESP+4]

    00411544  |.  53            PUSH EBX

    00411545  |.  05 17FCFFFF   ADD EAX,-3E9                             ;  Switch (cases 3E9..3ED)

    0041154A  |.  55            PUSH EBP

    0041154B  |.  56            PUSH ESI

    0041154C  |.  83F8 04       CMP EAX,4

    0041154F  |.  57            PUSH EDI

    00411550  |.  8BD9          MOV EBX,ECX

    00411552  |.  0F87 DF010000 JA JunQiRpg.00411737

    00411558  |.  FF2485 401741>JMP DWORD PTR DS:[EAX*4+411740]

    0041155F  |>  8B83 10010000 MOV EAX,DWORD PTR DS:[EBX+110]           ;  Case 3E9 of switch 00411545

    上面的代码是同级函数的开头部分。可以看出,这是一个switch语句。在00411540处下断点,发现状态显示:

    堆栈 SS:[0012F240]=000003EC

    EAX=00000000

    本地调用来自 004267AE

    也就是说,这个函数是被上级函数在地址为004267AE的地方调用的。而一直按F9,发现,这是一个无限循环。使用框架开发游戏都知道,一般的游戏框架有两个无限循环。一个是用来更新数据的,做逻辑操作的,而另外一个是用来写屏幕的。那么,这个函数可以理解成HGE(C++ 2d 游戏引擎)里的FrameFunc,或者XNA(.Net的一个3D游戏开发框架)离得Update函数。那么这段代码的意思呢,就是相当于:
     bool FrameFunc(){

         switch()

              case 1:

                  break;

              case 2

                  break;

    在CASE1处,汇编代码

    0041155F  |>  8B83 10010000 MOV EAX,DWORD PTR DS:[EBX+110]           ;  Case 3E9 of switch 00411545

    的地方下断点,发现,确实是走动会触发断点。这就表明,已经找到了正确的地方,至于这个CALL是在这段代码里,还是在这段代码调用的方法的里面,就需要再去分析。

    开发游戏都知道,FrameFunc调用频率是跟FPS有关的,一般来说一秒钟最少要调用24次。case1的代码必然带有对多线程的处理方式,这就给分析带来了很大的难度。在0041155F处下断点后,按F9,发现这段代码不只执行一次,原理上和一个栈相似。 压入步骤,然后在RenderFunc里按步骤写入屏幕。

    在004976F4地址上记录了操作数,在

    0041158B  |> \A1 F4764900   MOV EAX,DWORD PTR DS:[4976F4]

    处被读取,操作数被赋予EAX。在0041155F 和0041158B之间没有任何CALL,这段代码很可能与我们要找的东西有关,当然在下面肯定也能找到。一个棋子从一个地方移动到另外一个地方,上面可能已经赋予了From什么地方,TO什么地方这样的形式,而下面是对路径进行分析。

    实际上我们要拿的数据也就仅仅是From和To这两个数据。为什么这两个数据这么重要?如果用扫描内存的方式来开发记牌器的话,就会遇到这种麻烦。但你的子吃敌方子而牺牲时,到底是吃的哪个子呢?这就是麻烦的地方。

  • 相关阅读:
    hadoop 3.0.0 alpha3 安装、配置
    集群使用初步
    转 mysql 中sql 语句查询今天、昨天、7天、近30天、本月、上一月 数据
    java 内存溢出
    获取手机上安装的应用信息
    使apk具有system权限
    Android基础之sqlite 数据库简单操作
    转 Android:文件下载和写入SD卡学习小结
    Android判断Service是否运行
    Android 定时重复启动弹出窗口。
  • 原文地址:https://www.cnblogs.com/birdshover/p/1563745.html
Copyright © 2011-2022 走看看