t貓xsign unidbg逆向

t貓xsign unidbg逆向

加密流程來源于看雪一位大佬的分享

2591919-18a845cc4f30be83.png

findcrypt & findhash

既然已經(jīng)知道用到了HMAC-SHA1算法了缀程,那就先用findcryptfindhash找找

findcrypt

2591919-95eb1479b4668873.png

可以看到base64的常量

2591919-6be60f33765685ad.png

查看引用

2591919-2ec0cbbdae2a9193.png
2591919-1b409f8c4e5c5e47.png

sub_99BE0應(yīng)該就是進(jìn)行base64編碼的地方了

findhash

不知道出了什么問題搜吧,沒有找到hash常量。于是看了下findhash的代碼

2591919-7de05a0fa7ec7d9c.png

發(fā)現(xiàn)是在.texttext這兩個(gè)segment里進(jìn)行搜索杨凑,但是so里沒有這兩個(gè)segment滤奈。

2591919-0a580e8c7a53bf64.png

嘗試用frida_dump來dump內(nèi)存中的so,再看看它的segment

2591919-c99f0afd09a09611.png

多了幾個(gè)segment撩满,其中有個(gè)是.text&ARM.extab蜒程,對比一下base64函數(shù)

2591919-56cbfb2546dcaa45.png

可以看到segment信息被修復(fù)了。既然如此伺帘,修改一下findhash的代碼

if 'text' in (idc.get_segm_name(seg)).lower()

然后重新打開ida調(diào)用下findhash

2591919-d88d0c67d16732ae.png

發(fā)現(xiàn)sub_9AECEsub_9B1E0都包含了SHA1的常量昭躺,分別下斷點(diǎn)測試后發(fā)現(xiàn)調(diào)用的是sub_9B1E0

2591919-6d205a900f3c065a.png
2591919-e52199a9bd4c5d27.png

sub_9B1E0查看引用

2591919-6cdc423bdc3705fa.png

sub_9A0E0

2591919-f13e439033cddd1f.png

可以看到HMAC的常量。

base64 & hmac-sha1

hook一下base64和hmac函數(shù)的參數(shù)

public void hook_b64() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.enable_arm_arm64_b_branch();
    hookZz.wrap(module.base + 0x99BE0 + 1, new WrapCallback<HookZzArm32RegisterContext>() {
        @Override
        public void preCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer input = ctx.getPointerArg(0);
            byte[] inputHex = input.getByteArray(0, ctx.getR1Int());
            System.out.println("b64 input: " + Hex.encodeHexString(inputHex));
            //                System.out.println(Hex.encodeHexString(inputHex));

            Pointer output = ctx.getR2Pointer();
            ctx.push(output);
        }

        @Override
        public void postCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer output = ctx.pop();
            byte[] outputHex = output.getByteArray(0, ctx.getR0Int());
            System.out.println("b64 output: " + Hex.encodeHexString(outputHex));
        }
    });
    hookZz.disable_arm_arm64_b_branch();
}

public void hook_hmac() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.enable_arm_arm64_b_branch();
    hookZz.wrap(module.base + 0x9a0e0 + 1, new WrapCallback<HookZzArm32RegisterContext>() {
        @Override
        public void preCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer input = ctx.getPointerArg(3);
            byte[] inputHex = input.getByteArray(0, ctx.getR1Int());
            Inspector.inspect(inputHex, "hmac input");

            Pointer r2 = ctx.getR2Pointer();
            String key = r2.getString(0);
            System.out.println("hmac key: " + key);

            Pointer output = ctx.getR0Pointer();
            ctx.push(output);
        }

        @Override
        public void postCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            Pointer output = ctx.pop();
            Pointer pointer = output.getPointer(16);
            byte[] outputHex = pointer.getByteArray(0, ctx.getR0Int());
            Inspector.inspect(outputHex, "hmac output");
        }
    });
    hookZz.disable_arm_arm64_b_branch();
}

第一次hmac

2591919-d6ca74ff126213bf.png

base64

2591919-8666a5cf5407acab.png

第二次hmac

2591919-9206a4e32ff200c1.png

cyberchef測試一下

2591919-d845ade464ea75ab.png

說明沒有經(jīng)過魔改伪嫁。

白盒AES

根據(jù)base64輸入的長度领炫,猜測它就是AES的輸出,由于其長度為80张咳,再加上填充算法的原因帝洪,AES輸入的長度應(yīng)該在70-79之間。接下來的目標(biāo)就是從第一次hmac的輸出找到AES的輸入脚猾,另外還需要找到AES的key和iv(如果有)葱峡。

分析AES輸入

對第一次hmac的輸出進(jìn)行traceRead,看看誰對它進(jìn)行了讀取

emulator.traceRead(0xbffff168L, 0xbffff168L+20);
2591919-99b66462cbedfa98.png

