对PE文件进行十六进制代码(机器码)提取并保存到外部文件

前言与声明

秉持开源和共享的理念,博主在这里分享自己的代码。
博客中的代码可以将PE文件的十六进制代码(机器码)提取出来,这些机器码可用于机器学习、软件分析等。

声明: 转载请标明来处,创作不易!


代码使用说明

一共有四套代码:

  • create_hex_code_v1: 将一个文件的全部十六进制代码输出保存;
  • create_hex_code_v2: 将一个文件十六进制代码从地址00000400h处开始输出保存;
  • create_hex_code_v3: 将一个文件夹中的全部文件的全部十六进制代码输出保存;
  • create_hex_code_v4: 将一个文件夹中的全部十六进制代码从地址00000400h处开始输出保存;

注意事项:
代码以c++写成,核心代码函数未封装,所以网友们在使用的时候要把填写文件路径处的代码修改为您自己的路径。路径分割时切记用双斜杠

代码:

  • create_hex_code_v1:
#include <iostream>
#include <iomanip>
#include <windows.h>
#include <fstream>
#include <vector>
using namespace std;

DWORD FileSize() //获取PE文件的大小
{
	TCHAR szFileName[MAX_PATH] = TEXT("D:\\MC\\Minecraft 1.7.10 工业2自定义NPC 光影懒人包\\[启动器]HMCL-2.2.4.exe");
	HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		if (0 == GetLastError())
		{
			printf("file not exist");
		}
		return 0;
	}
	DWORD dwFileSize = 0;
	dwFileSize = GetFileSize(hFile, NULL);
	CloseHandle(hFile);
	return dwFileSize;
}
int main()
{
	vector<int>pe_hex_code; //创建容器pe_hex_code,类似于数组,但其长度是不受限的,可以完整地输出PE文件的十六进制代码
	ifstream fin("D:\\MC\\Minecraft 1.7.10 工业2自定义NPC 光影懒人包\\[启动器]HMCL-2.2.4.exe", ios::binary); //读PE文件
	if (!fin)
		exit(0);

	char c;
	long i = 0, j = 0;
	cout.setf(ios::uppercase); //ios::uppercase 在以科学计数法输出E和16进制数大写输出.
	DWORD leng = FileSize(); //PE文件大小
	DWORD count = 0; //用于记录容器pe_hex_code中正在输出的十六进制代码的index
	ofstream outfile("test.txt"); //将PE文件的十六进制代码输出
	outfile.setf(ios::uppercase);//ios::uppercase 在以科学计数法输出E和16进制数大写输出.
	while ((j * 16 + i) < leng)
	{
		c = fin.get();
		pe_hex_code.push_back(((int)c) & 0x000000ff);
		vector<int>::iterator it;
		it = pe_hex_code.begin() + count++;
		if (i == 0) 
		{
			cout << hex <<setfill('0')<< setw(7) << j << "0h: ";
			outfile << hex << setfill('0') << setw(7) << j << "0h: ";
		}
		cout << hex << setfill('0') << setw(2) << *it << " ";
		outfile << hex << setfill('0') << setw(2) << *it << " ";
		if (i++ == 15)
		{
			cout << endl;
			outfile << endl;
			i = 0;
			j++;
		}
	}
	fin.close();
	outfile.close();

	return 0;
}
  • create_hex_code_v2:
#include <iostream>
#include <iomanip>
#include <windows.h>
#include <fstream>
#include <vector>
using namespace std;

DWORD FileSize() //获取PE文件的大小
{
	TCHAR szFileName[MAX_PATH] = TEXT("D:\\MC\\Minecraft 1.7.10 工业2自定义NPC 光影懒人包\\[启动器]HMCL-2.2.4.exe");
	HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		if (0 == GetLastError())
		{
			printf("file not exist");
		}
		return 0;
	}
	DWORD dwFileSize = 0;
	dwFileSize = GetFileSize(hFile, NULL);
	CloseHandle(hFile);
	return dwFileSize;
}
int main()
{
	vector<int>pe_hex_code; //创建容器pe_hex_code,类似于数组,但其长度是不受限的,可以完整地输出PE文件的十六进制代码
	ifstream fin("D:\\MC\\Minecraft 1.7.10 工业2自定义NPC 光影懒人包\\[启动器]HMCL-2.2.4.exe", ios::binary); //读PE文件
	if (!fin)
		exit(0);

	char c;
	long i = 0, j = 0;
	cout.setf(ios::uppercase); //ios::uppercase 在以科学计数法输出E和16进制数大写输出.
	DWORD leng = FileSize(); //PE文件大小
	DWORD count = 0; //用于记录容器pe_hex_code中正在输出的十六进制代码的index
	ofstream outfile("test0.bytes"); //将PE文件的十六进制代码输出
	outfile.setf(ios::uppercase);//ios::uppercase 在以科学计数法输出E和16进制数大写输出.
	while ((j * 16 + i) < leng)
	{
		c = fin.get();
		pe_hex_code.push_back(((int)c) & 0x000000ff);
		vector<int>::iterator it;
		it = pe_hex_code.begin() + count++;
		if ((j * 16 + i) >= 0x00000400)
		{
			if (i == 0)
			{
				cout << hex << setfill('0') << setw(7) << j << "0h: ";
				outfile << hex << setfill('0') << setw(7) << j << "0h: ";
			}
			cout << hex << setfill('0') << setw(2) << *it << " ";
			outfile << hex << setfill('0') << setw(2) << *it << " ";
			if (i++ == 15)
			{
				cout << endl;
				outfile << endl;
				i = 0;
				j++;
			}
		}
		else if (i++ == 15)
		{
			i = 0;
			j++;
		}		
	}

	fin.close();
	outfile.close();
	
	return 0;
}
  • create_hex_code_v3:
