iOS逆向安防从入门到秃头--初探函数篇

1,028 阅读3分钟

小谷秃头合集

  • 雷迪斯俺的枕头们。小谷又来学习了~ 今天说一波比较常用--函数~

  • 兄弟们都听说过函数调用栈,今天就从汇编层次简单的理解下函数~

1. 栈

1.1. 栈的概念

  • 函数调用栈,不是通常所说的说的数据结构,这个栈指的是拥有特殊访问能力的存储空间FILO:first in last out,先进后出

  • 来一波图(我比较喜欢偷图,就离谱😆)

1.jpg

1.2. 栈的关键点

    1. 现在arm64,已经弱化了的形式,没有32位的(push,pop)操作了
    1. iOS开发中,栈是由高地址走向低地址存储
    1. iOS开发中。sp(栈顶指针)指向存储是向高地址
    1. 小谷画了一波图~(这个图是我画的)

2.png

1.3. SP和FP寄存器

上面那个图画的时候用的了sp,下面解释一下

  • SP寄存器:一直保存栈顶的地址

  • FP寄存器:有些时候需要他保存着栈底的地址,也是X29寄存器。

注:arm64 架构,对栈的操作是16字节对齐

1.4. 函数调用栈

  • 兄弟们应该都听说过函数调用栈,我们简单写一个函数看一波

简单函数调用

3.png

  • 常见的函数调用和开辟空间~

4.png

  • ";"代表注释~
StackFuncDemo`stackFuncTest:
->  0x102afa20c <+0>:  stp    x29, x30, [sp, #-0x10]!;首先将sp(栈顶指针)向低地址拉伸0x10,”!”代表拉伸完偏移sp,之后取地址,存储x29,x30寄存器
    0x102afa210 <+4>:  mov    x29, sp ;将sp(栈顶指针)存储的值压入x29
    0x102afa214 <+8>:  adrp   x0, 1
    0x102afa218 <+12>: add    x0, x0, #0xf69            ; =0xf69 
    0x102afa21c <+16>: bl     0x102afa5ac              ; symbol stub for: printf
    0x102afa220 <+20>: ldp    x29, x30, [sp], #0x10 ;将sp(栈顶指针)所在地址取值给x29,x30,然后在向高地址回放0x10,(栈平衡)
    0x102afa224 <+24>: ret  ;返回

这里面的倒数第二句,为什么要把sp所在地址的值重新赋值给x29,x30?,难道bl指令的时候,这其中寄存器发生改变了?

2. bl和ret指令

2.1. bl指令

    1. 上面我们看到了,bl操作过好像会发生改变。耐不住寂寞的我必须要来观察一波了
    1. 不知道大家是否和我一样:我马上去查了下bl指令

将下一条指令的地址放入lr(x30)寄存器

跳转到标号处执行指令

    1. 那我们观察下是否是lr(x30)寄存器调用bl之后发生改变就好了~
    1. 简单写个函数嵌套调用
void test2(){
    
}

void test1(){
    test2();
}

int main(int argc, char * argv[]) {
    
    printf("test-now\n");
//    stackFuncTest();
    test1();
    printf("test--end\n”);
}
    1. 断点看汇编~

5.png

我们证明了上面的问题,通过bl指令的确会是x30寄存器(别名:lr)发生改变

2.2. ret 指令

  • ret指令其实就是返回的意思

  • ret指令是跳转到x30寄存器里面所指向的地址~