C/C++ 實現內存特征碼搜索


#include<Windows.h>
#include<iostream>
#include<vector>
#include<time.h>
 
using namespace std;
 
#define BLOCKMAXSIZE 409600//每次讀取內存的最大大小
BYTE* MemoryData;//每次將讀取的內存讀入這里
short Next[260];
 
//特征碼轉字節集
WORD GetTzmArray(char* Tzm, WORD* TzmArray)
{
	int len = 0;
	WORD TzmLength = strlen(Tzm) / 3 + 1;
 
	for (int i = 0; i < strlen(Tzm); )//將十六進制特征碼轉為十進制
	{
		char num[2];
		num[0] = Tzm[i++];
		num[1] = Tzm[i++];
		i++;
		if (num[0] != '?' && num[1] != '?')
		{
			int sum = 0;
			WORD a[2];
			for (int i = 0; i < 2; i++)
			{
				if (num[i] >= '0' && num[i] <= '9')
				{
					a[i] = num[i] - '0';
				}
				else if (num[i] >= 'a' && num[i] <= 'z')
				{
					a[i] = num[i] - 87;
				}
				else if (num[i] >= 'A' && num[i] <= 'Z')
				{
					a[i] = num[i] - 55;
				}
 
			}
			sum = a[0] * 16 + a[1];
			TzmArray[len++] = sum;
		}
		else
		{
			TzmArray[len++] = 256;
		}
	}
	return TzmLength;
}
 
//獲取Next數組
void GetNext(short* next, WORD* Tzm, WORD TzmLength)
{
	//特征碼(字節集)的每個字節的范圍在0-255(0-FF)之間,256用來表示問號,到260是為了防止越界
	for (int i = 0; i < 260; i++)
		next[i] = -1;
	for (int i = 0; i < TzmLength; i++)
		next[Tzm[i]] = i;
}
 
//搜索一塊內存
void SearchMemoryBlock(HANDLE hProcess, WORD* Tzm, WORD TzmLength, unsigned __int64 StartAddress, unsigned long size, vector<unsigned __int64>& ResultArray)
{
	if (!ReadProcessMemory(hProcess, (LPCVOID)StartAddress, MemoryData, size, NULL))
	{
		return;
	}
 
	for (int i = 0, j, k; i < size;)
	{
		j = i; k = 0;
 
		for (; k < TzmLength && j < size && (Tzm[k] == MemoryData[j] || Tzm[k] == 256); k++, j++);
 
		if (k == TzmLength)
		{
			ResultArray.push_back(StartAddress + i);
		}
 
		if ((i + TzmLength) >= size)
		{
			return;
		}
 
		int num = Next[MemoryData[i + TzmLength]];
		if (num == -1)
			i += (TzmLength - Next[256]);//如果特征碼有問號,就從問號處開始匹配,如果沒有就i+=-1
		else
			i += (TzmLength - num);
	}
}
 
//搜索整個程序
int SearchMemory(HANDLE hProcess, char* Tzm, unsigned __int64 StartAddress, unsigned __int64 EndAddress, int InitSize, vector<unsigned __int64>& ResultArray)
{
	int i = 0;
	unsigned long BlockSize;
	MEMORY_BASIC_INFORMATION mbi;
 
	WORD TzmLength = strlen(Tzm) / 3 + 1;
	WORD* TzmArray = new WORD[TzmLength];
 
	GetTzmArray(Tzm, TzmArray);
	GetNext(Next, TzmArray, TzmLength);
 
	//初始化結果數組
	ResultArray.clear();
	ResultArray.reserve(InitSize);
 
	while (VirtualQueryEx(hProcess, (LPCVOID)StartAddress, &mbi, sizeof(mbi)) != 0)
	{
		//獲取可讀可寫和可讀可寫可執行的內存塊
		if (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE)
		{
			i = 0;
			BlockSize = mbi.RegionSize;
			//搜索這塊內存
			while (BlockSize >= BLOCKMAXSIZE)
			{
				SearchMemoryBlock(hProcess, TzmArray, TzmLength, StartAddress + (BLOCKMAXSIZE * i), BLOCKMAXSIZE, ResultArray);
				BlockSize -= BLOCKMAXSIZE; i++;
			}
			SearchMemoryBlock(hProcess, TzmArray, TzmLength, StartAddress + (BLOCKMAXSIZE * i), BlockSize, ResultArray);
 
		}
		StartAddress += mbi.RegionSize;
 
		if (EndAddress != 0 && StartAddress > EndAddress)
		{
			return ResultArray.size();
		}
	}
	free(TzmArray);
	return ResultArray.size();
}
 
int main()
{
	//初始化MemoryData大小
	MemoryData = new BYTE[BLOCKMAXSIZE];
 
	DWORD pid=0;
	vector<unsigned __int64> ResultArray;
	
	cout << "請輸入進程ID:" << endl;
	cin >> pid;
 
	//通過進程ID獲取進程句柄
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
 
	int start = clock();
	SearchMemory(hProcess, (char*)"FF 3F FF ?? FF F2", 0x410000, 0xFFFFFFFF, 30, ResultArray);
	int end = clock();
 
	cout << "用時:" << end-start << "毫秒"<<endl;
	cout << "搜索到" << ResultArray.size() << "個結果" << endl;
 
	for (vector<unsigned __int64>::iterator it = ResultArray.begin(); it != ResultArray.end(); it++)
	{
		printf("%x\n", *it);
	}
 
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM