Android SO逆向-数组与指针

来源:互联网 发布:浙师大行知学院怎么样 编辑:程序博客网 时间:2024/06/04 19:03

    0x00

    这一节主要分析一维数组、二维数组、数组指针和指针数组的汇编实现。


    0x01

    我们先直接看C++代码:

#include "com_example_ndkreverse3_Lesson3.h"#include <android/log.h>#define LOG_TAG "lesson3"#define ALOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))//参考http://blog.csdn.net/jltxgcy/article/details/17756391JNIEXPORT void JNICALL Java_com_example_ndkreverse3_Lesson3_main  (JNIEnv * env, jobject jobject) {int a[] = {1,2,3,4,5,6};for(int i = 0; i< 6; i++) {ALOGD("a=%d\n", a[i]);}}JNIEXPORT void JNICALL Java_com_example_ndkreverse3_Lesson3_main1  (JNIEnv * env, jobject jobject) {int b[][3]={{1,2},{3,4,5}};for(int i = 0; i< 2; i++) {for(int j = 0; j < 3; j++) {ALOGD("b=%d\n", b[i][j]);}}}JNIEXPORT void JNICALL Java_com_example_ndkreverse3_Lesson3_main2  (JNIEnv * env, jobject jobject) {char *d[] = {"12","345","6789"};for(int i = 0; i< 3; i++) {for(int j = 0; j < 4; j++) {ALOGD("d=%d\n", *(*(d + i) + j));}}}JNIEXPORT void JNICALL Java_com_example_ndkreverse3_Lesson3_main3  (JNIEnv * env, jobject jobject) {int a[] = {1,2,3,4,5,6};int *p = a;for(int i = 0; i< 6; i++) {ALOGD("p=%d\n", *(p + i));}}JNIEXPORT void JNICALL Java_com_example_ndkreverse3_Lesson3_main4  (JNIEnv * env, jobject jobject) {int b[][3]={{1,2},{3,4,5}};int (*p)[3] = b;for(int i = 0; i< 2; i++) {for(int j = 0; j < 3; j++) {ALOGD("p=%d\n", *(*(p + i) + j));}}}


    0x01

    下面我们用ida打开so,分别对不同函数的汇编形式的代码做出解释。

    Java_com_example_ndkreverse3_Lesson3_main:

