看雪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