/*#include <iostream>
#include <iomanip>
#include <windows.h>
#include <fstream>
using namespace std;

#define MAX 16*10000
int value[MAX];


int main()
{
	ifstream fin("D:\\MC\\Minecraft 1.7.10 工业2自定义NPC 光影懒人包\\[启动器]HMCL-2.2.4.exe" ,ios::binary); //读取文件
	if (!fin)
		exit(0);
	else
	{
		fin.seekg(0, ios::end);
		int size = (int)fin.tellg();
		cout << "size:" << size << endl;;
		char c;
		long i = 0, j = 0;
		cout.setf(ios::uppercase); //ios::uppercase 在以科学计数法输出E和16进制数大写输出.
		cout << setfill('0');
		while ((j * 16 + i) < size )
		{
			c = fin.get(); //ifstream的.get()函数用于读取一个字符,字符大小为一个byte
			value[j * 16 + i] = ( ((int)c) & 0x000000FF); //(int)c会将byte的内存空间高位补1(也就是按符号位补位)扩充到32位,所以前16位需要置0
			if (i == 0)
				cout << hex << setw(7) << j << "0h: ";
			cout << hex << setw(2) << value[j * 16 + i] << " ";
			if (i++ == 15)
			{
				cout << endl;
				i = 0;
				j++;
			}

		}
		fin.close();
	}
	return 0;
}
*/

#include <iostream>
#include <iomanip>
#include <windows.h>
#include <fstream>
#include <vector>
#include <io.h>
#include <direct.h>
using namespace std;

/*DWORD FileSize() //获取PE文件的大小
{
	TCHAR szFileName[MAX_PATH] = TEXT("D:\\MC\\Minecraft 1.7.10 工业2自定义NPC 光影懒人包\\[启动器]HMCL-2.2.4.exe");
	HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		if (0 == GetLastError())
		{
			printf("file not exist");
		}
		return 0;
	}
	DWORD dwFileSize = 0;
	dwFileSize = GetFileSize(hFile, NULL);
	CloseHandle(hFile);
	return dwFileSize;
}*/

vector<string> getFiles(string cate_dir)
{
	vector<string> files;//存放文件名

	_finddata_t file;
	long lf;
	//输入文件夹路径
	if ((lf = _findfirst(cate_dir.c_str(), &file)) == -1) {
		cout << cate_dir << " not found!!!" << endl;
	}
	else {
		while (_findnext(lf, &file) == 0) {
			//输出文件名
			//cout<<file.name<<endl;
			if (strcmp(file.name, ".") == 0 || strcmp(file.name, "..") == 0)
				continue;
			files.push_back(file.name);
		}
	}
	_findclose(lf);
	return files;
}
int main()
{
	vector<string> files = getFiles((string)"D:\\Dos\\DOSBox-0.74\\Documentation\\*");
	cout << "文件夹中有" << files.size() << "个文件" << endl;
	
	string filepath_big = "D:\\Dos\\DOSBox-0.74\\Documentation\\";
	for (int x = 0; x < files.size(); x++)
	{
		string filepath = filepath_big+files[x]; //获取文件名
		char* filepath_true = (char*)filepath.c_str();
		cout << "文件名:"<<filepath_true << endl;///////////////////////////////////////////////////////////////////////////
		struct _stat info;
		_stat(filepath_true, &info);
		DWORD size = info.st_size; //DWORD:4字节无符号整数*/
		cout << "文件大小:"<<size << endl;///////////////////////////////////////////////////////////////////////////
		vector<int>pe_hex_code; //创建容器pe_hex_code,类似于数组,但其长度是不受限的,可以完整地输出PE文件的十六进制代码
		ifstream fin(filepath_true, ios::binary); //读PE文件
		if (!fin) {
			cout << "文件"<<filepath<<"读取错误."<<endl;
			exit(0);
			
		}

		string filepath_x = files[x] + (string)".bytes";
		filepath_x= (char*)filepath_x.c_str();
		cout << filepath_x << endl;

		char c;
		long i = 0, j = 0;
		cout.setf(ios::uppercase); //ios::uppercase 在以科学计数法输出E和16进制数大写输出.
		DWORD leng = size; //PE文件大小
		DWORD count = 0; //用于记录容器pe_hex_code中正在输出的十六进制代码的index
		ofstream outfile(filepath_x); //将PE文件的十六进制代码输出
		outfile.setf(ios::uppercase);//ios::uppercase 在以科学计数法输出E和16进制数大写输出.
		while ((j * 16 + i) < leng)
		{
			c = fin.get();
			pe_hex_code.push_back(((int)c) & 0x000000ff);
			vector<int>::iterator it;
			it = pe_hex_code.begin() + count++;
			if (i == 0)
			{
				cout << hex << setfill('0') << setw(7) << j << "0h: ";
				outfile << hex << setfill('0') << setw(7) << j << "0h: ";
			}
			cout << hex << setfill('0') << setw(2) << *it << " ";
			outfile << hex << setfill('0') << setw(2) << *it << " ";
			if (i++ == 15)
			{
				cout << endl;
				outfile << endl;
				i = 0;
				j++;
			}
		}
		fin.close();
		outfile.close();
	}

	return 0;
}
  • create_hex_code_v4:
