iOS 逆向开发 文章汇总
目录
- 一、指针基础
1.1 指针的大小、1.2 指针的运算 - 二、指针的汇编
2.1普通指针、2.2 数组指针、2.3 指针取值、2.4 多级指针
一、指针基础
1.1 指针的大小
void func() {
int *a;
printf("%lu",sizeof(a));
}
int main(int argc, char * argv[]) {
func();
return 0;
}
003--指针`func:
0x1046a1ffc <+0>: sub sp, sp, #0x20 ; =0x20
0x1046a2000 <+4>: stp x29, x30, [sp, #0x10]
0x1046a2004 <+8>: add x29, sp, #0x10 ; =0x10
0x1046a2008 <+12>: adrp x0, 1
0x1046a200c <+16>: add x0, x0, #0xe15 ; 将printf的参数%lu(常量区)取出来作为第一个参数
0x1046a2010 <+20>: mov x8, sp
-> 0x1046a2014 <+24>: mov x9, #0x8
0x1046a2018 <+28>: str x9, [x8] ; 直接将指针的大小#0x8保存到栈顶作为第二个参数传递
0x1046a201c <+32>: bl 0x1046a239c ; symbol stub for: printf
0x1046a2020 <+36>: ldp x29, x30, [sp, #0x10]
0x1046a2024 <+40>: add sp, sp, #0x20 ; =0x20
0x1046a2028 <+44>: ret
从汇编中可以看到指针的宽度是8个字节, sizeof的本质就是一个操作符:sizeof(int)=4
1.2 指针的运算
思考以下fucn
函数的输出
指针的加法:
void func() {
int *a;
a = (int *)100;
printf("%d",a);
}
void func() {
int *a;
a = (int *)100;
a++;
printf("%d",a);
}
void func() {
char *a;
a = (char *)100;
a++;
printf("%d",a);
}
void func() {
int **a;
a = (int **)100;
a++;
printf("%d",a);
}
void func() {
int **a;
a = (int **)100;
a = a + 1;
printf("%d",a);
}
指针的减法:
void func() {
int *a;
a = (int *)100;
int *b;
b = (int *)200;
int x = a - b;
printf("%d",x);
}
答案:
加法:100、104、101、108、108
减法:-25:指针的运算单位是指向的数据类型的宽度!!
指针的自增自减和执行的数据类型的宽度有关!
类型可以强制转换,但是结构体和基本数据类型不能强制转换。任何变量都可以使用&获取地址
二、指针的汇编
2.1普通指针
void func() {
int *a;
int b = 10;
a = &b;
printf("hello");
}
003--指针`func:
-> 0x1044b1ff8 <+0>: sub sp, sp, #0x20 ; =0x20
0x1044b1ffc <+4>: stp x29, x30, [sp, #0x10]
0x1044b2000 <+8>: add x29, sp, #0x10 ; =0x10
0x1044b2004 <+12>: add x8, sp, #0x4 ; x8指向sp+ #0x4地址
0x1044b2008 <+16>: mov w9, #0xa ; w9 = 10
0x1044b200c <+20>: str w9, [sp, #0x4] ; 将10存储到sp+#0x4地址
0x1044b2010 <+24>: str x8, [sp, #0x8] ; 将x8指向sp+#0x4地址保存到sp+#0x8地址
0x1044b2014 <+28>: adrp x0, 1
0x1044b2018 <+32>: add x0, x0, #0xe15 ; 取出“hello”字符串常量
0x1044b201c <+36>: bl 0x1044b239c ; symbol stub for: printf
0x1044b2020 <+40>: ldp x29, x30, [sp, #0x10]
0x1044b2024 <+44>: add sp, sp, #0x20 ; =0x20
0x1044b2028 <+48>: ret
2.2 数组指针:
void func() {
int arr[5] = {1,2,3,4,5};
for (int i = 0; i < 5; i++) {
printf("%d",arr[i]);
printf("%d",*(arr + 1));
// int *a == &arr[0] == arr
}
printf("\nhello");
}
2.3 指针取值:
void func() {
int *p1;//指针 --> (X8)0x0
char c1 = *p1;//从p1地址取值
}
003--指针`func:
0x104f2602c <+0>: sub sp, sp, #0x10 ; 拉伸栈空间
0x104f26030 <+4>: ldr x8, [sp, #0x8] ; x8表示p1指针的默认值0x0
-> 0x104f26034 <+8>: ldr w9, [x8] ; 从0x0地址取值--->Crash
0x104f26038 <+12>: strb w9, [sp, #0x7]
0x104f2603c <+16>: add sp, sp, #0x10 ; =0x10
0x104f26040 <+20>: ret
void func() {
int *p1;//指针 --> (X8)0x0
char c1 = *p1;//[x8]
char d = *(p1 + 1);//[x8,#0x4]------>重点是加4
}
003--指针`func:
-> 0x1021fe020 <+0>: sub sp, sp, #0x10 ; 拉伸栈空间
0x1021fe024 <+4>: ldr x8, [sp, #0x8] ; x8表示p1指针的默认值0x0
0x1021fe028 <+8>: ldr w9, [x8] ; 从0x0地址取值--->Crash
0x1021fe02c <+12>: strb w9, [sp, #0x7] ; 存储c1变量到w9
0x1021fe030 <+16>: ldr x8, [sp, #0x8] ; x8表示p1指针的默认值0x0
0x1021fe034 <+20>: ldr w9, [x8, #0x4] ; 计算*(p1 + 1)
0x1021fe038 <+24>: strb w9, [sp, #0x6] ; 存储d变量到w9
0x1021fe03c <+28>: add sp, sp, #0x10 ; =0x10
0x1021fe040 <+32>: ret
2.4 多级指针:
void func() {
char **p1;
char c = **p1;
}
003--指针`func:
-> 0x1042b2028 <+0>: sub sp, sp, #0x10 ; =0x10
0x1042b202c <+4>: ldr x8, [sp, #0x8]
0x1042b2030 <+8>: ldr x8, [x8]
0x1042b2034 <+12>: ldrb w9, [x8] ;两次指针地址取值
0x1042b2038 <+16>: strb w9, [sp, #0x7]
0x1042b203c <+20>: add sp, sp, #0x10 ; =0x10
0x1042b2040 <+24>: ret
void func() {
char **p1;
char c = *(*(p1 + 2) + 2);
}
003--指针`func:
-> 0x100b96028 <+0>: sub sp, sp, #0x10 ; =0x10
0x100b9602c <+4>: ldr x8, [sp, #0x8]
0x100b96030 <+8>: ldr x8, [x8, #0x10] ; 第一次+0x10
0x100b96034 <+12>: ldrb w9, [x8, #0x2] ; 第二次+0x2
0x100b96038 <+16>: strb w9, [sp, #0x7]
0x100b9603c <+20>: add sp, sp, #0x10 ; =0x10
0x100b96040 <+24>: ret