iOS 逆向与安全

iOS逆向与安全11.1:初识汇编

2019-07-10  本文已影响0人  looha

初识汇编

我们是逆向iOS系统上面的APP.那么我们知道,一个APP安装在手机上面的可执行文件本质上是二进制文件.因为iPhone手机本质上执行的指令是二进制.是由手机上的CPU执行的.所以静态分析是建立在分析二进制上面.静态分析的基础是汇编,可以说掌握汇编知识的多少,决定着在逆向以及安全的道路上你能走多远。

汇编语言的发展

机器语言

由0和1组成的机器指令.

汇编语言(assembly language)

使用助记符代替机器语言

如:

高级语言(High-level programming language)

C\C++\Java\OC\Swift,更加接近人类的自然语言
比如C语言:

代码在终端设备上执行的过程:

代码执行

汇编语言的特点

汇编的用途

  1. 函数的本质究竟是什么?

  2. ++a + ++a + ++a 底层如何执行的?

3.编译器到底帮我们干了什么?

4.DEBUG模式和RELEASE模式有什么关键的地方被我们忽略

越底层越单纯!真正的程序员都需要了解的一门非常重要的语言,汇编!

汇编语言的种类

目前讨论比较多的汇编语言有

几个必要的常识

- 要想学好汇编,首先需要了解CPU等硬件结构
- APP/程序的执行过程
APP/程序的执行过程
- 硬件相关最为重要是CPU/内存
- 在汇编中,大部分指令都是和CPU与内存相关的

总线

image.png
- 每一个CPU芯片都有许多管脚,这些管脚和总线相连,CPU通过总线跟外部器件进行交互
- 总线:一根根导线的集合
- 总线的分类
image.png CPU工作流程
--地址总线
地址标示
--数据总线

cpu架构由数据总线来区分 arm32,arm64等等

控制总线
练习

内存

2990730-cb3c46652c7bad8e.png 2990730-49e73b88a2e7af92.png 2990730-d723c11cce5cdaaf.png

堆:低往高写
栈:高往低写

写入和读取后,给定地址后,数据写入从低往高写。

进制

很多人学不好进制,原因是总以十进制为依托去考虑其他进制,需要运算的时候也总是先转换成十进制,这种学习方法是错误的.
我们为什么一定要转换十进制呢?仅仅是因为我们对十进制最熟悉,所以才转换.
每一种进制都是完美的,想学好进制首先要忘掉十进制,也要忘掉进制间的转换!

进制的定义

自定义进制符号

进制的运算

0 1 2 3 4 5 6 7
10 11 12 13 14 15 16 17
20 21 22 23 24 25 26 27
...

1+1 = 2
1+2 = 3 2+2 = 4
1+3 = 4 2+3 = 5 3+3 = 6
1+4 = 5 2+4 = 6 3+4 = 7 4+4 = 10
1+5 = 6 2+5 = 7 3+5 = 10 4+5 = 11 5+5 = 12
1+6 = 7 2+6 = 10 3+6 = 11 4+6 = 12 5+6 = 13 6+6 = 14
1+7 = 10 2+7 = 11 3+7 = 12 4+7 = 13 5+7 = 14 6+7 = 15 7+7 = 16

0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27...
1x1 = 1
1x2 = 2 2x2 = 4
1x3 = 3 2x3 = 6 3x3 = 11
1x4 = 4 2x4 = 10 3x4 = 14 4x4 = 20
1x5 = 5 2x5 = 12 3x5 = 17 4x5 = 24 5x5 = 31
1x6 = 6 2x6 = 14 3x6 = 22 4x6 = 30 5x6 = 36 6x6 = 44
1x7 = 7 2x7 = 16 3x7 = 25 4x7 = 34 5x7 = 43 6x7 = 52 7x7 = 61

二进制的简写形式


       二进制: 1 0 1 1 1 0 1 1 1 1 0 0
三个二进制一组: 101 110 111 100
       八进制:   5   6   7   4
四个二进制一组: 1011 1011 1100
     十六进制:    b    b    c

二进制:从0 写到 1111
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
这种二进制使用起来太麻烦,改成更简单一点的符号:
0 1 2 3 4 5 6 7 8 9 A B C D E F 这就是十六进制了

自定义进制符号

现在有10进制数 10个符号分别是:2,9,1,7,6,5,4, 8,3 , A 逢10进1 那么: 计算123 + 234

十进制:    0  1  2  3  4  5  6  7  8  9
自定义:    2  9  1  7  6  5  4  8  3  A
         92 99 91 97 96 95 94 98 93 9A
         12 19 11 17 16 15 14 18 13 1A
         72 79 71 77 76 75 74 78 73 7A
         62 69 61 67 66 65 64 68 63 6A
         52 59 51 57 56 55 54 58 53 5A
         42 49 41 47 46 45 44 48 43 4A
         82 89 81 87 86 85 84 88 83 8A
         32 39 31 37 36 35 34 38 33 3A
         922