/*************************************************

Copyright:000000

Author:Enmin Zhu

Date:2020-02-18

Description:获取文件夹中所有PE文件的十六进制代码并输出保存为.bytes文件

*************************************************/


#include <iostream>
#include <iomanip>
#include <windows.h>
#include <fstream>
#include <vector>
#include <io.h>
#include <direct.h>
using namespace std;


/******************************************
Brief:		//将文件夹中所有文件的文件名存入容器中
Function:	//getFiles 
Param:		//cate_dir 文件夹路径
******************************************/
vector<string> getFiles(string cate_dir)
{
	vector<string> files;//存放文件名的容器
	_finddata_t file;
	long lf;
	if ((lf = _findfirst(cate_dir.c_str(), &file)) == -1) {
		cout << cate_dir << " not found!!!" << endl;
	}
	else {
		while (_findnext(lf, &file) == 0) {
			//输出文件名
			//cout<<file.name<<endl;
			if (strcmp(file.name, ".") == 0 || strcmp(file.name, "..") == 0)
				continue;
			files.push_back(file.name);
		}
	}
	_findclose(lf);
	return files;
}


int main()
{
	vector<string> files = getFiles((string)"D:\\Dos\\DOSBox-0.74\\Documentation\\*"); //手动改变文件夹路径,用双斜杠隔开,保留最后的*号
	//cout << "文件夹中有" << files.size() << "个文件" << endl;
	
	string filepath_folder = "D:\\Dos\\DOSBox-0.74\\Documentation\\"; //手动改变文件夹路径,用双斜杠隔开
	for (int x = 0; x < files.size(); x++) //遍历文件中的所有文件
	{
		string filepath_string = filepath_folder+files[x]; //获取文件路径
		char* filepath_char = (char*)filepath_string.c_str();
		cout << "文件名:"<<filepath_char << endl;

		//获取文件的大小
		struct _stat info;
		_stat(filepath_char, &info);
		DWORD size = info.st_size; //DWORD:4字节无符号整数
		cout << "文件大小:"<<size << endl;

		//创建容器pe_hex_code,类似于数组,但其长度是不受限的,可以完整地保存PE文件的十六进制代码
		vector<int>pe_hex_code; 
		ifstream fin(filepath_char, ios::binary); //读PE文件
		if (!fin) 
		{
			cout << "文件"<<filepath_string<<"读取错误."<<endl;
			exit(0);
		}

		//将PE文件输出保存为.bytes文件
		string filepath_x = files[x] + (string)".bytes";
		filepath_x= (char*)filepath_x.c_str();
		cout << filepath_x << endl;

		//打印并输出保存
		char c;
		long i = 0, j = 0;
		cout.setf(ios::uppercase); //ios::uppercase 在以科学计数法输出E和16进制数大写输出.
		DWORD leng = size; //PE文件大小
		DWORD count = 0; //用于记录容器pe_hex_code中正在输出的十六进制代码的index
		ofstream outfile(filepath_x); //将PE文件的十六进制代码输出
		outfile.setf(ios::uppercase);//ios::uppercase 在以科学计数法输出E和16进制数大写输出.
		while ((j * 16 + i) < leng)
		{
			c = fin.get();
			pe_hex_code.push_back(((int)c) & 0x000000ff);
			vector<int>::iterator it;
			it = pe_hex_code.begin() + count++;
			if ((j * 16 + i) >= 0x00000400) //从PE文件的00000400h处开始输出打印、保存
			{
				if (i == 0)
				{
					cout << hex << setfill('0') << setw(7) << j << "0h: ";
					outfile << hex << setfill('0') << setw(7) << j << "0h: ";
				}
				cout << hex << setfill('0') << setw(2) << *it << " ";
				outfile << hex << setfill('0') << setw(2) << *it << " ";
				if (i++ == 15)
				{
					cout << endl;
					outfile << endl;
					i = 0;
					j++;
				}
			}
			else if (i++ == 15)
			{
				i = 0;
				j++;
			}
		}

		fin.close();
		outfile.close();

		cout << endl;
	}

	return 0;
}
睡眼惺忪的玉子~
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章