飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2421|回复: 8

[Android] Frida对iTime签名校验分析

[复制链接]
  • TA的每日心情
    开心
    2021-12-6 12:14
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2021-12-1 10:32:36 | 显示全部楼层 |阅读模式
    本帖最后由 正己 于 2021-12-1 10:36 编辑

    1.iTime7.5.10
    2.jadx-gui
    3.MT管理器
    4.算法助手
    5.Frida




    早上注册邀请码没成功,只能发个帖子(呜呜呜),帖子很水,各位大佬轻喷。@Rooking 感谢R版大佬
    一、算法助手定位
    1.老规矩,直接签名看看是否有签名校验,果不其然,闪退!
    2.算法助手打开拦截应用退出和防止应用闪退
    3.运行软件,触发闪退,打开算法助手查看日志,看第一个触发的,接着根据堆栈调用去搜索



    二、jadx-gui静态分析
    1.定位到onCreate方法代码如下:
    [Java] 纯文本查看 复制代码
    public void onCreate() {
            int i2;
            super.onCreate();
            j0 j0Var = j0.f22466a;
            String V = com.blankj.utilcode.util.w.V(com.blankj.utilcode.util.c.r());  // r方法的值赋给字符串V
            k0.o(V, "encryp>真美妙5ToString(signatureMd5)"); //md5加密一次
            byte[] bytes = V.getBytes(f.f26826a);
            k0.o(bytes, "(this as java.lang.String).getBytes(charset)");//再base64加密
            if (!k0.g(new C().s(), Base64.encodeToString(bytes, 0))) {  //比较不通过就闪退
                System.exit(0);  
            }
            SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
            String string = defaultSharedPreferences.getString(getString(R.string.key_pref_ui_mode), com.wisdom.ticker.util.s.x);
            com.blankj.utilcode.util.b.d(getResources(), 375);
            if (string == null) {
                i2 = -1;
            } else {
                i2 = Integer.parseInt(string);
            }
            com.wisdom.ticker.util.n0.e.h(i2);
            a aVar = f20953a;
            aVar.n(new com.wisdom.ticker.service.f());
            aVar.j(new com.wisdom.ticker.service.c());
            aVar.k(new com.wisdom.ticker.service.d());
            f20955c = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), a.f20974a);
            g = j0Var.h(this);
            y.f22622a.f(this);
            SharedPreferences sharedPreferences = getSharedPreferences(com.wisdom.ticker.service.core.g.a.f21353b, 0);
            k0.o(sharedPreferences, "getSharedPreferences(AppConfig.SHARED_NAME, Context.MODE_PRIVATE)");
            aVar.l(sharedPreferences);
            z.f22624a.j(this);
            AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
            m.f22482a.c(defaultSharedPreferences.getBoolean(com.wisdom.ticker.service.core.g.a.I, true));
            DBBox.INSTANCE.init(this);
            com.wisdom.ticker.service.core.h.a.f21364a.d().o(this);
            if (defaultSharedPreferences.getBoolean(com.wisdom.ticker.service.core.g.a.q, true)) {
                for (Moment moment : i.f21294a.u()) {
                    LogUtils.l("升级计时:" + moment.getName() + '-' + moment.getTime() + '-' + moment.getSolarDate());
                    moment.setNeedUpdate(true);
                    i.H(i.f21294a, moment, false, 2, null);
                }
                defaultSharedPreferences.edit().putBoolean(com.wisdom.ticker.service.core.g.a.q, false).apply();
            }
            com.wisdom.ticker.util.o0.b.j(this);
            com.wisdom.ticker.util.o0.b e2 = com.wisdom.ticker.util.o0.b.e();
            k0.o(e2, "createInstance()");
            e2.a(new com.wisdom.ticker.util.m0.c()).a(new com.wisdom.ticker.util.m0.e()).a(new j()).a(new com.wisdom.ticker.util.m0.d()).a(new com.wisdom.ticker.util.m0.i()).a(new g()).a(new com.wisdom.ticker.util.m0.f());
            if (!defaultSharedPreferences.getBoolean(com.wisdom.ticker.service.core.g.a.A, true)) {
                e2.a(new h());
                h0.f22453a.d(this);
            }
            e2.n();
            e2.b();
            org.koin.core.d.a.c(new c(this));
            f.b.a.c h1 = f.b.a.c.h1();
            LogUtils.D("启动耗时:" + p0.P0(h, h1).k0() + 's');
            if (!defaultSharedPreferences.contains(f.j)) {
                defaultSharedPreferences.edit().putLong(f.j, h1.e()).apply();
            }
        }

    ​
    2.总的来说,就是先获取r方法的值,然后MD5加密一次,接着base64加密,最后和C类里的s方法的值进行对比,如果不相等就触发System.exit(0);3.跟进一下r方法,代码如下:
    [Java] 纯文本查看 复制代码
    private static String q(String str, String str2) {
            Signature[] p;
            if (!k1.A0(str) && (p = p(str)) != null && p.length > 0) {
                return k1.l(k1.j0(p[0].toByteArray(), str2)).replaceAll("(?<=[0-9A-F]{2})[0-9A-F]{2}", ":$0");
            }
            return "";
        }
    &#8203;
        public static String r() {
            return s(i1.a().getPackageName());  //获取包名信息传入s方法
        }
    &#8203;
        public static String s(String str) {
            return q(str, "MD5"); //MD5加密
        }
    &#8203;
    4.很明显r方法的返回值就是包名信息的MD5,这个可以直接用MT查看,当然我们也可以用Frida验证一下


    三、Frida动态Hook
    1.编写hook代码
    [JavaScript] 纯文本查看 复制代码
    function hookTest(){
        var money = Java.use("com.blankj.utilcode.util.c");
        money.r.implementation = function(){      
            var retval = this.r();
                    console.log("r方法的返回值",retval);  
                    return retval;
        }
    }
    &#8203;
    function main(){
        Java.perform(function(){
            hookTest(); //执行的方法
        });
    }
    &#8203;
    setImmediate(main);
    2.启动Frida并挂起apk(注意这里要用原版的apk!!!)
    3.查看hook结果:84:19:59:BE:9D:B3:72:E5:A1:42:90:9D:92:E1:AC:61
    和MT查看的一致
    4.接下来,我们再跟进一下C类里的s方法,是不是如我们所想的一样。一看是native方法,拖出对应的libitime.so,ida加载
    5.方法很少,直接定位到s方法
    6.这里读取了一串很可疑的字符串:RDFBRUE3NTUyMUIxMjk0MjhFMjE2Q0EzNTU4RjJGNjk=7.双击字符串发现跳转到.rodata段(只读数据段)
    8.根据我们前面的猜测,获取r方法的值,然后MD5加密一次,接着base64加密。
    9.结果一致,看样子我们的猜测没有错。由于是只读数据段,所以我们只能修改dex中的内容,把r方法的返回值写死即可,代码如下:
    [Java] 纯文本查看 复制代码
    .method public static r()Ljava/lang/String;
        .registers 1
    &#8203;
        .line 1
        const-string v0, "84:19:59:BE:9D:B3:72:E5:A1:42:90:9D:92:E1:AC:61"
    &#8203;
        return-object v0
    .end method

    &#8203;
    10.运行测试,正常不闪退!

    &#8203;

    评分

    参与人数 3威望 +11 飘云币 +21 收起 理由
    飘云 + 5 + 10 周年作品奖励!
    飞天 + 1 + 1 PYG有你更精彩!
    Rooking + 5 + 10 庆祝飘云阁论坛成立17周年!欢迎来稿

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2021-12-6 12:14
  • 签到天数: 5 天

    [LV.2]偶尔看看I

     楼主| 发表于 2021-12-1 10:35:20 | 显示全部楼层
    新人占个沙发
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    4 小时前
  • 签到天数: 116 天

    [LV.6]常住居民II

    发表于 2021-12-1 10:48:29 来自手机 | 显示全部楼层
    欢迎正己大佬来到这
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-12-1 09:04
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2021-12-1 11:06:08 | 显示全部楼层
    学习了新知识
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2023-3-11 15:00
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    发表于 2021-12-1 11:07:58 | 显示全部楼层
    大佬我来了
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2023-3-11 15:00
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    发表于 2021-12-1 11:10:49 | 显示全部楼层
    跟着大佬的脚步造安卓
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2021-12-1 11:49:20 来自手机 | 显示全部楼层
    跟着大佬混,三天饿九顿,偶尔还要挨钢棍;
    饿成霹雳琵琶骨,瘦成冻人白骨精,错被大圣当妖怪,一棍闪了腰,两棍挫了骨,三棍灭了魂。
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-3-25 15:21
  • 签到天数: 487 天

    [LV.9]以坛为家II

    发表于 2021-12-1 12:43:51 | 显示全部楼层
    庆祝飘云阁论坛成立17周年!欢迎来稿
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 19:29
  • 签到天数: 1401 天

    [LV.10]以坛为家III

    发表于 2021-12-1 17:23:56 | 显示全部楼层
    感谢分享教程经验。
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

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