.text:00000EC8                 EXPORT Java_com_example_ndkreverse3_Lesson3_main.text:00000EC8 Java_com_example_ndkreverse3_Lesson3_main.text:00000EC8.text:00000EC8 var_2C          = -0x2C.text:00000EC8 var_14          = -0x14.text:00000EC8.text:00000EC8                 PUSH    {R4-R6,LR}.text:00000ECA                 SUB     SP, SP, #0x20 ;开发了0x20个地址空间作为存储堆栈的位置.text:00000ECC                 ADD     R4, SP, #0x30+var_2C ;R4赋值为SP+4.text:00000ECE                 MOVS    R1, R4               ;R1和R4的值一样.text:00000ED0                 LDR     R2, =(__stack_chk_guard_ptr - 0xED6) ;位于.got段中__stack_chk_guard_ptr相对于下一条PC指令的偏移,取出来赋值给R2.text:00000ED2                 ADD     R2, PC ; __stack_chk_guard_ptr       ;R2中存放的是位于.got段中__stack_chk_guard_ptr的地址.text:00000ED4                 LDR     R2, [R2] ; __stack_chk_guard         ;取地址中的内容,我们看下面代码,这个地址是__stack_chk_guard,这个地址运行时分配的.text:00000ED6                 LDR     R3, [R2]                             ;取这个地址中的内容,我在动态调试状态下得到的内容为6BCAA164.text:00000ED8                 STR     R3, [SP,#0x30+var_14]                ;把这个值6BCAA164存放在SP+0x1C的位置.text:00000EDA                 LDR     R3, =(unk_226C - 0xEE0)              ;位于.rodata,unk_226C相对于下一条PC指令的偏移,取出来赋值给R3.text:00000EDC                 ADD     R3, PC ; unk_226C                    ;R3存放的是位于.rodata段中unk_226C的地址.text:00000EDE                 LDMIA   R3!, {R0,R5,R6}                      ;将R3地址堆栈中的内容依次赋值给R0,R5,R6.text:00000EE0                 STMIA   R1!, {R0,R5,R6}                      ;将R0,R5,R6的值分配存放到R1所指向的堆栈中,也就是刚才SUB SP,SP,#0x20,然后再加4的堆栈.text:00000EE2                 LDMIA   R3!, {R0,R5,R6}            ;同理.text:00000EE4                 STMIA   R1!, {R0,R5,R6}                      ;同理,这样堆栈中就初始化好了1,2,3,4,5,6。PS:堆栈中存放6的下一个地址中的数值就是0x6BCAA164.text:00000EE6                 MOVS    R6, #0                               ;R6初始化为9.text:00000EE8                 ADDS    R5, R2, #0                           ;R5初始化为R2,也就是__stack_chk_guard的地址.text:00000EEA.text:00000EEA loc_EEA                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main+36j.text:00000EEA                 LDR     R1, =(aLesson3 - 0xEF6).text:00000EEC                 LDR     R2, =(aAD - 0xEF8).text:00000EEE                 LDR     R3, [R4,R6]             ;从堆栈中取数.text:00000EF0                 MOVS    R0, #3.text:00000EF2                 ADD     R1, PC          ; "lesson3".text:00000EF4                 ADD     R2, PC          ; "a=%d\n".text:00000EF6                 ADDS    R6, #4                  ;为取下一个数做准备.text:00000EF8                 BL      j_j___android_log_print.text:00000EFC                 CMP     R6, #0x18               ;R6和0x18做比较.text:00000EFE                 BNE     loc_EEA                 ;如果不相等,就跳转到loc_EEA.text:00000F00                 LDR     R2, [SP,#0x30+var_14]   ;否则取出原来存入堆栈中的内容,为0x6BCAA164.text:00000F02                 LDR     R3, [R5]                ;从R5地址中取出的值赋值给R3,刚才R5被赋值为__stack_chk_guard的地址.text:00000F04                 CMP     R2, R3                  ;比较R2和R3的值.text:00000F06                 BEQ     loc_F0C                 ;如果相等,就跳转到loc_F0C.text:00000F08                 BL      j_j___stack_chk_fail    ;否则堆栈检查失败.text:00000F0C ; ---------------------------------------------------------------------------.text:00000F0C.text:00000F0C loc_F0C                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main+3Ej.text:00000F0C                 ADD     SP, SP, #0x20.text:00000F0E                 POP     {R4-R6,PC}
.text:00000F10 off_F10         DCD __stack_chk_guard_ptr - 0xED6.text:00000F10                                         ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main+8r.text:00000F14 off_F14         DCD unk_226C - 0xEE0    ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main+12r.text:00000F18 off_F18         DCD aLesson3 - 0xEF6    ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main:loc_EEAr.text:00000F18                                         ; "lesson3".text:00000F1C off_F1C         DCD aAD - 0xEF8         ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main+24r.text:00000F1C                                         ; "a=%d\n"
.got:00003FAC __stack_chk_guard_ptr DCD __stack_chk_guard
.rodata:0000226C unk_226C        DCB    1                ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main+14o.rodata:0000226C                                         ; Java_com_example_ndkreverse3_Lesson3_main+16o ....rodata:0000226D                 DCB    0.rodata:0000226E                 DCB    0.rodata:0000226F                 DCB    0.rodata:00002270                 DCB    2.rodata:00002271                 DCB    0.rodata:00002272                 DCB    0.rodata:00002273                 DCB    0.rodata:00002274                 DCB    3.rodata:00002275                 DCB    0.rodata:00002276                 DCB    0.rodata:00002277                 DCB    0.rodata:00002278                 DCB    4.rodata:00002279                 DCB    0.rodata:0000227A                 DCB    0.rodata:0000227B                 DCB    0.rodata:0000227C                 DCB    5.rodata:0000227D                 DCB    0.rodata:0000227E                 DCB    0.rodata:0000227F                 DCB    0.rodata:00002280                 DCB    6.rodata:00002281                 DCB    0.rodata:00002282                 DCB    0.rodata:00002283                 DCB    0

    我们可以看到首先开辟了堆栈来存储数组元素,数组元素的初始化值被放在了.rodata中。里面还有堆栈保护的代码。详情请参考代码中的注释。


    Java_com_example_ndkreverse3_Lesson3_main1:

