Android逆向筆記 - ZCTF2016題解

這是2016年zctf的一道Android題目,樣本和本文用到的部分工具在文章末尾可以下載

0x01 第一部分 靜態分析

安裝運行apk,需要輸入用戶名和密碼,用戶名為zctf,用jeb工具反編譯
文件結構如下:


圖1

如圖 assets目錄中有三個文件,bottom、flag.bin、key.db,還有一個JNIclass庫。

圖2

程序開始,先檢查密碼的長度(至少4位),然后調用auth方法驗證用戶名密碼是否正確,如果正確則執行OpenNewActivity方法

auth方法的第二個參數是用戶名密碼的組合,第三個為另一個方法databaseopt(),看名字應該是讀取數據庫,看下這個方法:


圖3

注:關于查找2131099679對應的字符串
先把數字轉換成16進制:0x7F06001F,然后在public.xml中找到對應索引,在去strings.xml中查看字符串
先把key.db從assets目錄拷貝到應用目錄中,然后調用sql語句查詢id為0對應字段的值
打開數據庫查到key為zctf2016
繼續看auth的實現:


圖4

先將用戶名密碼組成的字符串反轉,利用前面的key加密,然后和assets中的flag_bin做比較,如果相等就返回1
看下encrypt方法看到是DES加密,而且還提供了解密方法,所以可以直接解密出用戶名密碼:
圖5

java代碼解密:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            byte[] buffer = readbytes("flag.bin");
            System.out.println(buffer.length);
            byte[] result = decrypt(buffer, "zctf2016");
            System.out.println(new StringBuffer(new String(result)).reverse()
                    .toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static byte[] readbytes(String filedir) throws IOException {
        FileInputStream fis = new FileInputStream(new File(filedir));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] cache = new byte[1024];
        int len = 0;
        while ((len = fis.read(cache)) != -1) {
            baos.write(cache, 0, len);// 因為一般最后一次read不能裝滿cache,用這種方式確保不會將cache末尾空數據寫入數據流中
        }
        fis.close();
        baos.close();
        return baos.toByteArray();
    }

運行打印輸出:

16
zctf{Notthis}

所以密碼為{Notthis}

繼續往下看OpenNewActivity方法:

圖6

打開了一個新的activity,把密碼也傳過去了
看app.class的內容:

圖7

Activity啟動后先接收到傳過來的密碼,然后調用CheckOperatorNameAndroid方法檢測調試器,接著調用了dataProvider.add方法(native方法),如果返回結果為1就退出,如果不為1則調用pushthebottom和dataProvider.sayHelloInc。最終的flag應該就藏在sayHelloInc中
再仔細分析,先看CheckOperatorNameAndroid中啟動的定時任務this.task:


圖8

獲得當前activity的taskid,如果不為0就退出。(當前activity的taskid肯定不為0,所以一定會退出)
add方法是native方法,實現在libJNIclass.so中,用IDA打開F5查看

圖9

打開/proc/pid/status,讀取每一條信息到v5和v4中,計算v4的值進行反調試檢測

pushthebottom方法是將assets中的bottom文件拷貝到應用安裝目錄中:

圖10

最后看下native方法sayHelloInc,用IDA打開查看
sayHelloInc只有1個String參數,修改前兩個參數的類型為JavaVM和JNIEnv

圖11

這里調用了sub_14B0函數,其實就是上面的add調用的函數,用來反調試。然后就是打開bottom文件讀到內存中,調用DES_Decrypt解密數據到v24中,接著free釋放內存,所以需要在這個地方把解密的數據拷貝出來。

應用執行的整個流程如下:


圖12

0x02 第二部分 動態調試

前面的就是整個程序的靜態分析的過程,接下來需要從程序中拿到flag。
用戶名密碼已經通過解密算法計算出來了,還需要解決的問題有:
定時任務結束程序、add反調試和sub_14B0反調試。

在定時任務中先判斷getTaskId()是否為0,如果不為0就退出程序,解決方法主要有兩種:
i. 反編譯修改smali代碼的if語句繞過
ii. 用hook修改getTaskId的返回值

下面用xposed hook的方式修改getTaskId和add的返回值繞過干擾,相關代碼:

public class HookGetTaskId implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        if (!loadPackageParam.packageName.equals("com.zctf.app")) return;

        findAndHookMethod("android.app.Activity", loadPackageParam.classLoader, "getTaskId", new XC_MethodReplacement() {

            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                return 0;
            }
        });
        findAndHookMethod("com.zctf.app.JNIclass", loadPackageParam.classLoader, "add", int.class, int.class, new XC_MethodReplacement() {

            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                return 0;
            }
        });

//        findAndHookMethod("android.app.Activity", loadPackageParam.classLoader, "getTaskId", new XC_MethodHook() {
//
//
//            @Override
//            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//                XposedBridge.log("before gettaskid:" + param.getResult());
//                param.setResult(0);
//            }
//
//            @Override
//            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                XposedBridge.log("after gettaskid:" + param.getResult());
//                param.setResult(0);
//            }
//        });
    }
}

用replaceHookedMethod更省事,直接替換方法內容,修改返回值也行。

安裝xposed,重啟手機,運行apk就可以正常進入到sayHelloInc函數中,接下來就需要動態調試從內存中找flag。

在dvm.so中的open函數上下斷點,讓程序可以在加載jniclass.so的時候停下來,運行程序輸入用戶名密碼后,so文件加載到內存中,然后在sayHelloInc處下斷點,調試。

圖13

F8單步運行到反調試的地方,然后修改返回值R0為0,繞過反調試

圖14

單步運行結合F5查看偽代碼調試,直到解密出數據到內存中:

圖15
圖16

DES_Decrypt函數的第一個參數存的是解密前的數據,第二個參數是數據的大小對應R11+0x100為0x1338,第三個參數是解密的密鑰對應R8為{Notthis,第四個參數存的是解密后的數據對應R7,v23即0x77f9d008地址開始的就是解密后的數據,看到是png格式,在hex中選中數據保存為d.png
或者使用腳本導出:

auto fp,addr_start,addr_now,size,addr_end;
addr_start = R7;
size = 0x1338;
fp = fopen("d:\d.png","wb");
for(addr_now=addr_start;addr_now<addr_start+size;addr_now++)
    fputc(Byte(addr_now),fp);

到導出后打開圖片發現沒有flag,用stegsolve打開按下邊的’>’分層查看,最后在Red Plane層找到flag

圖17

apk樣本和stegsolve工具下載:http://pan.baidu.com/s/1nvHOOJZ

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,711評論 25 708
  • 每次離開學校的時候總會不自覺的回頭,看一眼我們的學校。在夜色中,“育全面發展之才”這幾個字在黑夜中熠熠生輝,...
    素心_5bc8閱讀 235評論 0 0
  • 發傳單賺點小錢對于女大學生是很常見的。我在以前從來去沒有干過這類似的事情,今年我去發傳單了,目前差不多類型也干過...
    一大杯白開水閱讀 370評論 0 1
  • 在任何時候都提高警惕,因為不知道什么時候你的信息就被泄露,擦亮眼睛保護好自己。 2017年8月9日 星期三...
    余七秒閱讀 509評論 3 2