Unity游戏逆向思路

拆弹专家,原谷歌游戏
downloadUrl:https://ww.lanzous.com/id06yjc(有广告版本)
本文只作为思路分享文章,无逆向成品,仅供学习交流
拿到apk首先还是解压一下看一下文件目录,看看游戏引擎

Unity游戏.png

这里就先借用一下Perfare大神的工具:Il2CppDumper
该工具用来分析so里面游戏逻辑的方法枚举,虽然没有函数体,但是通过函数名很大程度上还是可以帮助我们分析游戏的逻辑,工具很香,可以配合IDA使用,了解详情的可以自行查看GitHub文档
(7.2版本IDA直接去运行ida.py并加载script.json即可实现方法名的导入)

其次就是对反编译libil2cpp的dll文件可以使用Reflector或者dnSpy来查看(其实和查看dump.cs没有太大的区别,主要的差别在于使用Reflector可以直接去查看空命名空间的代码,过掉一些系统级别代码)

举例一下Reflector结合Frida的使用

Reflector示例.png

这里我们可以知道偏移地址(实际地址=基地址+偏移地址+ thumb指令?1:0))

  • showDilog() → 0x547484
  • showMessage() → 0x547F30

通过这种方式我们就可以轻松的批量断点我们希望断点的方法了
以下为一个简单的批量断点脚本示例:

function start(){
    //com.izyplay.defusethebomb.bazhang
    var arrayAddr = [0x54728C,0x547310,0x54745C,0x547DF8,0x547484,0x548218,0x547F30,0x55DF40
        ,0x679798,0x6798B4,0x687428,0x687350]; 
    var arrayName = ["AndroidDialog Create","AndroidDialog Create1","AndroidDialog init"
        ,"AndroidMessage Create","showDialog","CallStatic","showMessage","SetPressedState"
        ,"NativeDialog","NativeMessage","ToggleButton","OnClick"]; 
    
    var soAddr = Module.findBaseAddress("libil2cpp.so");
    console.error('\nsoAddr:' + soAddr + "\n");

    for (var index = 0; index < arrayAddr.length; index++) {  
        console.log("-------------------------");
        var currentAddr = soAddr.add(arrayAddr[index]);
        console.log('currentAddr:' + currentAddr);
        funcTmp(currentAddr,soAddr,index,arrayName);
        console.log("\t\t---->"+index,arrayAddr[index]+" is prepared ");  
    } 
    console.log("\n")
}

function funcTmp(currentAddr,soAddr,index,arrayName){
    Interceptor.attach(currentAddr, {
        onEnter: function(args){
            console.log("called : "+arrayName[index]+"  ----- addr : " + currentAddr.sub(soAddr) +"\n");
        },
        onLeave: function(retval){

        }
    });
}

已上是对so的一个简单处理分析
我们知道Unity游戏与Java的通信是通过UnitySendMessage()之类的函数来实现的
不同的代码可能写法不一样,但是这里注意几个关键词就是了
“Unity”,“Send”,“Message”,“Reward”,“Video”(拿到国内的谷歌游戏都是添加了广告的,自然是有一个video来展示广告,获取奖励Reward等等)自己排列组合,总能发现点东西

使用Jadx搜索关键字.png

随便点进去一个跟进代码不难发现其实最终就是去调用了Native方法




这里就不继续跟进了,回到初衷是要搞这个游戏的奖励
这里游戏原来的处理逻辑是点击观看广告视频,然后就可以成功获取奖励,上面说了,游戏与unity的通信是通过UnitySendMessage来实现的,这里我们只用再找到在哪里打开视频,打开视频看完了必然也会有一个成功回调,修改smali处理一下这个逻辑就搞定,于是我们又重新搜索关键字Reward,Video ... 发现如下

奖励获取.png

这里可以看到每种广告播放状态都向Unity发了一条消息(UnitySendMessage 是一个 public static方法),简单分析一下逻辑,成功后向Unity发的是什么消息,剩下的就是对这个smali为所欲为了

public static void UnitySendMessage(String str, String str2, String str3) {
        if (!m.c()) {
            f.Log(5, "Native libraries not loaded - dropping message for " + str + "." + str2);
            return;
        }
        try {
            nativeUnitySendMessage(str, str2, str3.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException unused) {
        }
    }

    const-string v0, "onRewardedVideoAdRewarded"

    const-string v1, "123"

    invoke-direct {p0, v0, v1}, Lcom/ironsource/unity/androidbridge/AndroidBridge;->sendUnityEvent(Ljava/lang/String;Ljava/lang/String;)V

至于以上我们是怎么找到这些关键点的话,我们还是使用我们的Frida大法,使用基于Frida的Objection来完成Class批量断点,非常好用,当然你也可以选择手写Frida批量下断脚本

Objection批量断点.png

想进行方法调用的测试,我们可以使用Frida的远程方法调用,静态变量值的获取等等

        Java.choose("com.ironsource.unity.androidbridge.AndroidBridge",{
            onMatch: function(obj){
               var ss = {"reward_amount":1,"placement_name":"DefaultRewardedVideo","reward_name":"Virtual Item"};
                obj.sendUnityEvent("onRewardedVideoAdRewarded","onRewardedVideoAdRewarded");
            },
            onComplete: function(){

            }
        });

        Java.choose("com.ironsource.mediationsdk.model.RewardedVideoConfigurations",{
            onMatch: function(obj){
                console.log("主动调用onRewardedVideoAdRewarded")
                var mRVPlacements = obj.mRVPlacements.value;
                console.log(mRVPlacements.size());
                console.log(mRVPlacements.get(0));
            },
            onComplete: function(){

            }
        });

最后来一个小tips:想不看广告只用对app重新签名就是,但是广告播放成功的回调自然也是失效了,所以还是需要稍微改改smali

以上就是这个Unity游戏的简单逆向过程

总结一下:
一般游戏逆向分为unity游戏,cocos游戏,或者一些自己写的游戏

unity主要可以看成两类,dll游戏和libil2cpp游戏,dll游戏比较简单,由于c#类似Js的语言特性,几乎就是可以明文随便篡改(dpy/),为了安全性的提升,所以才应运而生了libil2cpp用来转换dll to so ,但实际上逆向的时候使用ida分析libil2cpp的时候也差不多吧,有点汇编基础基本不难看懂,或者是结合frida去动态短点一些位置,或者是使用dwarf去动态调试一些位置,so我们只能修改不能新增指令,解决这个问题我们可以考虑用inlinehook完成新增。对于libil2cpp的情况,咋们可以用我分享的工具dps.py查找关键词函数,使用dpoint.js批量断点我们想查看的函数,动态断点方便我们快速找到想要hook的关键点后,使用inlinehook对其实现本地化为所欲为。对于一些自己写的游戏没有了dumper,但是我们可以考虑使用frida脚本枚举导出函数进行批批量hook,同时筛选函数名实现上述类似工作,至于cocos游戏也可以参照上述思路,咋们就简单分个类 cocos js 和 cocos lua,由于这篇文章主要介绍unity游戏,这里就不多说cocos,大概就这样哇 ~

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351