1、上次通過hook registerNativeMethod找到了metasec種唯一注冊的jni函數,本想着通過trace call來看看到底這個函數層層調用了哪些函數,結果trace出來的結果完全是錯的(用hook到的地址調用findModuleByAddress確認哪個so,直接報異常!),stalker trace call的代碼:
function trace_entry(tatgetAddr){ //var addr_1094d = targetSo.add(0x1094c+1); Interceptor.attach(tatgetAddr, { onEnter: function(args){ console.log("enter tatgetAddr===================================================================="); this.pid = Process.getCurrentThreadId(); Stalker.follow(this.pid,{ events:{ call:true, ret:false, exec:false, block:false, compile:false }, onReceive:function(events){ var all_events = Stalker.parse(events); console.log("on Received:",all_events.length); for(var i=0;i<all_events.length;i++){ //console.log(all_events[i]); var type=all_events[i][0]; if(type=="call"){ var addr1 = all_events[i][i]; try{ var module1=Process.findModuleByAddress(addr1); if(module1!=null&&module1.name=="libmetasec_ml.so"){ var addr2=all_events[i][2]; var module2=Process.findModuleByAddress(addr2); console.log("call:",module1.name+"!"+addr1.sub(module1.base),module2.name+"!"+addr2.sub(module2.base)); } }catch(error){ console.log("exception error:",error); console.log(all_events[i]); } } } }, onCallSummary:function(summary){ } }); },onLeave: function(retval){ Stalker.unfollow(this.pid); console.log("retval:"+retval); console.log("leave tatgetAddr===================================================================="); } }); } function main(){ var targetSo = Module.findBaseAddress('libmetasec_ml.so'); //var targetSo = new NativePointer(0x4200000); var tatgetAddr = targetSo.add(0x1096C+1); //var tatgetAddr = targetSo.add(0x6221c+1); trace_entry(tatgetAddr); } setImmediate(main);
其他app的trace是ok的,這里不行,大概率有反frida的跟蹤;
console.log('called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n')
用上面這個hook sub_6221c(就是調用base64碼表的關鍵函數)的結果如下:
sub_6221c called from:
0xb4cc14a3 libmetasec_ml.so!0x6c4a3
0xb4cc14a3 libmetasec_ml.so!0x6c4a3
0xb4c8a0d3 libmetasec_ml.so!0x350d3
0xb4c8bcf0 libmetasec_ml.so!0x36cf0
太少了,根本找不出啥!無奈只能老老實實繼續用ida在sub_6221c下斷點,自己在棧上和LR上回溯;這里也看出一點:frida的trace在x音這里失效了,估計是有反調試吧!
自己用ida根據棧回溯時遇到的問題:(1)x86有ebp作為棧幀,ebp+4就是返回地址;但arm沒有,只能自己在棧上挨個找!如果棧上的地址在代碼中是BL或BLX的下一行,就可以確認是函數調用關系了!如果不是在BL或BLX后面,可能是個局部變量或參數,暫時就不管了! (2)ida有些地址反編譯失敗,棧上有的地址在debug view時只能看到一堆“數據塊”,如下(這種塊太多了,這里只貼部分):
text:00034DE9 46 08 46 byte_34DE9 DCB 0x46, 8, 0x46 ; DATA XREF: sub_2F9A0+14↑o .text:00034DE9 ; sub_2F9A0+1E↑o ... .text:00034DEC 10 47 D0 E9+ DCD 3922741008, 1753362688, 4031727128, 3045112139, 553707984 .text:00034DEC 00 31 82 68+ DCD 4158473744, 3179346797, 1174713616, 4158482464, 1616967697 .text:00034DEC 18 46 4F F0+ DCD 3037773072, 1746945540, 4212848602, 3171967072, 1174713616 .text:00034DEC 4B B9 80 B5+ DCD 4220842046, 3171967008, 3922769280, 1175462144, 4286904302 .text:00034DEC D0 E9 00 21+ DCD 3037773184, 1746945540, 4267767802, 3171971360, 3922769280 .text:00034DEC 10 46 DD F7+ DCD 1175462144, 4219009018, 3044064640, 1747338756, 4158397744 .text:00034DEC 6D FB 80 BD+ DCD 1753284583, 2970100992, 3178262821, 4518150, 4292802524 .text:00034DEC 10 B5 04 46+ DCD 671115392, 620871624, 3178262821, 536930768, 22343936
剛開始沒太在意,覺得應該是ida解析出錯(有可能是故意加花指令“誤導”IDA的),直到有一次又遇到signal報錯:C18C31CC: got SIGSEGV signal (Segmentation violation) (exc.code b, tid 21480);我已經掛起了其他線程,這個signal是誰、怎么發出來的了?難道還有其他進程給主進程發signal?好在這里提示了報錯的地址,用這個地址減去metasec_ml的基址,得到0x351CC的偏移,剛好在上面這個數據塊內部;嘗試繼續用C或P,果然能正常識別成代碼!猜測這里是故意讓ida不識別,或則把這段內存設置成不可執行;一旦檢測到ida在調試,想辦法讓代碼跳轉到這里(代碼內部有很多間接跳轉,也就跳轉地址放在寄存器,這樣一來跳轉地址就不用寫死了,可根據實際情況決定跳轉位置,也能防止IDA的交叉引用功能查詢,絕啊!),產生異常報錯! 程序退出也是操作系統的行為,自生並未直接調用exit這類的函數,逆向人員不容易捕捉!
2、這里繼續用ida棧回溯,我個人的一些心得和技巧:
(1)棧上凡是標記了紅框框這種的建議去源碼看看,凡是在BL或BLX代碼下一行的都是函數調用,建議下斷點嘗試!
(2)寄存器重點監控兩類:malloc和heap!原因很簡單:數據要么存在stack,要么存heap,要么存操作系統的數據段;stack存的都是參數、返回地址、局部變了,函數調用一旦結束,這部分空間就釋放了,沒法繼續使用;操作系統數據段存的都是全局變量和static變量,所以這4個字段肯定存在heap上!所以建議重點關注執行heap內存的寄存器,和保存malloc分配地址的寄存器!
(3)根據上面的一些小技巧,不停地在棧上回溯,挨個查找、下斷點調試(這里純粹就是體力活了),找到幾個新的地址:
- R1指向的地址包含了X-Argus和X-Gorgon兩個字段,代碼偏移:0x14204
有時還能一次性出4個字段:
在這附近,有時候還能一次集齊5個字段:偏移0x1424C
這里看代碼更清晰:R1來自棧上,很有可能是C1A5D24C這里函數執行后保存在棧上sp+0x5c的!
- R1指向的地址包含了X-Gorgon,代碼偏移:0xD20C
這里也能找到X-Argus:
X-Tyhon也出現了:
- R1指向的地址包含了X-Argus,代碼偏移:0xD022
同樣的偏移,R1指向了X-Ladon;從代碼看,地址來自傳入的R1;
執行完 BLX unk_C1A50690后,R0也指向了X-Tyhon:
繼續往上根據函數調用關系找R1:發現來自R0;偏移:0x35008;這里的代碼看起來是不是有點奇怪了:
- 每段代碼都是push開頭、pop結尾,經過多次調試觀察,每段代碼都被執行過,這里感覺有點像VMP的handler;
- R2指向的是函數代碼入口,很有可能是通過BLX R2跳轉到這里的!通過寄存器的間接調用,可以防止在IDA通過xrefs查找調用關系,這是一絕啊!這該怎么繼續回溯了?看棧上我標紅的地址,從這里開始繼續回溯!
果然是通過BX R2跳轉的!這里的offset:C1A7DDE8-C1A49000=0x34DE8;IDA在這里還標注了引用關系,順着這個繼續回溯!
這里有點像VMP的入口,根據不同的R2跳轉到不同的地址(就是上面0x35008附近的代碼,每段代碼除了BL跳轉的地址不同,其他完全一樣)
下面就是通過BX R2跳轉到不同的地址:
接着BX R2的代碼回溯(ida已經標注了):這里多出取了PC的值,R1和R2指向了比較奇怪的字符串,R4和R6指向了代碼地址,這么做的動機暫時不明! 先記下offset: C1A7DD56-C1A49000=0x34D56
其他重要偏移:0xD20E, 函數執行完后R1指向了X-argus:
偏移:0xD220,BL執行完R1就保存了X-argus的地址!
同樣的地方R1保存了X-Ladon:
這幾天通過棧回溯,找到了一些線索!但感覺還是沒找到直接生成這些字段的代碼;在目前找到的這些關鍵函數中,還是要想辦法trace一下,或用unidbg執行試試,看看完整的代碼是怎么執行的!