我们在学习iOS逆向编程开发之前,我们要了解一个基本的逆向原理。首先我们是iOS系统上面的App是我们逆向的目标,那么我们知道,一个App安装在手机上面的可执行文件本质上是二进制文件。因为iPhone手机本质上执行的指令是二进制。是由手机上的CPU执行的。所以逆向开发是建立在分析二进制上面。所以今天从非常基础的汇编语言来介绍。
一、汇编语言的发展
1.机器语言
机器语言是由0和1组成的机器指令。
例如:
- 加: 0100 0000
- 减: 0100 1000
- 乘: 1111 0111 1110 0000
- 除: 1111 0111 1111 0000
2.汇编语言(Assembly Language)
汇编语言是使用助记符代替机器指令的语言。
如:
- 加: INC EAX 通过编译器 0100 0000
- 减: DEC EAX 通过编译器 0100 1000
- 乘: MUL EAX 通过编译器 1111 0111 1110 0000
- 除: DIV EAX 通过编译器 1111 0111 1111 0000
3.高级语言(High-level Programming Language)
C\C++\Java\OC\Swift,更加接近人类的自然语言。
比如C语言:
如:
- 加: A+B 通过编译器 0100 0000
- 减: A-B 通过编译器 0100 1000
- 乘: A*B 通过编译器 1111 0111 1110 0000
- 除: A/B 通过编译器 1111 0111 1111 0000
高级语言的代码在终端设备上转换的过程:
- 汇编语言与机器语言一一对应,每一条机器指令都有与之对应的汇编指令
- 汇编语言可以通过编译得到机器语言,机器语言可以通过反汇编得到汇编语言
- 高级语言可以通过编译得到汇编语言 \ 机器语言,但汇编语言\机器语言几乎不可能还原成高级语言
4.汇编语言的特点
- 可以直接访问、控制各种硬件设备,比如存储器、CPU等,能最大限度地发挥硬件的功能
- 能够不受编译器的限制,对生成的二进制代码进行完全的控制
- 目标代码简短,占用内存少,执行速度快
- 汇编指令是机器指令的助记符,同机器指令一一对应。每一种CPU都有自己的机器指令集\汇编指令集,所以汇编语言不具备可移植性
- 知识点过多,开发者需要对CPU等硬件结构有所了解,不易于编写、调试、维护
- 不区分大小写,比如mov和MOV是一样的
总结:越底层越单纯!真正的程序员都需要了解的一门非常重要的语言,就是汇编语言!
5.汇编的用途
- 编写驱动程序、操作系统(比如Linux内核的某些关键部分)
- 对性能要求极高的程序或者代码片段,可与高级语言混合使用(内联汇编)
- 软件安全(1.病毒分析与防治。2.逆向\加壳\脱壳\破解\外挂\免杀\加密解密\漏洞\黑客)
- 理解整个计算机系统的最佳起点和最有效途径
- 为编写高效代码打下基础
- 弄清代码的本质(1.函数的本质究竟是什么?2.++a + ++a + ++a 底层如何执行的?3.编译器到底帮我们干了什么?4.DEBUG模式和RELEASE模式有什么关键的地方被我们忽略等等)
6.汇编语言的种类
目前讨论比较多的汇编语言有
- 8086汇编(8086处理器是16bit的CPU)
- Win32汇编
- Win64汇编
- ARM汇编(嵌入式、Mac、iOS)
- ......
我们iPhone里面用到的是ARM汇编,但是不同的设备也有差异,因CPU的架构不同。iPhone设备的ARM汇编架构列举如下:
架构 | 设备 |
---|---|
armv6 | iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch |
armv7 | iPhone3GS, iPhone4, iPhone4S,iPad, iPad2, iPad3(The New iPad), iPad mini, iPod Touch 3G, iPod Touch4 |
armv7s | iPhone5, iPhone5C, iPad4(iPad with Retina Display) |
arm64 | iPhone5S 以后 iPhoneX , iPad Air, iPad mini2以后 |
二、几个必要的常识
- APP/程序的执行过程
- 要想学好汇编,首先需要了解CPU等硬件结构
- 硬件相关最为重要是CPU/内存
- 在汇编中大部分指令都是和CPU与内存相关的
三、总线
总线是指一根根导线的集合。总线分为:地址总线、数据总线、控制总线。每一个CPU芯片都有许多管脚,这些管脚和总线相连,CPU就是通过总线跟外部器件进行交互。
举个例子:CPU从内存的3号单元读取数据,则CPU先通过地址总线发送3的地址,再通过控制总线获取CPU的操作指令为读操作,最后通过数据总线将3号单元内的数据08发送给CPU。具体流程如下图:
特别注意
总线类型 | 功能 |
---|---|
地址总线 | 它的宽度决定了CPU的寻址能力 。一般来说,若地址总线为n位,则可寻址空间为2^n位。例如:8086有20 根地址总线,所以寻址能力是1M = (2^20)Byte = (8x(2^20))Bit (注意:地址总线是8位的,所以8086的寻址空间为(8x(2^20)) 位)。举个例子吧,地址是二进制系统的门牌号,形如01001000011110011011(二十位长度)。长度是二十位,就叫他二十位地址总线。这一点理解了吧。因为是二十位,从0000000000000000000到,11111111111111111111总共1M个可能性。也就是可以表示1M个地址(门牌)。而每个门牌可以代表1bit或者8bit(一字节),有些处理器处理器单门牌可以双字节都行。一般是一字节。 |
数据总线 | 它的宽度决定了CPU的单次数据传送量,也就是数据传送速度 。例如:8086的数据总线宽度是16 ,所以单次最大传递2个字节 的数据 |
控制总线 | 它的宽度决定了CPU对其他器件能有多少种控制的控制能力
|
单位换算
1 字节(Byte) = 8 比特(Bit)
1 千字节(KB) = 1024 字节(Byte)
1 兆(MB) = 1024 千字节(KB)
1 千兆字节(GB) = 1024 兆(MB)
1 百万兆字节(TB) = 1024 千兆字节(GB)换算的基本幂次方
2^5 = 32,2^6 = 64,2^7 = 128,2^8 = 256,2^9 = 512,2^10 = 1024
四、内存
-
内存地址空间的大小受CPU地址总线宽度的限制。8086的地址总线宽度为20,可以定位2^20个不同的内存单元(内存地址范围0x00000~0xFFFFF),所以8086的内存空间大小为1MB
-
0x00000~0x9FFFF:主存储器。可读可写
-
0xA0000~0xBFFFF:向显存中写入数据,这些数据会被显卡输出到显示器。可读可写
-
0xC0000~0xFFFFF:存储各种硬件\系统信息。只读属性
网友评论