TA的每日心情 | 郁闷 2024-11-5 11:43 |
---|
签到天数: 293 天 [LV.8]以坛为家I
超级版主
- UID
- 5
- 元宝
- 3451
- 威望
- 528
- 贡献
- 130
- 信誉值
- 0
- 精华
- 0
- 在线时间
- 139 小时
- 注册时间
- 2014-1-11
- 最后登录
- 2024-11-5
- 违规
- 1
- 积分
- 1927
|
本帖最后由 1724663133 于 2019-5-2 00:16 编辑
一个安卓天文APP(Star Chart)的静态分析修改经验分享
不知不觉来论坛两年,一直都是伸手党,也没尝试过自己原创一些作品,因为上学的时候,觉得汇编还是觉得比较麻烦的,虽然基本语法确实不难,但是因为它和硬件底层关系太紧密,很多时候你不得不去了解一些硬件知识才能更好的编写你的程序,更何况是看别人写出来机器反汇编的东西,找不到关键,很多东西就很难进行下去。当然高级语言也有很多深水区,开始接触逆向主要是还是希望对得起自己的老师们,不至于把自己辛苦学习的知识丢的太久,总要有新的用武之地,不能只守着自己熟悉的业务代码过日子。
开场白扯远了,下面进入主题,今天我们主要讲静态分析,不涉及动态调试。就以我最近发布的软件来说吧。
我们来讲那款天文软件,这软件没混淆,源代码几乎透明,很适合如我一样的新人入门。
关于环境的搭建论坛有很多优秀的帖子,我就略去不说了,我这里用的是Androidkiller集成套件,以及反编译环境GDA最新4.64版本,GDA作用的是把中间码模拟成Java代码,在smali代码不太好读的情况下,帮我们理解整个工程流程。
首先我们把源码放入GDA看一下,我当初是一开始是想找验证类型方法,搜索Check、Verify等等关键词,发现只能找到谷歌框架的验证,改了之后直接闪退,而且谷歌框架的验证庞大而繁琐,要手动完全去掉是很耗时的。
于是我观察整个工程,发现居然有兑换码相关方法。代码如下:
- const/4 v0, 0x4,//4赋值给v0
- new-array v0, v0, [Lcom/escapistgames/starchart/xplat/AppDataNativeInterface$AppDataElementEnum;//
- //建立数据数组,上一句定义了v0=4,所以数组长度是4。
-
- const/4 v1, 0x0 //v1=0很明显是要给往数组里面存东西了。
-
- sget-object v2, Lcom/escapistgames/starchart/xplat/AppDataNativeInterface$AppDataElementEnum;->ExploreMode:Lcom/escapistgames/starchart/xplat/AppDataNativeInterface$AppDataElementEnum;
- //把相应的字段放入v2,注意看这个指向符号(指针)引用->ExploreMode:正是几个内购数据模型中的一个,这个字段可以替换为前面说过的内购数据类型中的任何一个,比如ExtendedSolarSystem。
复制代码 下一句:
- aput-object v2, v0, v1 //是把v2中的字段放到相应的数组元素当中,元素索引正是v1中的值,所以我们可以看到下面的语句是重复这几句,只是v1值不同而已。
-
- const/4 v1, 0x1
-
- sget-object v2, Lcom/escapistgames/starchart/xplat/AppDataNativeInterface$AppDataElementEnum;->BasicConstellationImages:Lcom/escapistgames/starchart/xplat/AppDataNativeInterface$AppDataElementEnum;
-
- aput-object v2, v0, v1
复制代码 我们这里要做两个工作,一是要把数组扩大,第二是要把缺少的内购项目仿照其他已存在语句加到兑换码类的初始方法中,就可以实现用兑换码一次兑换所有的内购项目了。
至于具体如何修改,如果你看懂了我的讲解,应该难不倒你了,就留给各位读者去思考吧。
上面我们只是解决了用兑换码解锁内购的问题,还有一个问题是这个App它有谷歌框架验证,如果我们要完整(如果用幸运破解器之类的去掉能成功,但是在有谷歌框架的机器中会闪退不能运行)去掉谷歌框架验证非常麻烦,但这个程序有一个好玩的地方,它可以修改支付类型绕过谷歌验证。先看在控制兑换码的类的下面的类中有一项明显的商店类型的说明:
- static void StoreType.<clinit>() //method@4269
- {
- StoreType.NONE = new StoreType("NONE", 0);
- StoreType.GOOGLE = new StoreType("GOOGLE", 1);
- StoreType.SAMSUNG = new StoreType("SAMSUNG", 2);
- StoreType.AMAZON = new StoreType("AMAZON", 3);
- StoreType.DUMMY = new StoreType("DUMMY", 4);
- StoreType.GOOGLE_EDUCATION = new StoreType("GOOGLE_EDUCATION", 5);
- StoreType[] v0 = new StoreType[6];
- v0[0]=StoreType.NONE;
- v0[1]=StoreType.GOOGLE;
- v0[2]=StoreType.SAMSUNG;
- v0[3]=StoreType.AMAZON;
- v0[4]=StoreType.DUMMY;
- v0[5]=StoreType.GOOGLE_EDUCATION;
- StoreType.$VALUES = v0;
- return;
- }
复制代码 你看它支持亚马逊、三星等支付类型。
搜索关键词check你会发现下列验证函数:
- public SCLicenseChecker PlatformSpecificObjects.GetLicenseChecker() //method@43e4
- {
- GooglePlayLicenseChecker v0;
- SamsungAppsLicenseChecker v0_1;
- switch (PlatformSpecificObjects$1.$SwitchMap$com$escapistgames$starchart$iaps$StoreType[this.meLicenseType.ordinal()]){
- case 1:
- v0 = new GooglePlayLicenseChecker(this.mxActivity);
- break;
- case 2:
- v0_1 = new SamsungAppsLicenseChecker(this.mxActivity);
- break;
- default:
- Log.e("StarChartBase", "No license checker found for this store type!");
- v0 = 0;
- }
- return v0;
- }
复制代码 很明显只有在支付方式是三星或谷歌的时候才会有验证,如果我们设置其他支付方式就可以绕过验证了。
那么支付类型在哪里修改呢?答案是在入口的onCreate方法。
- public void StarChart.onCreate(Bundle savedInstanceState) //method@4756
- {
- super.onCreate(savedInstanceState, StoreType.GOOGLE, StoreType.GOOGLE);
- return;
- }
复制代码 调用父类方法的时候,参数中指定了谷歌的支付方式,请你回头再看一下,上面的支付类型,经过观察工程和实际实验设置成 NONE是不行的,但设置成DUMMY(虚支付)是可行的。
至于如何修改smali文件,和上面相似,也是修改一个指向参数的指针,具体方法也留给读者自己去研究吧。
这就是今天的全部内容了,鄙人不才,其实是很简单的东西,对于逆向而言,找到关键点弄懂流程是最重要的,动态和静态都是如此。
|
|