一泌辫、目標(biāo)
App安全的主戰(zhàn)場(chǎng)在Native層随夸,分析Native層的so,最趁手的兵器就是Frida和Unidbg了震放。
今天我們的目標(biāo)是 某汽車社區(qū)App v8.0.1 so 的分析宾毒。
二、步驟
特征字符串定位
我們?cè)谏弦黄坛?某汽車社區(qū)App 簽名和加解密分析 已經(jīng)定位了,數(shù)據(jù)加密和解密函數(shù)再java層的位置殿遂。
按照常理來說诈铛,這個(gè)java類文件中,應(yīng)該有個(gè) System.loadLibrary("libxxx") 來方便我們定位對(duì)應(yīng)的so墨礁。
可惜的是幢竹,這個(gè)樣本里找不到。原因大概率是脫殼不完整饵溅。
既然沒這么簡(jiǎn)單妨退,我們?cè)倩貞浺幌录用艽奶卣鳎?/p>
1、sd= 開頭
2蜕企、數(shù)據(jù)都是大寫的M開頭
3咬荷、== 結(jié)尾,那大概率是Base64
有共性就好辦了轻掩,我們?cè)贜ative層匹配下 M 開頭的字符串,匹配到了就打印Native層的堆棧幸乒。
if(string.toString().length > 50 && string.toString().indexOf("M") == 0){
var threadef = Java.use('java.lang.Thread');
var threadinstance = threadef.$new();
console.log("[NewStringUTF] bytes:" + string);
console.log(Thread.backtrace(this.context, Backtracer.FUZZY)
.map(DebugSymbol.fromAddress).join("\n"))
}
跑一下
結(jié)果是出來了,但是這個(gè)結(jié)果很有料呀唇牧。 沒聽說過江湖上有 1ef38371-d2a4-4ade-8510-d08f5c05fe5f-32.so 這種名號(hào)的so罕扎。
全局搜索
這個(gè)奇怪的so在apk里面肯定是找不到了。我們?cè)谑謾C(jī)里去找一找丐重。
要玩好Android腔召,那么linux命令不可少,搜索文件用find命令
find / -name '1ef38371-d2a4-4ade-8510-d08f5c05fe5f-32.so' -print
我去扮惦,沒道理呀臀蛛,居然搜不到?當(dāng)然不會(huì)是我們find命令輸錯(cuò)了崖蜜。
在加密或者加殼的手段下浊仆,是可以實(shí)現(xiàn)手機(jī)只有加密文件,只在內(nèi)存中加載解密后的so豫领。
Frida Dump So
今天的重頭戲就是這個(gè)了抡柿。so在內(nèi)存里面,如何把它搞出來等恐?
第一步: 把冰箱門打開
var libxx = Process.getModuleByName("210f3bcc-51b1-4f3c-9ca4-c429ad93ded1-32.so");
console.log("*****************************************************");
console.log("name: " +libxx.name);
console.log("base: " +libxx.base);
console.log("size: " +ptr(libxx.size));
打印出了這個(gè)神奇的so的地址和大小
*****************************************************
name: 210f3bcc-51b1-4f3c-9ca4-c429ad93ded1-32.so
base: 0xc380c000
size: 0xec9000
第二步:把大象塞進(jìn)冰箱
var file_path = "/data/data/com.clxxx.lxxxlxxxbxxx/" + libxx.name + "_" + libxx.base + "_" + ptr(libxx.size) + ".so";
console.log(file_path);
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
Memory.protect(ptr(libxx.base), libxx.size, 'rwx');
var libso_buffer = ptr(libxx.base).readByteArray(libxx.size);
file_handle.write(libso_buffer);
file_handle.flush();
file_handle.close();
console.log("[dump]:", file_path);
}
注意: 寫so文件的時(shí)候洲劣,把文件寫在 /data/data/包名 目錄下备蚓,這個(gè)目錄大概率下是可以讀寫的。
第三步: 把冰箱門關(guān)上
最后把dump的so用adb命令 pull出來闪檬。
如果沒有pull /data/data/包名 這個(gè)目錄的權(quán)限星著,那就先copy到 /data/local/tmp 目錄下面。
現(xiàn)在可以拖進(jìn)ida愉快的分析了粗悯。
三、總結(jié)
先找共性同欠,然后再定位样傍。字符串定位的套路都是一樣的。
如果樣本沒有調(diào)用 NewStringUTF 或者 GetStringUTFChars 怎么辦铺遂?
我覺得還可以考慮libc.so, malloc strcpy 這些標(biāo)準(zhǔn)C函數(shù) Hook一下衫哥,應(yīng)該也會(huì)有驚喜。
Linux命令可以熟悉下襟锐,關(guān)鍵時(shí)刻還是有用的撤逢。
俄羅斯方塊教會(huì)了我們,如果你合群粮坞,就會(huì)消失蚊荣。