首页
社区
课程
招聘
[原创]IOS游戏辅助--QQ欢乐斗地主记牌器的实现
发表于: 2014-4-3 16:05 37547

[原创]IOS游戏辅助--QQ欢乐斗地主记牌器的实现

2014-4-3 16:05
37547

叉叉助手是目前做得比较好一款手机游戏辅助的工具.(官网地址:http://www.xxzhushou.cn),里面集成了不少的游戏辅助,包括微信游戏的天天系列,还有COC,我叫MT等等一些游戏的辅助. 其实这些游戏辅助实现的方式,都大同小异,都是挂钩了几个关键函数,然后做一些适当的修改和记录,来达到辅助的目的.

   最近分析了一下叉叉助手中的QQ欢乐斗地主的记牌器,抛砖引玉,和大家一块探讨下IOS/Android游戏辅助的分析和实现.

1. Cydia Substrate
    使用 TheOS 做越狱开发的同学,肯定都知道 Cydia Substrate 这个东西,其实所谓的 Substrate 就是类似Windows上的Hook框架(Detours,MHook),提供了一套标准的Hook函数: MSHookFunction,MSHookMessage,MSFindSymbol 等等给大家使用. 根据官网的介绍,这套框架不仅支持IOS,而且还支持Android平台. 游戏辅助的开发者,也是期望能迅速开发,所以也是会利用Substrate来实现的. 所以我们分析游戏辅助插件的时候,只需要紧紧盯着这几个 MSHook** 的函数,就能迅速定位到关键所在.

2. 获取二进制文件
    AppStore下载QQ欢乐斗地主,使用iTools,将名为QQHLDDZ的文件导入到电脑上. 同样下载好叉叉助手,安装好欢乐斗地主记牌器插件,然后使用itools,从 MobileSubstrate\DynamicLibrary 目录下获取 xxHLDDZPlugin.dylib.

3. 反汇编 xxHLDDZPlugin.dylib
   使用IDA Pro 或者 Hopper 打开 xxHLDDZPlugin.dylib. 对 MSHookFunction 函数查找引用,我们会发现在一个名为 sethook()的函数里面会调用MSHookFunction(), 使用Hopper的伪代码功能可以看到:


提醒下Hopper的伪代码功能不是特别好用,仅供参考(还有就是Hopper的反汇编识别函数的能力也比IDA Pro 弱太多了). 所以这里只看到 MSHookFunction() 只调用了一次,看看sethook()的汇编,这里应该是调用了两次 MSHookFunction().

所以 sethook()里面的实现应该是:
MSHookFunction(_offset_new_add + module_base ,func_hook_xx_new_add,&func_orig_xx_new_add)
MSHookFunction(_offset_new_start + module_base,func_hook_xx_new_start,&func_orig_xx_new_start)


根据 MSHookFunction() 函数的定义:
void MSHookFunction(void*function,void* replacement,void** p_original);
所以第一个参数就是我们要hook的函数.找到第一个参数 _offset_new_add和 _offset_new_start定义的地方,我们会看到:
_offset_new_add =  0x004b2b68;
_offset_new_start = 0x004f0978;

这里记牌器插件使用的 Offset + 基地址 来动态获取函数的地址,然后再进行Hook.

4. 反汇编 QQHLDDZ
  使用IDA Pro 或者 Hopper 打开 QQHLDDZ,然后跳转到那两个offset.

  对于 _offset_new_add = 0x004b2b68; 我们能看到一个名为: “__ZN12XOutCardCtrl14AddNormalCardsEjPhjj”的函数,Hopper 伪代码如下,从函数名猜测下这个 XOutCardCtrl::AddNormalCards,应该是记录了每个玩家的出牌.


  对于 _offset_new_start = 0x004f0978; 我们也能看到一个名为: “ __ZN8XGameMgr11OnGameStartEv “的函数, Hopper伪代码如下,同样从函数名看到,这个函数 XGameMgr::OnGameStart,应该是表示新一轮游戏的开始.


5. 分析待Hook函数的定义
从上面我们可以看到函数的定义,XOutCardCtrl::AddNormalCards函数有4个参数,但是无法得知每个参数的具体用途,这里就需要自己去分析和调试了,过程比较琐碎和需要耐心,这里就不仔细叙述了.

具体定义如下:
int AddNormalCards(void* self, int player,unsigned char* cards,int count);
第一个参数  self,是 self 指针.
第二个参数 player,是int 类型,表示的每个玩家的编号. 范围是 0 - 2 (实际调试发现,我自己是2,左玩家是 0 ,右玩家是 1)
第三个参数 cards, 是个 unsigned char类型数组,用来记录玩家每次出的牌.
第四个参数 count, 用来表示 参数3 cards 数组的大小,也就是出牌的数量.

int XGameMgr::OnGameStart()
无参数,用来表示每次牌局的开始.

6. 实现记牌器
使用TheOS 创建一个 Tweak 工程. 在Tweak.xm 里面添加我们自己的代码.
%ctor
{
    initPokerTable();
     MSHookFunction((void*)MSFindSymbol(NULL,"__ZN12XOutCardCtrl14AddNormalCardsEjPhjj"),(void*)my_newadd,(void **)&orig_newadd);
     MSHookFunction((void*)MSFindSymbol(NULL,"__ZN8XGameMgr11OnGameStartEv"),(void*)my_newstart,(void **)&orig_newstart);
}

initPokerTable(); 初始化了一个NSMutableArray的全局变量,名为PokerTable,里面存储了从 黑桃A 到 大王 的 54 张扑克牌,方便我们查看调试信息.
MSHookFunction(),会调用MSFindSymbol()函数来查找原始函数的地址.
为什么使用MSFindSymbol(),而不是使用xx记牌器里面的 module_base + offset 的方式,其实尝试了使用 offset 这种硬编码的方式,但是很容易造成程序崩溃,多次尝试下,还是改为MSFindSymbol()函数,这个函数的实现其实是查找Mach-o文件格式的symbol表,然后获得函数地址. 这个和Windows 里面查找PE文件的 Import(Export) Address Table 函数的方式类似. 所以这种方式更加稳定可靠.

my_newadd()函数只是打印了每一轮牌局(GameRound),每个玩家(Player) 出的牌. (也就是实现了记牌器的功能.)
int my_newadd(void* self, int player,unsigned char* cards,int count)
{
     for(int i = 0; i < count; i++)
     {
          NSLog(@"GameRound%d:player%d:%@",Round,player,[PokerTable objectAtIndex:cards[i] - 1]);
     }
     NSLog(@"GameRound ---------------------------------------");
     return orig_newadd(self,player,cards,count);
}

my_newstart()函数,会对 Round 变量递增,然后打印信息,表示新一轮游戏开始了.
int my_newstart()
{
     Round++;
     NSLog(@"GameRound%d begin!",Round);
     return orig_newstart();
}

7. 查看调试输出
在 terminal 输入 make package install,对工程编译打包,并发送到设备上.
再 ssh root@你的IP. 到设备上.
然后你开始玩一局QQ欢乐斗地主,
然后在teminal上输入 grep GameRound /var/log/syslog   (注意,请安装好syslogd插件) 会看到如下的调试信息:



这里,你能清楚的看到每个玩家所出的牌. 这样我们就实现了一个记牌器所需要的核心功能.

8. 总结
其实上面的调试输出只是一个简单的演示罢了,要做成产品给用户使用,还需要像叉叉助手一样,在QQ欢乐斗地主那,添加自己的subview,然后再绘制控件,再将信息展现给用户,还有很多事情需要完善.
再说说其他游戏辅助插件的分析原理,其实分析和这个类似.按照这个思路一步一步耐心分析,就能实现同样的功能了.
再补充一下Android平台,叉叉助手的Android平台其实也是使用同样的技术,和上面的分析大同小异.
最后,此文抛砖引玉,还希望各位朋友对此不吝赐教! ( 欢迎各位同仁交流和认识)

Author: coltor
Email(QQ): coltor#qq.com
交流群: 12399218 (欢迎各位童鞋加入讨论)


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (29)
雪    币: 2308
活跃值: (2200)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
2
勃起哥牛逼啊,过来学习下。
2014-4-3 16:29
0
雪    币: 6
活跃值: (1509)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我想说  开源的你  比那些坑爹的卖视屏教程   和搞实地 高尚的 没法子说了   泪牛满面的说  顶
2014-4-3 16:31
0
雪    币: 69
活跃值: (41)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
感兴趣的话,后面我有空会陆续把天天系列的游戏辅助,以及所谓的加速器也都开源了~
2014-4-3 17:00
0
雪    币: 129
活跃值: (2763)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
开源的都要围观系啊
2014-4-3 18:26
0
雪    币: 11111
活跃值: (158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
支持~~~
2014-4-3 19:16
0
雪    币: 269
活跃值: (906)
能力值: ( LV12,RANK:345 )
在线值:
发帖
回帖
粉丝
7
支持下,这年头想赚点外快必须是搞游戏了,之前一直不知道搞游戏如何赚钱直到前两天,一个人聊天人家是一个司机,闲暇之余写点外挂赚钱,这让我很震惊于是这几天程序也不写了,开搞hp
2014-4-3 20:05
0
雪    币: 6
活跃值: (1509)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
那是肯定要置顶啊   等你发布
2014-4-3 23:55
0
雪    币: 67
活跃值: (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
高手啊!!希望多分享点这方面的资料
2014-4-4 00:08
0
雪    币: 0
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
开源,必须支持阿。。。
2014-4-4 09:27
0
雪    币: 174
活跃值: (260)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
11
文章不错,读起来很舒服。调试有符号的程序那真是一件幸福的事啊。。。

我猜作者用ModuleBase+Offset的原因应该是不想轻易被模仿哈。
不过在无符号的情况下,这是唯一的选择。
2014-4-4 11:34
0
雪    币: 4320
活跃值: (3820)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
Dave 牛啊。
2014-4-4 13:33
0
雪    币: 2323
活跃值: (4113)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
13
支持,支持,谢谢分享
2014-4-14 11:05
0
雪    币: 42
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
支持开源
2014-4-14 13:55
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
留名并膜拜之
2014-4-14 14:50
0
雪    币: 2210
活跃值: (12)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
强顶留名,太强了, 顶, 期待后续的作品!
2014-4-14 21:56
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
好流逼的啊
2014-4-14 22:30
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
外挂这一块居然开源。。不得不顶啊
2014-4-15 01:06
0
雪    币: 85
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
太爽,好好看
2014-4-15 04:10
0
雪    币: 216
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
然后使用itools,从 MobileSubstrate\DynamicLibrary 目录下获取 xxHLDDZPlugin.dylib.
这个文件一直都找不到?是不是改名了?还是什么?我是5.1.1
2014-4-15 23:25
0
雪    币: 322
活跃值: (113)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
分析的太精辟了,期待后续之作,呵呵
2014-4-16 21:38
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
分析的好精彩,学习了,感谢~~~~
2014-4-23 16:37
0
雪    币: 210
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
这个要留个脚印
2014-5-8 18:16
0
雪    币: 4761
活跃值: (4184)
能力值: ( LV8,RANK:138 )
在线值:
发帖
回帖
粉丝
24
支持开源啊
2014-6-8 01:02
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
这个必须留名膜拜
2015-2-10 09:19
0
游客
登录 | 注册 方可回帖
返回
//