0x00前言
由于第四题较直接,一个md5的比较,fa3733c647dca53a66cf8df953c2d539通过md5查询解密出来是monkey99,
然后真码就是monkey99了。这个第五题是混淆。理清逻辑还是不算难的。
0x01java代码分析
1.没有apk文件,只有一个jar文件
【补充:JFrame是指一个计算机语言-java的GUI程序的基本思路是以JFrame为基础,它是屏幕上window的对象,能够最大化、最小化、关闭】
拖进jd-gui查看java代码
首先来到MANIFEST.MF文件,看到Main-Class,也就是程序的入口类
【补充:MANIFEST.MF:这个 manifest 文件定义了与扩展和包相关的数据。单词“manifest”的意思是“显示”】
2.找到关键判断函数
3.进入\u2111\u210C\u2133方法
发现好多unicode码混淆眼睛,不急,从头往下分析,比如\u548C\u548A解析不了,把它当成input,方法上面两个A-Z的String 命名为str1和str2,然后代码就明朗很多。
我在SublimeText中修复完以后代码是这样的
这里注意一下,arraycopy是java自带的方法,这里它用自己写的System类重写了arraycopy方法,第一次被骗了,呵呵
4.跟踪arraycopy
跟到了System类中的arraycopy方法,发现它调用了Start类中的main方法(真够混淆的,又是system又是main)
跟进main方法,这main非比main,正常的主函数是public static void main(String[] args) 这样的
仔细一看,返回值是String类型,那么x就是最终赋值,直接copy到Eclipse中计算就好啦,然并果,又遇到问题
5.修复乱码问题
其实在jd-gui翻译过来的vȾ¤ÊʬÆÆÊv̤ʲʲÀΤ¨¸¬是真确的字符串,复制到了Eclipse中成了乱码,OMG,How come?
不行,拿出我强大的JEB 1.5工具
ok,看到ascii码了,but,怎么有300多的,不是应该0-255吗,于是我经过失败的尝试,然后百度,哦,八进制
举个栗子,小写v,十进制118,八进制变成166,所以不解释了
放上IDA反汇编代码,下面绿色的就是那个字符串的ascii部分,v已经被转化
拿到Eclipse中操作一下
百度了一下八进制用\0表示,十六进制用\x表示,ascii转字符用char转化
ok got it
6.计算出0x01-3中的通过arraycopy()计算得到的str1,JsnatterrtJuaththovacke
7.分析判断逻辑
别的支离破碎的函数去所在类一个个挖出来,最后做一个全局的分析,让verify的结果能返回true
8.追到真码
直接上java代码
public static void main(String[] args) {
verify("1234567890123456789");
}
public static String getStr1() {
String s ="v\\310\\276\\244\\312\\312\\254\\306\\306\\312v\\314\\244\\312\\262\\312\\262\\300\\316\\244\\250\\270\\254" ;
int[] num = {0166,0310,0276,0244,0312,0312,0254,0306,0306,0312,0166,0314,0244,0312,0262,0312,0262,0300,0316,0244,0250,0270,0254};
String str = "";
for(int i = 0; i<num.length; i++) {
str += (char)num[i]; //修复后的乱码
}
String x = "";
char[] arrayOfChar;
int j = (arrayOfChar = str.toCharArray()).length;
for (int i = 0; i < j; i++)
{
int $ = arrayOfChar[i];
x = x + (char)(($ >> 1) + 15);
}
return x; //arraycopy计算结果字符串返回
}
public static boolean verify(String input)
{
if ((input != null) && (input.length() == 19))
{
//str1 = System.arraycopy(str2, 0, str1, 5, 5); //http://blog.csdn.net/catroom/article/details/51840580
String str1 = getStr1(); //so str1 = "ABCDEZYXWVKLMNOPQRSTUVWXYZ"
boolean keyGuessWrong = true;
int k = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++) {
if (input.charAt(k + j) != str1.charAt(func(k + j, str1))) {
keyGuessWrong = false;
System.out.print(str1.charAt(func(k + j, str1)));
}
}
k += 5;
}
return keyGuessWrong;
}
return false;
}
public static int func(int paramInt1, String paramString1)
{
return re(paramInt1) % paramString1.length();
}
private static int re(int paramInt1)
{
if (paramInt1 > 2) {
return re(paramInt1 - 1) + re(paramInt1 - 2);
}
return 1;
}
追到真码{sssntrtktceaakJr}
这里还有个陷阱,就是input == 19,这里的sssntrtktceaakJr分割下是15位
要用-分割,sssn-trtk-tcea-akJr,15+4=19,我们的爱情到这,...。
还是分析一下吧:
外部for意思是循环4次,内部for意思是每次外部循环内比较四次
第一轮比较0、1、2、3位,然后k = 5
第二轮比较5、6、7、8位,然后k = 10
...
input[4]和input[9]正好就是分隔符-。
int k = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++) {
if (input.charAt(k + j) != str1.charAt(Start.func(k + j, str1))) {
keyGuessWrong = false;
}
}
k += 5;
}
0x02总结
今天分析应该挺到位的,从理清入口类,判断关键比较方法,跟踪方法,修复混淆代码,明清混淆方法名,结合ascii转化为字符,在Eclipse中模拟java代码比较部分,拼接出真码。OVER
前些日子有点懈怠了,还是不要为琐事烦恼先,每日进步一点,多注重结果。2018年3月18日 23:34:49