.text:00000F20                 EXPORT Java_com_example_ndkreverse3_Lesson3_main1.text:00000F20 Java_com_example_ndkreverse3_Lesson3_main1.text:00000F20.text:00000F20 s               = -0x2C.text:00000F20 var_14          = -0x14.text:00000F20.text:00000F20                 PUSH    {R4-R6,LR}.text:00000F22                 LDR     R4, =(__stack_chk_guard_ptr - 0xF2C) .text:00000F24                 SUB     SP, SP, #0x20   ;开辟堆栈.text:00000F26                 ADD     R5, SP, #0x30+s.text:00000F28                 ADD     R4, PC ; __stack_chk_guard_ptr.text:00000F2A                 LDR     R4, [R4] ; __stack_chk_guard.text:00000F2C                 MOVS    R0, R5          ; s.text:00000F2E                 LDR     R3, [R4].text:00000F30                 MOVS    R1, #0          ; c.text:00000F32                 MOVS    R2, #0x18       ; n.text:00000F34                 STR     R3, [SP,#0x30+var_14].text:00000F36                 BL      j_j_memset      ;将s中前n个字节用 c(0) 替换并返回 s 。.text:00000F3A                 MOVS    R3, #1.text:00000F3C                 STR     R3, [SP,#0x30+s] ;初始化堆栈中的数组.text:00000F3E                 MOVS    R3, #2.text:00000F40                 STR     R3, [R5,#4]      ;[R5,#8]直接略过.text:00000F42                 MOVS    R3, #3.text:00000F44                 STR     R3, [R5,#0xC].text:00000F46                 MOVS    R3, #4.text:00000F48                 STR     R3, [R5,#0x10].text:00000F4A                 MOVS    R3, #5.text:00000F4C                 MOVS    R6, #0.text:00000F4E                 STR     R3, [R5,#0x14].text:00000F50.text:00000F50 loc_F50                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main1+44j.text:00000F50                 LDR     R1, =(aLesson3 - 0xF5C).text:00000F52                 LDR     R2, =(aBD - 0xF5E).text:00000F54                 LDR     R3, [R5,R6]     ;取数组元素,R5是 sp - 0x20 + 0x4,分别取出1,2,0.text:00000F56                 MOVS    R0, #3.text:00000F58                 ADD     R1, PC          ; "lesson3".text:00000F5A                 ADD     R2, PC          ; "b=%d\n".text:00000F5C                 ADDS    R6, #4.text:00000F5E                 BL      j_j___android_log_print.text:00000F62                 CMP     R6, #0xC        ;R6的值与0xC的值比较.text:00000F64                 BNE     loc_F50         ;如果不相等,就跳转到loc_F50.text:00000F66                 MOVS    R6, #0          ;否则,继续运行.text:00000F68.text:00000F68 loc_F68                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main1+5Ej.text:00000F68                 LDR     R1, =(aLesson3 - 0xF76).text:00000F6A                 LDR     R2, =(aBD - 0xF78).text:00000F6C                 ADDS    R3, R5, R6.text:00000F6E                 LDR     R3, [R3,#0xC]   ;取数组元素,分别取出3,4,5.text:00000F70                 MOVS    R0, #3.text:00000F72                 ADD     R1, PC          ; "lesson3".text:00000F74                 ADD     R2, PC          ; "b=%d\n".text:00000F76                 ADDS    R6, #4.text:00000F78                 BL      j_j___android_log_print.text:00000F7C                 CMP     R6, #0xC.text:00000F7E                 BNE     loc_F68         ;和loc_F50同理.text:00000F80                 LDR     R2, [SP,#0x30+var_14]  .text:00000F82                 LDR     R3, [R4].text:00000F84                 CMP     R2, R3          ;堆栈检查.text:00000F86                 BEQ     loc_F8C.text:00000F88                 BL      j_j___stack_chk_fail.text:00000F8C ; ---------------------------------------------------------------------------.text:00000F8C.text:00000F8C loc_F8C                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main1+66j.text:00000F8C                 ADD     SP, SP, #0x20.text:00000F8E                 POP     {R4-R6,PC}
.text:00000F90 off_F90         DCD __stack_chk_guard_ptr - 0xF2C.text:00000F90                                         ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main1+2r.text:00000F94 off_F94         DCD aLesson3 - 0xF5C    ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main1:loc_F50r.text:00000F94                                         ; "lesson3".text:00000F98 off_F98         DCD aBD - 0xF5E         ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main1+32r.text:00000F98                                         ; "b=%d\n".text:00000F9C off_F9C         DCD aLesson3 - 0xF76    ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main1:loc_F68r.text:00000F9C                                         ; "lesson3".text:00000FA0 off_FA0         DCD aBD - 0xF78         ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main1+4Ar.text:00000FA0                                         ; "b=%d\n"
.rodata:00002284 aLesson3        DCB "lesson3",0         ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main+2Ao.rodata:00002284                                         ; .text:off_F18o ....rodata:0000228C aAD             DCB "a=%d",0xA,0        ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main+2Co.rodata:0000228C                                         ; .text:off_F1Co ....rodata:00002292 aBD             DCB "b=%d",0xA,0        ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main1+3Ao.rodata:00002292                                         ; Java_com_example_ndkreverse3_Lesson3_main1+54o ...
    我们看到二维数组的本质上和一维数组是一致的,这里二维数组初始化的值并不是存放在.rodata段中,而是用寄存器赋值。

    Java_com_example_ndkreverse3_Lesson3_main2:
