硬编码学习笔记(一)—— 经典定长指令

硬编码学习笔记(一)—— 经典定长指令

前言

本次学习仅基于intel x86模式

指令结构

描述:对于任何一条指令,都由以下几部分组成,但不是每部分都必须存在
长度:最短1个字节,最长15个字节
硬编码学习笔记(一)—— 经典定长指令Instruction Prefixes:指令前缀
Opcode: 主操作码
ModR/M:在内存中引用一个操作数的许多指令都有一个寻址方式的指定符字节(称为ModR/M字节)跟随在主操作码之后
SIB:ModR/M字节的某些编码需要第二个寻址字节(SIB字节)
Displacement:一些寻址方式包含紧跟ModR/M字节(或者SIB字节,如果有的话)的位移
Immediate:立即数

符号说明

寻址符号

符号 意义
A 直接寻址
C 控制寄存器
D 调试寄存器
E 寄存器/内存
F EFLAGS/RFLAGS寄存器
G 通用寄存器
I 立即数
J 要添加到指令指针寄存器的相对偏移量
M ModR/M字节可能仅指向内存。
N MMX 技术寄存器
O 该指令没有ModR/M字节。操作数的偏移量在指令中被编码为一个字或双字(取决于地址大小属性)。
P ModR/M字节的reg字段选择一个打包的四字MMX技术寄存器
Q ModR/M字节跟随操作码并指定操作数。该操作数要么是MMX技术寄存器,要么是内存地址。
R ModR/M字节的R/M字段可能仅指一个通用寄存器
S ModR/M字节的reg字段选择一个段寄存器
U ModR/M字节的R/M字段选择一个128位的XMM寄存器。
V ModR/M字节的reg字段选择一个128位的XMM寄存器。
W ModR/M字节跟随操作码并指定操作数。操作数要么是一个128位的XMM寄存器要么是一个内存地址。
X 由DS:rSI寄存器对寻址的内存
Y 由ES:rDI寄存器对寻址的内存

操作数符号

符号 意义
a 内存中的两个单字操作数或内存中的两个双字操作数,具体取决于操作数大小属性(仅由BOUND指令使用)
b 字节
c 字节/字
d 双字
dq 四字
p 32位/48位/80位指针
pd 128位封装的双精度浮点数据
pi 双四字,MMX技术寄存器(例如:mm0)
ps 128位封装的单精度浮点数据
q 四字
s 6字节或10字节的伪描述符
ss 128位打包的单精度浮点数据的标量元素
si 双字整数寄存器(例如:eax)
v 字、双字或四字(取决于当前CPU的模式)
w
z 16位操作数大小的字或32位或64位操作数大小的双字

上标符号