那么刚才通过10进制运算可以转化10进制然后查表!但是如果是其他进制.我们就不能转换,要直接学会查表


十进制:    0  1  2  3  4  5  6  7  8  
自定义:    2  9  1  7  6  5  4  8  3  
         92 99 91 97 96 95 94 98 93 
         12 19 11 17 16 15 14 18 13 
         72 79 71 77 76 75 74 78 73 
         62 69 61 67 66 65 64 68 63 
         52 59 51 57 56 55 54 58 53 
         42 49 41 47 46 45 44 48 43 
         82 89 81 87 86 85 84 88 83 
         32 39 31 37 36 35 34 38 33 
         922

数据的宽度

数学上的数字,是没有大小限制的,可以无限的大。但在计算机中,由于受硬件的制约,数据都是有长度限制的(我们称为数据宽度),超过最多宽度的数据会被丢弃。


#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int test(){
    int cTemp = 0x1FFFFFFFF;
    return cTemp;
}

int main(int argc, char * argv[]) {
    printf("%x\n",test());
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

计算机中常见的数据宽度

那么计算机存储数据它会分为有符号数和无符号数.


数据符号

有符号:最大数据宽度的一半标示

无符号数,直接换算!
有符号数:
正数:  0    1    2    3    4    5    6    7 
负数:  F    E    D    B    C    A    9    8
      -1   -2   -3   -4   -5   -6   -7   -8

CPU&寄存器

内部部件之间由总线连接


15193738988252.jpg

CPU的运算速度是非常快的,为了性能CPU在内部开辟一小块临时存储区域,并在进行运算时先将数据从内存复制到这一小块临时存储区域中,运算时就在这一小快临时存储区域内进行。我们称这一小块临时存储区域为寄存器。

浮点和向量寄存器

因为浮点数的存储以及其运算的特殊性,CPU中专门提供浮点数寄存器来处理浮点数

现在的CPU支持向量运算.(向量运算在图形处理相关的领域用得非常的多)为了支持向量计算系统了也提供了众多的向量寄存器.

image.png

浮点和向量寄存器

2.比如 w0 就是 x0的低32位!

32位比64位低32位

注意:
了解过8086汇编的同学知道,有一种特殊的寄存器段寄存器:CS,DS,SS,ES四个寄存器来保存这些段的基地址,这个属于Intel架构CPU中.在ARM中并没有

15193699098685.jpg 15193703231861.jpg

1.CPU首先会将红色内存空间的值放到X0寄存器中:mov X0,红色内存空间
2.然后让X0寄存器与1相加:add X0,1
3.最后将值赋值给内存空间:mov 蓝色内存空间,X0

pc寄存器(program counter)

  1. 可以当做数据 0xE003008AA
  2. 也可以当做指令 mov x0, x8
  1. CPU将pc指向的内存单元的内容看做指令
  2. 如果内存中的某段内容曾被CPU执行过,那么它所在的内存单元必然被pc指向过

cpu先读取内存,内存读取的速度决定代码读取执行速度,为了弥补这个短板,有了高速缓存

高速缓存

iPhoneX上搭载的ARM处理器A11它的1级缓存的容量是64KB,2级缓存的容量8M.

1.系统将内存的指令保存到高速缓存中
2.建立内存地址到高速缓存的映射关系
3.操作系统先去高速缓存中寻找指令的映射,如果没有映射,触发系统再次加载代码到高速缓存区,执行1和2步骤,再次读取的数据和映射关系会覆盖原来的指令和映射关系。

查看pc寄存器


image.png

每一条指令4个字节,大于4个字节时溢出

标示常量

pc寄存器标示cpu接下来要执行的指令
修改pc地址后可修改代码执行顺序和逻辑

修改pc地址 修改pc地址后可修改代码执行顺序和逻辑

bl指令

bl指令 -- 练习

新建汇编文件

新建汇编文件

汇编文件参与编译


汇编文件
.text  //macho 中text段
.global _A,_B // 全局标号 外部可以调用  相当于声明

_A:
    mov x0,#0xa
    mov x1,#0x00
    add x1,x0,#0xff
    MOV X0,x1
    bl _B
    mov x0,#0x00
    ret
_B:
    add x0,x0,#0x10
    ret

调用


int A(void); //声明 成功链接

int main(int argc, char * argv[]) {
    A();
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

汇编断点查看

image.png

总结

汇编概述:

总线:是有一堆导线的集合

进制

寄存器:CPU为了性能,在内部开辟了一小块临时存储区域

上一篇 下一篇

猜你喜欢

热点阅读