zoukankan      html  css  js  c++  java
  • android逆向奇技淫巧二十二:ida栈回溯加密算法跟踪(未完待续)(七)

      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:
    ' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('
    ') + '
    ')

      用上面这个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执行试试,看看完整的代码是怎么执行的!

  • 相关阅读:
    QML的默认属性default property
    QtCreator下QML翻译
    QML开发常见错误(原)
    qt下的跨目录多工程编译(转)
    git使用笔记
    osgQt支持触摸屏
    Qt资源整理ING
    Visual assint x(转)
    C#开发重用方法
    UDP问题
  • 原文地址:https://www.cnblogs.com/theseventhson/p/15204159.html
Copyright © 2011-2022 走看看