反汇编引擎:
BeaEngine
把headers和库文件win32两个文件夹拷贝到项目目录下。
预定义宏、包含头文件和库文件
#include "stdafx.h"
#include <windows.h>
#define BEA_ENGINE_STATIC
#define BEA_USE_STDCALL
#include "headers/BeaEngine.h"
#pragma comment(lib, "Win32/Lib/BeaEngine.lib")
#pragma comment(linker, "/NODEFAULTLIB:\"crt.lib\"")
使用头文件中的结构体:
#pragma pack(1)
typedef struct _Disasm {
UIntPtr EIP; // 你要反汇编的机器码的起始地址(数组)
UInt64 VirtualAddr; // 输出汇编语句时候指定的地址
UInt32 SecurityBlock;
char CompleteInstr[INSTRUCT_LENGTH]; //反汇编结果字符串
UInt32 Archi; // 平台,0表示X86_32,1表示X86_64
UInt64 Options; // 语法
INSTRTYPE Instruction; // 结果 操作码
ARGTYPE Argument1; // 结果 操作数1
ARGTYPE Argument2; // 结果 操作数2
ARGTYPE Argument3; // 结果 操作数3
PREFIXINFO Prefix; // 结果 前缀
UInt32 Reserved_[40];
} DISASM, *PDISASM, *LPDISASM;
#pragma pack()
// 反汇编引擎_beaengine.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#define BEA_ENGINE_STATIC
#define BEA_USE_STDCALL
#include "headers/BeaEngine.h"
#pragma comment(lib, "Win32/Lib/BeaEngine.lib")
#pragma comment(linker, "/NODEFAULTLIB:\"crt.lib\"")
int main()
{
BYTE bTest[] = { 0x68,0x37,0x31,0x40,0x00,0xFF,0x15,0x0C,0x20,0x40,0x00,0x83,0xC4,0x04,0xE8,0x0E,0x00,0x00,0x00,0xE8,0x3E,0x00,0x00,0x00,0xEB,0xE6,0x6A,0x00,0xE8,0x63,0x00,0x00 };
// 1. 初始化反汇编引擎
DISASM objDiasm;
objDiasm.EIP = (UIntPtr)bTest; // 起始地址
objDiasm.VirtualAddr = (UINT64)0x400000; // 虚拟内存地址(反汇编引擎用于计算地址)
objDiasm.Archi = 0; // AI-X86
objDiasm.Options = MasmSyntax; // MASM
UINT uLen = Disasm(&objDiasm);
CHAR szOpcode[32] = {};
PCHAR pOpcode = szOpcode;
for (UINT i = 0; i < uLen; i++) {
sprintf_s(&szOpcode[2 * i], 20, "%02x", bTest[i]);
}
printf("%s:%s\n", szOpcode, objDiasm.CompleteInstr);
return 0;
}
Capstone
拷贝include文件夹和库文件capstone_x86.lib到项目文件夹下。
#include "include/capstone.h"
#ifdef _64
#pragma comment(lib,"capstone_x64.lib")
#else
#pragma comment(lib,"capstone_x86.lib")
#endif
定义cs_opt_mem
结构体变量,然后依次使用4个函数:
cs_option()
,注册堆空间管理组函数cs_open()
,初始化反汇编器句柄,(x86_64架构,32位模式,句柄)cs_disasm()
,反汇编cs_free(pInsn, count);
,释放内存
// 反汇编引擎_capstone.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "include/capstone.h"
#ifdef _64
#pragma comment(lib,"capstone_x64.lib")
#else
#pragma comment(lib,"capstone_x86.lib")
#endif // _64
int _tmain(int argc, _TCHAR* argv[])
{
csh handle;
cs_err err;
cs_insn* pInsn;
unsigned int count = 0;
// 在编译capstone库的时候, 如果选择了用户自定义堆空间管理组(没有定义`CAPSTONE_USE_SYS_DYN_MEM`宏)
// 则需要调用cs_option函数来设定堆空间管理组函数
// 然后用结构体来配置回调函数.
// 定义结构体, 配置堆空间的回调函数
cs_opt_mem memop;
memop.calloc = calloc;
memop.free = free;
memop.malloc = malloc;
memop.realloc = realloc;
memop.vsnprintf = (cs_vsnprintf_t)vsprintf_s;
// 注册堆空间管理组函数
cs_option(0, CS_OPT_MEM, (size_t)&memop);
//初始化反汇编器句柄,(x86_64架构,32位模式,句柄)
err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle);
if (err != CS_ERR_OK) {
printf("初始化反汇编器句柄失败\n");
return 0;
}
unsigned char szOpcode[] = { "\x53\x83\xEC\x18\x83\x3D\x20\x20\x48\x00\x02\x8B\x44\x24\x24" };
// 开始反汇编.
count = cs_disasm(handle,/*反汇编器句柄,从cs_open函数得到*/
szOpcode,/*需要反汇编的opcode的缓冲区首地址*/
sizeof(szOpcode), /*opcode的字节数*/
0x401000, /*opcode的所在的内存地址*/
0, /*需要反汇编的指令条数,如果是0,则反汇编出全部*/
&pInsn/*反汇编输出*/
);
size_t j;
for (j = 0; j < count; j++) {
printf("0x%llx:%s %s\n",
pInsn[j].address, /*指令地址*/
pInsn[j].mnemonic,/*指令操作码*/
pInsn[j].op_str/*指令操作数*/
);
}
cs_free(pInsn, count);
return 0;
}
汇编引擎:
汇编引擎包下基本都有x86和x64两个版本。
XEDParse
拷贝XEDParse文件夹到项目目录中。
//1. 包含头文件和静态库
#include "XEDParse/XEDParse.h"
#ifdef _WIN64
#pragma comment (lib,"XEDParse/x64/XEDParse_x64.lib")
#else
#pragma comment (lib,"XEDParse/x86/XEDParse_x86.lib")
#endif
汇编结构体和api:
XEDPARSE xed = { 0 };
XEDParseAssemble(&xed);
//XEDParse structs
#pragma pack(push,8)
struct XEDPARSE
{
bool x64; // use 64-bit instructions
ULONGLONG cip; //instruction pointer (for relative addressing)
unsigned int dest_size; //destination size (returned by XEDParse)
CBXEDPARSE_UNKNOWN cbUnknown; //unknown operand callback
unsigned char dest[XEDPARSE_MAXASMSIZE]; //destination buffer
char instr[XEDPARSE_MAXBUFSIZE]; //instruction text
char error[XEDPARSE_MAXBUFSIZE]; //error text (in case of an error)
};
#pragma pack(pop)
- bool x64; // 是否使用X64指令集
- ULONGLONG cip; //汇编的起始地址值,你给的
- unsigned int dest_size; //汇编结果指令字节数
- unsigned char dest[XEDPARSE_MAXASMSIZE]; //opcode存放地址
- char instr[XEDPARSE_MAXBUFSIZE]; //汇编语句
#include "stdafx.h"
#include "XEDParse/XEDParse.h"
#ifdef _WIN64
#pragma comment (lib,"XEDParse/x64/XEDParse_x64.lib")
#else
#pragma comment (lib,"XEDParse/x86/XEDParse_x86.lib")
#endif // _WIN64
void printOpcode(const unsigned char* pOpcode, int nSize)
{
for (int i = 0; i < nSize; ++i) {
printf("%02X ", pOpcode[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
XEDPARSE xed = { 0 };
do {
printf("地址 指令:");
// 接受指令的地址和汇编指令
scanf_s("%llx", &xed.cip);
gets_s(xed.instr, XEDPARSE_MAXBUFSIZE);
if (XEDPARSE_OK != XEDParseAssemble(&xed)) {
printf("指令错误:%s\n", xed.error);
continue;
}
printf("%08X : ", (UINT)xed.cip);
printOpcode(xed.dest, xed.dest_size);
printf("\n");
} while (*xed.instr);
return 0;
}
地址 指令:00401000 push ebp
00401000 : 55
keystone
拷贝keystone文件夹到项目目录中。
包含头文件和静态库:
#include "keystone/keystone.h"
#pragma comment (lib,"keystone/x86/keystone_x86.lib")
使用的结构体是空的,我们需要定义一个指针。
struct ks_struct;
typedef struct ks_struct ks_engine;
四个步骤:
ks_open()
ks_asm()
ks_free()
ks_close()
// 汇编引擎_keystone.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//1. 包含头文件
#include "keystone/keystone.h"
//2. 包含静态库
#ifdef _WIN64
#pragma comment (lib,"keystone/x64/keystone_x86.lib")
#else
#pragma comment (lib,"keystone/x86/keystone_x86.lib")
#endif // _WIN64
// 打印opcode
void printOpcode(const unsigned char* pOpcode, int nSize)
{
for (int i = 0; i < nSize; ++i) {
printf("%02X ", pOpcode[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
ks_engine *pengine = NULL;
if (KS_ERR_OK != ks_open(KS_ARCH_X86, KS_MODE_32, &pengine)) {
printf("反汇编引擎初始化失败\n");
return 0;
}
unsigned char* opcode = NULL; // 汇编得到的opcode的缓冲区首地址
unsigned int nOpcodeSize = 0; // 汇编出来的opcode的字节数
// 汇编指令
// 可以使用分号,或者换行符将指令分隔开
char asmCode[] =
{
"mov eax,edx;mov eax,1;mov dword ptr ds:[eax],20"
};
int nRet = 0; // 保存函数的返回值,用于判断函数是否执行成功
size_t stat_count = 0; // 保存成功汇编的指令的条数
nRet = ks_asm(pengine, /* 汇编引擎句柄,通过ks_open函数得到*/
asmCode, /*要转换的汇编指令*/
0x401000, /*汇编指令所在的地址*/
&opcode,/*输出的opcode*/
&nOpcodeSize,/*输出的opcode的字节数*/
&stat_count /*输出成功汇编的指令的条数*/
);
// 返回值等于-1时反汇编错误
if (nRet == -1) {
// 输出错误信息
// ks_errno 获得错误码
// ks_strerror 将错误码转换成字符串,并返回这个字符串
printf("错误信息:%s\n", ks_strerror(ks_errno(pengine)));
return 0;
}
printf("一共转换了%d条指令\n", stat_count);
// 打印汇编出来的opcode
printOpcode(opcode, nOpcodeSize);
// 释放空间
ks_free(opcode);
// 关闭句柄
ks_close(pengine);
return 0;
}