1. 程式人生 > >2017年陝西省網路空間安全技術大賽·Mobile T5

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