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.youkuaiyun.com/jltxgcy/article/details/17756391
JNIEXPORT 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}