昨夜星辰恰似你 发表于 2020-2-9 17:02

2020春节红包第三题算法静态分析

本帖最后由 昨夜星辰恰似你 于 2020-6-23 10:02 编辑

## java层
首先把apk拖到jeb或者其他java反编译工具查看

可以看到onClick和checkFlag是native方法
## so层
看下init段有没有初始化函数

知道so加载的时候**init_array数组**中的函数会先于**jni_onload**方法执行,原理就去看看安卓**linker**源码吧(不熟悉安卓)
看到定义了一个**sub_4DF0**函数

初始化了一些全局变量就没了,基本没啥用,忽视

看jni_onload函数

很多**符号和全局变量**我都做了重命名,方便理解
其中函数**sub_6A04**作用是**初始化和创建**后面需要用到的j一些**java类**

这些符号我都做了对应的重命名
其实上面说的**这些和解出这道题关系不大**,只是刚接触安卓为了搞懂这些东西的作用

看onclick方法

获取了编辑框输入然后调用checkFlag方法验证

checkFlag算法首先把下面这个字符串分为三个部分
```
thisiskey52pojie_2020_happy_chinese_new_year20200125
```
用伪代码表示
```
StringBuilder s1=new StringBuilder("thisiskey");
StringBuilder s2=new StringBuilder("52pojie_2020_happy_chinese_new_year");
StringBuilder s3=new StringBuilder("20200125");
```



然后利用s2和s3计算出另一个中间字符串
具体算法是循环35次,每次循环取一个字符,如果本次计数器是能被4整除就从s3中亦或取字符,如果不是就s2中取字符
```
for (int i=0;i<35;i++){
    if ((i%4==0)&&(i!=0)){
      int index=((i>>2)-1);
      System.out.println(i);
      char c=s3.charAt(index);
      tmp1.append(c);
    }else {
      tmp1.append(s2.charAt(i));
    }
}
```








最后计算tmp1的md5值,注意的是并不是已经转换成16进制字符串的32位字符MD5,而是经过md5运算得到的长度为16的byte数组,然后把md5字节数组和s1字符串取余亦或得到16字节的数组,在转换成32位16进制字符串T,取中间第二位到倒数第二位字符串,也就是T共30位字符串和输入字符串比较

完整Java代码如下
```
static void PrintHex(byte[] buff){
      System.out.print("char data[]={");
      for (int i=0;i<buff.length;i++){
            System.out.printf("0x%x,",buff^0xFF);
      }
      System.out.print("}\n");
    }

    static void ctf(){
      StringBuilder s1=new StringBuilder("thisiskey");
      StringBuilder s2=new StringBuilder("52pojie_2020_happy_chinese_new_year");
      StringBuilder s3=new StringBuilder("20200125");
      StringBuilder tmp1=new StringBuilder();

      for (int i=0;i<35;i++){
            if ((i%4==0)&&(i!=0)){
                int index=((i>>2)-1);
                System.out.println(i);
                char c=s3.charAt(index);
                tmp1.append(c);
            }else {
                tmp1.append(s2.charAt(i));
            }
      }

      System.out.println(tmp1.toString());

      try {
            byte[] buff=tmp1.toString().getBytes();
            System.out.println(buff.length);
            MessageDigest md5=MessageDigest.getInstance("MD5");
            byte[] md5Bytes=md5.digest(buff);
            System.out.println(toHex(md5Bytes));
            byte[] s1_bytes=s1.toString().getBytes();
            for (int i=0;i<md5Bytes.length;i++){
                md5Bytes^=s1_bytes;
            }
            PrintHex(md5Bytes);
            PrintHex(s1_bytes);
            System.out.println(toHex(md5Bytes));
            System.out.println(toHex(md5Bytes).substring(1,31));
      }catch (Exception se){
            se.printStackTrace();
      }
    }
```

这道题就是用**了java2C**,Java层逻辑全部用**NDK**实现而已,如果有**调试设备**完全可以不用逆向什么算法,一步到位,**动态跟踪也行,hook也行**,因为最后出现了**明文比较**,算是这道题比较弱的地方。可惜回家没有带安卓调试机器,电脑上也没有安卓开发环境(懒得去折腾了),不然可以写**xposed 插件+VirtulXposed免Root**搞定,还是太菜了,刚学安卓,环境什么的折腾起来太费劲了

Hmily 发表于 2020-2-10 20:15

@昨夜星辰恰似你 我发现你传的图还是有问题,别用md的代码展现图片,用discuz直接点击的方式展现图片,不然传的图过段时间缓存没了就失效了,你看这个方式贴图:https://www.52pojie.cn/misc.php?mod=faq&action=faq&id=29&messageid=36

昨夜星辰恰似你 发表于 2020-2-9 17:35

gunxsword 发表于 2020-2-9 17:33
第三题没搞定,KEY也看到了,也看出了和MD5有关,就是中间算法没看明白,动态调试也试了,但是第一次IDA动态,也 ...
动态调试的话,你可以跟踪到最后比较的地方,有明文,或者直接hook equal函数

梦游枪手 发表于 2020-2-9 17:26

我也是静态看出来的,那天刚好没办法调试,不过第四题就只能调试分析了{:1_909:}

昨夜星辰恰似你 发表于 2020-2-9 17:28

梦游枪手 发表于 2020-2-9 17:26
我也是静态看出来的,那天刚好没办法调试,不过第四题就只能调试分析了

第四题真的。。。静态看半天,啥都看不出来,调试设备又没有&#128514;&#128514;难受,老哥,等你的文章{:1_893:}

赌狗人生丶 发表于 2020-2-9 17:29

感谢分享哈哈哈            

gunxsword 发表于 2020-2-9 17:33

第三题没搞定,KEY也看到了,也看出了和MD5有关,就是中间算法没看明白,动态调试也试了,但是第一次IDA动态,也不是很会,最终失败!

Hmily 发表于 2020-2-9 17:42

尾部几个图是多的?

昨夜星辰恰似你 发表于 2020-2-9 17:50

Hmily 发表于 2020-2-9 17:42
尾部几个图是多的?
是的,当时写md不会贴图,传了几个附件试试,忘了删除{:1_909:}

zs823455667 发表于 2020-2-9 17:57

感谢大佬分享^_^~~~~

johnwen 发表于 2020-2-9 18:02

感谢大佬,我不会,只能为你加油了
页: [1] 2 3 4 5 6 7 8 9
查看完整版本: 2020春节红包第三题算法静态分析