吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9624|回复: 35
收起左侧

[Android 原创] 某apk破解之利用异步回调机制实现软件注册的分析(1)

  [复制链接]
killer5 发表于 2015-7-26 15:20
新人刚接触android逆向,请多多包涵!今天分析了一款apk,apk作者利用异步回调机制来实现该apk的注册,该注册机制实现的思路是很新颖的,并且在分析的过程中还出现了点小惊喜。
下面我将以软件注册机制初探、注册机制系统分析和破解之法进行详细讲解。
注意:本文仅用于移动安全的研究,勿用于非法用途,由此带来的后果与本文作者无关。如果感觉好用,请支持正版,毕竟软件作者也是不容易的。

下面将以第一视角来讲解第一部分
-----------------------------------------------

          一        软件注册机制初探
-----------------------------------------------
初次拿到该apk,安装。
1.PNG
如果点击设置皮肤,则会弹出需要激活对话框,提示需要50的积分。
2.PNG
点击关于对话框,其中会提示“免费版”和“移除广告”等,点击购买付费版,则会提示购买和授权等
3.PNG

4.PNG

5.PNG

看到这里,我想该软件的注册流程大家应该熟悉了吧。如果不清楚,可以看我上一篇文章《某APK注册机制分析与多思路破解方法》,在此就不啰嗦了。
进入正题......
看到这,破解的思路:如果搞到正式版本,那么相应的功能限制便会一一解除。
载入JEB,找到AboutActivity类(看名字就知道对应的正是关于对话框)中的oncreate()方法,如下:
[Java] 纯文本查看 复制代码
public void onCreate(Bundle arg11) {
        this.requestWindowFeature(1);
        super.onCreate(arg11);
        this.setContentView(2130903040);
        Log.d("tt", "onCreate");
        this.a = s.a(((Activity)this));
        this.e = new bf(((Activity)this));
        this.a();
        this.findViewById(2131361792).setOnClickListener(new g(this));
        this.findViewById(2131361794).setOnClickListener(new i(this));
        this.findViewById(2131361796).setOnClickListener(new j(this));
        this.findViewById(2131361797).setOnClickListener(new k(this));
        this.findViewById(2131361798).setOnClickListener(new l(this));
        this.findViewById(2131361799).setOnClickListener(new m(this));
        View v0 = this.findViewById(2131361802);
        View v1 = this.findViewById(2131361803);
        View v2 = this.findViewById(2131361804);
        View v3 = this.findViewById(2131361805);
        View v4 = this.findViewById(2131361807);
        View v5 = this.findViewById(2131361808);
        ((ImageView)v0).setOnClickListener(new r(this, String.valueOf("http://pocket.ndtv.com.cn:1086/others/")
                 + "BlessSmsFree.apk"));
        ((ImageView)v1).setOnClickListener(new r(this, String.valueOf("http://pocket.ndtv.com.cn:1086/others/")
                 + "Foyin.apk"));
        ((ImageView)v2).setOnClickListener(new r(this, String.valueOf("http://pocket.ndtv.com.cn:1086/others/")
                 + "Flashlight.apk"));
        ((ImageView)v3).setOnClickListener(new r(this, String.valueOf("http://pocket.ndtv.com.cn:1086/others/")
                 + "KnotGuideFree.apk"));
        ((ImageView)v4).setOnClickListener(new r(this, String.valueOf("http://pocket.ndtv.com.cn:1086/others/")
                 + "Geomancy.apk"));
        ((ImageView)v5).setOnClickListener(new p(this));
    }

首先看最底下的6个点击事件注册函数,其中传入了BlessSmsFree.apk、Foyin.apk、Flashlight.apk、KnotGuideFree.apk、Geomancy.apk等,
再回头看上面第三张图,这几个点击事件正好对应图中最下面五款apk的安装。
因此,购买付费版的点击事件注册函数应该是
[Java] 纯文本查看 复制代码
this.findViewById(2131361799).setOnClickListener(new m(this));

