2018腾讯游戏安全技术竞赛Android 组决赛第一轮

本博客由闲散白帽子胖胖鹏鹏胖胖鹏潜力所写,仅仅作为个人技术交流分享,不得用做商业用途。转载请注明出处,禁止未经许可将本博客内所有内容转载、商用。

“横看成岭侧成峰,远近高低各不同”

——苏轼

        大家好,紧张的游戏安全竞赛结束了,虽然结果还没有揭晓,但是我已经迫不及待的想和大家分享我的做题思路(其实是我记性不好很容易忘记,赶紧写下来)。

吾爱破解的WriteUp链接:https://www.52pojie.cn/forum-77-1.html

0x00 これは何ですか        

        拿到题目,直接运行,发现屏幕上只有一个箭头,顺着箭头的方向拖动几下,嗯?有一些杂乱无章的方块。这时我意识到,这里杂乱无章的方块应该就是FLag,这下子可难住我了,从来没有接触过,也没有试过写3d图形界面。但是,通过分析代码就应该能够找到线索,之后顺藤摸瓜,就知道怎么做了。得嘞,咱们先解包再说。

0x01 NativeActivity初探

        按照惯例,把APK拖到jadax,结果发现啥都没有!仔细翻了翻,还是一点有用的代码都没有!脑子中飘过无数的反调试、反反编译技术,后来定了定神,我们不还是有一个so嘛。把so拖到IDA,搜索关键字“Java”一般native方法都会有这个关键词,结果还是啥都没有!再搜索“Activity”关键字,总算是见到了“AnativeActivity”。不太懂这是什么,先google一下。看了看资料才知道,原来是native方法,用c++写的activity,感觉自己Android开发学的并不扎实这里坑了下。参考着[1][2]学习了下NativeActivity的开发和代码。具体的加载流程我们就不赘述了,建议先看完这两篇参考文献再看下面内容。我们先追到ANativeActivity_onCreate函数,这也是我们的程序入口。对这前面两篇文章的代码,自己一点点标记函数。


        其他的函数我们不用关系,红框中标记的内容就是处理消息、绘制窗口的函数线程。我们继续跟进这个函数,这个函数主要就是一些配置环境、创建消息队列之类的工作,其中有一个我们比较关心,就是处理各种消息的线程,我们也称之为app_main。把android_app_entry这个函数也贴一下。


        红框中就是我们需要的app_main函数,这个函数主要是不断地在消息循环里面抓取消息进行处理,或者做其他事情,直到控制退出,最终Activity随着Apk一起退出。那么他到底是做了什么呢?

扫描二维码关注公众号,回复: 1103853 查看本文章


        可以看到他用ALooper_pollAll抓取时间,然后丢给sub_30098函数去处理,跟进去一看,我的乖乖这函数可不得了,这么长,其中还有很复杂的计算。看了看调用的第一个函数glClearColor,百度一下,OpenGL?哈,看来找对了。

0x10 OpenGL和EGL初探

        虽说自己知道OpenGL是用来渲染2D、3D图像的,但是自己也没学过。看了下OpenGL和EGL的科普[3],还是有点不懂,不过也无所谓,代码在那里,先找找教程看看有没得什么可对照的,这一找可不要紧,教程[4]里面写的清清楚楚,看了看函数,再看了看资源,基本上一模一样啊,就这样把函数标记了一下。


        OpenGL里面有局部空间、世界空间、观察空间、裁剪空间,对应的有三个矩阵模型矩阵、观察矩阵、投影矩阵。这几个名词在我提供的教程中已经有很详尽的叙述,我拿一个正方体举例。假设正方体贴近地面、正对着你的那面的左下角为坐标原点(0,0,0),那么该面右下角的点坐标就是(1,0,0),以此类推。也就是说,我们正方体模型的所有顶点都在这个局部空间内,也就是相对于我们物体来说,是局部的;那么我们构建的世界不可能只有一个正方体,而这个正方体也可能在任意位置、任意朝向,放我们把他放到世界里的时候,这就是世界空间。而我们从局部空间变换到世界空间的这个过程,是模型矩阵帮我们完成的;观察空间,就是我们的视角(也成为摄像机)能够看到的内容,我们刚刚存储在世界空间里面的物体,需要经过一些变换,这个变换是观察矩阵完成的;最后不在我们视角范围内的物品需要裁减掉,这就是裁剪空间。裁剪的过程由投影矩阵帮我们完成。我上文说过,他应该是通过旋转视角挡住了Flag那么我们旋转回去就行了。旋转摄像机,我们需要修改观察矩阵(view)。上图红框内容就设置view矩阵,v65指向的就是view矩阵。

0x11 教练,我想看到Flag

        其实要做的很简单,找到旋转镜头的方式,逆向推回去,然后重新设置view矩阵就好撒。但是我懒!我很懒!我不想看代码!那直接修改也好的嘛。使用IDA动态调试下APK,看到了view矩阵,改动确实很大,想动态修改IDA却不提供这个功能,这就让我十分怀念OD,怀念在x86下面搞逆向的日子(误)。此路不通,就只能patch so咯,之前自己没做过,正好也尝试下。还是上一张图里面的代码,看看v65被sub_30F14修改了,我们直接跳到这个函数里面,直接设置我们想要的view矩阵的值。这里推荐一个小工具Arm汇编转换工具[5],可知写汇编,然后直接转成二进制的机器码,超级方便。我们要修改的矩阵是这样的

view[0]~view[3]:0.01599892        0.0        0.0        0.0
view[4]~view[7]:   0.0     0.02299991        0.0        0.0
view[8]~view[11]:  0.0            0.0    0.002999958    0.0
view[12]~view[15]: 0.0            0.0      -9.000000  1.000000

        都是float数据,我一时也不知道什么比较好的转换工具,个人比较喜欢用Python,就用python的pack函数做了float to Hex的转化,这个挺简单的,可以百度出来。修改过程,就是不同的MOV R0,#view_value;STR R0,view[x]。就这样,一个值一个值的存储进去,最后别忘了删掉原来函数中修改view矩阵数值的部分。这里不建议之间删除机器码,因为文件长度、函数位置都会改变,直接改成0x00 00 nop掉就好。放几张修改时的汇编代码。

修改之前:


修改之后:


        patch之后使用apktool重打包、重签名、再安装。最终看到了Flag。


参考文献:

[1] https://blog.csdn.net/ldpxxx/article/details/9253369

[2] https://blog.csdn.net/jscese/article/details/51005447

[3] https://blog.csdn.net/lewif/article/details/50946236

[4] https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/

[5]  https://bbs.pediy.com/thread-195634.htm

猜你喜欢

转载自blog.csdn.net/zhuzhuzhu22/article/details/80306203