二进制入门学习笔记-14.windows硬编码

1.windows硬编码简介

od中中间这一栏就是所谓的硬编码,这是计算机能够识别的真正代码,计算机不能直接执行汇编和c语言代码,这个才是操作系统识别的指令。

1.1 硬编码结构

指令编码的结构如下图所示:

指令说明如下

  • 0、每一条指令,最短1字节,最长15字节
  • 1、Intel对指令参数的设计了一种表示方式,格式是Zz一个大写字母加上一个小写字母。
  • 2、大写字母表示寻找方式编码(寄存器,ModR/M,跳转相对地址,16:32地址格式等等),从A-Z共26种.
  • 3、小写字母表示操作数的类型(byte,word,dword,fword等等不定,根据cpu模式或改写指令决定)。z有大约十几种表示方式。
  • 4、他们的组合再加上纯寄存器表示了intel的所有操作对象。

2.经典定长指令上(修改寄存器)

2.1 push系列

指令码 汇编码
0x50 PUSH EAX
0x51 PUSH ECX
0x52 PUSH EDX
0x53 PUSH EBX
0x54 PUSH ESP
0x55 PUSH EBP
0x56 PUSH ESI
0x57 PUSH EDI

2.2 pop系列

指令码 汇编码
0x58 POP EAX
0x59 POP ECX
0x5A POP EDX
0x5B POP EBX
0x5C POP ESP
0x5D POP EBP
0x5E POP ESI
0x5F POP EDI

2.3 INC/DEC系列

指令码 汇编码
0x40 INC EAX
0x41 INC ECX
0x42 INC EDX
0x43 INC EBX
0x44 INC ESP
0x45 INC EBP
0x46 INC ESI
0x47 INC EDI
0x48 DEC EAX
0x49 DEC ECX
0x4A DEC EDX
0x4B DEC EBX
0x4C DEC ESP
0x4D DEC EBP
0x4E DEC ESI
0x4F DEC EDI

2.4 MOV Rb, Ib系列

指令码 汇编码
0xB0 MOV AL, 一byte立即数
0xB1 MOV CL, 一byte立即数
0xB2 MOV DL, 一byte立即数
0xB3 MOV BL, 一byte立即数
0xB4 MOV AH, 一byte立即数
0xB5 MOV CH, 一byte立即数
0xB6 MOV DH, 一byte立即数
0xB7 MOV BH, 一byte立即数

2.5 MOV ERX, Id系列

指令码 汇编码
0xB8 MOV EAX, 两byte立即数
0xB9 MOV ECX, 两byte立即数
0xBA MOV EDX, 两byte立即数
0xBB MOV EBX, 两byte立即数
0xBC MOV ESP, 两byte立即数
0xBD MOV EBP, 两byte立即数
0xBE MOV ESI, 两byte立即数
0xBF MOV EDI, 两byte立即数

2.6 XCHG EAX, ERX系列

指令码 汇编码
0x90 NOP
0x91 XCHG EAX,ECX
0x92 XCHG EAX,EDX
0x93 XCHG EAX,EBX
0x94 XCHG EAX,ESP
0x95 XCHG EAX,EBP
0x96 XCHG EAX,ESI
0x97 XCHG EAX,EDI

3.经典定长指令(修改EIP)

3.1 0x70 - 0x7F系列条件跳转

  • 条件跳转后跟一个字节立即数的偏移(有符号),共两个字节。
  • 如果条件成立,跳转到 当前指令地址 + 当前指令长度 + Ib
  • 最大值:向前跳7f,向后跳80
指令码 汇编码
0x70 JO
0x71 JNO
0x72 JB/JNAE/JC
0x73 JNB/JAE/JNC
0x74 JZ/JE
0x75 JNZ/JNE
0x76 JBE/JNA
0x77 JNBE/JA
0x78 JS
0x79 JNS
0x7A JP/JPE
0x7B JNP/JPO
0x7C JL/JNGE
0x7D JNL/JGE
0x7E JLE/JNG
0x7F JNLE/JG

