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**搞定,还是太菜了,刚学安卓,环境什么的折腾起来太费劲了 @昨夜星辰恰似你 我发现你传的图还是有问题,别用md的代码展现图片,用discuz直接点击的方式展现图片,不然传的图过段时间缓存没了就失效了,你看这个方式贴图:https://www.52pojie.cn/misc.php?mod=faq&action=faq&id=29&messageid=36 gunxsword 发表于 2020-2-9 17:33
第三题没搞定,KEY也看到了,也看出了和MD5有关,就是中间算法没看明白,动态调试也试了,但是第一次IDA动态,也 ...
动态调试的话,你可以跟踪到最后比较的地方,有明文,或者直接hook equal函数 我也是静态看出来的,那天刚好没办法调试,不过第四题就只能调试分析了{:1_909:} 梦游枪手 发表于 2020-2-9 17:26
我也是静态看出来的,那天刚好没办法调试,不过第四题就只能调试分析了
第四题真的。。。静态看半天,啥都看不出来,调试设备又没有😂😂难受,老哥,等你的文章{:1_893:} 感谢分享哈哈哈 第三题没搞定,KEY也看到了,也看出了和MD5有关,就是中间算法没看明白,动态调试也试了,但是第一次IDA动态,也不是很会,最终失败! 尾部几个图是多的? Hmily 发表于 2020-2-9 17:42
尾部几个图是多的?
是的,当时写md不会贴图,传了几个附件试试,忘了删除{:1_909:} 感谢大佬分享^_^~~~~ 感谢大佬,我不会,只能为你加油了