可以看到是在libc.so進(jìn)行了讀操作婚陪,打開unidbg-android/src/main/resources/android/sdk23/lib/libc.so看看

2591919-aa537161df11cbbc.png

調(diào)用了memcpy函數(shù)族沃,那就hook一下

public void hook_memcpy() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.enable_arm_arm64_b_branch();
    hookZz.wrap(module.findSymbolByName("memcpy"), new WrapCallback<HookZzArm32RegisterContext>() {
        @Override
        public void preCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            UnidbgPointer output = ctx.getPointerArg(0);
            UnidbgPointer input = ctx.getR1Pointer();
            int length = ctx.getR2Int();
            String hex = Hex.encodeHexString(input.getByteArray(0, length));
            System.out.println("src: " + input + ", dst: " + output + ", data: " + hex);
        }
    });
    hookZz.disable_arm_arm64_b_branch();
}
2591919-30677e2904901b45.png

繼續(xù)對0x402cd4f8進(jìn)行讀跟蹤

2591919-70e9b7987fa87298.png

跳轉(zhuǎn)過去看看

2591919-c0a7e4fe67982d87.png
2591919-699423b82dad6023.png

下斷點(diǎn)看看函數(shù)的輸入輸出

2591919-9f39b335b463c661.png
2591919-348751eaf7584b08.png

r2應(yīng)該是buffer,存儲返回值的泌参,blr下斷點(diǎn)脆淹,c執(zhí)行到返回處,看看原r2的數(shù)據(jù)

2591919-ebad8c3209be8a56.png

就做了個(gè)byte轉(zhuǎn)hex的操作沽一。

對0x402db090進(jìn)行讀跟蹤

2591919-9c08ec9eb2029447.png

還是在libc.somemcpy進(jìn)行讀取盖溺,看看之前hook的記錄

2591919-0f745efeebee962b.png

此次memcpy之后還有幾次memcpy,并且后面連接了一些字符

2591919-11254b1504370440.png

可以發(fā)現(xiàn)是hmac的key铣缠,此時(shí)字符串的長度是73烘嘱,符合之前提到的AES輸入的長度要求,我們可以合理推斷它就是AES的輸入蝗蛙。

對最后一次寫入的地址0x4043a000進(jìn)行讀跟蹤

2591919-001ffbbc5c5cd3e3.png

跳轉(zhuǎn)過去

2591919-d9247292f124737f.png

下個(gè)斷點(diǎn)看看

2591919-a766a97303fd084f.png
2591919-32e5c1a402b19db6.png

可以看到后面進(jìn)行了填充蝇庭。

設(shè)置AES輸入和iv

已經(jīng)知道是白盒AES,那我們接下來要做些準(zhǔn)備工作捡硅,把輸入設(shè)置到一個(gè)分組哮内,把iv設(shè)置為0。

在此處bt看看調(diào)用棧

2591919-932be504391da127.png
2591919-3a291a0212f8b694.png

hook看看函數(shù)入?yún)?/p>

2591919-ccd2d9ea8bc01344.png
2591919-bc1017358282a2d0.png

0x49=73正是字符串的長度壮韭。

那就hook函數(shù)改一下入?yún)?/p>

public void set_input() {
    IHookZz hookZz = HookZz.getInstance(emulator);
    hookZz.enable_arm_arm64_b_branch();
    hookZz.wrap(module.base + 0x6A864 + 1, new WrapCallback<HookZzArm32RegisterContext>() {
        @Override
        public void preCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
            UnidbgPointer r2 = ctx.getR2Pointer();
            UnidbgPointer input = r2.getPointer(0);
            String str = "everhu";
            input.write(str.getBytes());
            r2.setInt(4, str.length());
            System.out.println("set aes input: " + str);
        }
    });
    hookZz.disable_arm_arm64_b_branch();
}
2591919-50fa78495ad835ec.png

地址已經(jīng)改變了

2591919-5bf7fc0071c764a9.png

可以看到AES的輸入已經(jīng)變成一個(gè)分組

接下來找找iv北发,分析一下匯編指令

2591919-7c1ad382c55f186c.png

0x6AE72處r1加載了輸入的地址,0x6AE82處加載輸入的數(shù)據(jù)喷屋,0x6AE84處r1和r2進(jìn)行了異或琳拨,由此猜測r2是iv,r2是在0xAE7A從lr加載的。

下斷點(diǎn)看看

2591919-08abfddf904bf941.png
2591919-5ab0790d3d9180c7.png

方便后續(xù)的dfa,把iv設(shè)為0坝初,選擇了偷懶的方式象浑,直接patch 0x6AE84的語句,改為nop血柳,相當(dāng)于沒有進(jìn)行異或。

public void set_iv() {
    emulator.getMemory().pointer(module.base + 0x6AE84).write(new byte[] {0x00, (byte) 0xbf});
}

重新hook看看base64的輸入,也就是AES的結(jié)果看看

