1. 程式人生 > >看雪ctf2017 |WP Ericky.apk

看雪ctf2017 |WP Ericky.apk

前言

看雪的ctf還是很有水平的,我這菜雞表示只能看看

分析

用jeb開啟,發現做了很噁心的混淆,汗顏。使用n鍵對變數重新命名。
這裡寫圖片描述
java層的分析我就不寫了,這題的考點在於so層演算法的分析以及指令的混淆。
ps:我幾乎用了一天的時間,去看這個check函式

去除指令混淆

要麼手動的patch要麼寫個指令碼去除,我看還是寫個指令碼吧,我剛開始手動patch,實在是太累了!!!

#include <idc.idc>

static main()
{
    auto i,pos,size,JMP_SIZE,FLOWER1_SIZE,FLOWER2_SIZE;
    pos
=0x286C; //START size=0x1A000;//SIZE JMP_SIZE = 0x40; FLOWER1_SIZE = 0x1e; FLOWER2_SIZE = 0x8; for ( i=0; i < size;i++ ) { //PATCH JMPS if ( (Byte(pos)==0x13)&&(Byte(pos+1)==0xe0)&&(Byte(pos+2)==0xbd)&& (Byte(pos+3)==0xe8)&& (Byte(pos
+4)==0xf0)&&(Byte(pos+5)==0x47)) { for(i=0;i<JMP_SIZE;i++) { PatchByte(pos+i,0x0);//change } HideArea(pos,pos+JMP_SIZE,atoa(pos),atoa(pos),atoa(pos+JMP_SIZE),-1); continue; } // PATCH FLOWER1 //.text:00002
A80 B1 B5 PUSH {R0,R4,R5,R7,LR} //.text:00002A82 82 B0 SUB SP, SP, #8 //.text:00002A84 12 46 MOV R2, R2 //.text:00002A86 02 B0 ADD SP, SP, #8 //.text:00002A88 00 F1 01 00 ADD.W R0, R0, #1 //.text:00002A8C A0 F1 01 00 SUB.W R0, R0, #1 //.text:00002A90 1B 46 MOV R3, R3 //.text:00002A92 BD E8 B1 40 POP.W {R0,R4,R5,R7,LR} //.text:00002A96 01 F1 01 01 ADD.W R1, R1, #1 //.text:00002A9A A1 F1 01 01 SUB.W R1, R1, #1 if ( (Byte(pos)==0xb1)&&(Byte(pos+1)==0xb5)&&(Byte(pos+2)==0x82)&&(Byte(pos+3)==0xb0)&& (Byte(pos+0x1a)==0xa1)&&(Byte(pos+0x1b)==0xf1)&&(Byte(pos+0x1c)==0x01)&&(Byte(pos+0x1d)==0x01)) { for(i=0;i<FLOWER1_SIZE;i++) { PatchByte(pos+i,0x0); } HideArea(pos,pos+FLOWER1_SIZE,atoa(pos),atoa(pos),atoa(pos+FLOWER1_SIZE),-1); continue; } //PATCH FLOWER2 // "PUSH.W {R4-R10,LR}" // "POP.W {R4-R10,LR}" if ( (Byte(pos)==0x2d)&&(Byte(pos+1)==0xe9)&&(Byte(pos+2)==0xf0)&&(Byte(pos+3)==0x47)&& (Byte(pos+4)==0xbd)&&(Byte(pos+5)==0xe8)&&(Byte(pos+6)==0xf0)&&(Byte(pos+7)==0x47)) { for(i=0;i<FLOWER2_SIZE;i++) { PatchByte(pos +i,0x0); } HideArea(pos,pos+FLOWER2_SIZE,atoa(pos),atoa(pos),atoa(pos+FLOWER2_SIZE),-1); continue; } pos++; } Message("\n" + "DE-FLOWERS FINISH BY Ericky\n"); }

重新create function

手動的刪除check和jni_load中間的函式,然後重新create_function,之後便可以使用F5反彙編了。雖然仍存在很多混淆指令,但這樣已經可以看到check的整個程式碼了。
可以使用流程圖,看整個函式的執行過程
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
接下來就是需要動態除錯去跟了。

動態除錯

由於我們修改了so檔案,因此在載入的時候要注意。使ida載入本地的so,而不是手機中的so(只需要預設選擇就好)
這裡寫圖片描述
經過初始化後可以看到該值,這一串字元就是最終我們需要匹配的。也就是最後的密文。
這裡寫圖片描述

19931012應該就是加密的密匙

最後分析演算法(可能也是猜測吧,分析是不可能的,永遠也不可能的!),可以知道為rc4演算法,找一個線上rc4加解密的網站。最後可以解得密碼madebyericky94528

總結

可以說這題折騰了很久,但是最終還是沒有整出來,一方面是對指令混淆不熟,說白了也就是對arm指令不熟,另一方面就是對各種演算法的反彙編不熟悉,真的很難。而且這兩天我心情也不好,很難靜下心來仔細的分析。這篇文章匆匆寫下,其實那個rc4演算法我還是沒有看懂,而且密匙為什麼是199931012而不是199310124853呢?問題還有很多,我不想折騰了。演算法看重的不是加密的過程,而是注意輸入和輸出,抓住這兩點,那麼即使這個演算法你識別不出來,也是可以看懂的。
這兩天心情真的是糟透了,每天都活的很累,好好的假期,每天卻如同末日一般。我的心懸在高處,只能用枯燥的指令佔據我的邏輯。
程式設計師是孤獨的,因為很少有人能懂他在幹什麼。不奢求別人能懂,只希望在放鬆的時候能有人噓寒問暖 –2018.4.7