2017年陕西省网络空间安全技术大赛·Mobile T5

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转化

int a=031; //8进制,以数字0开始 int b=0x1B; //16进制,以0x开始


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

猜你喜欢

转载自blog.csdn.net/guchenjun789/article/details/79605447