• qq四国军旗2.1 beat03 builde017记牌器开发思路(一)


    一、棋盘结构分析

    首先,根据存档文件找到棋子

    军旗:0x00000002
    地雷:0x00000003
    炸弹:0x00000004
    司令:0x00000005
    军长:0x00000006
    师长:0x00000007
    旅长:0X00000008
    团长:0X00000009
    营长:0X0000000A
    连长:0X0000000B
    排长:0X0000000C
    工兵:0X0000000D

    而 0表示无,1表示有,但是不知道是什么棋子。

    可以用CE找出棋盘结构的内存地址。在上紫色下蓝色的情况下,蓝色正左上角的地址是004991dc(也就是中间九格的左下。)

    用OD找到附近地址

    004991B4  00 00 00 00 08 00 00 00 02 00 00 00 00 00 00 00  ..............

    004991C4  0A 00 00 00 02 00 00 00 00 00 00 00 07 00 00 00  ..............

    004991D4  02 00 00 00 00 00 00 00 07 00 00 00 02 00 00 00  .............

    004991E4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

    004991F4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

    00499204  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

    加粗的07就是004991dc,而分析地址的连续性可以看出,这是一个数组,类型大小为12字节。应该是

    struct{
         int 
         int
         int 

    } ...

    这个第一个Int很明显是棋子,而第二个Int根据测试是表示颜色(00橘红色,01蓝色,02绿色,03紫色),第三个不知道是什么。这是在复盘中查看的数据,在实际对战中,除了自己家的棋子,其它的棋子都是1.

    二、如何进行记牌

    记牌的方式有3种,动态扫描内存、拦截API(替换CALL)和网络协议分析。对于图形识别方式的记牌不考虑,没啥意思。

    1、动态扫描内存
    这种思路最为简单,在内存中定义一个棋盘结果,单位时间内根据内存变化,来实现记牌。比如,在 某时刻,004992c0(蓝色一行3列)位置,师长叫吃004998df8(紫色一行3列),结果蓝色棋子消失(004992c0值为0),而紫色棋子还在(004998df8值为1),则004998df8处棋子为39+(军长以上,包括军长)。004992c0 +4值表示了颜色,004998df8+4值表示颜色。

    这种方式算法上比较复杂,效率也较低,在卡了的情况下要注意处理。这种方式太过简单,效果不太理想。

    2、拦截API(替换CALL)

    这种方式首先要分析,得出注入点,也就是找CALL。实现方式等同于网游内挂。对数据的识别也是采用内存读取,但是驱动方式改有游戏驱动外挂,而不是外挂去扫描游戏。难点在于找到CALL函数。四国军旗的棋子走动CALL比较难找,今天刚找,还没找到,汗~~~切入点在于数据。用CE监视内存004991dc,右键,查找写入该地址的代码:

    在0041e67e处下断点。开始调试调试,上下找一找,找到了播放音乐的call,汗。

    004115BD   /0F84 CA000000   JE JunQiRpg.0041168D

    004115C3   |68 88DE4500     PUSH JunQiRpg.0045DE88                   ; res\move.wav

    004115C8   |B9 A0CB4900     MOV ECX,JunQiRpg.0049CBA0

    004115CD   |E8 3E2F0100     CALL JunQiRpg.00424510

    004115D2   |8B4424 14       MOV EAX,DWORD PTR SS:[ESP+14]

    004115CD 这句,CALL JunQiRpg.00424510 就是播放音乐,换成c++就是

    void JunqiRpgCall::MovePlay(void)

    {

        DWORD address = 0x424510;

        __asm{

            pushad

            PUSH 0x45DE88                   //res\move.wav

            MOV ECX,0x49CBA0

            CALL address

            popad

        }

    拦截CALL呢就是要把这段汇编改掉,在汇编中实现跳转到自己的程序(在这里实现记牌),然后再跳回正常流程。(参考API注入)。

    3、网络协议分析

    这种难度很大,相当于自己实现客户端,原理等同于网游脱机外挂。就不讨论了。

  • 相关阅读:
    Python GUI编程(Tkinter)19、Frame控件
    Python GUI编程(Tkinter)18、Combobox下拉控件
    D
    C
    B
    A
    wordpress调用服务器本地的头像
    杂七杂八的问题处理03--jenkins发邮件提示Error sending to the following VALID addresses
    杂七杂八的问题处理02--allure报告显示loading问题
    vue一次下载多个文件
  • 原文地址:https://www.cnblogs.com/birdshover/p/1563371.html
Copyright © 2020-2023  润新知