美文网首页
iOS-逆向04-判断&循环&选择

iOS-逆向04-判断&循环&选择

作者: 一亩三分甜 | 来源:发表于2021-04-01 10:21 被阅读0次

    《iOS底层原理文章汇总》

    1.cmp(Compare)比较指令

       CMP 把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。
       一般CMP做完判断后会进行跳转,后面通常会跟上B指令!

    • BL 标号:跳转到标号处执行
    • B.LT 标号:比较结果是小于,执行标号,否则不跳转
    • B.LE 标号:比较结果是小于等于,执行标号,否则不跳转
    • B.GT 标号:比较结果是大于(greater than),执行标号,否则不跳转
    • B.GE 标号:比较结果是大于等于(greater than or equal to),执行标号,否则不跳转
    • B.EQ 标号:比较结果是等于,执行标号,否则不跳转
    • B.HI 标号:比较结果是无符号大于,执行标号,否则不跳转
    • B.NE 标号:比较结果不等于
    • B.HI 标号:无符号大于

    2.内存分区

    1.代码区:存放代码,可读,可执行,MachO文件只有一部分是代码,还有一部分是数据,还有一部分是MachO文件描述信息
    2.栈区:参数,局部变量,临时数据
    3.堆区:动态申请,可读,可写
    4.全局变量:可读可写
    5.常量区:只读

    I.全局变量和常量

    图片.png 图片.png

    68 61 68 61
    h a h a 前面四个字节表示haha

    0x104c93f9f: 68 61 68 61 00 01 00 00 00 1c 00 00 00 02 00 00 haha............
    0x104c93faf: 00 24 00 00 00 00 00 00 00 24 00 00 00 02 00 00 ..............

    以上两个十六个字节分别对应字符,x0获取到的内存地址属于字符串常量区,

    image
    0x104c9218c <+20>: adrp   x0, 1
    0x104c92190 <+24>: add    x0, x0, #0xf9f            ; =0xf9f 
    

    上面两句代码是如何得到字符串常量区的内存地址0x0000000104c93f9f并存放到x0寄存器中的呢?adrp表示以页来寻址(address page),将1的值左移12位,十六进制左移0x1000,相当于二进制左移12位,将当前pc寄存器的地址加上1左移12位的值,且将原来的地址最后3位(低12位)清零

    0x104c9218c --- > 0x104c9218c
    0x1000 0x1000

    0x104c93000得到尾数是000,则地址值是16的倍数,也是4的倍数,iOS中一页数据的大小PAGESIZE是16K,也就是会偏移0x4000,Mac中一页数据PAGESIZE的大小是4K,0x104c93000是一页数据的开头,加上偏移地址f9f得到存放字符串常量“haha”的内存地址0x104c93f9f

    image

    页号是在编译器编译时候确定的,以PC寄存器作为参照相当于以当前代码段的地址作为参照

    为什么不能直接加这个地址,需要偏移呢?
    我们不能得到一个确定的内存地址,但是我们能得到一个参照

    程序在内存中的地址通常会通过ASLR,即实际地址+ASLR = 偏移地址,ASLR -> 0x0000000102e18000,
    实际地址 + ASLR -> 0x0000000102e18000 = 偏移地址 0x0000000102e1e18c

    偏移值作为参照会有两种参照方式:从文件的起始位置偏移或从当前代码的地址偏移,常量区的内存地址的计算是从当前代码的地址偏移

    同理,取全局变量g的内存地址 0x104f16194 ---> 0x104f19648


    image 图片.png image

    通过汇编拿到地址-aspr 得到MachO文件中的地址
    0x f9f
    0x104c93f9f
    0xf9f的值是编译器给的

    image

    若是0x1002bf888 <+20>: adrp x0,2
    01002c1000
    最后结果是将“haha”字符串出放入x0寄存器中传入printf函数

    通过内存地址无法判断是字符串常量还是全局变量

    3.通过汇编代码还原高级语言

    1.编译当前工程

    2.在product目录下.app中显示包内容,将app同名的MachO文件拖入hopper disassembler v4中

    image 图片.png image

    直接adrp的地址已经算好,是没有aslr的地址0x100007000+0xf9f
    在MachOView烂苹果中查找0x100007f9f的地址,得到字符串常量haha的值,字符串常量存在String区

    image image

    同理查找全局变量g的值0x100009000 + 0x648
    在MachOView烂苹果中查找0x100009648的地址,得到全局变量g的值12,字符串常量存在String区,全局变量存在于section64,data部分

    图片.png 图片.png

    精简代码

    image

    得到原来高级代码

    image

    3.代码的执行流程并不关心,只关心执行的结果和原始的一样

    4.if

    image

    两者相减,若小于0,跳入loc_1000061c0
    若大于0,直接往下走

    image

    还原高级语言代码

    图片.png image

    5.循环(loop)

    do{}while();循环

    图片.png image

    while(){};循环

    image image

    for循环 和 while循环一模一样

    image 图片.png

    5.Switch

    1、假设switch语句的分支比较少的时候(例如3,少于4的时候没有意义)没有必要使用此结构,相当于if。
    2、各个分支常量的差值较大的时候,编译器会在效率还是内存进行取舍,这个时候编译器还是会编译成类似于if,else的结构。
    3、在分支比较多的时候:在编译的时候会生成一个表(跳转表每个地址四个字节)。

    switch三个case情况

    image image

    switch四个case情况:建立一张数据表8字节、8字节、8字节,将每一个条件要做的事情放到不同的连续地址8字节,得到index到数据表中去查找地址,找到后直接执行地址中保存的代码,通过一次运算,直接查表,找到要执行的地址,不需要多次if else判断

    switch判断条件比较多,一直if else会浪费时间比较多

    image image

    switch若判断条件无规则呢?没有查表,进行多次比较

    图片.png image

    条件有规律的情况下,如何建表,查表的呢?且看下文分析。

    相关文章

      网友评论

          本文标题:iOS-逆向04-判断&循环&选择

          本文链接:https://www.haomeiwen.com/subject/thsahltx.html