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