首页
论坛
课程
招聘
[原创]unity3d手游破解(三)--基于inline hook
2018-4-25 01:46 16317

[原创]unity3d手游破解(三)--基于inline hook

2018-4-25 01:46
16317
再分享一个,目标APK--风之旅X,挺好玩的。
一、前言
有的时候unity3d的解密函数被保护起来,因此这里提供一套基于inline hook的方案来实现破解,当前这个APK的Assembly-CSharp.dll是加密的,如下图所示,而且在libmono.so的mono_image_open_from_data_with_name的函数上下文找了几圈都没找到解密函数。


二、思路
首先,APK的所有dll都是通过 libmono.so的mono_image_open_from_data_with_name的函数加载的,输入的是原始的dll,返回的时候解密后的dll,因此我们通过hook这个函数来实现dll的dump和替换,把修改过的dll替换掉原来的实现破解。

三、Hook
首先获取 libmono.so的基址,这里我们通过读maps来获取,再从IDA里面找到 mono_image_open_from_data_with_name的偏移0x196C4C,相加得到函数的地址,然后把该函数hook到我们自己的new_game_proxy函数,在new_game_proxy函数里面实现dll的dump和替换。
 


这个APK上只有ARM的so,因此我们做arm的inline hook,把目标函数的前两条指令,替换成跳转指令( ldr pc,[pc,#-4] )+跳转地址( new_game_proxy 函数),实现跳转到 new_game_proxy 函数,替换之前先把指令保存到缓存g_OrigCode_game_proxy数组。

接着再在 g_OrigCode_game_proxy中添加跳转回原函数的指令: 跳转指令(ldr pc,[pc,#-4])+跳转地址(原函数+8),最后把 g_OrigCode_game_proxy的内存设置可执行,在 new_game_proxy函数中调用 g_OrigCode_game_proxy就回到原函数继续执行了。



mono_image_open_from_data_with_name 函数的返回结构如下图所示

其中raw_data就是解密dll的内存,raw_data_len就是dll的大小,在 new_game_proxy函数中把dll dump到/data/local/tmp/目录中,如果这个目录已经存在Assembly-CSharp.dll就把该dll加载替换原来的dll。剩下的就是对dll的修改了。


四、加载so
把APK中的dex拉出来反编译,找到com.silverera.sao.YHGameActivity的smali,把加载so的代码插进去,回编译替换回去。再把上面的hookso放进APK的lib目录,重打包APK。


hookso被加载之后会开一个线程等待libmono.so完成加载再hook,至于为什么不直接先加载libmono.so,再加载hookso直接hook的原因后面会说。


五、修改dll
把解密后的dll拉出来,用reflector打开,找关键函数,通常要经过各种尝试和修改才能找到合适的函数。这里展示一个我之前改过的函数吧,在这个游戏里面ChangeSP是释放技能消耗魔法的函数,因为这个游戏技能是没有CD的,但是魔法很少,放不了几个技能。把 ChangeSP函数直接return,然后就不掉魔法,所以可以无限技能。


有一个问题就是用reflector反编译过的dll替换回去是加载不了的,原因我还没找到,因此我们只能手动修改二进制来实现破解,不过也不复杂,用IDA打开 Assembly-CSharp.dll,查找ChangeSP函数,可以看到这个函数的地址是0x19c994,用UltraEdit打开 Assembly-CSharp.dll定位到这个地址,把第一个字节改成0x2A,也就是ret,替换回去就实现了无限技能。还有无敌、秒杀之类的有兴趣的可以自己摸索一下。


六、彩蛋
运行的时候查看HOOK日志,发现我们要hook的 mono_image_open_from_data_with_name函数居然还被其他人hook过,original code日志显示的应该是 mono_image_open_from_data_with_name的前8个字节,但是这里变成了ldr pc,[pc,#-4]+0x14d038d0,跟下面我们的hook一样,地址不同。


跟踪一下地址0x14d038d0,发现这个地址位于libexecdll.so。


用IDA打开 libexecdll.so,发现是ijiami的,应该是ijiami把解密函数保护起来了。之前hook太快导致程序崩溃,所以我们先让ijiami hook,然后我们再hook。


七、结束语
hookso的源码放在附件。下图是我把怪物的攻击和血量都改成1。


[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

最后于 2019-2-2 10:47 被admin编辑 ,原因: 图片本地化
上传的附件:
收藏
点赞0
打赏
分享
最新回复 (26)
雪    币: 5708
活跃值: 活跃值 (385)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
cqzhou 活跃值 2018-4-25 08:51
2
0
学习了LZ厉害
雪    币: 82
活跃值: 活跃值 (101)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
RorschachL 活跃值 2018-4-25 09:39
3
0
看着加密好像是爱加密的,就是一个查表
雪    币: 462
活跃值: 活跃值 (630)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
gtict 活跃值 2018-4-25 09:53
4
0
ijm这样保护多low,,用了几年的技术
雪    币: 756
活跃值: 活跃值 (1124)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
sonyps 活跃值 2018-4-25 13:28
5
0
应该改写CLR虚拟机,另外创造一种字节码
雪    币: 5462
活跃值: 活跃值 (227)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
nsec 活跃值 2018-4-25 14:21
6
0
顶礼膜拜,楼主可以否介绍一下某讯的游戏呢。
雪    币: 631
活跃值: 活跃值 (508)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huluxia 活跃值 2018-4-25 18:57
7
0
已经密切关注楼主。必须顶顶
雪    币: 500
活跃值: 活跃值 (425)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
茅山小僧 活跃值 2018-4-28 09:45
8
0
大佬搞UE4吗,出篇教程呗
雪    币: 6817
活跃值: 活跃值 (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
聖blue 活跃值 2018-4-28 23:20
9
0
雪    币: 13
活跃值: 活跃值 (165)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_时间 活跃值 2018-4-29 16:14
10
0
很牛
雪    币: 1034
活跃值: 活跃值 (76)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yikuaiyingbi 活跃值 2018-4-29 19:16
11
0
牛!
雪    币: 133
活跃值: 活跃值 (309)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
koflfy 活跃值 1 2018-5-1 10:28
12
0
不错不错,学习了。。
雪    币: 301
活跃值: 活跃值 (385)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天边之云 活跃值 2018-5-2 00:26
13
0
大佬,我找了好久,没找到解密代码,请问,能具体说一下么,再次拜谢
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无能为力 活跃值 2018-5-15 21:09
14
0
厉害哥
雪    币: 5059
活跃值: 活跃值 (482)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
战马 活跃值 2018-5-19 15:51
15
0
大佬用什么编译器编译的myhook.so,  我用r17版的ndk,编译提示"arithmetic  on  a  pointer  to  void",就是  mono_func  +=  0x190A7C;计算libmono.so基址+  mono_image_open_from_data_with_name偏移量这行报错了.
雪    币: 5059
活跃值: 活跃值 (482)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
战马 活跃值 2018-5-19 15:52
16
0

编译提示
雪    币: 2694
活跃值: 活跃值 (77)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
BlackJZero 活跃值 2018-5-19 19:14
17
0
雪    币: 0
活跃值: 活跃值 (108)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
godofrock 活跃值 2018-5-20 22:25
18
0
where dll decrypt?
雪    币: 5059
活跃值: 活跃值 (482)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
战马 活跃值 2018-5-21 19:38
19
0
搞好了,这里有个错误,,得加上
result = (_MonoImage*)retValue;这行才行,搞了好久.如果编译器提示我上面说的那个错误的话,mono_func += 0x196C4C;改为mono_func = (char*)mono_func + 0x190A7C;就可以了.还有注意,我红米note4x运行这个代码失败,闪退(打印出来的hook地址和hook之前的地址相差非常远,估计是小米系统so库加载方式不一样吧),用模拟器运行没问题.
雪    币: 5708
活跃值: 活跃值 (385)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
cqzhou 活跃值 2018-5-21 20:44
20
0
楼上是用NDK  build的嘛
雪    币: 0
活跃值: 活跃值 (108)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
godofrock 活跃值 2018-5-21 20:52
21
0
战马 搞好了,这里有个错误,,得加上result = (_MonoImage*)retValue;这行才行,搞了好久.如果编译器提示我上面说的那个错误的话,mono_func += 0x196C4C;改 ...
thanks
雪    币: 3496
活跃值: 活跃值 (512)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
smartdon 活跃值 1 2018-5-22 10:40
22
0
学习
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Rhined 活跃值 2018-10-10 19:35
23
0
学习了+1
雪    币: 654
活跃值: 活跃值 (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
miyuecao 活跃值 2018-12-12 16:09
24
0
厉害厉害,学习下思路
雪    币: 209
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
布丁 活跃值 2019-12-25 17:04
25
0
dll攻击改成返回1浮点数 游戏会闪退
游客
登录 | 注册 方可回帖
返回