首页
论坛
课程
招聘
雪    币: 2741
活跃值: 活跃值 (64)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝

[调试逆向] [原创]为了理解反汇编引擎而写的X86/X64反汇编引擎

2020-2-26 01:37 5406

[调试逆向] [原创]为了理解反汇编引擎而写的X86/X64反汇编引擎

2020-2-26 01:37
5406

        自己学习逆向一段时间了,发现很不得法。就想自己写个东西来巩固一下。翻了论坛,发现很多人都写了自己的反汇编引擎。自己翻看了获益良多。但是发现没有人详细的写过X64指令的解析过程。所以自己就打算写一个X64的反汇编引擎。后来研究过后发现,其实X86和X64的解析差不多的,就把X86和X64一起合起来写了。为了写一个反汇编引擎发现自己也是够拼了。自己翻译了Intel手册的几个章节。后来发现intel手册的一个很大缺点,就是X64的说明很少。例如X64下的ModR/M、SIB解析表根本没有。我就去翻看了AMD的文档,发现了宝贝。AMD不愧是X64的发明人,手册把X64的各种资料都包含了进去。自己很是兴奋,就把介绍指令概述的章节给翻译了。能够把X86/X64讲明白的,我就服AMD的文档。他用一张图把怎么解析指令给概括了。就是下图


原本我在看完Intel文档之后各种思路被这个图串联起来了。这里不能不说一声AMD YES!还有就是要感谢大神@ mik,是大神的文档帮我省了很多时间。我写代码的过程中无意中发现了大神的文档。是从X度文库下来下的,花了我一个月的会员啊,为了一篇文档。不过大神的网站上不了了。非常遗憾。附上大神在看雪的主页@mik

我在写的过程之中发现X86/X64指令的解析过程很麻烦,有些前面部分的解析和后面的字节有关,后面的字节的解析也可能和前面的字节有关。指令各部分长度的不一致。写得我心烦。接下来我会先分析Intel/AMD手册说明解析一条指令跟什么有关系。让然后再逐个分析解析指令的各个部分的详细过程。

手册里对解析指令最重要的就是 OPCODE TABLES。 一个字节是一条指令里的什么部分都能从 OPCODE TABLES里面查出来。

OpcodeMap里面的包含的元素

(1) Opcode :                                             例如PUSH  (注意缩写还有就是简写)一对多的放在类型说明里面

(2) Addressing Method + Operand Type :例如 Gv, Ev  一对多的单独作为一个类型

(3) Register Codes :                                 例如 rBX/r11   一对多的单独作为一个类型

(4) Superscripts :                                      例如 1A、i64   视情况而定,也是比较少。不适合做单独的类型

(5) Opcode Extensions Group Number :  例如 Grp 2  (intel的前面可能会有对该组的描述性文字如 Immediate)

(6) Prefix                                                      例如 : Operand Size (Prefix)

(7) REX Prefix                                              例如 : REX.X  类型说明

(8) 描述性文字                                             例如 : word, double-word or quad-word register with rAX

(9) 距离                                                        例如 : near  类型说明,或者其他

(10)说明位于其他表                                     例如 : 3-byte escape,VEX+2byte

(11)空白                                                       直接类型说明,为0,与通用的一样,不过后面的opcode没有name

(12)异常代码                                                例如 : UD0   太少不放进去结构体了

加粗的都是关键,其他的只是说明注解。

        那么应该怎么使用 OPCODE TABLES建议大家去看Intel文档的Volume 2 (2A, 2B, 2C & 2D):Instruction Set Reference, A-Z中的Appendix A Opcode Map面的

A.1 USING OPCODE TABLES ,我已经做了翻译(见附件)。我概括如下

1、看位于哪个OPCODE表

2、取出指令,寻址类型还有操作数类型

3、注意符合寄存器表示方式的解析与操作数类型相关

4、写死在opcode里面的寄存器需要表示,这个是单独的。跟第5点不是存在一样的表示

5、根据寻址类型还有操作数类型确定后面是否有 ModR/M字节、SIB字节、偏移量字节(1、2、4、8字节)、立即数字节(1、2、4、8字节)。

