Step.1_引擎大纲
Step.2_框架搭建
Step.3_经典定长指令的解析
Step.4_变长指令复习1
Step.5_变长指令复习2 - 指令前缀
Step.6_引擎核心->函数封装
在前面5章中,我们完成了定长指令的解析
也学习了变长指令的解析方法
,在开始变长指令解析代码编写
前,我们观察一下我们在Step3
中所写的代码,大量冗余代码,如果要进行扩展,需要更改每一个函数,因此,本章我们不进行变长指令的解析,我们进行一下代码的优化
在Step3
代码中,我们看到了很多类似这样的代码:
大量的重复代码会使我们接下来的开发和维护变得异常困难,因此我们将这些代码进行整合提取,封装成一个函数buildStr
,合并后的代码如下:
可以看到代码明显减少,而且层次分明了许多,具体合并代码不贴了,上传在附件里,大家可以自行下载阅读
我只在这里说一下我封装后的函数:buildStr
的参数说明
如下是buildStr
的函数声明:
我将目前能考虑到的所有情况全部封装成一个函数,这样不管什么汇编指令,只要传入的参数正确,我就可以正确的解析出一条指令,下面我将具体说明下每个参数的含义和作用
Opcode首地址,代表了当前解析的硬编码开始地址,这个地址不应该包含前缀,如: E8 12 34 56 78,则pOpcode代表E8的地址
此参数不可为空
整条硬编码的字节长度,不包含前缀,如 66 50 ,因为66是前缀,所以此参数应传递1
此参数不可为空
操作数1类型 ,0为寄存器 ,1为内存 ,2为单立即数操作 ,-1为单指令如nop retn
当指令类似 MOV EAX,0X12345678时,EAX
我将其称之为操作数1
,后面的12345678
我将其称之为操作数2
操作数1应当满足以下几种情况中的一种:
操作数2类型, 0为寄存器 ,1为内存 ,2为立即数 ,3为段寄存器 ,-1为单寄存器操作 , -2为舍弃
当指令类似 MOV EAX,0X12345678时,EAX
我将其称之为操作数1
,后面的12345678
我将其称之为操作数2
操作数2应当满足以下几种情况中的一种:
很尴尬,这是我上周写的函数,当时忘了是咋回事来着,我发现单寄存器操作满足不了我的需求,又加了一个类型为舍弃,我也忘了我当时写这俩啥区别了 淦....
操作数宽度,此参数代表整行指令出现MOV类的赋值语句时,需要指定当前操作的数据宽度是多少(和立即数大小无关,这点请注意),如 MOV EAX,[0x12346578],我们都知道这条指令操作的是4字节的内存,所以此参数传入4,若不是MOV语句,则此参数必须传入4
常量数宽度,也是立即数宽度,代表整行指令出现的立即数的字节数是多少
如 : PUSH 0x1234,向堆栈压入0x1234,则此参数应传入4
(为啥不是2,请自行百度内存对齐相关知识)
如: MOV AL,0x12 ,则此参数传入1
如: MOV byte ptr ds:[EAX+0x1234],AL 则此参数传入4
如: MOV byte ptr ds:[EAX+0x12],AL 则此参数传入1
如: RETN 0x1234 则此参数传入2
没有常量数时,此参数传入0
指令名字字符串,宽字符,代表当前指令的指令是什么,类似MOV JMP PUSH DEC INC RETN
的其中一个
寄存器1名字,如果操作数1为寄存器或包含寄存器,则此参数传入寄存器名字
如: MOV AL,0x12 ,则此参数传入AL
如: MOV byte ptr ds:[EAX+0x1234],AL 则此参数传入EAX
如 : PUSH 0x1234 ,则此参数传入""
(空,不能传0,会空指针异常)
寄存器2名字,如果操作数2为寄存器或包含寄存器,则此参数传入寄存器名字
如: MOV byte ptr ds:[EAX+0x1234],AL 则此参数传入AL
如 : PUSH 0x1234 ,则此参数传入""
(空,不能传0,会空指针异常)
如: MOV AL,0x12 ,则此参数传入""
(空,不能传0,会空指针异常)
此条指令是否需要计算偏移
如JCC系列 CALL
等修改EIP
的指令,都需要进行偏移的计算,这时此参数传入1
,不需要计算则传0
代码就上传附件了,这章没啥东西,就是封装了一个函数
感谢各位阅读
/
*
0F80
~
0F8F
的解析
*
/
void Translate_0F80_0F8F() {
switch (codeList[index
+
1
])
{
case
0x80
:
{
/
/
取出跳转后面的四字节偏移
DWORD im
=
*
((DWORD
*
)(codeList
+
index
+
2
));
/
/
计算跳转实际位置
im
=
im
+
6
+
baseAddr
+
index;
TCHAR
*
tt
=
(TCHAR
*
)malloc(
256
);
memset(tt,
0
,
256
);
BYTE b1
=
*
((BYTE
*
)(codeList
+
index
+
3
));
BYTE b2
=
*
((BYTE
*
)(codeList
+
index
+
4
));
BYTE b3
=
*
((BYTE
*
)(codeList
+
index
+
5
));
BYTE b4
=
*
((BYTE
*
)(codeList
+
index
+
6
));
_stprintf(tt, L
"0F80%02X%02X%02X%02X\t\tJO %08X\r\n"
, b1, b2, b3, b4, im);
append(tt);
free(tt);
break
;
}
case
0x81
:
{
/
/
取出跳转后面的四字节偏移
DWORD im
=
*
((DWORD
*
)(codeList
+
index
+
2
));
/
/
计算跳转实际位置
im
=
im
+
6
+
baseAddr
+
index;
TCHAR
*
tt
=
(TCHAR
*
)malloc(
256
);
memset(tt,
0
,
256
);
BYTE b1
=
*
((BYTE
*
)(codeList
+
index
+
2
));
BYTE b2
=
*
((BYTE
*
)(codeList
+
index
+
3
));
BYTE b3
=
*
((BYTE
*
)(codeList
+
index
+
4
));
BYTE b4
=
*
((BYTE
*
)(codeList
+
index
+
5
));
_stprintf(tt, L
"0F81 %02X%02X%02X%02X\tJNO %08X\r\n"
, b1, b2, b3, b4, im);
append(tt);
free(tt);
break
;
}
/
*
0F80
~
0F8F
的解析
*
/
void Translate_0F80_0F8F() {
switch (codeList[index
+
1
])
{
case
0x80
:
{
/
/
取出跳转后面的四字节偏移
DWORD im
=
*
((DWORD
*
)(codeList
+
index
+
2
));
/
/
计算跳转实际位置
im
=
im
+
6
+
baseAddr
+
index;
TCHAR
*
tt
=
(TCHAR
*
)malloc(
256
);
memset(tt,
0
,
256
);
BYTE b1
=
*
((BYTE
*
)(codeList
+
index
+
3
));
BYTE b2
=
*
((BYTE
*
)(codeList
+
index
+
4
));
BYTE b3
=
*
((BYTE
*
)(codeList
+
index
+
5
));
BYTE b4
=
*
((BYTE
*
)(codeList
+
index
+
6
));
_stprintf(tt, L
"0F80%02X%02X%02X%02X\t\tJO %08X\r\n"
, b1, b2, b3, b4, im);
append(tt);
free(tt);
break
;
}
case
0x81
:
{
/
/
取出跳转后面的四字节偏移
DWORD im
=
*
((DWORD
*
)(codeList
+
index
+
2
));
/
/
计算跳转实际位置
im
=
im
+
6
+
baseAddr
+
index;
TCHAR
*
tt
=
(TCHAR
*
)malloc(
256
);
memset(tt,
0
,
256
);
BYTE b1
=
*
((BYTE
*
)(codeList
+
index
+
2
));
BYTE b2
=
*
((BYTE
*
)(codeList
+
index
+
3
));
BYTE b3
=
*
((BYTE
*
)(codeList
+
index
+
4
));
BYTE b4
=
*
((BYTE
*
)(codeList
+
index
+
5
));
_stprintf(tt, L
"0F81 %02X%02X%02X%02X\tJNO %08X\r\n"
, b1, b2, b3, b4, im);
append(tt);
free(tt);
break
;
}
/
*
90
~
97
的解析
*
/
void Translate_90_97() {
switch (codeList[index])
{
case
0x90
:
append(buildStr((char
*
)(codeList
+
index),
1
,
-
1
,
-
2
,
4
,
0
, (TCHAR
*
)(L
"NOP"
), (TCHAR
*
)(L""),
0
,
0
));
break
;
case
0x91
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"ECX"
),
0
));
break
;
case
0x92
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EDX"
),
0
));
break
;
case
0x93
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EBX"
),
0
));
break
;
case
0x94
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"ESP"
),
0
));
break
;
case
0x95
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EBP"
),
0
));
break
;
case
0x96
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"ESI"
),
0
));
break
;
case
0x97
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EDI"
),
0
));
break
;
}
/
/
解析完成后索引
+
1
,之所以加一,是因为
90
~
97
全部是一字节的定长指令
index
+
+
;
}
/
*
B0~BF的解析
*
/
void Translate_B0_BF() {
switch (codeList[index])
{
case
0xB0
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"AL"
),
0
,
0
));
break
;
}
case
0xB1
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"CL"
),
0
,
0
));
break
;
}
case
0xB2
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"DL"
),
0
,
0
));
break
;
}
case
0xB3
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"BL"
),
0
,
0
));
break
;
}
case
0xB4
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"AH"
),
0
,
0
));
break
;
}
case
0xB5
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"CH"
),
0
,
0
));
break
;
}
case
0xB6
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"DH"
),
0
,
0
));
break
;
}
case
0xB7
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"BH"
),
0
,
0
));
break
;
}
case
0xB8
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"EAX"
),
0
,
0
));
break
;
}
case
0xB9
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"ECX"
),
0
,
0
));
break
;
}
case
0xBA
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"EDX"
),
0
,
0
));
break
;
}
case
0xBB
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"EBX"
),
0
,
0
));
break
;
}
case
0xBC
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"ESP"
),
0
,
0
));
break
;
}
case
0xBD
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"EBP"
),
0
,
0
));
break
;
}
case
0xBE
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"ESI"
),
0
,
0
));
break
;
}
case
0xBF
:
{
append(buildStr((char
*
)(codeList
+
index),
5
,
0
,
2
,
4
,
4
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"EDI"
),
0
,
0
));
break
;
}
}
if
(codeList[index]<
0xB8
)
{
index
+
=
2
;
}
else
{
index
+
=
5
;
}
}
/
*
90
~
97
的解析
*
/
void Translate_90_97() {
switch (codeList[index])
{
case
0x90
:
append(buildStr((char
*
)(codeList
+
index),
1
,
-
1
,
-
2
,
4
,
0
, (TCHAR
*
)(L
"NOP"
), (TCHAR
*
)(L""),
0
,
0
));
break
;
case
0x91
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"ECX"
),
0
));
break
;
case
0x92
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EDX"
),
0
));
break
;
case
0x93
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EBX"
),
0
));
break
;
case
0x94
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"ESP"
),
0
));
break
;
case
0x95
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EBP"
),
0
));
break
;
case
0x96
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"ESI"
),
0
));
break
;
case
0x97
:
append(buildStr((char
*
)(codeList
+
index),
1
,
0
,
0
,
4
,
0
, (TCHAR
*
)(L
"XCHG"
), (TCHAR
*
)(L
"EAX"
), (TCHAR
*
)(L
"EDI"
),
0
));
break
;
}
/
/
解析完成后索引
+
1
,之所以加一,是因为
90
~
97
全部是一字节的定长指令
index
+
+
;
}
/
*
B0~BF的解析
*
/
void Translate_B0_BF() {
switch (codeList[index])
{
case
0xB0
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"AL"
),
0
,
0
));
break
;
}
case
0xB1
:
{
append(buildStr((char
*
)(codeList
+
index),
2
,
0
,
2
,
1
,
1
, (TCHAR
*
)(L
"MOV"
), (TCHAR
*
)(L
"CL"
),
0
,
0
));
break
;
}
case
0xB2
:
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!