3.2 0x0F0x80 - 0x0F0x8F系列条件跳转

  • 条件跳转,后跟四个字节立即数的偏移(有符号),共五个字节。
  • 如果条件成立,跳转到 当前指令地址 + 当前指令长度 + Id
  • 最大值:向前跳7FFFFFFFF,向后跳80000000
-指令码的十六进制- -对应的汇编代码-
0x0F0x80 JO
0x0F0x81 JNO
0x0F0x82 JB/JNAE/JC
0x0F0x83 JNB/JAE/JNC
0x0F0x84 JZ/JE
0x0F0x85 JNZ/JNE
0x0F0x86 JBE/JNA
0x0F0x87 JNBE/JA
0x0F0x88 JS
0x0F0x89 JNS
0x0F0x8A JP/JPE
0x0F0x8B JNP/JPO
0x0F0x8C JL/JNGE
0x0F0x8D JNL/JGE
0x0F0x8E JLE/JNG
0x0F0x8F JNLE/JG

4.经典变长指令_ModR/M

经典的变长指令主要包括如下几个指令:

0x88    MOV Eb, Gb          G:通用寄存器         
0x89    MOV Ev, Gv          E:寄存器/内存            
0x8A    MOV Gb, Eb          b:字节            
0x8B    MOV Gv, Ev          vWord, doubleword or quadword          

当指令中出现内存操作对象的时候,就需要在操作码后面附加一个字节来进行补充说明,这个字节被称为ModR/M

4.1 ModR/M解析

这一个字节(八位)可以被分为如下图所示的三个部分:

4.1.1 Reg/Opcode

Reg/Opcode(第3、4、5位)描述指令中的G部分,即寄存器,寄存器的对应关系如下图所示:

4.1.2 Mod和R/M

Mod(第6、7位)和R/M(第0、1、2位)共同描述指令中的E部分,即寄存器/内存。使用方法查下表即可:

例,查询8801的过程如下图,首先根据88得知操作宽度MOV Eb, Gb,存在对内存操作且宽度为byte,ModR/M内容查上表即可:

4.1.3 特殊情况

  • 1、ESP指向栈顶,是浮动的,不确定的,Inter将这个编码废弃,由另外的格式来说明。
  • 2、EBP指向栈底,而[EBP]通常存储上一个EBP,所以[EBP]无数据操作意义,Inter将这个编码废弃,改为立即数寻址。例如88 05 12 34 56 78 的汇编指令为 MOV BYTE PTR DS:[78563412], AL.

5.经典变长指令_Reg/Opcode

在第四节当中学的3-5位是用来标志寄存器的,有时其实也用来表示Opcode,比如指令白皮书中表A-2中发现80、81、82、83这几个编码并没有指定明确的操作码,如下图: 这里显示的操作码是Grp1 /1A,此时应该查表A-6,如下图:

例,80 65 08 FF查表过程如下:

  • 1、第一个字节为80 查Table-2表,得到对应结构:Eb,Ib
  • 2、第二个字节为ModR/M字段,所以拆分65变为(01 100 101)
  • 3、Mod 与 R/M字段 查Table2-2 得到对应的结构:[EBP+DIS8]
  • 4 、100 字段 查表TableA-6 得到对应操作码为:AND
  • 5、最终指令为AND BYTE PTR SS:[EBP+08],0xFF

6.经典变长指令SIB字段

ModR/M字段是用来进行内存寻址的,可当地址形如DS:[EAX + ECX*2 + 12345678]时,仅仅靠ModR/M字段,是描述不出来的,所以就有了这个SIB字段,如下图所示是之前根据mod字段、R/M字段查表时ESP所对应的选项。

上图中的三种情况在ModR/M字节后,还紧跟着一个SIB字节。SIB字节的8个位被分成了三部分:

这三个部分生成表达式的过程如下:

具体对应关系查下表即可:

7.附件

Intel操作指令白皮书点此下载