iOS逆向-05: 指针
2021-05-03 本文已影响0人
恍然如梦_b700
在oc中对象其实是结构体指针,当然在oc中都叫对象,为了研究对象,这里简单补充一下指针
下面代码输出什么?
void test() {
int *a;
a = (int *)10;
a++;
printf("%d",a);
}
14?

为什么呢?这里其实是c语言的知识了
- 指针的自增自减和执行的数据类型的宽度有关!
- 指针的运算单位是执行的数据类型的宽度!
也就是说当指针+n的时候,也就是10+n*sizeof(Int)
但是这么写显然不符合常理😀,这里只是了解一下指针的运算
一般我们这么写
void test() {
int *a;
int b = 10;
a = &b;
printf("%d",*a);
}
我们主要研究汇编是如何实现的

主要研究一下圈出的部分
- add x8, sp, #0x4 ; =0x4
x8 指向 sp + 0x4 这个地址 - mov w9, #0xa
w9 寄存器值赋值为0xa ,相当于int b = 10 - str w9, [sp, #0x4]
w9的值存入到sp + 0x4 这个地址,此时x8也是指向这个地址的 - str x8, [sp, #0x8]
x8存入到sp + 0x8这个地址。
也就是说sp + 0x8这个地址里面存的就是指向10的这个指针,也就是指针变量
指针和数组
基本用法,可以了解一下
void testAry() {
int arr[5] = {1,2,3,4,5};
int * a = arr; for (int i = 0; i < 5; i++) {
printf("%d",*(a++));
}
printf("boy");
}
int *a; //在iOS中是0x0
int b = *a;//运行时崩溃,野指针

可以看到x8为0 在通过x8的地址[0x0]取值的时候就会崩溃,这也就是野指针在汇编层面的崩溃
二级指针
int ** p;
int c = **p;

这种两次ldr取值的形式一般为二级指针,拉伸空间为0x10,这也可以说明开辟空间是以16字节对齐的
那我们看下面代码要拉伸多少呢
void pointer() {
// int *a; //在iOS中是0x0
// int b = *a;//运行时崩溃,野指针
int ** p;
int ** k;
char a;
}
8 + 8 + 1 = 17 ,16字节对齐为32那也就是要拉伸0x20,看汇编验证

我们来看看二级指针的偏移
void pointer() {
// int *a; //在iOS中是0x0
// int b = *a;//运行时崩溃,野指针
int ** p;
int c = *(*(p+2) + 3);
}

*(p+2) 偏移了0x10 因为p 是int **类型 是指针占8个字节
((p+2) + 3); (p+2)的类型是 int * ,按照数据类型的宽度相加 也就是 4 所以偏移0xc(34)