C/C++ BeaEngine 反汇编引擎

反汇编引擎有很多,这个引擎没有Dll,是纯静态链接库,适合r3-r0环境,你可以将其编译为DLL文件,驱动强制注入到游戏进程中,让其快速反汇编,读取出反汇编代码并保存为txt文本,本地分析。

地址:GitHub - BeaEngine/beaengine: BeaEngine disasm project

BeaEngine 反汇编特定字符串

#include <stdio.h>
#include <Windows.h>
#define BEA_ENGINE_STATIC  // 指明使用静态Lib库
#define BEA_USE_STDCALL    // 指明使用stdcall调用约定

extern "C"
{
	#include "G:/beaengine/x64/BeaEngine.h"
	#pragma comment(lib, "G:/BeaEngine/x64/lib_static/BeaEngine.lib")
}

void DisassembleCode(char *start_offset, int size)
{
	DISASM Disasm_Info;
	int len;
	char *end_offset = (char*)start_offset + size;
	(void)memset(&Disasm_Info, 0, sizeof(DISASM));
	Disasm_Info.EIP = (UInt64)start_offset;
	Disasm_Info.Archi = 1;
	Disasm_Info.Options = MasmSyntax;
	while (!Disasm_Info.Error)
	{
		Disasm_Info.SecurityBlock = (UInt64)end_offset - Disasm_Info.EIP;
		if (Disasm_Info.SecurityBlock <= 0)
			break;
		len = Disasm(&Disasm_Info);
		switch (Disasm_Info.Error)
		{
		case OUT_OF_BLOCK:
			break;
		case UNKNOWN_OPCODE:
			printf("%s \n", &Disasm_Info.CompleteInstr);
			Disasm_Info.EIP += 1;
			Disasm_Info.Error = 0;
			break;
		default:
			printf("%s \n", &Disasm_Info.CompleteInstr);
			Disasm_Info.EIP += len;
		}
	}
}

int main(int argc,char *argv)
{
	char *buffer = "\x55\x8b\xec\x81\xec\x24\x03\x00\x00\x6a\x17";
	DisassembleCode(buffer, 11);
	
	BYTE bTest[] = { 0x68, 0x37, 0x31, 0x40, 0x00, 0xFF, 0x15, 0x0C, 0x20, 0x40 };
	DisassembleCode(buffer, 14);

	system("pause");
	return 0;
}

反汇编字节数组

// 反汇编字节数组
void DisassembleCodeByte(BYTE *ptr,int len)
{
	
	DISASM Disasm_Info;
	char *end_offset = (char*)ptr + 10;
	(void)memset(&Disasm_Info, 0, sizeof(DISASM));
	Disasm_Info.EIP = (UInt64)ptr;
	Disasm_Info.Archi = 1;                      // 1 = 表示反汇编32位 / 0 = 表示反汇编64位
	Disasm_Info.Options = MasmSyntax;           // 指定语法格式 MASM

	while (!Disasm_Info.Error)
	{
		Disasm_Info.SecurityBlock = (UInt64)end_offset - Disasm_Info.EIP;
		if (Disasm_Info.SecurityBlock <= 0)
			break;
		len = Disasm(&Disasm_Info);
		switch (Disasm_Info.Error)
		{
		case OUT_OF_BLOCK:
			break;
		case UNKNOWN_OPCODE:
			Disasm_Info.EIP += 1;
			Disasm_Info.Error = 0;
			break;
		default:
			printf("%s \n", &Disasm_Info.CompleteInstr);
			Disasm_Info.EIP += len;
		}
	}
}


int main(int argc, char *argv)
{
	BYTE bTest[] = { 0x55, 0x8b, 0xec, 0x81, 0xec, 0x24, 0x03, 0x00, 0x00, 0x6a, 0x17 };
	DisassembleCodeByte(bTest,10);
	system("pause");
	return 0;
}

反汇编时,显示虚拟地址