接着来到class m(作者对类名做了混淆)类的点击事件函数:
[Java] 纯文本查看 复制代码
public void onClick(View arg6) {
        DialogInterface$OnClickListener v4 = null;
        if(AboutActivity.c(this.a).o()) {
            new AlertDialog$Builder(this.a).setMessage("您已购买付费版,谢谢您的支持!").setPositiveButton("知道了", v4)
                    .show();
        }
        else {
            new AlertDialog$Builder(this.a).setMessage("5元升级为永久无广告无限制的付费版,格机或刷机后均无需再次付费(点击“授权”即可)。目前可以通过支付宝在线支付。\n账号:[email]fengyun2108@163.com[/email]\n户名:谢文杰\n付款界面请按照以下信息填写:\n—————————————\n汇款金额:5元\n汇款说明:"
                     + this.a.getSystemService("phone").getDeviceId() + "\n" + "—————————————" + "\n"
                     + "付费成功后隔天点击“授权”即可升级为付费版。确定吗?").setNegativeButton("取消", v4).setNeutralButton("授权", 
                    new n(this)).setPositiveButton("付款", new o(this)).show();
        }
    }

看到此处,我想应该就是找到关键点了吧。该函数的流程为:
点击购买付费版->首先检测是否已购买付费(是,则弹出提示购买成功的对话框)->否则会提示上面第四张图的内容
另外,如果点击第四张种的“授权”,则会提示图5的内容(其中会提示,授权失败,但是付款成功,请等待一段时间后,重试),提示的内容可能大家有个疑问,既然付款成功了,怎么还没授权呢。那是因为该apk在付款成功后,作者会在服务器端进行处理,然后才能返回是否可以授权,因此不管付费成功与否,都会这样提示,最后根据服务端传回的信息,判断是否真的可以授权。


那我们该怎么破解呢,当然是在最初判断那里做文章了,如下代码所示的位置。
[Java] 纯文本查看 复制代码
 if(AboutActivity.c(this.a).o()) {
            new AlertDialog$Builder(this.a).setMessage("您已购买付费版,谢谢您的支持!").setPositiveButton("知道了", v4)
                    .show();
        }

来到0()方法,如下:
[Java] 纯文本查看 复制代码
public boolean o() {
        return this.o;
    }


其中返回的值为s类的  private boolean o; 一个布尔型。
如果使该值为true,那不就注册成功了吗
查看S类,可以看到在a(Activity arg14)和h(boolean arg1)中有赋值操作,分别如下:
[Java] 纯文本查看 复制代码
public static s a(Activity arg14) {
        s v0 = new ce().a(arg14);
        if(v0 == null) {
            v0 = new s();
            v0.a("0");
            v0.b("0");
            v0.g(true);
            v0.h(false);
            v0.c("");
        }
......
        return v0;
    }

----------------------------
[Java] 纯文本查看 复制代码
public void h(boolean arg1) {
        this.o = arg1;
    }


可以看出,应该在public static s a(Activity arg14)函数中,在函数内部首先新建了一个ce类,并调用了其a()方法,如下:
[Java] 纯文本查看 复制代码
s v0 = new ce().a(arg14);

来到ce类的a()方法,如下:
[Java] 纯文本查看 复制代码
 public s a(Activity arg3) {
        s v0_2;
        try {
            FileInputStream v0_1 = arg3.openFileInput("config.xml");
            this.a = new bi();
            v0_2 = this.a.a(((InputStream)v0_1));
        }
        catch(Exception v0) {
            Log.e("XML", v0.getMessage());
            v0_2 = null;
        }

        return v0_2;
    }