.text:00000FA4                 EXPORT Java_com_example_ndkreverse3_Lesson3_main2.text:00000FA4 Java_com_example_ndkreverse3_Lesson3_main2.text:00000FA4.text:00000FA4 var_28          = -0x28.text:00000FA4 var_24          = -0x24.text:00000FA4 var_20          = -0x20.text:00000FA4 var_1C          = -0x1C.text:00000FA4.text:00000FA4                 LDR     R3, =(__stack_chk_guard_ptr - 0xFAC).text:00000FA6                 PUSH    {R4-R7,LR}.text:00000FA8                 ADD     R3, PC ; __stack_chk_guard_ptr.text:00000FAA                 LDR     R3, [R3] ; __stack_chk_guard.text:00000FAC                 SUB     SP, SP, #0x14        ;开辟堆栈.text:00000FAE                 MOV     R6, SP.text:00000FB0                 MOVS    R5, #0.text:00000FB2                 MOVS    R4, R3.text:00000FB4                 LDR     R2, [R3].text:00000FB6                 STR     R2, [SP,#0x28+var_1C] ;存入堆栈保护数值.text:00000FB8                 LDR     R2, =(a12 - 0xFBE).text:00000FBA                 ADD     R2, PC          ; "12" ;向堆栈中存入"12"的地址.text:00000FBC                 STR     R2, [SP,#0x28+var_28].text:00000FBE                 LDR     R2, =(a345 - 0xFC4).text:00000FC0                 ADD     R2, PC          ; "345" ;向堆栈中存入"345"的地址.text:00000FC2                 STR     R2, [SP,#0x28+var_24].text:00000FC4                 LDR     R2, =(a6789 - 0xFCA).text:00000FC6                 ADD     R2, PC          ; "6789" ;“向堆栈中村如6789”的地址.text:00000FC8                 STR     R2, [SP,#0x28+var_20].text:00000FCA.text:00000FCA loc_FCA                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main2+44j.text:00000FCA                 MOVS    R7, #0.text:00000FCC.text:00000FCC loc_FCC                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main2+3Ej.text:00000FCC                 LDR     R3, [R6,R5]     ;从堆栈中取出首地址.text:00000FCE                 LDR     R1, =(aLesson3 - 0xFDA).text:00000FD0                 LDR     R2, =(aDD - 0xFDC).text:00000FD2                 LDRB    R3, [R3,R7]     ;从.rodata段中取出字符.text:00000FD4                 MOVS    R0, #3.text:00000FD6                 ADD     R1, PC          ; "lesson3".text:00000FD8                 ADD     R2, PC          ; "d=%d\n".text:00000FDA                 ADDS    R7, #1          ;每次加1,取一个字符.text:00000FDC                 BL      j_j___android_log_print.text:00000FE0                 CMP     R7, #4          ;.text:00000FE2                 BNE     loc_FCC         ;第二层循环.text:00000FE4                 ADDS    R5, #4          ;取下一个指针,也是下一个字符串的首地址.text:00000FE6                 CMP     R5, #0xC.text:00000FE8                 BNE     loc_FCA         ;第一层循环.text:00000FEA                 LDR     R2, [SP,#0x28+var_1C].text:00000FEC                 LDR     R3, [R4].text:00000FEE                 CMP     R2, R3.text:00000FF0                 BEQ     loc_FF6.text:00000FF2                 BL      j_j___stack_chk_fail.text:00000FF6 ; ---------------------------------------------------------------------------.text:00000FF6.text:00000FF6 loc_FF6                                 ; CODE XREF: Java_com_example_ndkreverse3_Lesson3_main2+4Cj.text:00000FF6                 ADD     SP, SP, #0x14.text:00000FF8                 POP     {R4-R7,PC}
.rodata:00002284 a12             DCB "12",0              ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main2+16o.rodata:00002284                                         ; .text:off_1000o.rodata:00002287 a345            DCB "345",0             ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main2+1Co.rodata:00002287                                         ; .text:off_1004o.rodata:0000228B a6789           DCB "6789",0            ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main2+22o.rodata:0000228B                                         ; .text:off_1008o.rodata:00002290 aDD             DCB "d=%d",0xA,0        ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main2+34o.rodata:00002290                                         ; .text:off_1010o.rodata:00002296 aPD             DCB "p=%d",0xA,0        ; DATA XREF: Java_com_example_ndkreverse3_Lesson3_main3+2Co.rodata:00002296                                         ; .text:off_1068o ...

    指针数组的执行请参考代码中的注释,字符串依然存储在.rodata段中。依然是开辟堆栈空间去存储指针数组。


    Java_com_example_ndkreverse3_Lesson3_main3(指针)和Java_com_example_ndkreverse3_Lesson3_main汇编代码是一致的。

    Java_com_example_ndkreverse3_Lesson3_main4(数组指针)和Java_com_example_ndkreverse3_Lesson3_main1汇编代码是一致的。    

0 0
原创粉丝点击