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