其中新建了bi类,并调用了该类的a()方法,来到bi类的a()方法,如下:
[Java] 纯文本查看 复制代码
public s a(InputStream arg6) {
        XmlPullParser v2 = Xml.newPullParser();
        v2.setInput(arg6, "UTF-8");
        s v0 = null;
        int v1 = v2.getEventType();
    label_8:
        if(v1 == 1) {
            return v0;
        }

        switch(v1) {
            case 0: {
                goto label_14;
            }
            case 2: {
                goto label_16;
            }
        }

        goto label_12;
    label_16:
        if(v2.getName().equals("result")) {
            v2.next();
            v0.a(v2.getText());
            goto label_12;
        }

        if(v2.getName().equals("activedSkins")) {
            v2.next();
            v0.b(v2.getText());
            goto label_12;
        }

        if(v2.getName().equals("showWelcome")) {
            v2.next();
            v0.g(Boolean.parseBoolean(v2.getText()));
            goto label_12;
        }

        if(v2.getName().equals("payVersion")) {
            v2.next();
            v0.h(Boolean.parseBoolean(v2.getText()));
            goto label_12;
        }

        if(!v2.getName().equals("removeAdDate")) {
        }
        else {
            v2.next();
            v0.c(v2.getText());
            goto label_12;
        label_14:
            v0 = new s();
        }

    label_12:
        v1 = v2.next();
        goto label_8;
        return v0;
    }

看到这,应该明白了吧,这一系列函数会读取config.xml文件,根据该文件中payVersion标签位置的值,设置s类的布尔型变量o,然后购买时,会根据该布尔值,判断是否支付过,最后在说明一点public static s a(Activity arg14)函数其实是在AboutActivity类的oncreate中调用的,如下:
[Java] 纯文本查看 复制代码
public void onCreate(Bundle arg11) {
        this.requestWindowFeature(1);
        super.onCreate(arg11);
        this.setContentView(2130903040);
        Log.d("tt", "onCreate");
        this.a = s.a(((Activity)this));

整个流程如下:
6.PNG

到此,你是否认为只需要pull回来config.xml文件,然后修改payVersion标签为true,再push回去,就可以了。
那我们可以试试,如下:
文件在config.xml /data/data/xwj.calculator/files目录下
7.PNG


那pull回来看看内容,
8.PNG
修改为true后,push回去看看,如下:
9.PNG

然后,再点击“关于”看看
10.PNG
试试功能是否都能解禁,换个皮肤看看
11.PNG

到此,你是否觉得的已经成功破解了呢?
答案是否定的,因为作为文章来说,异步回调机制实现软件注册我还没有讲解,不可能这样就结束的。

重启软件看看有什么效果,
12.PNG




看到没“非法正式版用户”,关于中又显示为免费版了
原因是作者利用异步回调机制来实现软件的注册和非法用户检查的。
接下来,我们继续讲解------柳暗花明之注册机制系统分析


由于文章有点长,第二部分的内容和破解之道,我会放到下篇文章中讲解。










点评

更新的链接呢,亲爱的,看来学会查询代码的方法和引用很重要哟~  发表于 2017-5-2 22:31

免费评分

参与人数 8威望 +1 热心值 +8 收起 理由
叠噢 + 1 感谢发布原创作品
睡觉做梦 + 1 我很赞同!
caleb110 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
Monitor + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
powerjiang + 1 已答复!
qtfreet00 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
Super817 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
奔放的青春 + 1 已经处理,感谢您对吾爱破解论坛的支持!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
稚柚 发表于 2015-7-26 15:25
提示: 作者被禁止或删除 内容自动屏蔽
syrmb 发表于 2015-7-26 15:52
好厉害~期待来点脱壳的教程 现在apk几乎都是加固的了
光彩影 发表于 2015-7-26 17:07
小米粥吖 发表于 2015-7-27 13:22
谢谢楼主分享
Monitor 发表于 2015-7-27 14:06
很不错,喜欢这种分析。一系列的话可以创建一个导航帖
caleb110 发表于 2015-7-27 14:12
向楼主学习,多谢楼主分享!
封神之剑 发表于 2015-7-27 14:40
这是个什么软件呀
古今第一 发表于 2015-7-27 14:55 来自手机
学习了。。。
古子熙 发表于 2015-7-27 14:55
我们需要你
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 07:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表