zoukankan      html  css  js  c++  java
  • ida动态调试so,在init_array和JNI_ONLOAD处下断点

        本文涉及到的apk。请在github下载https://github.com/jltxgcy/AliCrack/AliCrackme_2.apk

       0x00

        怎样在JNI_ONLOAD下断点。參考安卓逆向学习笔记(5) - 在JNI_Onload 函数处下断点避开针对IDA Pro的反调试。最好使用模拟器调试,确保 Attach to process后,相应进程在DDMS中出现小红蜘蛛。

        以下将怎样在init_array下断点,首先要找到so的init_array端。把so拖入ida,然后按Crtl+s,会出现该so的全部段。例如以下:

         

        进入.init_array。例如以下:

        

       当中sub_2378就是init_array的代码。

       

       我们在这里下断点,详细调试的步骤和在JNI_ONLOAD下断点调试是一样的。參考安卓逆向学习笔记(5) - 在JNI_Onload 函数处下断点避开针对IDA Pro的反调试。网上有非常多其它方法在init_array下断点。比如Android安全–linker载入so流程。在.init下断点。我还是认为上面的方法比較方便。

       调试时使用jdb -connect com.sun.jdi.SocketAttach:port=8700,hostname=localhost,有时会报例如以下错误:


        此时,我们先观察DDMS。


        使用jdb -connect com.sun.jdi.SocketAttach:port=8622,hostname=localhost就可以。


      0x01

       也讲一下ida静态分析so。

       首先列出C++源代码:

    #include "com_example_jnidemo_JniGg.h"
    
    int switch1(int a, int b, int i, int j, int k,int q){
    	char *w = "i am winner in this year";
    	switch (i){
    	case 1:
    		return a + b + j + k;
    		break;
    	case 2:
    		return a - b;
    		break;
    	case 3:
    		return a * b;
    		break;
    	case 4:
    		return a / b;
    		break;
    	default:
    		return a + b;
    		break;
    	}
    }
    
    JNIEXPORT jstring JNICALL Java_com_example_jnidemo_JniGg_ggPrintHello
      (JNIEnv * env, jobject this)
    {
    
         return (*env)->NewStringUTF(env, "Current Coin is --  ");
    
    }
    
    JNIEXPORT jint JNICALL Java_com_example_jnidemo_JniGg_getCoin
      (JNIEnv * env, jobject this)
    {
    
    	return switch1(1,2,1,4,5,6);
    
    }
        编译成so。然后拖进ida进行分析。

    .text:00000E38                 EXPORT Java_com_example_jnidemo_JniGg_getCoin
    .text:00000E38 Java_com_example_jnidemo_JniGg_getCoin
    .text:00000E38
    .text:00000E38 var_10          = -0x10
    .text:00000E38 var_C           = -0xC
    .text:00000E38
    .text:00000E38                 PUSH    {LR}
    .text:00000E3A                 SUB     SP, SP, #0xC
    .text:00000E3C                 MOVS    R3, #5
    .text:00000E3E                 STR     R3, [SP,#0x10+var_10]
    .text:00000E40                 MOVS    R3, #6
    .text:00000E42                 STR     R3, [SP,#0x10+var_C]
    .text:00000E44                 MOVS    R0, #1
    .text:00000E46                 MOVS    R1, #2
    .text:00000E48                 MOVS    R2, #1
    .text:00000E4A                 MOVS    R3, #4
    .text:00000E4C                 BL      switch1
    .text:00000E50                 ADD     SP, SP, #0xC
    .text:00000E52                 POP     {PC}
    .text:00000E52 ; End of function Java_com_example_jnidemo_JniGg_getCoin
        arm的參数传递规范,和函数中的局部变量定义规范,请參考ARM子函数定义中的參数放入寄存器的规则

    这里使用R0,R1。R2,R3来传递前4个參数,使用堆栈来传递后两个參数。

    .text:00000DEC
    .text:00000DEC                 EXPORT switch1
    .text:00000DEC switch1                                 ; CODE XREF: Java_com_example_jnidemo_JniGg_getCoin+14p
    .text:00000DEC
    .text:00000DEC arg_0           =  0
    .text:00000DEC
    .text:00000DEC                 PUSH    {R4,LR}
    .text:00000DEE ; 6:   v5 = a3 - 1;
    .text:00000DEE                 SUBS    R2, #1
    .text:00000DF0 ; 7:   v6 = a1;
    .text:00000DF0                 MOVS    R4, R0
    .text:00000DF2 ; 8:   result = a1 + a2;
    .text:00000DF2                 ADDS    R0, R0, R1
    .text:00000DF4 ; 9:   if ( (unsigned int)v5 <= 3 )
    .text:00000DF4                 CMP     R2, #3          ; switch 4 cases
    .text:00000DF6                 BHI     def_DFA         ; jumptable 00000DFA default case
    .text:00000DF8 ; 11:     result = v5;
    .text:00000DF8                 MOVS    R0, R2
    .text:00000DFA ; 12:     switch ( v5 )
    .text:00000DFA                 BL      __gnu_thumb1_case_uqi ; switch jump
    .text:00000DFA ; ---------------------------------------------------------------------------
    .text:00000DFE jpt_DFA         DCB 2                   ; jump table for switch statement
    .text:00000DFF                 DCB 0xA
    .text:00000E00                 DCB 7
    .text:00000E01                 DCB 0xC
    .text:00000E02 ; ---------------------------------------------------------------------------
    .text:00000E02 ; 15:         result = v6 + a2 + a4 + a5;
    .text:00000E02
    .text:00000E02 loc_E02                                 ; CODE XREF: switch1+Ej
    .text:00000E02                 LDR     R2, [SP,#8+arg_0] ; jumptable 00000DFA case 0
    .text:00000E04                 ADDS    R4, R4, R1
    .text:00000E06                 ADDS    R3, R4, R3
    .text:00000E08 ; 16:         break;
    .text:00000E08                 ADDS    R0, R3, R2
    .text:00000E0A
    .text:00000E0A def_DFA                                 ; CODE XREF: switch1+Aj
    .text:00000E0A                                         ; switch1+24j ...
    .text:00000E0A                 POP     {R4,PC}         ; jumptable 00000DFA default case
    .text:00000E0C ; ---------------------------------------------------------------------------
    .text:00000E0C ; 18:         result = a2 * v6;
    .text:00000E0C
    .text:00000E0C loc_E0C                                 ; CODE XREF: switch1+Ej
    .text:00000E0C                 MOVS    R0, R1          ; jumptable 00000DFA case 2
    .text:00000E0E                 MULS    R0, R4
    .text:00000E10 ; 19:         break;
    .text:00000E10                 B       def_DFA         ; jumptable 00000DFA default case
    .text:00000E12 ; ---------------------------------------------------------------------------
    .text:00000E12 ; 21:         result = v6 - a2;
    .text:00000E12
    .text:00000E12 loc_E12                                 ; CODE XREF: switch1+Ej
    .text:00000E12                 SUBS    R0, R4, R1      ; jumptable 00000DFA case 1
    .text:00000E14 ; 22:         break;
    .text:00000E14                 B       def_DFA         ; jumptable 00000DFA default case
    .text:00000E16 ; ---------------------------------------------------------------------------
    .text:00000E16 ; 24:         result = v6 / a2;
    .text:00000E16
    .text:00000E16 loc_E16                                 ; CODE XREF: switch1+Ej
    .text:00000E16                 MOVS    R0, R4          ; jumptable 00000DFA case 3
    .text:00000E18                 BLX     __divsi3
    .text:00000E1C ; 25:         break;
    .text:00000E1C ; 26:       default:
    .text:00000E1C                 B       def_DFA         ; jumptable 00000DFA default case
    .text:00000E1C ; End of function switch1
        在这个函数中因为使用了R4作为局部变量,所以在開始时要把R4放入堆栈,为了返回后程序能够继续执行,所以把LR也压入了堆栈。

    这样堆栈地址就减去了8个字节(R4,LR都被压入堆栈)。所以取第一个參数要使用指令LDR R2, [SP,#8+arg_0]。

  • 相关阅读:
    分享:CodeLite 5.1 发布,C++ 集成开发环境
    Elementary Sockets:readn, writen, and readline Functions
    How to handle boost::iostreams::gzip_dec C++ Forum
    分享:python/c++ 深拷贝与浅拷贝(转)写∽好
    我刚刚通过 @盛大网盘EverBox 分享了 Web协议与实践HTTP.、网络协议、缓存技术和....pdf, 欢迎大家下载!
    Is zlib threadsafe?
    print "\v"
    分享:混合编译c和cpp的makefile模板
    Elementary Sockets:readn, writen, and readline Functions
    c的socket教程 二进制 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7020148.html
Copyright © 2011-2022 走看看