返回顶部
扩大
缩小

Zhang_derek

逆向初级-汇编(一)

1.1.进制

进制的定义:
八进制的定义:由八个符号组成,分别是01234567逢八进一。
十进制的定义:由十个符号组成,分别是0123456789逢十进一。
N进制的定义:由N个符号组成,逢N进一。

1.2、进制的运算

八进制运算

2+3=5
2*3=6
4+5=11
4*5=24
277+333= 632
276*54= 162
237-54= 20250
234/4= 47

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

八进制加法表

2+3=5
2*3=6
4+5=11
4*5=24
277+333= 632
276*54= 162
237-54= 20250
234/4= 47

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

八进制加法表
image
八进制乘法表
image

1.3.二进制简写形式

计算机为什么使用二进制
计算机是需要用电的,电路只有两种状态: 1真(通电) 0假(未通电)
计算机中存储的任何文件、接收的任何指令都是由0和1组成的

二进制与十六进制

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

1.4.数据宽度

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

计算机中常见的数据宽度:

1)位(BIT) 1位
2)字节(Byte) 8位
3)字(Word) 16位
4)双字(Doubleword) 32位

存储范围:
字节(Byte): 0 ~ 0xFF
字(Word): 0 ~ 0xFFFF
双字:0~ 0xFFFFFFFF
如果要存储的数据超过最大宽度,那么多余的数据将被丢弃!

1.5.无符号数有符号数

无符号数的编码规则

10011010
十六进制:0x9A
十进制:154

有符号数的编码规则

正数编码规则(第一位是0),如果是正数就和无符号数编码规则一样
00011010

负数编码规则(第一位是1)
10011010

1.6.原码反码补码

有符号数的编码规则
原码:最高位为符号位,其余各位为数值本身的绝对值
反码:
正数:反码与原码相同
负数:符号位为1,其余位对原码取反
补码:
正数:补码与原码相同
负数:符号位为1,其余位对原码取反加1

-1
原码:10000001
反码:11111110
补码:11111111     (负数在计算机里面是采用补码的形势存储的)

-7
原码:10000111
反码:11111000
补码:11111001     (负数在计算机里面是采用补码的形势存储的)

1.7.计算机不会做加法

image
image
image
image
image
image

1.8.位运算之加减乘除

4+5=的运算过程
image
4-5=?的运算过程
image

1.9.汇编环境安装

下载DTdebug工具,打开后设置UDD和plugin的路劲。Options-->Appearance
image
image

1.10.通用寄存器

1寄存器
存储数据:
CPU>内存>硬盘
32位CPU: 8 16 32
64位CPU: 8 16 32 64

2、通用寄存器
32位通用寄存器:
EAX
ESP
ECX
EBP
EDX
ESI
EBX
EDI

3、MOV指令
<1> 立即数到内存
<2>寄存器到内存
<3>内存到寄存器

按F8单步运行
image
4.通用寄存器
image

1.11.内存

image
2、内存地址
<1>内存太大没法起名字,所以只能用编号。当我们想向内存中存储数据,或者从内存中读取数据时,必须用到这个编号,就像写信必须要写收信人地址一样。
<2>这个编号又称为内存地址(32位,前面0可以省略)。

3、往内存中写入值

MOV DWORD PTR DS:[19FF90],12345678

# DWORD表示四个字节长度
#PTR DS:[19FF90]表示内存地址

1.12.内存地址的五种形式

1、形式一: [立即数]
读取内存的值:
MOV EAX,DWORD PTR DS:[Ox13FFC4]
向内存中写入数据:
MOV DWORD PTR DS:[0x13FFC4],EAX

2、形式二: [reg] reg代表寄存器可以是8个通用寄存器中的任意一个
读取内存的值:
MOV ECX,0x13FFD0
MOV EAX,DWORD PTR DS:[ECX]
向内存中写入数据:
MOV EDX,0x13FFD8
MOV DWORD PTR DS:[EDX],0x87654321

3、形式三: [reg+立即数]
读取内存的值:
MOV ECX,0x1 3FFD0
MOV EAX,DWORD PTR DS:[ECX+4]
向内存中写入数据:
MOV EDX,0x13FFD8
MOV DWORD PTR DS:[EDX+0xC],0x87654321

4、形式四: [reg+reg*{1,2,4,8}]
读取内存的值:
MOV EAX,13FFC4
MOV ECX,2
MOV EDX,DWORD PTR DS:[EAX+ECX4]
向内存中写入数据:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX
4],87654321

5、形式五: [reg+reg*{1 ,2,4,8}+立即数]
读取内存的值:
MOV EAX,13FFC4
MOV ECX,2
MOV EDX,DWORD PTR DS:[EAX+ECX4+4]
向内存中写入数据:
MOV EAX,13FFC4
MOV ECX,2
MOV DWORD PTR DS:[EAX+ECX
4+4],87654321

