选定项目启动
反汇编引擎:OPCODE->汇编指令
BeaEngine_4.1的介绍
BeaEngine_4.1的使用
第一步:
1.包含头文件
#include “headers/BeaEngine.h”
2.包含静态库
#pragma comment(lib,”win32/lib/BeaEngine.lib”)
第二步:
初始化反汇编引擎
DISASM objDism;
第三步:传入
objDism.EIP = (UIntPtr)bCODE; // 将EIP指向我们定义的字节数组
objDism.VirtualAddr = 0x411650; // 虚拟内存地址(反汇编引擎用于计算地址,验证时填为当前测试OD中的地址)
objDism.Archi = 0; // 平台X86
objDism.Options = MasmSyntax; // 汇编器语法
DWORD dwTmpEip = (DWORD)bCODE;
第四步:调用传出
Disasm(&objDism);
例如:DWORD dwVirtualAddr = (DWORD)objDism.VirtualAddr; // 用于输出的虚拟地址
printf(“0x%08X:\t%s\n”, dwVirtualAddr, objDism.CompleteInstr); // 用于打印测试
#define BEA_ENGINE_STATIC
#define BEA_USE_STDCALL
#include "headers/BeaEngine.h"
// 将win32文件夹和header复制到当前代码处
#pragma comment(lib,"win32/lib/BeaEngine.lib")
#pragma comment(linker,"/NODEFAULTLIB:\"CRT.lib\"")
#include <windows.h>
#include <stdio.h>
int main()
{
// 将字节码翻译成汇编指令
BYTE bCODE[] = { // 测试字节码,随意从X32DBG中抠取一段字节码出来
0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x44, 0x53, 0x56, 0x57, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x6A, 0x02, 0x6A, 0x01, 0xE8, 0x2B, 0xFC, 0xFF, 0xFF, 0x83, 0xC4, 0x08, 0x89, 0x45, 0xFC, 0x33,
0xC0, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3 };
// 1.初始化反汇编引擎
DISASM objDism;
objDism.EIP = (UIntPtr)bCODE; // 将EIP指向我们定义的字节数组
objDism.VirtualAddr = 0x411650; // 虚拟内存地址(反汇编引擎用于计算地址,验证时填为当前测试OD中的地址)
objDism.Archi = 0; // 平台X86
objDism.Options = MasmSyntax; // 汇编器语法
DWORD dwTmpEip = (DWORD)bCODE;
while (TRUE)
{
if ((objDism.EIP - (DWORD)bCODE) >= sizeof(bCODE)) // 此测试代码用于不要越过数组而已
{
break;
}
DWORD dwLen = Disasm(&objDism); // 开始反汇编,返回值是汇编指令总字节数
dwTmpEip += dwLen;
DWORD dwVirtualAddr = (DWORD)objDism.VirtualAddr; // 用于输出的虚拟地址
printf("0x%08X:\t%s\n", dwVirtualAddr, objDism.CompleteInstr); // 用于打印测试
objDism.EIP = dwTmpEip; // 每次修改一下反汇编引擎的EIP和虚拟地址,否则对一些指令的解析将不准确
objDism.VirtualAddr = objDism.VirtualAddr + dwLen;
}
return 0;
}
capstone的介绍
capstone-4.0.1-win32.zip
capstone-4.0.1-win64.zip
capstone的使用
第一步:
1.包含头文件
#include “capstone-4.0.1-win32/include/capstone/capstone.h”
2.显示调用
// 使用显示调用的方式
HMODULE hcs = LoadLibrary(L”capstone-4.0.1-win32/capstone.dll”);
// 定义函数指针
typedef cs_err(cdecl pFun_cs_open)(cs_arch, cs_mode, csh);
typedef size_t(cdecl pFun_cs_disasm)(csh, const uint8_t, size_t, uint64_t, size_t, cs_insn *insn);
pFun_cs_open pcs_Open = (pFun_cs_open)GetProcAddress(hcs, “cs_open”);//
pFun_cs_disasm pcs_Disasm = (pFun_cs_disasm)GetProcAddress(hcs, “cs_disasm”);
这两个函数的作用
第二步:初始化反汇编句柄
csh csHandle;
cs_err csErr;
csErr = pcs_Open(CS_ARCH_X86, CS_MODE_32, &csHandle);
第三步:传入
// 将字节码翻译成汇编指令
BYTE bCODE[] = { // 测试字节码,随意从X32DBG中抠取一段字节码出来
0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x44, 0x53, 0x56, 0x57, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x6A, 0x02, 0x6A, 0x01, 0xE8, 0x2B, 0xFC, 0xFF, 0xFF, 0x83, 0xC4, 0x08, 0x89, 0x45, 0xFC, 0x33,
0xC0, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3 };
DWORD dwVirtualAddr = 0x411650;
cs_insn* pInsn;
第四步:调用传出
dwCnt = pcs_Disasm(csHandle, (uint8_t)bCODE, sizeof(bCODE), dwVirtualAddr, NULL, &pInsn);
// 输出反汇编信息
for (int i = 0; i < dwCnt; i++)
{
printf(“0x%08X:\t%s %s\n”, (DWORD)pInsn[i].address, pInsn[i].mnemonic, pInsn[i].op_str);
}
关于#prama的用法:https://blog.csdn.net/qq_23350817/article/details/100672387
#include <windows.h>
#include <stdio.h>
#ifdef _64
#include "capstone-4.0.1-win64/include/capstone/capstone.h"
#else
#include "capstone-4.0.1-win32/include/capstone/capstone.h"
#endif // _64
// 定义函数指针
typedef cs_err(__cdecl *pFun_cs_open)(cs_arch, cs_mode, csh*);
typedef size_t(__cdecl *pFun_cs_disasm)(csh, const uint8_t, size_t, uint64_t, size_t, cs_insn **insn);
int main()
{
// 使用显示调用的方式
HMODULE hcs = LoadLibrary(L"capstone-4.0.1-win32/capstone.dll");
if (!hcs)
{
printf("没有找到反汇编模块\n");
return 0;
}
pFun_cs_open pcs_Open = (pFun_cs_open)GetProcAddress(hcs, "cs_open");
pFun_cs_disasm pcs_Disasm = (pFun_cs_disasm)GetProcAddress(hcs, "cs_disasm");
if ((pcs_Open == 0) || (pcs_Disasm == 0))
{
printf("函数获取失败\n");
return 0;
}
csh csHandle;
cs_err csErr;
cs_insn* pInsn;
DWORD dwCnt = 0;
// 初始化反汇编句柄
csErr = pcs_Open(CS_ARCH_X86, CS_MODE_32, &csHandle);
if (CS_ERR_OK != csErr)
{
printf("初始化反汇编器句柄失败\n");
return 0;
}
// 将字节码翻译成汇编指令
BYTE bCODE[] = { // 测试字节码,随意从X32DBG中抠取一段字节码出来
0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x44, 0x53, 0x56, 0x57, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x6A, 0x02, 0x6A, 0x01, 0xE8, 0x2B, 0xFC, 0xFF, 0xFF, 0x83, 0xC4, 0x08, 0x89, 0x45, 0xFC, 0x33,
0xC0, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3 };
DWORD dwVirtualAddr = 0x411650;
dwCnt = pcs_Disasm(csHandle, (uint8_t)bCODE, sizeof(bCODE), dwVirtualAddr, NULL, &pInsn);
// 输出反汇编信息
for (int i = 0; i < dwCnt; i++)
{
printf("0x%08X:\t%s %s\n", (DWORD)pInsn[i].address, pInsn[i].mnemonic, pInsn[i].op_str);
}
return 0;
}
汇编引擎:汇编指令->OPCODE
keystone的介绍
keystone的使用
第一步:1. 包含头文件
#include “keystone/keystone.h”
2. 包含静态库
#pragma comment (lib,”keystone/x86/keystone_x86.lib”)
第二步:初始化汇编引擎
ks_engine* pEngine = NULL;
ks_open(KS_ARCH_X86, KS_MODE_32, &pEngine)
第三步:传入
unsigned char* opcode = NULL; // 汇编得到的opcode的缓冲区首地址
unsigned int nOpcodeSize = 0; // 汇编出来的opcode的字节数
size_t stat_count = 0; // 保存成功汇编的指令的条数
CHAR szAsmCode[MAX_PATH] = { 0 };
DWORD dwVirtualAddr = 0;
printf(“输入要写入的地址:\n”);
scanf_s(“%x”, &dwVirtualAddr);
第四步:调用输出
ks_asm(pEngine,
szAsmCode,
dwVirtualAddr, /汇编指令所在的地址/
&opcode, /输出的opcode/
&nOpcodeSize, /输出的opcode的字节数/
&stat_count /输出成功汇编的指令的条数/);
#include <stdio.h>
//1. 包含头文件
#include "keystone/keystone.h"
//2. 包含静态库
#pragma comment (lib,"keystone/x86/keystone_x86.lib")
// 打印opcode
void printOpcode(const unsigned char* pOpcode, int nSize)
{
for (int i = 0; i < nSize; ++i) {
printf("%02X ", pOpcode[i]);
}
}
#include <windows.h>
int main()
{
ks_engine* pEngine = NULL;
// 初始化汇编引擎
if (KS_ERR_OK != ks_open(KS_ARCH_X86, KS_MODE_32, &pEngine))
{
printf("反汇编引擎初始化失败\n");
return 0;
}
int nRet = 0; // 保存函数的返回值,用于判断函数是否执行成功
unsigned char* opcode = NULL; // 汇编得到的opcode的缓冲区首地址
unsigned int nOpcodeSize = 0; // 汇编出来的opcode的字节数
size_t stat_count = 0; // 保存成功汇编的指令的条数
// 输入汇编指令
// 可以使用分号,或者换行符将指令分隔开
CHAR szAsmCode[MAX_PATH] = { 0 };
DWORD dwVirtualAddr = 0;
printf("输入要写入的地址:\n");
scanf_s("%x", &dwVirtualAddr);
getchar();
while (TRUE)
{
gets_s(szAsmCode, MAX_PATH);
nRet = ks_asm(pEngine, szAsmCode,
dwVirtualAddr, /*汇编指令所在的地址*/
&opcode, /*输出的opcode*/
&nOpcodeSize, /*输出的opcode的字节数*/
&stat_count /*输出成功汇编的指令的条数*/);
// 返回值等于-1时 汇编错误
if (nRet == -1) {
// 输出错误信息
// ks_errno 获得错误码
// ks_strerror 将错误码转换成字符串,并返回这个字符串
printf("错误信息:%s\n", ks_strerror(ks_errno(pEngine)));
// 清空字节码
memset(szAsmCode, 0, MAX_PATH);
}
printf("一共转换了%d条指令\n", stat_count);
// 打印汇编出来的opcode
printOpcode(opcode, nOpcodeSize);
}
// 释放空间
ks_free(opcode);
// 关闭句柄
ks_close(pEngine);
return 0;
}
XEDParse的介绍
XEDParse的使用
第一步:
1.包含头文件
#include “XEDParse/XEDParse.h”
2.导入静态库
#pragma comment(lib,”XEDParse/x86/XEDParse_x86.lib”)
第二步:初始化引擎
XEDPARSE xed = { 0 };
第三步:传入
printf(“输入汇编指令:\n”);
gets_s(xed.instr, XEDPARSE_MAXBUFSIZE);
第四步:调用输出
XEDParseAssemble(&xed);
#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
#include <stdio.h>
int main()
{
XEDPARSE xed = { 0 };
do
{
printf("输入汇编指令:\n");
gets_s(xed.instr, XEDPARSE_MAXBUFSIZE);
DWORD dwRet = XEDParseAssemble(&xed);
if (XEDPARSE_OK != dwRet)
{
printf("指令错误\n", xed.error);
continue;
}
BYTE* dbAddr = xed.dest;
for (int i = 0; i < xed.dest_size; i++)
{
printf("%1X ", *dbAddr);
dbAddr++;
}
printf("\n");
} while (*xed.instr);
return 0;
}