6、依次解码opcode还有操作数1-3

        我的代码是首先构造一个和OPCODE表const OPCODE_STRUCT Primary_opcodemap[0x10][0x10] ,这个表是由结构体数组组成的,其实就是AMD文档里的 OPCODE TABLES的基本结构
typedef struct OPCODE_STRUCT
{
	const char *opcode;
	int  AddressingMethod1st;
	int  OperandType1st;
	int  AddressingMethod2nd;
	int  OperandType2nd;
	int  AddressingMethod3rd;
	int  OperandType3rd;
	int  SelfType;     //该指令字节码的类型
}OPCODE_STRUCT, *POPCODE_STRUCT;

因为 OPCODE TABLES里包含各种各种类型的元素,有些OPCODE有多种解析方式。所以在解析之前需要做处理。
	//解析具体的opcode,先返回opcode字符串,还有就是处理操作数寻址方式还有操作数大小,方便后面统一处理
	//开始先对三个操作数的寻址方式和操作数类型做默认的处理
	decode_struct.AddressingMethod[0] = popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].AddressingMethod1st;
	decode_struct.OperandType[0] = popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].OperandType1st;
	decode_struct.AddressingMethod[1] = popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].AddressingMethod2nd;
	decode_struct.OperandType[1] = popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].OperandType2nd;
	decode_struct.AddressingMethod[2] = popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].AddressingMethod3rd;
	decode_struct.OperandType[2] = popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].OperandType3rd;
	switch (popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].SelfType)
	{
	case 0://通用的类型opcode解析
		Result = Result + popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].opcode;
		//还是在这里处理寻址方式和寻址类型然后返回相关信息,接下来再根据相关信息去解析出后面的字节(等指针移动之后)。
		//通用的类型通用类型的直接获取opcode字符串,然后获取三个操作数的寻址方式还有操作数类型
		break;
	case PUPO:
		if (REX_B_Flag)
		{
			decode_struct.AddressingMethod[0] = decode_struct.AddressingMethod[1];
			decode_struct.AddressingMethod[1] = UNCON;
		}
		else
			decode_struct.AddressingMethod[1] = UNCON;
		Result = Result + Result + popcodemap[(int)HighNibble(*POpcode)][(int)LowNibble(*POpcode)].opcode;
		break;
//篇幅有限,只是贴一部分代码

先根据 SelfType 还有具体的情况确认opcode,然后再确定寻址方式还有寻址类型(需要做统一的处理)。
	//先判断opcode后面的字节有没有ModRM字节
	for (int icount = 0; icount <3;icount++)
	{
		switch (decode_struct.AddressingMethod[icount])
		{
		case C:
		case D:
		case G:
		case P:
		case S:
		case V:
		case E:
		case M:
		case N:
		case Q:
		case R:
		case U:
		case W:
			ModRM_Flag = true;
			if (0x4== RM(*(POpcode + 1)) && 0x3 != MOD(*(POpcode + 1)))//当ModRM.r/m == 100(0x4)且Mod ≠11b时,存在SIB字节
				SIB_Flag = true;
			if (0x0 == MOD(*(POpcode + 1)) && 0x5 == RM(*(POpcode + 1)))//当ModRM.r/m == 101(0x5)且MOD == 0时,disp为4字节
				idispcount = 4;
			if (0x1 == MOD(*(POpcode + 1)))//当ModRM.MOD == 1时,disp为1字节
				idispcount = 1;
			if (0x2 == MOD(*(POpcode + 1)))//当ModRM.MOD == 2时,disp为4字节
				idispcount = 4;
			if (true == SIB_Flag && 0x5 == BASE(*(POpcode + 2)) && 0x0 == MOD(*(POpcode + 1)))//有SIB且base域为5,当ModRM.MOD == 0时,disp为4字节
				idispcount = 4;
			if (true == SIB_Flag && 0x5 == BASE(*(POpcode + 2)) && 0x1 == MOD(*(POpcode + 1)))//有SIB且base域为5,当ModRM.MOD == 1时,disp为1字节
				idispcount = 1;
			if (true == SIB_Flag && 0x5 == BASE(*(POpcode + 2)) && 0x2 == MOD(*(POpcode + 1)))//有SIB且base域为5,当ModRM.MOD == 2时,disp为4字节
				idispcount = 4;
			break;
		default:
			break;
		}
	}