void DisassembleCodeInstr(char *start_offset, char *end_offset, int virtual_address)
{
	DISASM Disasm_Info;
	int len;
	(void)memset(&Disasm_Info, 0, sizeof(DISASM));
	Disasm_Info.EIP = (UINT64)start_offset;
	Disasm_Info.VirtualAddr = (UINT64)virtual_address;
	Disasm_Info.Archi = 0;
	Disasm_Info.Options = MasmSyntax;

	while (!Disasm_Info.Error)
	{
		Disasm_Info.SecurityBlock = (UInt64)end_offset - Disasm_Info.EIP;
		if (Disasm_Info.SecurityBlock <= 0)
			break;
		len = Disasm(&Disasm_Info);
		switch (Disasm_Info.Error)
		{
		case OUT_OF_BLOCK:
			break;
		case UNKNOWN_OPCODE:
			Disasm_Info.EIP += 1;
			Disasm_Info.VirtualAddr += 1;
			break;
		default:
			printf("%.16llx > %s\n", Disasm_Info.VirtualAddr,&Disasm_Info.CompleteInstr);
			Disasm_Info.EIP += len;
			Disasm_Info.VirtualAddr += len;
		}
	}
}

int main(int argc,char *argv)
{
	
	/*
	char *buffer = "\x55\x8b\xec\x81\xec\x24\x03\x00\x00\x6a\x17";
	DisassembleCode(buffer, 11);
	*/
	void *pBuffer = malloc(200);
	memcpy(pBuffer, main, 200);
	DisassembleCodeInstr((char *)pBuffer, (char *)pBuffer + 200, 0x401000);
	system("pause");
	return 0;
}

检查EAX寄存器状态: 如何只检索修改寄存器eax的指令,也就是说,当我们的寄存器REG0零号,发生写入请求时,将自动获取到此处的汇编代码位置。

void DisassembleCodeInstr(char *start_offset, char *end_offset, int virtual_address)
{
	DISASM Disasm_Info;
	int len;
	(void)memset(&Disasm_Info, 0, sizeof(DISASM));
	Disasm_Info.EIP = (UINT64)start_offset;
	Disasm_Info.VirtualAddr = (UINT64)virtual_address;
	Disasm_Info.Archi = 0;
	Disasm_Info.Options = MasmSyntax;

	while (!Disasm_Info.Error)
	{
		Disasm_Info.SecurityBlock = (UInt64)end_offset - Disasm_Info.EIP;
		if (Disasm_Info.SecurityBlock <= 0)
			break;
		len = Disasm(&Disasm_Info);
		switch (Disasm_Info.Error)
		{
		case OUT_OF_BLOCK:
			break;
		case UNKNOWN_OPCODE:
			Disasm_Info.EIP += 1;
			Disasm_Info.VirtualAddr += 1;
			break;
		default:
			if (
				((Disasm_Info.Operand1.AccessMode == WRITE) && (Disasm_Info.Operand1.Registers.gpr & REG0)) ||
				((Disasm_Info.Operand2.AccessMode == WRITE) && (Disasm_Info.Operand2.Registers.gpr & REG0)) ||
				(Disasm_Info.Instruction.ImplicitModifiedRegs.gpr & REG0)
				)
			{
				printf("%.16llx > %s \n", Disasm_Info.VirtualAddr, &Disasm_Info.CompleteInstr);
			}
			Disasm_Info.EIP += len;
			Disasm_Info.VirtualAddr += len;
		}
	}
}

解码第三方可执行文件:

void DisassembleCodeRange(unsigned char *StartCodeSection, unsigned char *EndCodeSection, int(Virtual_Address))
{
	DISASM Disasm_Info;
	int len;
	memset(&Disasm_Info, 0, sizeof(DISASM));
	Disasm_Info.EIP = (UInt64)StartCodeSection;
	Disasm_Info.VirtualAddr = (UInt64)Virtual_Address;
	Disasm_Info.Archi = 0;
	Disasm_Info.Options = MasmSyntax;

	while (!Disasm_Info.Error)
	{
		Disasm_Info.SecurityBlock = (int)EndCodeSection - Disasm_Info.EIP;
		len = Disasm(&Disasm_Info);
		if (Disasm_Info.Error >= 0)
		{
			printf("%.16llx > %s \n", Disasm_Info.VirtualAddr, &Disasm_Info.CompleteInstr);
			Disasm_Info.EIP += len;
			Disasm_Info.VirtualAddr += len;
		}
	}
}

int main(int argc, char *argv)
{
	void *uBuffer;
	FILE *fp  = fopen("c://main.exe", "rb+");
	fseek(fp, 0, SEEK_END);

	DWORD FileSize = ftell(fp);
	rewind(fp);

	uBuffer = malloc(FileSize);
	memset(uBuffer, 0, sizeof(uBuffer));
	fread(uBuffer, 1, FileSize, fp);
	fclose(fp);

	// 反汇编文件偏移为1025-1099处的机器指令.
	DisassembleCodeRange((unsigned char*)uBuffer + 1025, (unsigned char*)uBuffer + 1099, 0x401000);
	system("pause");
	return 0;
}

XEDPARSE 汇编引擎: 将汇编代码汇编为机器码,keystone 汇编引擎也可,Download – Keystone – The Ultimate Assembler

#include <stdio.h>
#include <Windows.h>
#define BEA_ENGINE_STATIC  // 指明使用静态Lib库
#define BEA_USE_STDCALL    // 指明使用stdcall调用约定

extern "C"
{
	#include "G:/XEDParse/XEDParse.h"
	#pragma comment(lib, "G:/XEDParse/XEDParse_x86.lib")
}
void printOpcode(const unsigned char* pOpcode, int nSize)
{
	for (int i = 0; i < nSize; ++i)
	{
		printf("%02X ", pOpcode[i]);
	}
}

int main(int argc, char *argv)
{
	XEDPARSE xed = { 0 };

	xed.x64 = TRUE;
	scanf_s("%llx", &xed.cip);

	// 获取汇编字符串
	gets_s(xed.instr, XEDPARSE_MAXBUFSIZE);
	if (XEDPARSE_OK != XEDParseAssemble(&xed))
	{
		printf("指令错误: %s\n", xed.error);
	}

	// 输出汇编机器码
	printf("%s : ", xed.instr);
	printOpcode(xed.dest, xed.dest_size);
	system("pause");
	return 0;
}

一次汇编多条指令

#include <stdio.h>
#include <Windows.h>
#define BEA_ENGINE_STATIC  // 指明使用静态Lib库
#define BEA_USE_STDCALL    // 指明使用stdcall调用约定

extern "C"
{
#include "G:/XEDParse/XEDParse.h"
#pragma comment(lib, "G:/XEDParse/XEDParse_x86.lib")
}
void printOpcode(const unsigned char* pOpcode, int nSize)
{
	for (int i = 0; i < nSize; ++i)
	{
		printf("%02X ", pOpcode[i]);
	}
	printf("\n");
}

int main(int argc, char *argv)
{
	XEDPARSE xed = { 0 };

	xed.x64 = FALSE;
	char *abc[] = {
		"xor eax,eax",
		"xor ebx,ebx",
		"push eax",
		"push ebx",
		"mov ecx,3"
	};

	for (int x = 0; x < 5; x++)
	{
		strcpy(xed.instr, abc[x]);
		if (XEDPARSE_OK != XEDParseAssemble(&xed))
		{
			printf("指令错误: %s\n", xed.error);
		}

		// 输出汇编机器码
		printf("%s : ", xed.instr);
		printOpcode(xed.dest, xed.dest_size);
	}

	system("pause");
	return 0;
}

汇编引擎实现转ShellCode:

#include <stdio.h>
#include <Windows.h>