1.13.存储模式

image
2、DTDEBUG内存窗口的使用
<1>分别以字节/字/双字形式来查看内存(db dw dd)
image
<2>向内存中写入四个字节的数据,并观察存储形式(大端存储/小端存储)
image

1.14.常用汇编指令

1、MOV指令
指令格式:
1、MOV r/m8,r8 r通用寄存器
2、MOV r/m16,r16 m代表内存
3、MOV r/m32,r32 ; imm代表立即数
4、MOVr8,r/m8 r8代表8位通用寄存器
5、MOV r16,r/m16 m8代表8位内存
6、MOV r32,r/m32 ; imm8代表8位立即数
7、MOV r8, imm8
8、MOV r16, imm16
9、MOV r32, imm32

2、ADD指令
指令格式:
ADD r/m8, imm8
ADD r/m16, imm16
ADD r/m32,imm32
ADD r/m16, imm8
ADD r/m32, imm8
ADD r/m8, r8
ADD r/m16, r16
ADD r/m32, r32
ADD r8, r/m8
ADD r16, r/m16
ADD r32, r/m32

3、SUB指令
指令格式:
SUB r/m8, imm8
SUB r/m1 6,imm16
SUB r/m32,imm32
SUB r/m16, imm8
SUB r/m32, imm8
SUB r/m8, r8
SUB r/m16, r16
SUB r/m32, r32
SUB r8, r/m8
SUB r16, r/m16
SUB r32, r/m32

4、AND指令
AND r/m8, imm8
AND r/m16,imm16
AND r/m32,imm32
AND r/m16, imm8
AND r/m32, imm8
AND r/m8, r8
AND r/m16, r16
AND r/m32, r32
AND r8, r/m8
AND r16, r/m16
AND r32, r/m32

5、OR指令
OR r/m8, imm8
OR r/m16 ,imm16
OR r/m32,imm32
OR r/m16, imm8
OR r/m32, imm8
OR r/m8, r8
OR r/m16, r16
OR r/m32, r32
OR r8, r/m8
OR r16, r/m16
OR r32, r/m32

6、XOR指令
XOR r/m8, imm8
XOR r/m16,imm16
XOR r/m32 ,imm32
XOR r/m16, imm8
XOR r/m32, imm8
XOR r/m8, r8
XOR r/m16, r16
XOR r/m32, r32
XOR r8, r/m8
XOR r16, r/m16
XOR r32, r/m32

7、NOT指令
NOT r/m8
NOT r/m16
NOT r/m32

1.15.内存复制指令

1、MOVS指令:移动数据内存-内存
BYTENWORD/DWORD
MOVS BYTE PTR ES:[EDJ,BYTE PTR DS:[ESI] 简写为: MOVSB
MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] 简写为: MOVSW
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 简写为: MOVSD

例子: .
MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
观察EDI的值
修改标志寄存器中D位的值,然后在执行下面的指令:
MOV EDI,12FFD8
MOV ESI,12FFD0MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

2、STOS指令: 将AI/AX/EAX的值存储到[EDI]指定的内存单元
STOS BYTE PTR ES:[EDI] 简写为STOSB
STOS WORD PTR ES:[EDI] 简写为STOSW
STOS DWORD PTR ES:[EDI] 简写为STOSD

例子:

MOV EAX, 12345678 观察EDI的值
MOV EDI, 12FFC4
STOS BYTE PTR ES:[EDI]
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]
修改标志寄存器中D位的值,然后在执行下面的指令:
MOV EAX, 12345678 观察EDI的值
MOV EDI, 12FFC4
STOS BYTE PTR ES:[EDI]
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]

3、REP指令: 按计数寄存器(ECX)中指定的次数重复执行字符串指令
MOV ECX,10
REP MOVSD
REP STOSD

1.16.堆栈相关指令

1、什么是堆栈?
1)就是一块内存,操作系统在程序启动的时候已经分配好的,供程序执行时使用。
2)和数据结构的堆栈无关。
3)查看堆栈。

2、栈指针寄存器
ESP中存储了当前的堆栈用到哪里了

3、堆栈的使用
<1>存储数据
<2>修改栈顶指针

4、PUSH指令
<1>向堆栈中压人数据
<2>修改栈项指针ESP寄存器
指令格式:
1、PUSH r32
2、PUSH r16
3、PUSH m16
4、PUSH m32
5、PUSH imm8/imm1 6/imm32

5、POP指令:
<1>将栈顶数据存储到寄存器/内存
<2>修改栈项指针ESP寄存器
指令格式:|
1、POP r32
2、POPr16
3、POP m16
4、POP m32