2591919-9380edcc68bf14fd.png
查找state

繼續(xù)分析異或之后的操作批什,0x6AE8A將異或后的結(jié)果存到了r2處的地址,下斷點(diǎn)看看

2591919-2cad04c54b953454.png

數(shù)據(jù)存入了0x402dabc0社搅,對其進(jìn)行讀跟蹤

2591919-3db3f4ece899f3e9.png
2591919-bac61eacacf47848.png

0x6AFD0讀取數(shù)據(jù)到r5之后驻债,0x6AFE2又將其存到了r3。

下斷點(diǎn)看看地址

2591919-6a2357cf49662c63.png

對0xbffff028進(jìn)行讀跟蹤

2591919-145ab5f33c69c45d.png

發(fā)現(xiàn)了9輪讀取形葬,看來這就是AES的state合呐,看看匯編

2591919-78336188786175fa.png

下斷點(diǎn)看看

2591919-f3ddb5ec765208f4.png

發(fā)現(xiàn)地址對不上

同時(shí)進(jìn)行讀跟蹤和下斷點(diǎn)

2591919-61f897ece6371f04.png

重新在0x6bb12下斷點(diǎn)

2591919-bc8234bd82d2844d.png

確實(shí)是在這進(jìn)行讀取。

DFA

接下來進(jìn)行DFA攻擊笙以,函數(shù)在0x6bb12進(jìn)行了16*9次數(shù)據(jù)讀取淌实,由于DFA需要在第8輪列混淆和第9輪列混淆之間進(jìn)行操作,因此在第16*8次讀取時(shí)隨機(jī)修改一個(gè)字節(jié)。

public void dfa() {
    emulator.attach().addBreakPoint(module.base + 0x6bb12, new BreakPointCallback() {
        @Override
        public boolean onHit(Emulator<?> emulator, long address) {
            Arm32RegisterContext ctx = emulator.getContext();
            if (count == 16 * 8) {
                UnidbgPointer r3 = ctx.getR3Pointer();
                r3.setByte(randInt(0, 16), (byte) randInt(0, 0xff));
                System.out.println("dfa");
            }
            count += 1;
            return true;
        }
    });
}
2591919-e72276a85e7d67e1.png

和正確結(jié)果對比拆祈,發(fā)現(xiàn)有4個(gè)字節(jié)不同恨闪,說明操作是對的。

接下來就是去掉多余的輸出放坏,調(diào)整打印的格式咙咽,多次調(diào)用。

public static void main(String[] args) {
    Logger.getLogger("com.github.unidbg.linux.ARM32SyscallHandler").setLevel(Level.ERROR);
    TMall test = new TMall();
    test.call_init();
    //        test.hook_memcpy();
    test.hook_b64();
    //        test.hook_hmac();
    test.set_input();
    test.set_iv();
    
    test.callXSign();
    
    test.dfa();

    for (int i=0; i<16; i++) {
        test.count = 0;
        test.callXSign();
    }
}
2591919-b5b841ab4b48720d.png

之后就比較簡單了淤年,調(diào)用JeanGrey/phoenixAESSideChannelMarvels/Stark即可還原出key钧敞。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市麸粮,隨后出現(xiàn)的幾起案子溉苛,更是在濱河造成了極大的恐慌,老刑警劉巖弄诲,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愚战,死亡現(xiàn)場離奇詭異,居然都是意外死亡威根,警方通過查閱死者的電腦和手機(jī)凤巨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洛搀,“玉大人敢茁,你說我怎么就攤上這事×裘溃” “怎么了彰檬?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谎砾。 經(jīng)常有香客問我逢倍,道長,這世上最難降的妖魔是什么景图? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任较雕,我火速辦了婚禮,結(jié)果婚禮上挚币,老公的妹妹穿的比我還像新娘亮蒋。我一直安慰自己,他們只是感情好妆毕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布慎玖。 她就那樣靜靜地躺著,像睡著了一般笛粘。 火紅的嫁衣襯著肌膚如雪趁怔。 梳的紋絲不亂的頭發(fā)上湿硝,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機(jī)與錄音润努,去河邊找鬼关斜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛任连,可吹牛的內(nèi)容都是我干的蚤吹。 我是一名探鬼主播例诀,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼随抠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了繁涂?” 一聲冷哼從身側(cè)響起拱她,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扔罪,沒想到半個(gè)月后秉沼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矿酵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年唬复,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片全肮。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敞咧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辜腺,到底是詐尸還是另有隱情休建,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布评疗,位于F島的核電站测砂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏百匆。R本人自食惡果不足惜砌些,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望加匈。 院中可真熱鬧存璃,春花似錦、人聲如沸矩动。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悲没。三九已至篮迎,卻和暖如春男图,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甜橱。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工逊笆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岂傲。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓难裆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镊掖。 傳聞我的和親對象是個(gè)殘疾皇子乃戈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容