确定一条指令包含什么部分:
先确定有没有ModRM字节-->然后确定有没有SIB字节
                   |
                   I-->确定有没有Disp字节(有几字节?)3的寻址方式还有类型确认后面的有什么字节

再确定有没有 immediate 字节(有几字节)这个可以到最后解码immediate字节的时候再做。

一、先解码寄存器操作数


//General Registers in Legacy and Compatibility Modes OR General Registers in 64-Bit Mode Without REX
const char *GPRs32[0x3][0x8] =
{
  {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" },//8bit
  {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI" },//16bit
  {"EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI"} //32bit
};

//General Registers in 64-Bit Mode With REX
const char *GPRs64[0x4][0x10] =
{
  {"AL", "CL", "DL", "BL", "SPL", "BPL", "SIL", "DIL", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B"},//8bit
  {"AX", "CX", "DX", "BX", "SP" , "BP" , "SI" , "DI" , "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"},//16bit
  {"EAX","ECX","EDX","EBX","ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"},//32bit
  {"RAX","RCX","RDX","RBX","RSP", "RBP", "RSI", "RDI", "R8" , "R9" , "R10" , "R11" , "R12",  "R13" , "R14" , "R15" } //64bit
};
		switch (decode_struct.AddressingMethod[icount])
		{
		case rAX:
		case rCX:
		case rDX:
		case rBX:
		case rSP:
		case rBP:
		case rSI:
		case rDI:
		case r8:
		case r9:
		case r10:
		case r11:
		case r12:
		case r13:
		case r14:
		case r15://解析直接出现的寄存器操作数
			if (UNCON != decode_struct.OperandType[icount])
				Result = Result + GPRs64[decode_struct.OperandType[icount]][decode_struct.AddressingMethod[icount]];
			else
			{
				if (MODE32 == Mode)
				{
					if (OPSizeFlag)
					    Result = Result + GPRs32[_16BIT][decode_struct.AddressingMethod[icount]];
					else
						Result = Result + GPRs32[_32BIT][decode_struct.AddressingMethod[icount]];
				}
				else
				{
					if (REX_W_Flag || REX_B_Flag)
						Result = Result + GPRs64[_64BIT][decode_struct.AddressingMethod[icount]];
					else
					{
						if (OPSizeFlag)
							Result = Result + GPRs64[_16BIT][decode_struct.AddressingMethod[icount]];
						else
							Result = Result + GPRs64[_32BIT][decode_struct.AddressingMethod[icount]];
					}
				}
			}
			break;

  寄存器的解码
  1、根据当前的模式还有就是有没有操作数大小覆盖前缀来确定(没有大小描述的情况)
  2、直接解码返回(有大小描述的情况)

二、解码Mod.reg域

//当不存在REX时,REG域数组,[具体的选项][REG]
const char *ModRM_REG0[0xA][0x8] =
{
  {"AL",  "CL",  "DL",  "BL",  "AH",  "CH",  "DH",  "BH" },//reg8
  {"AX",  "CX",  "DX",  "BX",  "SP",  "BP",  "SI",  "DI" },//reg16
  {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"},//reg32
  {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI"},//reg64
  {"MMX0","MMX1","MMX2","MMX3","MMX4","MMX5","MMX6","MMX7"},//mmx
  {"XMM0","XMM1","XMM2","XMM3","XMM4","XMM5","XMM6","XMM7"},//xmm
  {"YMM0","YMM1","YMM2","YMM3","YMM4","YMM5","YMM6","YMM7"},//ymm
  {"ES",  "CS",  "SS",  "DS",  "FS",  "GS",  "invalid","invalid"},//sReg
  {"CR0", "CR1", "CR2", "CR3", "CR4", "CR5", "CR6", "CR7" },//cReg
  {"DR0", "DR1", "DR2", "DR3", "DR4", "DR5", "DR6", "DR7" } //dReg
};
//当存在REX且REX.R为0时,REG域数组,[具体的选项][REG]
const char *ModRM_REG10[0xA][0x8] =
{
  {"AL",  "CL",  "DL",  "BL",  "SPL", "BPL", "SIL", "DIL"},//reg8
  {"AX",  "CX",  "DX",  "BX",  "SP",  "BP",  "SI",  "DI" },//reg16
  {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"},//reg32
  {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI"},//reg64
  {"MMX0","MMX1","MMX2","MMX3","MMX4","MMX5","MMX6","MMX7"},//mmx
  {"XMM0","XMM1","XMM2","XMM3","XMM4","XMM5","XMM6","XMM7"},//xmm
  {"YMM0","YMM1","YMM2","YMM3","YMM4","YMM5","YMM6","YMM7"},//ymm
  {"ES",  "CS",  "SS",  "DS",  "FS",  "GS","invalid","invalid"},//sReg
  {"CR0", "CR1", "CR2", "CR3", "CR4", "CR5", "CR6", "CR7"},//cReg
  {"DR0", "DR1", "DR2", "DR3", "DR4", "DR5", "DR6", "DR7"} //dReg
};
//当存在REX且REX.R为1时,REG域数组,[具体的选项][REG]
const char *ModRM_REG11[0xA][0x8] =
{
  {"R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B"},//reg8
  {"R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W"},//reg16
  {"R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D"},//reg32
  {"R8",  "R9",  "R10",  "R11",  "R12",  "R13",  "R14",  "R15"},//reg64
  {"MMX0","MMX1","MMX2", "MMX3", "MMX4", "MMX5", "MMX6", "MMX7"},//mmx
  {"XMM8","XMM9","XMM10","XMM11","XMM12","XMM13","XMM14","XMM15"},//xmm
  {"YMM8","YMM9","YMM10","YMM11","YMM12","YMM13","YMM14","YMM15"},//ymm
  {"ES",  "CS",  "SS",   "DS",   "FS",   "GS",   "invalid","invalid"},    //sReg
  {"CR8", "CR9", "CR10", "CR11", "CR12", "CR13", "CR14", "CR15" },//cReg
  {"DR8", "DR9", "DR10", "DR11", "DR12", "DR13", "DR14", "DR15" } //dReg
};
//解码Mod.REG域函数
static void DecodeREG(BYTE* PModRM, CString &Result, bool REX_Flag, bool REX_W_Flag, bool REX_R_Flag, int Mode, bool OPSizeFlag, int DecodeType)
{
	if (MODE32 == Mode)
	{
		if (GPRS != DecodeType)
			Result = Result + " " + ModRM_REG0[DecodeType][REG(*PModRM)] + " ";
		else
		{
			if (OPSizeFlag)
				Result = Result + " " + ModRM_REG0[REG16][REG(*PModRM)] + " ";
			else
				Result = Result + " " + ModRM_REG0[REG32][REG(*PModRM)] + " ";
		}
	}
	else
	{
		if (REX_Flag)
		{
			if (REX_R_Flag)
			{
				if (GPRS != DecodeType)
					Result = Result + " " + ModRM_REG11[DecodeType][REG(*PModRM)] + " ";
				else
				{
					if (REX_W_Flag)
						Result = Result + " " + ModRM_REG11[REG64][REG(*PModRM)] + " ";
					else
					{
						if (OPSizeFlag)
							Result = Result + " " + ModRM_REG11[REG16][REG(*PModRM)] + " ";
						else
							Result = Result + " " + ModRM_REG11[REG32][REG(*PModRM)] + " ";
					}
				}
			}
			else
			{
				if (GPRS != DecodeType)
					Result = Result + " " + ModRM_REG10[DecodeType][REG(*PModRM)] + " ";
				else
				{
					if (REX_W_Flag)
						Result = Result + " " + ModRM_REG10[REG64][REG(*PModRM)] + " ";
					else
					{
						if (OPSizeFlag)
							Result = Result + " " + ModRM_REG10[REG16][REG(*PModRM)] + " ";
						else
							Result = Result + " " + ModRM_REG10[REG32][REG(*PModRM)] + " ";
					}
				}
			}
		}
		else
		{
			if (GPRS != DecodeType)
				Result = Result + " " + ModRM_REG0[DecodeType][REG(*PModRM)] + " ";
			else
			{
				if (REX_W_Flag)
					Result = Result + " " + ModRM_REG0[REG64][REG(*PModRM)] + " ";
				else
				{
					if (OPSizeFlag)
						Result = Result + " " + ModRM_REG0[REG16][REG(*PModRM)] + " ";
					else
						Result = Result + " " + ModRM_REG0[REG32][REG(*PModRM)] + " ";
				}
			}
		}

	}
}


  使用三个二维数组表示[具体的选项][REG]
  具体的选项包括reg8、reg16、reg32、reg64、mmx、xmm、ymm,其中通用寄存器需要确定大小(reg8~reg64)
  使用一个函数解码,需要用到一个指向二维数组的指针(因为数组大小都是一样的)。
  
三、解码Mod.R/M域


//ModRM R/M Field Encoding, 32-Bit and 64-Bit Addressing

//32位且Mod≠11时的RM域数组,[Mod][R/M]
const char *ModRM_RM32[0x3][0x8] =
{
  {"EAX","ECX","EDX","EBX","","",   "ESI","EDI"},
  {"EAX","ECX","EDX","EBX","","EBP","ESI","EDI"},
  {"EAX","ECX","EDX","EBX","","EBP","ESI","EDI"}
};
//64位REX.B = 0且Mod≠11时的RM数组,[Mod][R/M]
const char *ModRM_RM64_0[0x3][0x8] =
{
  {"RAX","RCX","RDX","RBX","","",   "RSI","RDI"},
  {"RAX","RCX","RDX","RBX","","RBP","RSI","RDI"},
  {"RAX","RCX","RDX","RBX","","RBP","RSI","RDI"}
};
//64位REX.B = 1且Mod≠11时的RM数组,[Mod][R/M]
const char *ModRM_RM64_1[0x3][0x8] =
{
  {"R8","R9","R10","R11","","",   "R14","R15"},
  {"R8","R9","R10","R11","","R13","R14","R15"},
  {"R8","R9","R10","R11","","R13","R14","R15"}
};
//32位且Mod =11时的RM域数组,[具体的选项][R/M]
const char *ModRM_RM32_11[0x5][0x8] =
{
  {"AL",  "CL",  "DL",  "BL",  "AH",  "CH",  "DH",  "BH"  },//reg8
  {"AX",  "CX",  "DX",  "BX",  "SP",  "BP",  "SI",  "DI"  },//reg16
  {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" },//reg32
  {"MMX0","MMX1","MMX2","MMX3","MMX4","MMX5","MMX6","MMX7"},//mmx
  {"XMM0","XMM1","XMM2","XMM3","XMM4","XMM5","XMM6","XMM7"} //xmm
};
//64位REX.B = 0且Mod = 11时的RM数组,[具体的选项][R/M]
const char *ModRM_RM64_110[0x7][0x8] =
{
  {"AL",  "CL",  "DL",  "BL",  "SPL", "BPL", "SIL", "DIL" },//reg8
  {"AX",  "CX",  "DX",  "BX",  "SP",  "BP",  "SI",  "DI"  },//reg16
  {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" },//reg32
  {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI" },//reg64
  {"MMX0","MMX1","MMX2","MMX3","MMX4","MMX5","MMX6","MMX7"},//mmx
  {"XMM0","XMM1","XMM2","XMM3","XMM4","XMM5","XMM6","XMM7"},//xmm
  {"YMM0","YMM1","YMM2","YMM3","YMM4","YMM5","YMM6","YMM7"},//ymm
};
//64位REX.B = 1且Mod = 11时的RM数组,[具体的选项][R/M]
const char *ModRM_RM64_111[0x7][0x8] =
{
  {"R8B", "R9B", "R10B",  "R11B",  "R12B",  "R13B",  "R14B",  "R15B" },//reg8
  {"R8W", "R9W", "R10W",  "R11W",  "R12W",  "R13W",  "R14W",  "R15W" },//reg16
  {"R8D", "R9D", "R10D",  "R11D",  "R12D",  "R13D",  "R14D",  "R15D" },//reg32
  {"R8" , "R9" , "R10" ,  "R11" ,  "R12",   "R13" ,  "R14" ,  "R15"  },//reg64
  {"MMX0","MMX1","MMX2",  "MMX3",  "MMX4",  "MMX5",  "MMX6",  "MMX7" },//mmx
  {"XMM8","XMM9","XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15"},//xmm
  {"YMM8","YMM9","YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15"},//ymm
};
//解码代码太长,不贴了。请看附件源代码DecodeModRM函数

   Mod为00b~10b使用三个二维数[Mod][R/M](32位,64位的当REX.B = 0与REX.B = 1,三种情况,其中01,10需要解析出disp字节),Mod为11b单独使用[具体的选项][R/M]为三个二维数组32位,64位的当REX.B = 0与REX.B = 1,三种情况),根据具体的情况传入[具体选项]与[R/M],返回字符串 
   注意有SIB字节的情况,这种情况单独处理
   处理函数的步骤:
   先通过位数(模式)、REX.B和Mod来确定二维数组
   1、Mod ≠ 11b,直接通过[Mod][R/M]就可以返回,通过Mod与R/M确定有没有SIB需要特殊处理,有Disp就解析出来。
   2、Mod = 11b,通用寄存器需要确定大小(reg8~reg64)作为[具体的选项],mmx xmm ymm不需要。不需要解析SIB和Disp
   

//32位SIB解析数组[scale比例][index索引]
const char *ScaledIndex32[0x4][0x8]
{
	{"EAX",  "ECX",  "EDX",  "EBX",  "","EBP",  "ESI",  "EDI"},
	{"EAX*2","ECX*2","EDX*2","EBX*2","","EBP*2","ESI*2","EDI*2"},
	{"EAX*4","ECX*4","EDX*4","EBX*4","","EBP*4","ESI*4","EDI*4"},
	{"EAX*8","ECX*8","EDX*8","EBX*8","","EBP*8","ESI*8","EDI*8"}
};
//64位当REX.X = 0时SIB解析数组[scale比例][index索引]
const char *ScaledIndex64_0[0x4][0x8]
{
	{"RAX",  "RCX",  "RDX",  "RBX",  "","RBP",  "RSI",  "RDI"},
	{"RAX*2","RCX*2","RDX*2","RBX*2","","RBP*2","RSI*2","RDI*2"},
	{"RAX*4","RCX*4","RDX*4","RBX*4","","RBP*4","RSI*4","RDI*4"},
	{"RAX*8","RCX*8","RDX*8","RBX*8","","RBP*8","RSI*8","RDI*8"}
};
//64位当REX.X = 1时SIB解析数组[scale比例][index索引]
const char *ScaledIndex64_1[0x4][0x8]
{
	{"R8",  "R9",  "R10",  "R11",  "R12",  "R13",  "RR14",  "R15"},
	{"R8*2","R9*2","R10*2","R11*2","R12*2","R13*2","RR14*2","R15*2"},
	{"R8*4","R9*4","R10*4","R11*4","R12*4","R13*4","RR14*4","R15*4"},
	{"R8*8","R9*8","R10*8","R11*8","R12*8","R13*8","RR14*8","R15*8"}
};

   SIB 字节由 ModRM.r/m = 100且Mod ≠ 11 引导出来
   解码SIB字节
   三个[scale][index]二维数组(32位,64位的当REX.X = 0与REX.X = 1,三种情况)
   SIB解析数组[scale][index]确定索引和比例 64位的base域是有两种情况的即REX.B = 0 或 REX.B = 1.当base域为101b时与Mod域有关联

   函数参数(指向ModR/M的指针,用来返回结果的CString对象的引用,REX_W_Flag,REX_X_Flag,REX_B_Flag,ModRM_Flag,SIB_Flag,idispcount(用来确定disp),Mode,OPSizeFlag,ADSizeFlag(用来确定操作数大小),
   [具体选项](这个只是很少的情况需要))

四、解码immediate字节
   根据前面判断的位置和大小取出(先转换指针类型,然后解指针)。

详细的解码只贴一个代码片段,就是通过操作数寻址类型和操作数大小判断出操作数位于上面指出的哪个位置然后解码的
		case E:
			if (0x3 != MOD(*(POpcode + 1)) && "" != StrPrefix1)
				Result = Result + " " + StrPrefix1 + ":";
			switch (decode_struct.OperandType[icount])
			{
			case v:
				if (0x3 != MOD(*(POpcode + 1)))
				    DecodeModRM((POpcode + 1), Result, REX_W_Flag, REX_X_Flag, REX_B_Flag, ModRM_Flag, SIB_Flag, idispcount, Mode, OPSizeFlag, ADSizeFlag, 0);
				else
					DecodeModRM((POpcode + 1), Result, REX_W_Flag, REX_X_Flag, REX_B_Flag, ModRM_Flag, SIB_Flag, idispcount, Mode, OPSizeFlag, ADSizeFlag, GPRS);
				break;
			case b:
				if (0x3 != MOD(*(POpcode + 1)))
				    DecodeModRM((POpcode + 1), Result, REX_W_Flag, REX_X_Flag, REX_B_Flag, ModRM_Flag, SIB_Flag, idispcount, Mode, OPSizeFlag, ADSizeFlag, _BYTEP);
				else
					DecodeModRM((POpcode + 1), Result, REX_W_Flag, REX_X_Flag, REX_B_Flag, ModRM_Flag, SIB_Flag, idispcount, Mode, OPSizeFlag, ADSizeFlag, REG8);
				break;
			default:
				break;
			}
			break;

32位效果,左边的是OllyDbg的反汇编结果

64位效果,左边是X64Dbg的反汇编结果

我只是做了Primary Opcode Map一个表,所以会出现问题。不过这个主要是用来理解指令的,所以就这样子了。不想去打磨了,生命无价,不要浪费时间在造轮子上。理解原理就够了。(intel的文档我就不上传了,自己去官网下),还有就是源代码我是使用VS2017构建的。那个压缩文件就是源代码,还有测试代码
        以上,让我再喊一声    AMD YES!

HWS计划·2020安全精英夏令营来了!我们在华为松山湖欧洲小镇等你

最后于 2020-2-26 04:12 被不化的雪编辑 ,原因:
上传的附件:
打赏 + 10.00
打赏次数 1 金额 + 10.00
 
赞赏  RinceLeung   +10.00 2020/03/12 支持樓主好文章!
最新回复 (29)
雪    币: 2741
活跃值: 活跃值 (64)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
不化的雪 活跃值 1 2020-2-26 01:41
2
0
我贴上去的代码怎么显示不了?奇怪了。还有就是,编辑器可不可以增加预览功能。
可以了,原来贴代码之后要回车,我只是点了确定
最后于 2020-2-26 03:41 被不化的雪编辑 ,原因: 找到粘贴不了代码的原因了
雪    币: 801
活跃值: 活跃值 (60)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zzcl558 活跃值 2020-2-26 03:49
3
0
谢谢分享!虽然我还看不懂
雪    币: 208
活跃值: 活跃值 (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
evilbeast 活跃值 2020-2-26 04:51
4
0
真有耐心
雪    币: 2104
活跃值: 活跃值 (99)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
syser 活跃值 2020-2-26 05:26
5
0
确实...造轮子太累了
雪    币: 4768
活跃值: 活跃值 (2500)
能力值: (RANK:65 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 2020-2-26 08:55
6
0
感谢分享~
雪    币: 3781
活跃值: 活跃值 (55)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
alphc 活跃值 2020-2-26 09:16
7
0
这个牛逼了,mark一个
雪    币: 479
活跃值: 活跃值 (26)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
heyiuo 活跃值 2020-2-26 09:58
8
0
牛逼,顶一个!
雪    币: 1807
活跃值: 活跃值 (73)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
拍拖 活跃值 2 2020-2-26 13:45
9
0
牛人。真有耐性。
雪    币: 2741
活跃值: 活跃值 (64)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
不化的雪 活跃值 1 2020-2-26 15:54
10
0
Editor 感谢分享~
可以给个优秀吗?花了好多时间的。
雪    币: 950
活跃值: 活跃值 (784)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2020-2-26 15:59
11
0
不化的雪 可以给个优秀吗?花了好多时间的。
必须精华,期待更精彩的文章!
雪    币: 2741
活跃值: 活跃值 (64)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
不化的雪 活跃值 1 2020-2-26 16:11
12
0
kanxue 必须精华,期待更精彩的文章!
谢谢坛主,我会继续努力的!
雪    币: 220
活跃值: 活跃值 (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
东京好嗨冷 活跃值 2 2020-2-26 20:30
13
0
雪    币: 272
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
榴莲味奥利奥 活跃值 2020-2-27 00:49
14
0
牛批,我选择OD
雪    币: 3627
活跃值: 活跃值 (45)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
IamHuskar 活跃值 4 2020-2-28 10:34
15
0
榴莲味奥利奥 牛批,我选择OD
。。。。  有功夫研究这个的都是牛人~
最后于 2020-2-28 10:35 被IamHuskar编辑 ,原因:
雪    币: 3297
活跃值: 活跃值 (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zlykcaj 活跃值 2020-2-28 13:47
16
0
雪中送炭的好文。。。
雪    币: 4445
活跃值: 活跃值 (50)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
TopC 活跃值 2020-2-28 14:58
17
0
感谢分享
雪    币: 222
活跃值: 活跃值 (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
云才哥 活跃值 2020-3-1 15:12
18
0
这才是真正受人于渔
雪    币: 153
活跃值: 活跃值 (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
人在塔在 活跃值 2020-3-1 20:46
19
0
好文,收藏
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
小明的同学 活跃值 2020-3-2 20:30
20
0
学习一下!!
雪    币: 137
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wkaka 活跃值 2020-3-8 00:07
21
0
这个必须支持,配服
雪    币: 4768
活跃值: 活跃值 (2500)
能力值: (RANK:65 )
在线值:
发帖
回帖
粉丝
Editor 活跃值 2020-3-9 10:45
22
0
感谢分享!mark!
雪    币: 2198
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
fjqisba 活跃值 2020-3-16 17:03
23
0
很多时候造轮子是有必要的,比如要做定制的轮子的时候。
雪    币: 3016
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
blowfish 活跃值 2020-3-19 12:40
24
0
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiasj 活跃值 2020-3-20 10:55
25
0
这个必须支持!
雪    币: 1912
活跃值: 活跃值 (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
boyving 活跃值 2020-3-21 11:32
26
0
非常不错的一篇文章,需要慢慢品。
雪    币: 933
活跃值: 活跃值 (104)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
又见飞刀z 活跃值 2020-3-21 12:39
27
0
大佬,有没有研究过ARM解析啊,我想做个ARM反汇编引擎,但是每次想到那种令人绝望的难度就放弃了,还是大佬有毅力
雪    币: 2741
活跃值: 活跃值 (64)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
不化的雪 活跃值 1 2020-3-21 14:39
28
0
又见飞刀z 大佬,有没有研究过ARM解析啊,我想做个ARM反汇编引擎,但是每次想到那种令人绝望的难度就放弃了,还是大佬有毅力
没碰过安卓开发,这个就不知道了。
雪    币: 654
活跃值: 活跃值 (5200)
能力值: ( LV9,RANK:166 )
在线值:
发帖
回帖
粉丝
0x指纹 活跃值 3 2020-4-9 18:15
29
0
膜膜膜
游客
登录 | 注册 方可回帖
返回