符号 意义
1A ModR/M字节的第5、4和3位用作操作码扩展
1B 使用0F0B操作码(UD2指令)或0FB9H操作码时,故意尝试生成无效的操作码异常(#UD)
1C 在Pentium III处理器中添加的一些指令可以使用相同的双字节操作码。如果指令有变化,或者操作码代表不同的指令,则使用ModR/M字节来区分指令。
i64 该指令无效或在64位模式下不可编码。40到4F(单字节INC和DEC)是64位模式下的REX前缀组合(对INC和DEC使用FE/FF Grp 4和5)。
o64 指令仅在64位模式下可用。
d64 当处于64位模式时,指令默认为64位操作数大小,并且不能对32位操作数大小进行编码。
f64 在64位模式下,操作数大小被强制为64位操作数大小(在64位模式下,该指令会忽略改变操作数大小的前缀)。

One-Byte Opcode Map

硬编码学习笔记(一)—— 经典定长指令
硬编码学习笔记(一)—— 经典定长指令

经典定长指令:修改寄存器

0x40~0x47

指令长度:共1个字节

40	INC EAX
41	INC ECX
42	INC EDX
43	INC EBX
44	INC ESP
45	INC EBP
46	INC ESI
47	INC EDI

0x48~0x4F

指令长度:共1个字节

48	DEC EAX
49	DEC ECX
4A	DEC EDX
4B	DEC EBX
4C	DEC ESP
4D	DEC EBP
4E	DEC ESI
4F	DEC EDI

0x50~0x57

指令长度:共1个字节

50	PUSH EAX
51	PUSH ECX
52	PUSH EDX
53	PUSH EBX
54	PUSH ESP
55	PUSH EBP
56	PUSH ESI
57	PUSH EDI

0x58~0x5F

指令长度:共1个字节

58	POP EAX
59	POP ECX
5A	POP EDX
5B	POP EBX
5C	POP ESP
5D	POP EBP
5E	POP ESI
5F	POP EDI

0x90~0x97

指令长度:共1个字节

90	NOP	//XCHG EAX, EAX
91	XCHG EAX,ECX
92	XCHG EAX,EDX
93	XCHG EAX,EBX
94	XCHG EAX,ESP
95	XCHG EAX,EBP
96	XCHG EAX,ESI
97	XCHG EAX,EDI

0xB0~0xB7

指令长度:共2个字节

B0 00	MOV AL,0x0
B1 01	MOV CL,0x1
B2 02	MOV DL,0x2
B3 03	MOV BL,0x3
B4 04	MOV AH,0x4
B5 05	MOV CH,0x5
B6 06	MOV DH,0x6
B7 07	MOV BH,0x7

0xB8~0xBF

指令长度:共5个字节

B8 00 00 00 10		MOV EAX,0x10000000
B9 01 00 00 10		MOV ECX,0x10000001
BA 02 00 00 10		MOV EDX,0x10000002
BB 03 00 00 10		MOV EBX,0x10000003
BC 04 00 00 10		MOV ESP,0x10000004
BD 05 00 00 10		MOV EBP,0x10000005
BE 06 00 00 10		MOV ESI,0x10000006
BF 07 00 00 10		MOV EDI,0x10000007

经典定长指令:修改EIP

0x70~0x7F

指令长度:共2个字节
偏移量:1个字节
偏移量<0x80时:EIP = 当前指令地址+当前指令长度+偏移量
偏移量>0x80时:EIP = 当前指令地址+当前指令长度-偏移量

70	JO
71	JNO
72	JB/JNAE/JC
73	JNB/JAE/JNC
74	JZ/JE
75	JNZ/JNE
76	JBE/JNA
77	JNBE/JA
78	JS
79	JNS
7A	JP/JPE
7B	JNP/JPO
7C	JL/JNGE
7D	JNL/JGE
7E	JLE/JNG
7F	JNLE/JG

硬编码学习笔记(一)—— 经典定长指令

0x0F80~0x0F8F

硬编码学习笔记(一)—— 经典定长指令

指令长度:共6个字节
偏移量:4个字节
EIP = 当前指令地址+当前指令长度+偏移量

0F80	JO
0F81	JNO
0F82	JB/JNAE/JC
0F83	JNB/JAE/JNC
0F84	JZ/JE
0F85	JNZ/JNE
0F86	JBE/JNA
0F87	JNBE/JA
0F88	JS
0F89	JNS
0F8A	JP/JPE
0F8B	JNP/JPO
0F8C	JL/JNGE
0F8D	JNL/JGE
0F8E	JLE/JNG
0F8F	JNLE/JG

硬编码学习笔记(一)—— 经典定长指令

0xE0

指令长度:共2个字节

LOOPNE/LOOPNZ Ib(Jb)

ZF==0&&ECX!=0时:EIP=当前指令地址+当前指令长度+IbECX=ECX-1

0xE1

指令长度:共2个字节

LOOPE/LOOPZ Ib(Jb)

ZF==1&&ECX!=0时:EIP=当前指令地址+当前指令长度+IbECX=ECX-1

0xE2

指令长度:共2个字节

LOOP Ib(Jb)

ECX!=0时:EIP=当前指令地址+当前指令长度+IbECX=ECX-1

0xE3

指令长度:共2个字节

JrCXZ Ib(Jb)	//在32位模式中,rCX为ECX

ECX==0时:EIP=当前指令地址+当前指令长度+Ib

0xE8

指令长度:共5个字节

CALL Id(Jd)

下一条指令地址入栈EIP=当前指令地址+当前指令长度+Id

0xE9

指令长度:共5个字节

JMP Id(Jd)

EIP=当前指令地址+当前指令长度+Id

0xEA

指令长度:共7个字节

JMP Ap		//Ap为六字节长度的直接地址
JMP CS:Id	//将Ap中的高2位赋值给CS,低4位赋值给EIP

0xEB

指令长度:共2个字节

JMP Ib(Jb)

EIP=当前指令地址+当前指令长度+Ib

0xC2

指令长度:共3个字节

RET Iw	//POP EIP;ESP=ESP+Iw

0xC3

指令长度:共1个字节

RET	//POP EIP

0xCA

指令长度:共1个字节

RETF	//POP EIP;POP CS

0xCB

指令长度:共3个字节

RETF Iw	//POP EIP;POP CS;ESP=ESP+Iw
上一篇:加密与解密示例程序TraceMe.exe逆向&算法分析


下一篇:matlab中gatbx工具箱的添加