re基础知识(复习)
re基础知识(复习)
一 动态调试
1.exe与elf的区别
可执行文件指的是可以由操作系统进行加载执行的文件
可执行文件的文件格式常见有:exe 和 dll(Windows 系列)、elf(Linux 系列)
EXE(Executable)是Windows操作系统中的可执行文件格式,它是一种二进制格式,包含了程序的机器代码和相关的资源。EXE文件可以直接在Windows上运行,它通常以.exe作为文件扩展名。EXE文件可以包含多个可执行程序和库文件,它们可以通过链接器和加载器来进行连接和加载。
ELF(Executable and Linkable Format)是一种通用的可执行文件格式,主要用于UNIX和类UNIX操作系统,如Linux。ELF文件也是一种二进制格式,包含了程序的机器代码、数据和相关的元数据。ELF文件可以通过链接器和加载器来进行连接和加载,它支持动态链接和共享库的使用。
总的来说,EXE和ELF是不同操作系统中的可执行文件格式,它们在文件结构和使用方式上有一些区别。
文件结构上的区别:
- EXE文件通常包含一个程序的完整可执行代码,以及相关的资源和数据。它可以有多个节(section)来存储不同类型的数据。
- ELF文件也包含程序的可执行代码,但它使用节(section)和段(segment)的概念来组织数据。节用于存储不同类型的数据,而段用于定义内存映射的相关信息。
使用方式上的区别:
- EXE文件主要用于Windows操作系统,可以直接在Windows上运行。它可以通过Windows的API和资源管理器来访问和执行。
- ELF文件主要用于UNIX和类UNIX操作系统,如Linux。它可以通过命令行或者调用系统调用来执行。ELF文件还支持动态链接和共享库的使用,可以在运行时加载和链接所需的库。
此外,EXE和ELF还有一些其他细微的差异,比如文件头部的结构和字段的定义,以及特定操作系统的特定功能和限制。
2.IDA中F7和F8区别
F8 | Step Over 表示跳到下一步 |
---|---|
F7 | Step Into 表示进入到代码 |
一句话:1、想要点进方法里面就按F7
2、想要跳转到下一行就按F8
3.调试sub.elf
首先将IDA的linux_server64放在虚拟机中,再在虚拟机命令行里用管理员(sudo linux_server64)打开,再在命令行运行要调试的sub.elf,在回主机打开IDA,在debugger里找到Attach,再找到remote linux debugger,输入虚拟机的ip(用ifconfig -a命令查找),确认完毕后,即可对sub.elf进行调试(包括F2下断点,F7和F8的步入和步过)
注:如果要调试安卓的文件等,要先运行android_x64_server等文件(注意版本问题),其他步骤类似同上。
二. 位运算
1.位运算概述
从现代计算机中所有的数据二进制的形式存储在设备中。即 0、1 两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算。
2.位运算概览:
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 两个位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
注意:
逻辑运算符:位与(&),位或(|),位异或(^),位非(~)。
移位运算符:左移(<<),右移(>>),无符号右移(>>>)。
3.按位与运算符(&):
定义:参加运算的两个数据,按二进制位进行”与”运算。
运算规则:
1 | 0&0=0 0&1=0 1&0=0 1&1=1 |
总结:两位同时为1,结果才为1,否则结果为0。
例如:3&5 即 0000 0011& 0000 0101 = 0000 0001,因此 3&5 的值得1。
注意:负数按补码形式参加按位与运算。
4.与运算的用途:
1)清零
如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
2)取一个数的指定位
比如取数 X=1010 1110 的低4位,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位与运算(X&Y=0000 1110)即可得到X的指定位。
3)判断奇偶
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。
5.按位或运算符(|):
定义:参加运算的两个对象,按二进制位进行”或”运算。
1 | 0|0=0 0|1=1 1|0=1 1|1=1 |
总结:参加运算的两个对象只要有一个为1,其值为1。
例如:3|5即 0000 0011| 0000 0101 = 0000 0111,因此,3|5的值得7。
注意:负数按补码形式参加按位或运算。
6.或运算的用途:
常用来对一个数据的某些位设置为1
比如将数 X=1010 1110 的低4位设置为1,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行按位或运算(X|Y=1010 1111)即可得到。
7.异或运算符(^):
定义:参加运算的两个数据,按二进制位进行”异或”运算。
运算规则:
1 | 0^0=0 0^1=1 1^0=1 1^1=0 |
总结:参加运算的两个对象,如果两个相应位相同为0,相异为1。
8.异或运算的用途:
1)翻转指定位
比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到。
2)与0相异或值不变
例如:1010 1110 ^ 0000 0000 = 1010 1110
3)使一个数的最低位为零
使a的最低位为0,可以表示为:a & 1。1的值为 1111 1111 1111 1110,再按”与”运算,最低位一定为0。因为” ~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。
9.异或的几条性质:
- 1、交换律
- 2、结合律 (a^b)^c == a^(b^c)
- 3、对于任何数x,都有 x^x=0,x^0=x
- 4、自反性: a^b^b=a^0=a;
10.取反运算符 (~):
定义:参加运算的一个数据,按二进制进行”取反”运算。
运算规则:
1 | ~1=0 |
总结:对一个二进制数按位取反,即将0变1,1变0。
11.左移运算符(<<):
定义:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
设 a=1010 1110,a = a<< 2 将a的二进制位左移2位、右补0,即得a=1011 1000。
若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
12.右移运算符(>>):
定义:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
例如:a=a>>2 将a的二进制位右移2位,在符号位左补0 或者 左补1得看被移数是正还是负。
操作数每右移一位,相当于该数除以2。
三、寄存器,汇编
一 通用寄存器
通用寄存器是一种用于存储和操作数据的硬件组件【一个典型CPU一般由运算器,控制器,寄存器等器件组成】。它们是计算机体系结构中的一部分,用于临时存储和处理数据。通用寄存器通常具有固定的位数大小,在一台计算机中可能会有多个通用寄存器。(例如AX,BX,CX,DX四个寄存器通常存放一般性数据,因此被称为通用寄存器。)
通用寄存器的主要功能包括:
- 存储数据:通用寄存器可以用来存储指令中的操作数、临时结果和其他需要在计算过程中保存的数据。
- 数据操作:通过通用寄存器,可以对存储在其中的数据执行各种数学和逻辑操作,如加法、减法、乘法、移位和逻辑运算等。
- 数据传输:通用寄存器可以用来传输数据,比如从内存中读取数据到寄存器,或将寄存器中的数据写回到内存中。
通用寄存器在计算机体系结构中起着重要的作用,因为它们提供了一个快速访问和操作数据的方式。不同的体系结构可能会有不同数量和命名方式的通用寄存器。
二 标志寄存器
标志寄存器是计算机中的一种特殊寄存器,用于存储特定的标志位或状态信息。它通常用于记录程序运行过程中的条件和结果,以便进行条件分支、循环等控制操作。
常见的标志寄存器包括:
- 零标志位(ZF):用于表示运算结果是否为零。
- 进位标志位(CF):用于表示无符号数运算过程中是否发生进位或借位。
- 溢出标志位(OF):用于表示有符号数运算过程中是否发生溢出。
- 符号标志位(SF):用于表示运算结果的符号。
- 奇偶标志位(PF):用于表示运算结果中 1 的个数的奇偶性。
三 基础汇编指令
基础汇编指令是用于编写汇编语言程序的基本指令集。这些指令用于执行各种操作,例如数据传输、运算、控制流程等。下面是一些常见的基础汇编指令:
1.数据传送指令:
指令 | 名称 | 示例 | 备注 |
---|---|---|---|
MOV | 传送指令 | MOV dest, src | 将数据从src移动到dest |
PUSH | 进栈指令 | PUSH src | 把源操作数src压入堆栈 |
POP | 出栈指令 | POP desc | 从栈顶弹出字数据到dest |
相关补充:movb传送字节;movw传送字(2Byte):movl传送双字;movq传送四字。
2.算术运算指令:
指令 | 名称 | 示例 | 备注 |
---|---|---|---|
ADD | 加法指令 | ADD dest, src | 在dest基础上加src |
SUB | 减法指令 | SUB dest, src | 在dest基础上减src |
3.逻辑运算指令:
指令 名称 示例 备注
NOT 取反运算指令 NOT dest 把操作数dest按位取反
AND 与运算指令 AND dest, src 把dest和src进行与运算之后送回dest
OR 或运算指令 OR dest, src 把dest和src进行或运算之后送回dest
XOR 异或运算 XOR dest, src 把dest和src进行异或运算之后送回dest
4.转移指令:
指令 名称 示例 备注
JMP 无条件转移指令 JMP lable 无条件地转移到标号为label的位置
CALL 过程调用指令 CALL labal 直接调用label
JE 条件转移指令 JE lable zf =1 时跳转到标号为label的位置
JNE 条件转移指令 JNE lable zf=0 时跳转到标号为label的位置
5.其他:
RET指令则是将栈顶的返回地址弹出到EIP,然后按照EIP此时指示的指令地址继续执行程序。
JZ跳转 ZF=1,运算结果为0 跳转
JNZ跳转 ZF≠1,运算结果不为0时 跳转
四 栈
百度百科解释:栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
栈是一种数据结构,它按照后进先出(LIFO)的原则存储和访问数据。这意味着最后进入栈的元素首先被访问和移除。栈有两个主要操作:推入(push)将元素放入栈的顶部,弹出(pop)将顶部元素移除。
五 内存分区
在没有运行程序前,也就是说程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、数据区(data) 和 未初始化数据区(bss) 3 个部分(有人直接把data和bss合起来叫做静态区或全局区)
代码区
存放 CPU 执行的机器指令。
通常代码区是可共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止程序意外地修改了它的指t令。另外,代码区还规划了局部变量的相关信息。
全局初始化数据区/静态数据区(data段)
该区包含了在程序中明确被初始化的全局变量、已经初始化的静态变量(包括全局静态变量和t)和常量数据(如字符串常量)。
未初始化数据区(又叫 bss 区)
存入的是全局未初始化变量和未初始化静态变量。未初始化数据区的数据在程序开始执行之前被内核初始化为 0 或者空(NULL)。
总体来讲说,程序源代码被编译之后主要分成两种段:程序指令(代码区)和程序数据(数据区)。代码段属于程序指令,而数据域段和.bss段属于程序数据。