正己 发表于 2021-12-1 10:32:36

Frida对iTime签名校验分析

本帖最后由 正己 于 2021-12-1 10:36 编辑

1.iTime7.5.102.jadx-gui3.MT管理器4.算法助手5.Frida


早上注册邀请码没成功,只能发个帖子(呜呜呜),帖子很水,各位大佬轻喷。@Rooking 感谢R版大佬一、算法助手定位1.老规矩,直接签名看看是否有签名校验,果不其然,闪退!2.算法助手打开拦截应用退出和防止应用闪退https://zhengji666.coding.net/p/jiaochengtuchuang/d/img/git/raw/master/Screenshot_2021-09-27-22-01-09-919_com.png3.运行软件,触发闪退,打开算法助手查看日志,看第一个触发的,接着根据堆栈调用去搜索https://zhengji666.coding.net/p/jiaochengtuchuang/d/img/git/raw/master/IMG_20210927_214911.jpghttps://zhengji666.coding.net/p/jiaochengtuchuang/d/img/git/raw/master/IMG_20210927_214940.jpg

二、jadx-gui静态分析1.定位到onCreate方法代码如下: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方法,代码如下: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.toByteArray(), str2)).replaceAll("(?<={2}){2}", ":$0");
      }
      return "";
    }

    public static String r() {
      return s(i1.a().getPackageName());//获取包名信息传入s方法
    }

    public static String s(String str) {
      return q(str, "MD5"); //MD5加密
    }
​4.很明显r方法的返回值就是包名信息的MD5,这个可以直接用MT查看,当然我们也可以用Frida验证一下
三、Frida动态Hook1.编写hook代码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;
    }
}

function main(){
    Java.perform(function(){
      hookTest(); //执行的方法
    });
}

setImmediate(main);2.启动Frida并挂起apk(注意这里要用原版的apk!!!)https://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210927221654.png3.查看hook结果:84:19:59:BE:9D:B3:72:E5:A1:42:90:9D:92:E1:AC:61https://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210927235954.png和MT查看的一致https://zhengji666.coding.net/p/jiaochengtuchuang/d/img/git/raw/master/Screenshot_2021-09-28-00-04-12-826_bin.png4.接下来,我们再跟进一下C类里的s方法,是不是如我们所想的一样。一看是native方法,拖出对应的libitime.so,ida加载https://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210928000703.png5.方法很少,直接定位到s方法https://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210928000923.png6.这里读取了一串很可疑的字符串:RDFBRUE3NTUyMUIxMjk0MjhFMjE2Q0EzNTU4RjJGNjk=7.双击字符串发现跳转到.rodata段(只读数据段)https://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210928123638.png8.根据我们前面的猜测,获取r方法的值,然后MD5加密一次,接着base64加密。https://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210928123757.pnghttps://cdn.jsdelivr.net/gh/ZJ595/Picgo-img@main/img/20210928123838.png9.结果一致,看样子我们的猜测没有错。由于是只读数据段,所以我们只能修改dex中的内容,把r方法的返回值写死即可,代码如下:.method public static r()Ljava/lang/String;
    .registers 1

    .line 1
    const-string v0, "84:19:59:BE:9D:B3:72:E5:A1:42:90:9D:92:E1:AC:61"

    return-object v0
.end method
​10.运行测试,正常不闪退!https://zhengji666.coding.net/p/jiaochengtuchuang/d/img/git/raw/master/Screenshot_2021-09-28-14-12-25-084_com.png

正己 发表于 2021-12-1 10:35:20

新人占个沙发

怜渠客 发表于 2021-12-1 10:48:29

欢迎正己大佬来到这

littleWhiteDuck 发表于 2021-12-1 11:06:08

学习了新知识{:4_280:}

n1598k 发表于 2021-12-1 11:07:58

大佬我来了{:biggrin:}

n1598k 发表于 2021-12-1 11:10:49

跟着大佬的脚步造安卓

yuanyxh 发表于 2021-12-1 11:49:20

跟着大佬混,三天饿九顿,偶尔还要挨钢棍;
饿成霹雳琵琶骨,瘦成冻人白骨精,错被大圣当妖怪,一棍闪了腰,两棍挫了骨,三棍灭了魂。

Rooking 发表于 2021-12-1 12:43:51

庆祝飘云阁论坛成立17周年!欢迎来稿

飞天 发表于 2021-12-1 17:23:56

感谢分享教程经验。
页: [1]
查看完整版本: Frida对iTime签名校验分析