1.17.修改EIP的指令

1、JMP指令:
MOV EIP,寄存器/立即数/内存 简写为 JMP寄存器/立即数/内存

2、CALL指令:
PUSH下一行地址
MOV EIP,立即数/寄存器/内存 简写为: CALL立即数/寄存器/内存
与JMP唯--的区别:
在堆栈中存储Call指令下一-行地址

3、RET指令:
ADD ESP,4
MOV EIP,[ESP-4]

简写为: RET

1.18.汇编眼中的函数

1、什么是函数
函数就是一系列指令的集合,为了完成某个会重复使用的特定功能。
例子:向寄存器中赋值

2、如何执行一个函数?即函数调用
<1>用JMP来执行函数
<2> 用CALL来执行函数

3、 什么是参数?什么是返回值?
例子:编写一个函数,能够得到任意2个整数的值。

1.19.堆栈平衡

什么是堆栈平衡?
1)如果要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址。
2)如果通过堆栈传递参数了,那么在函数执行完毕后,要平衡参数导致的堆栈变化。

1.20.JCC指令

1、JE, JZ 结果为零则跳转(相等时跳转) ZF=1
2、JNE, JNZ 结果不为零则跳转(不相等时跳转) ZF=0
3、JS 结果为负则跳转 SF=1
4、JNS 结果为非负则跳转 SF=0
5、JP, JPE 结果中1的个数为偶数则跳转 PF=1
6、JNP, JPO 结果中1的个数为偶数则跳转 PF=0
7、J0 结果溢出了则跳转 0F=1
8、JNO 结果没有溢出则跳转 0F=0

9、JB, JNAE 小于则跳转(无符号数) CF=1
10、JNB, JAE 大于等于则跳转(无符号数) CF=0
11、JBE, JNA 小于等于则跳转(无符号数) CF=1 or ZF=1
12、JNBE, JA 太于则跣转(无符号数) CF=0 and ZF=0中
13、JL, JNGE 小于则跳转(有符号数) SF≠OF

14、JN, JGE 大于等于则跳转(有符号数) SF=OF
15、JLE, JNG 小于等于则跳转(有符号数) ZF=1 or SF≠0F
16、JNLE, JG 因于则来转(有符号数) ZF=0 and SF=OF

1、标志寄存器:EFLAGS
image
2、CF (bit 0) [Carry fiag]
若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。
这个标志通常用来指示无符号整型运算的溢出状态。

例:
MOV AL,0xFE MOV AL,0x7F
ADD AL,2 或者 SUB AL ,0xFF

3、PF(bit 2) [Parity flag]
如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。

利用PF可进行奇偶校验检查:
需要传输"11001110",数据中含5个"1", 所以其奇校验位为"0",同时把"110011100"传输给接收方,接收方收到数据后再- - 次计算奇偶性,"110011100"中仍然含有5个"1",所以接收方计算出的奇校验位还是"0",与发送方一致,表示在此次传输过程中未发生错误

例子:
MOV AL,OCE
ADDAL,0

4、AF(bit 4) [Adjust Flag]
如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。
这个标志在BCD(binary-code decimal)算术运算中被使用。

5、ZF(bit 6) [Zero flag]
若结果为0则将其置1,反之清零。
经常与CMP或者TEST等指令-起使用:

例1:判断2个值是否相等

MOV EAX, 100
MOV ECX, 100
CMP EAX, ECX
(CMP指令相当干SUB指令.但是相减的结果并不保存到第一个操作数中)

例2:判断某个值是否为0
TEST EAX,EAX
(TEST指令相当于AND指令,但是与的结果并不保存到第-一个操作数中)

6、SF(bit 7) [Sign flag]
该标志被设置为有符号整型的最高有效位。
(0指示结果为正,反之则为负)
例子:
MOV AL ,0x7F MOV AL ,0xFE
ADD AL,2 ADDAL,2

7、OF(bit 11) [Overflow flag]
溢出标志OF用于反映有符号数加减运算所得结果是否溢出。

可以这样理解:
如果是无符号数运算,是否溢出看CF位。
如果是有符号数运算,是否溢出看OF位。
例子:
MOV AL ,0x7F
ADD AL,2

8、DF(bit 10) [Direction Flag]
这个方向标志控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF
标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使
得串指令自动递增。
STD以及CLD指令分别用于设置以及清除DF标志。

作者:zhang_derek

个性签名:其实人跟树一样,越是向往高处的阳光,它的根就越要伸向黑暗的地底。

posted on 2021-04-09 00:11  zhang_derek  阅读(148)  评论(0编辑  收藏  举报

导航