extern "C"
{
#include "G:/XEDParse/XEDParse.h"
#pragma comment(lib, "G:/XEDParse/XEDParse_x86.lib")
}

int main(int argc, char *argv)
{

	XEDPARSE xed = { 0 };
	xed.x64 = FALSE;
	

	unsigned char *p;
	p = (unsigned char *)malloc(256);

	char *OpCode[15] = {
		"push ebp",
		"push ebp",
		"xor eax,eax",
		"mov eax,1",
		"endp"
	};

	for (int x = 0; x < sizeof(OpCode) / sizeof(OpCode[0]); x++)
	{
		if (strcmp(OpCode[x], "endp") == 0)
			break;

		strcpy(xed.instr, OpCode[x]);
		if (XEDPARSE_OK != XEDParseAssemble(&xed))
			break;

		// 将汇编机器码生成为ShellCode
		for (int y = 0; y < xed.dest_size; y++)
		{
			p[y] = xed.dest[y];
		}	
	}

	system("pause");
	return 0;
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vs2017建立一个静态库lib工程 起号工程名字BeaEngine  然后选release配置选项 1,把headers\Includes下面到2个头文件拖到src\Includes的目录下面 2,把headers\BeaEngine.h拖出放到cpp工程所在目录下,并导入到vs2017的项目头文件栏 3,把src\BeaEngine.c 拖出放到cpp工程所在目录下,并导入到vs2017的项目源文件栏 4,把src目录下面的文件夹拖到cpp工程所在目录下. 把include\下面的beaengine文件夹拖出放到cpp工程所在目录下.把src\Includes文件夹拖出放到cpp工程所在目录下 4,项目-->属性--> c/c++ -->预编译头-->选择 不使用预编译头 5,项目-->属性--> c/c++ -->附加包含目录 beaengine文件夹, Includes文件夹, Includes\instr_set文件夹(注意后面2个文件夹是src拖出来到cpp工程所在目录下的) 6,注意错误提示,若有则单击提示,把#include <xxx> 修改为#include "xxx.h" 7,项目-->属性--> 常规-->无全程序优化 ,字符集选--》多字节字符集 8,项目-->属性--> c/c++ -->代码生成-->运行库 选择多线程(/MT) 9,项目-->属性--> c/c++ -->高级-->调用约定选择 __stdcall (lib和调用主程序都需要选择 __stdcall,否则默认以c调用,带@的符号找不到的错误提示) 10,调用主程序最好把headers\BeaEngine.h拖出放到cpp工程所在目录下,并导入到vs2017项目的头文件栏中 11,项目-->属性--> 常规-->字符集选--》多字节字符集使用 Unicode 字符集(已测试过能正常使用!lib和调用主程序都要做此项相同设置) 12,项目-->属性-->配置属性-->C/C++-->命令行-->附加选项,加入【/D "_CRT_SECURE_NO_DEPRECATE" 】(注:加入中括号中完整的内容),可修正如下提示错误 使用VS2005以上版本(VS2005、VS2008、VS2010)编译在其他编译器下正常通过的C语言程序,你可能会遇到类似如下的警告提示: 引用内容 warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1>          c:/program files/microsoft visual studio 10.0/vc/include/string.h(105) : 参见“strcpy”的声明 warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1>          c:/program files/microsoft visual studio 10.0/vc/include/stdio.h(234) : 参见“fopen”的声明 原因解释 这种微软的警告,主要因为那些C库的函数,很多函数内部是不进行参数检测的(包括越界类的),微软担心使用这些会造成内存异常,所以就改写了同样功能的函数,改写了的函数进行了参数的检测,使用这些新的函数会更安全和便捷。关于这些改写的函数你不用专门去记忆,因为编译器对于每个函数在给出警告时,都会告诉你相应的安全函数,查看警告信息就可以获知,在使用时也再查看一下MSDN详细了解。库函数改写例子:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值