Nic*app的native層算法破解

Nic*app的native層算法破解

案例:就不放了

抓包分析

這裏抓包分析的過程不詳細說了 可以看到主要有兩個參數 sign和signV1

反編譯

1、 sign破解

搜索關鍵詞定位以及跳轉到聲明之後,最後就是一個md5,用objection看看就完事了這是java層的sign破解,完事。

2、*-sign-v1破解

這個算法主要是在native層,這裏藉助了frida進行破解,最後換成cpp代碼。這裏定位到這個,剛開始我也不知道這裏,就瞎找,分析到這裏。最後確定到這兩個方法,用objection確定下,最後native走的那個方法可以看到最後走的是getSignRequest這個方法,並且根據上圖,就可以看到so是libsalt.so。

2.1 分析so
  • 導入jni頭文件,這裏沒有jni_onload,就是靜態註冊的。在 Java_com_*_main_helpers_utils_*SignUtils_getSignRequest找到一個加密的函數,追下去看看。

  • 看到這麼多函數,根據名字就猜測一下了,md5操作,看看是不是導出函數。

  • 果然是導出函數,直接frida就去Hook一下導出函數。
Interceptor.attach(Module.findExportByName("libsalt.so""*_md5"), {
    onEnter: function (args) {
        console.log("*_md5 onEnter", Memory.readCString(args[0]))
    },
    onLeave: function (retvalue) {
        console.log("*_md5 onLeave", Memory.readCString(retvalue))
    }
})

Hook之後得到這麼多其實a4698cf0eea7a9b92a0194618079aba9是did2a0194618079aba9a4698cf0eea7a9b9中間進行切割,然後交換位置。5nhrec75lf3drenb09a349366a5b7eda4ee99d7a104fb38b8a5f746c1c9c99c0b458e1ed510845e5 是隨機字符串+md5(a4698cf0eea7a9b92a0194618079aba9)+8a5f746c1c9c99c0b458e1ed510845e5的結果8a5f746c1c9c99c0b458e1ed510845e5是固定值,隨機字符串是java層算法。python這一部分的實現

   did = '2a0194618079aba9a4698cf0eea7a9b9'
    rstr = 'yqkdfs6y4d2ci8wm'  # 隨機字did[:符串
    new_did = did[len(did) // 2:] + len(did) // 2]
    did_md5 = get_md5(new_did)
    sss = rstr + did_md5 + '8a5f746c1c9c99c0b458e1ed510845e5'
    dest = get_md5(sss)

cpp實現:

    string did = "2a0194618079aba9a4698cf0eea7a9b9";
    string ranstr = "28npqz4cpmw6ifpc";
    string new_did = getStringSubs(did);
    string did_md5 = getMd5(new_did);
    string sss = ranstr + did_md5 + "8a5f746c1c9c99c0b458e1ed510845e5";
    string dest = getStringSubs(getMd5(sss));

上邊的dest是新字符串拼接需要的

這裏有一個json的操作,其實剛開始我也不知道幹了什麼,最後我用frida-trac 就輕鬆解決了。

frida-trace -FU -i "strlen"

file
array[i] = buffer[2 * i] & 0xF0 | buffer[2 * i + 1] & 0xF;

這個是對字符串進行了高低位的操作,也就是這個app的signV3唯一個非標準算法。拿到高低位操作之後的字符串之後,拼接了之前的dest(我自己寫的那個),然後進行sha1操作。sha1之後取了第8位到最後的字符串,然後又中間進行切割,然後交換位置,最後生成的就是signV3的結果。cpp最後實現的算法:

string getMd5(const string &message) {
    return MD5(message).toStr();
}
string getSha1(const string &message) {
    SHA1 checksum;
    checksum.update(message);
    const string hash = checksum.final();
    return hash;
}
string getStringSubs(const string &message) {
    string string1 = message.substr(0, message.length() / 2);
    string string2 = message.substr(message.length() / 2);
    return string2 + string1;
}
void SignV3() {
    string did = "2a0194618079aba9a4698cf0eea7a9b9";
    string ranstr = "28npqz4cpmw6ifpc";
    string new_did = getStringSubs(did);
    string did_md5 = getMd5(new_did);
    string sss = ranstr + did_md5 + "8a5f746c1c9c99c0b458e1ed510845e5";
    string dest = getStringSubs(getMd5(sss));
    string arr = "aid=fbef33334c2388ccee5757dc2dbb0b45&comments_sort=asc&isnewsession=false&mark_read_sid=361595316249559936&mcc=&mnc=&nextkey=×tamp=1592463682&ua=Mozilla/5.0 (Linux; Android 8.1.0; AOSP on msm8996 Build/OPM4.171019.021.D1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36";
    const char *buffer = "aid=fbef33334c2388ccee5757dc2dbb0b45&comments_sort=asc&isnewsession=false&mark_read_sid=361595316249559936&mcc=&mnc=&nextkey=×tamp=1592463682&ua=Mozilla/5.0 (Linux; Android 8.1.0; AOSP on msm8996 Build/OPM4.171019.021.D1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36";
    int i = 0;
//這裏的算法可以看看ida的圖 自己實現吶
   string new_sss = arr.substr(0, i) + dest;
    string sha1Res = getSha1(new_sss).substr(8);
    string sign_v3 = getStringSubs(sha1Res);
    cout << "_sign_v3=" << sign_v3;
}
int main() {
    SignV3();
    return 0;
}

算法檢驗

至於爲什麼最後不放python算法,實在是因爲,還原成python之後,高低位操作的時候,部分數據不對了。。就只有cpp了

           
更多推薦
           

修改xposed特徵並刷機

破解某交(y)友(p)app的VIP&&半自動im機器人

編譯xposed、刷機並送書
       

本文分享自微信公衆號 - 小白技術社(xbjss123)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章