天天看點

ida動态調試_初試IDA&FRIDA聯合調試簡單ollvm保護的加密函數源碼

ida動态調試_初試IDA&FRIDA聯合調試簡單ollvm保護的加密函數源碼

本文為看雪論壇優秀文章

看雪論壇作者ID:無造

本文為看雪安卓高研3w班(5月班)優秀學員作品。

下面先讓我們來看看講師對學員學習成果的點評,以及學員的學習心得吧! 講師點評

ollvm混淆強度不是很強的時候,可以通過IDA靜态分析參數的交叉引用和傳回值的來源,定位到與參數相關的函數,然後使用frida hook這些函數,定位到處理參數或生成傳回結果的關鍵函數。

但是ollvm混淆強度比較強的時候,還是需要用到3月學習的trace方法來分析出參數被加密算法計算的過程。

學員感想 這是3W班5月的習題。題目要求是 e 函數需要逆向出源碼。 yang老師本意應該是訓練下trace的彙編代碼閱讀能力,但是由于ollvm混淆開得比較低,是以IDA的反彙編代碼也是可以閱讀,當時偷懶就沒有專心去閱讀trace了。 通過本題初次嘗試了還原so檔案代碼,在沒有開太多混淆的情況下還是可以使用IDA配合frida還原,像之前3月題目混淆開的高一點這種方式就要搞死掉了。

現在,看雪《安卓進階研修班(網課)》9月班開始招生啦!點選檢視詳情報名吧~

解題過程 還原代碼

#include  /* Swap bytes in 32 bit value.  */#define __builtin_bswap32(x) \     ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >>  8) |         \      (((x) & 0x0000ff00u) <<  8) | (((x) & 0x000000ffu) << 24))#define bswap32(x) ((unsigned int)__builtin_bswap32(x)) void myenc(char* str) {    /**********  程式寫死 **********/    char* strWWW = "www.pediy.com&kanxue";    char* stryy = "yy";    unsigned char hexData[264] = {        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,        0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,        0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,        0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,        0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,        0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,        0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,        0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,        0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00    };     /**********  計算長度 **********/    unsigned int lenStr = strlen(str);    unsigned int lenPadding = (-(signed int)lenStr & 0xf);    unsigned int lenEncStr = lenStr + 6 + lenPadding;    unsigned char* bufEnc = (unsigned char*)malloc(lenEncStr);    memset(bufEnc, 0, lenEncStr);     /**********  開始填充 **********/    unsigned char* offBuf = (unsigned char*) (bufEnc + 6);    //memmove(offBuf, strWWW, lenStrWWW);    memmove(offBuf, str, lenStr);    bufEnc[0] = stryy[0];    bufEnc[1] = stryy[1];    bufEnc[2] = 0x3;    bufEnc[3] = lenPadding;    //這裡分2次設定 100    bufEnc[4] = 0x00;    bufEnc[5] = 0x01;      /**********  第一步加密 **********/    int i = 0;    for (i = 6; i < lenEncStr; i++) {        unsigned char tmpc = bufEnc[i];        unsigned char changec = hexData[tmpc];        bufEnc[i] = changec;    }     /**********  第二步加密 **********/    //生成第二步秘鑰    unsigned int lenStrWWW = strlen(strWWW);    //這裡隻複制0x10位    unsigned int lenBufKey = 0x10;    unsigned char* bufKeyWWW = (unsigned char*)malloc(lenBufKey);    memset(bufKeyWWW, 0, lenEncStr);    memmove(bufKeyWWW, strWWW, lenBufKey);    for (i = 0; i < lenBufKey; i++) {        unsigned char tmpc = bufKeyWWW[i];        unsigned char changec = hexData[tmpc];        bufKeyWWW[i] = changec;    }     unsigned int* bufKeyWWWInt = (unsigned int*) bufKeyWWW;    for (i = 0; i < 0x10 / 4; i++) {        bufKeyWWWInt[i] = bswap32(bufKeyWWWInt[i]);    }         unsigned int* bufEncInt = (unsigned int*)offBuf;    for (i = 0; i < (lenEncStr - 6) / 4; i++) {        unsigned int part = bswap32(bufEncInt[i]);        unsigned int partchange = part;        if (i % 4 > 0) {            partchange = (part >> 32 - i % 4 * 8) ^ (part << i % 4 * 8);        }        bufEncInt[i] = bswap32(partchange ^ bufKeyWWWInt[i%4]);    }     /**********  列印結果 **********/    for (i = 0; i < lenEncStr; i++) {        if(bufEnc[i] < 0x10)            printf("0", bufEnc[i]);        printf("%x", bufEnc[i]);    }    printf("\nDone");} int main() {    myenc("pediy_imyang_abcdefghij");}
           

解題思路 本來想使用IDA Trace,拿到日志後,沒有直接定位到計算的地方,是以整個還原是使用IDA動态調試和Frida來完成的。 步驟1:檢視函數e

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

函數e中直接使用了sub_1500C,傳入v42就是bytes數組,v41就是我們傳回的秘鑰。

var addr_1500C = base_native.add(0x1500C);        Interceptor.attach(addr_1500C, {            onEnter: function (args) {                this.args0 = args[0];                console.log("addr_1500C onEnter args0:",hexdump(this.args0));                var args1addr = ptr(args[1]).add(Process.pointerSize*2).readPointer();                console.log("addr_1500C onEnter args1:",args1addr.readCString());            },            onLeave: function (retval) {                var resultaddr = ptr(this.args0).add(Process.pointerSize*5).readPointer();                console.log("addr_1500C onLeave args0:",hexdump(resultaddr));            }        });
           

使用Frida可驗證,這裡傳回值存儲的位置需要注意。 步驟2:檢視sub_1500C

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

sub_1500C中計算了加密字元串長度,然後引入了新字元串www.pediy.com&kanxue。之後直接調用sub_13CE4計算加密。 參數清單 x0 字元串pediy_imyang_abcdefghij x1 字元串長度 x2 字元串www.pediy.com&kanxue x3 字元串長度 x4 需要設定的buff 步驟3:檢視sub_13CE4

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

前2步,拷貝字元串pediy_imyang_abcdefghij到buf,設定頭為7979("yy") sub_13808 使用www.pediy.com&kanxue生成一串0x10長度的key,這個後面依次和更改順序的加密資料異或。

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼
ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

第3,4步,填充頭,通過轉換表byte_42108轉換字元串。

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

很多sub_172D0是用來轉換位置的,比如AABBCCDD改成BBCCDDAA。共3種模式。修改後和上面加密key進行異或。 主要的加密都在sub_13CE4中。

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

- End -

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

看雪ID:無造

https://bbs.pediy.com/user-571058.htm

  *本文由看雪論壇 無造 原創,轉載請注明來自看雪社群。

推薦文章++++

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

* 記一次so檔案動态解密

* 阿裡2015第二屆安全挑戰賽第三題題解

* VSCode搭建輕量驅動開發環境

* 惡意代碼分析之反射型DLL注入

* 使用Frida簡單實作函數粒度脫殼

好書推薦

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼
ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

﹀ ﹀ ﹀

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼

公衆号ID:ikanxue 官方微網誌:看雪安全 商務合作:[email protected] ps. 覺得對你有幫助的話,别忘點分享,點贊和在看,支援看雪哦~

ida動态調試_初試IDA&amp;amp;FRIDA聯合調試簡單ollvm保護的加密函數源碼