硬编码学习笔记(一)—— 经典定长指令
硬編碼學(xué)習(xí)筆記(一)—— 經(jīng)典定長指令
- 前言
- 指令結(jié)構(gòu)
- 符號說明
- 尋址符號
- 操作數(shù)符號
- 上標(biāo)符號
- One-Byte Opcode Map
- 經(jīng)典定長指令:修改寄存器
- 0x40~0x47
- 0x48~0x4F
- 0x50~0x57
- 0x58~0x5F
- 0x90~0x97
- 0xB0~0xB7
- 0xB8~0xBF
- 經(jīng)典定長指令:修改EIP
- 0x70~0x7F
- 0x0F80~0x0F8F
- 0xE0
- 0xE1
- 0xE2
- 0xE3
- 0xE8
- 0xE9
- 0xEA
- 0xEB
- 0xC2
- 0xC3
- 0xCA
- 0xCB
前言
本次學(xué)習(xí)僅基于intel x86模式
指令結(jié)構(gòu)
描述:對于任何一條指令,都由以下幾部分組成,但不是每部分都必須存在
長度:最短1個字節(jié),最長15個字節(jié)
Instruction Prefixes:指令前綴
Opcode: 主操作碼
ModR/M:在內(nèi)存中引用一個操作數(shù)的許多指令都有一個尋址方式的指定符字節(jié)(稱為ModR/M字節(jié))跟隨在主操作碼之后
SIB:ModR/M字節(jié)的某些編碼需要第二個尋址字節(jié)(SIB字節(jié))
Displacement:一些尋址方式包含緊跟ModR/M字節(jié)(或者SIB字節(jié),如果有的話)的位移
Immediate:立即數(shù)
符號說明
尋址符號
| A | 直接尋址 |
| C | 控制寄存器 |
| D | 調(diào)試寄存器 |
| E | 寄存器/內(nèi)存 |
| F | EFLAGS/RFLAGS寄存器 |
| G | 通用寄存器 |
| I | 立即數(shù) |
| J | 要添加到指令指針寄存器的相對偏移量 |
| M | ModR/M字節(jié)可能僅指向內(nèi)存。 |
| N | MMX 技術(shù)寄存器 |
| O | 該指令沒有ModR/M字節(jié)。操作數(shù)的偏移量在指令中被編碼為一個字或雙字(取決于地址大小屬性)。 |
| P | ModR/M字節(jié)的reg字段選擇一個打包的四字MMX技術(shù)寄存器 |
| Q | ModR/M字節(jié)跟隨操作碼并指定操作數(shù)。該操作數(shù)要么是MMX技術(shù)寄存器,要么是內(nèi)存地址。 |
| R | ModR/M字節(jié)的R/M字段可能僅指一個通用寄存器 |
| S | ModR/M字節(jié)的reg字段選擇一個段寄存器 |
| U | ModR/M字節(jié)的R/M字段選擇一個128位的XMM寄存器。 |
| V | ModR/M字節(jié)的reg字段選擇一個128位的XMM寄存器。 |
| W | ModR/M字節(jié)跟隨操作碼并指定操作數(shù)。操作數(shù)要么是一個128位的XMM寄存器要么是一個內(nèi)存地址。 |
| X | 由DS:rSI寄存器對尋址的內(nèi)存 |
| Y | 由ES:rDI寄存器對尋址的內(nèi)存 |
操作數(shù)符號
| a | 內(nèi)存中的兩個單字操作數(shù)或內(nèi)存中的兩個雙字操作數(shù),具體取決于操作數(shù)大小屬性(僅由BOUND指令使用) |
| b | 字節(jié) |
| c | 字節(jié)/字 |
| d | 雙字 |
| dq | 四字 |
| p | 32位/48位/80位指針 |
| pd | 128位封裝的雙精度浮點(diǎn)數(shù)據(jù) |
| pi | 雙四字,MMX技術(shù)寄存器(例如:mm0) |
| ps | 128位封裝的單精度浮點(diǎn)數(shù)據(jù) |
| q | 四字 |
| s | 6字節(jié)或10字節(jié)的偽描述符 |
| ss | 128位打包的單精度浮點(diǎn)數(shù)據(jù)的標(biāo)量元素 |
| si | 雙字整數(shù)寄存器(例如:eax) |
| v | 字、雙字或四字(取決于當(dāng)前CPU的模式) |
| w | 字 |
| z | 16位操作數(shù)大小的字或32位或64位操作數(shù)大小的雙字 |
上標(biāo)符號
| 1A | ModR/M字節(jié)的第5、4和3位用作操作碼擴(kuò)展 |
| 1B | 使用0F0B操作碼(UD2指令)或0FB9H操作碼時,故意嘗試生成無效的操作碼異常(#UD) |
| 1C | 在Pentium III處理器中添加的一些指令可以使用相同的雙字節(jié)操作碼。如果指令有變化,或者操作碼代表不同的指令,則使用ModR/M字節(jié)來區(qū)分指令。 |
| i64 | 該指令無效或在64位模式下不可編碼。40到4F(單字節(jié)INC和DEC)是64位模式下的REX前綴組合(對INC和DEC使用FE/FF Grp 4和5)。 |
| o64 | 指令僅在64位模式下可用。 |
| d64 | 當(dāng)處于64位模式時,指令默認(rèn)為64位操作數(shù)大小,并且不能對32位操作數(shù)大小進(jìn)行編碼。 |
| f64 | 在64位模式下,操作數(shù)大小被強(qiáng)制為64位操作數(shù)大小(在64位模式下,該指令會忽略改變操作數(shù)大小的前綴)。 |
One-Byte Opcode Map
經(jīng)典定長指令:修改寄存器
0x40~0x47
指令長度:共1個字節(jié)
40 INC EAX 41 INC ECX 42 INC EDX 43 INC EBX 44 INC ESP 45 INC EBP 46 INC ESI 47 INC EDI0x48~0x4F
指令長度:共1個字節(jié)
48 DEC EAX 49 DEC ECX 4A DEC EDX 4B DEC EBX 4C DEC ESP 4D DEC EBP 4E DEC ESI 4F DEC EDI0x50~0x57
指令長度:共1個字節(jié)
50 PUSH EAX 51 PUSH ECX 52 PUSH EDX 53 PUSH EBX 54 PUSH ESP 55 PUSH EBP 56 PUSH ESI 57 PUSH EDI0x58~0x5F
指令長度:共1個字節(jié)
58 POP EAX 59 POP ECX 5A POP EDX 5B POP EBX 5C POP ESP 5D POP EBP 5E POP ESI 5F POP EDI0x90~0x97
指令長度:共1個字節(jié)
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,EDI0xB0~0xB7
指令長度:共2個字節(jié)
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,0x70xB8~0xBF
指令長度:共5個字節(jié)
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經(jīng)典定長指令:修改EIP
0x70~0x7F
指令長度:共2個字節(jié)
偏移量:1個字節(jié)
當(dāng)偏移量<0x80時:EIP = 當(dāng)前指令地址+當(dāng)前指令長度+偏移量
當(dāng)偏移量>0x80時:EIP = 當(dāng)前指令地址+當(dāng)前指令長度-偏移量
0x0F80~0x0F8F
指令長度:共6個字節(jié)
偏移量:4個字節(jié)
EIP = 當(dāng)前指令地址+當(dāng)前指令長度+偏移量
0xE0
指令長度:共2個字節(jié)
LOOPNE/LOOPNZ Ib(Jb)當(dāng)ZF==0&&ECX!=0時:EIP=當(dāng)前指令地址+當(dāng)前指令長度+Ib;ECX=ECX-1
0xE1
指令長度:共2個字節(jié)
LOOPE/LOOPZ Ib(Jb)當(dāng)ZF==1&&ECX!=0時:EIP=當(dāng)前指令地址+當(dāng)前指令長度+Ib;ECX=ECX-1
0xE2
指令長度:共2個字節(jié)
LOOP Ib(Jb)當(dāng)ECX!=0時:EIP=當(dāng)前指令地址+當(dāng)前指令長度+Ib;ECX=ECX-1
0xE3
指令長度:共2個字節(jié)
JrCXZ Ib(Jb) //在32位模式中,rCX為ECX當(dāng)ECX==0時:EIP=當(dāng)前指令地址+當(dāng)前指令長度+Ib
0xE8
指令長度:共5個字節(jié)
CALL Id(Jd)下一條指令地址入棧;EIP=當(dāng)前指令地址+當(dāng)前指令長度+Id
0xE9
指令長度:共5個字節(jié)
JMP Id(Jd)EIP=當(dāng)前指令地址+當(dāng)前指令長度+Id
0xEA
指令長度:共7個字節(jié)
JMP Ap //Ap為六字節(jié)長度的直接地址 JMP CS:Id //將Ap中的高2位賦值給CS,低4位賦值給EIP0xEB
指令長度:共2個字節(jié)
JMP Ib(Jb)EIP=當(dāng)前指令地址+當(dāng)前指令長度+Ib
0xC2
指令長度:共3個字節(jié)
RET Iw //POP EIP;ESP=ESP+Iw0xC3
指令長度:共1個字節(jié)
RET //POP EIP0xCA
指令長度:共1個字節(jié)
RETF //POP EIP;POP CS0xCB
指令長度:共3個字節(jié)
RETF Iw //POP EIP;POP CS;ESP=ESP+Iw總結(jié)
以上是生活随笔為你收集整理的硬编码学习笔记(一)—— 经典定长指令的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Fuzz学习笔记(一)—— WinAFL
- 下一篇: 硬编码学习笔记(二)—— 经典变长指令