首页 C/C++修行正文

C++ 特征码搜索

欲儿 C/C++修行 2022-07-02 352 0

编译环境:Unicode字符集

编译代码:

#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <Tlhelp32.h>
#include <string>
using namespace std;
//参数分别为:进程句柄、特征码、偏移、读取长度、开始扫描位地置、扫描结束位置
uintptr_t hanshu_dizhi; //记录特征码对应的地址
uintptr_t ScanAddress(HANDLE process, char *markCode, int nOffset, unsigned long dwReadLen = 4, uintptr_t StartAddr = 0x400000, uintptr_t EndAddr = 0x7FFFFFFF, int InstructionLen = 0)
{
	//************处理特征码,转化成字节*****************
	if (strlen(markCode) % 2 != 0) return 0;
	//特征码长度
	int len = strlen(markCode) / 2;  //获取代码的字节数

	//将特征码转换成byte型 保存在m_code 中
	BYTE *m_code = new BYTE[len];
	for (int i = 0; i < len; i++)
	{
		//定义可容纳单个字符的一种基本数据类型。
		char c[] = { markCode[i * 2], markCode[i * 2 + 1], '\0' };
		//将参数nptr字符串根据参数base来转换成长整型数
		m_code[i] = (BYTE)::strtol(c, NULL, 16);
	}
	//每次读取游戏内存数目的大小
	const DWORD pageSize = 4096;

	// 查找特征码 /
	//每页读取4096个字节
	BYTE *page = new BYTE[pageSize];
	uintptr_t tmpAddr = StartAddr;
	//定义和特征码一样长度的标识
	int compare_one = 0;

	while (tmpAddr <= EndAddr)
	{
		::ReadProcessMemory(process, (LPCVOID)tmpAddr, page, pageSize, 0); //读取0x400000的内存数据,保存在page,长度为pageSize

		//在该页中查找特征码
		for (int i = 0; i < pageSize; i++)
		{
			if (m_code[0] == page[i])//有一个字节与特征码的第一个字节相同,则搜索
			{
				for (int j = 0; j<len - 1; j++)
				{
					if (m_code[j + 1] == page[i + j + 1])//比较每一个字节的大小,不相同则退出
					{
						compare_one++;
					}
					else
					{
						compare_one = 0;
						break;
					}//如果下个对比的字节不相等,则退出,减少资源被利用
				}

				if ((compare_one + 1) == len)
				{
					// 找到特征码处理
					//赋值时要给初始值,避免冲突
					uintptr_t dwAddr = tmpAddr + i + nOffset;
					uintptr_t ullRet = 0;
					::ReadProcessMemory(process, (void*)dwAddr, &ullRet, dwReadLen, 0);
					//cout<<dwAddr<<endl;
					//这里的dwAddr已经对应的是搜索到的地址
					//地址输出的也是10进制    需要转化为16进制 
					hanshu_dizhi = dwAddr;//记录地址
					if (InstructionLen)
					{
						ullRet += dwAddr + dwReadLen;
					}

					return ullRet;
				}
			}
		}

		tmpAddr = tmpAddr + pageSize - len;//下一页搜索要在前一页最后长度len 开始查找,避免两页交接中间有特征码搜索不出来
	}

	return 0;
}

//10到16 用法在下面
/*
int ret = 10;
string result = tentosixteen(ret);
cout << result << endl;
*/

int quzheng(unsigned int tendoc)
{
	int qian = tendoc / 16;
	return qian;
}

string huanzhi(int numtype)
{
	string us = std::to_string(numtype);
	if (us == "0")
	{
		string result = "0";
		return result;
	}
	else if (us == "1")
	{
		string result = "1";
		return result;
	}
	else if (us == "2")
	{
		string result = "2";
		return result;
	}
	else if (us == "3")
	{
		string result = "3";
		return result;
	}
	else if (us == "4")
	{
		string result = "4";
		return result;
	}
	else if (us == "5")
	{
		string result = "5";
		return result;
	}
	else if (us == "6")
	{
		string result = "6";
		return result;
	}
	else if (us == "7")
	{
		string result = "7";
		return result;
	}
	else if (us == "8")
	{
		string result = "8";
		return result;
	}
	else if (us == "9")
	{
		string result = "9";
		return result;
	}
	else if (us == "10")
	{
		string result = "A";
		return result;
	}
	else if (us == "11")
	{
		string result = "B";
		return result;
	}
	else if (us == "12")
	{
		string result = "C";
		return result;
	}
	else if (us == "13")
	{
		string result = "D";
		return result;
	}
	else if (us == "14")
	{
		string result = "E";
		return result;
	}
	else if (us == "15")
	{
		string result = "F";
		return result;
	}
	else if (us == "16")
	{
		string result = "10";
		return result;
	}
}

string daoxu(string sixteendoc)
{
	int length = strlen(sixteendoc.c_str());
	int i = 0;
	string ret;
	string result;
	while (i < length || i == length)
	{
		ret = sixteendoc.substr(length - i, 1);
		result = result + ret;
		//cout << ret << endl;
		i = i + 1;
	}
	return result;
}

string tentosixteen(unsigned int tendoc)
{
	//int tendoc = 426;
	int zhengshu = quzheng(tendoc);
	string sixteendoc = "";
	while (true)
	{
		if (zhengshu > 16)
		{
			int cha = tendoc - zhengshu * 16;
			tendoc = zhengshu;
			//cout << cha << endl;
			string result = huanzhi(cha);
			sixteendoc = sixteendoc + result;
			zhengshu = quzheng(tendoc);
		}
		else if (zhengshu == 16)
		{
			int cha = tendoc - zhengshu * 16;
			tendoc = zhengshu;
			//cout << cha << endl;
			string result = huanzhi(cha);
			sixteendoc = sixteendoc + result;
			zhengshu = quzheng(tendoc);
		}
		else
		{
			int cha = tendoc - zhengshu * 16;
			tendoc = zhengshu;
			//cout << cha << endl;
			//cout << zhengshu << endl;//最后一个整数也是差值
			string result1 = huanzhi(cha);
			string result2 = huanzhi(zhengshu);
			sixteendoc = sixteendoc + result1 + result2;
			break;
		}
	}
	string oversixdoc = daoxu(sixteendoc);//这个时候sixteendoc是反着的所以倒序倒为正了
	//cout << "oversixdoc:" << oversixdoc << endl;
	int length = strlen(oversixdoc.c_str());
	string tianchong;
	//cout <<"length:"  <<  length << endl;
	int i = 8 - length;
	while (true)
	{
		if (i > 0)
		{
			tianchong = tianchong + "0";
		}
		else
		{
			break;
		}
		i = i - 1;
	}
	//cout << "tianchong" << tianchong << endl;
	string result = tianchong + oversixdoc;
	//string result = tianchong + oversixdoc;
	return result;
}


//16到10 用法在下面
/*
string typesixteen = "ABCDEFAB";
unsigned int result =  sixteentoten(typesixteen);
cout << "结果:" << result << endl;
*/

int beishu(int length)
{
	int ji = 1;
	int length1 = 7 - length;
	int i = 0;
	while (true)
	{
		if (i < length1)
		{
			ji = ji * 16;
		}
		else
		{
			break;
		}
		i = i + 1;
	}
	//cout << "ji : " << ji << endl;
	return ji;
}

int callback(string ret, int i)
{
	unsigned int callback = 1;
	//cout << "i:" << i << "ret" << ret << endl;
	//cout << "beishu : " << beilv << endl;
	if (ret == "0")
	{
		int beilv = beishu(i);
		callback = beilv * 0;
	}
	else if (ret == "1")
	{
		int beilv = beishu(i);
		callback = beilv * 1;
	}
	else if (ret == "2")
	{
		int beilv = beishu(i);
		callback = beilv * 2;
	}
	else if (ret == "3")
	{
		int beilv = beishu(i);
		callback = beilv * 3;
	}
	else if (ret == "4")
	{
		int beilv = beishu(i);
		callback = beilv * 4;
	}
	else if (ret == "5")
	{
		int beilv = beishu(i);
		callback = beilv * 5;
	}
	else if (ret == "6")
	{
		int beilv = beishu(i);
		callback = beilv * 6;
	}
	else if (ret == "7")
	{
		int beilv = beishu(i);
		callback = beilv * 7;
	}
	else if (ret == "8")
	{
		int beilv = beishu(i);
		callback = beilv * 8;
	}
	else if (ret == "9")
	{
		int beilv = beishu(i);
		callback = beilv * 9;
	}
	else if (ret == "A" || ret == "a")
	{
		int beilv = beishu(i);
		callback = beilv * 10;
	}
	else if (ret == "B" || ret == "b")
	{
		int beilv = beishu(i);
		callback = beilv * 11;
	}
	else if (ret == "C" || ret == "c")
	{
		int beilv = beishu(i);
		callback = beilv * 12;
	}
	else if (ret == "D" || ret == "d")
	{
		int beilv = beishu(i);
		callback = beilv * 13;
	}
	else if (ret == "E" || ret == "e")
	{
		int beilv = beishu(i);
		callback = beilv * 14;
	}
	else if (ret == "F" || ret == "f")
	{
		int beilv = beishu(i);
		callback = beilv * 15;
	}
	return callback;
}

int sixteentoten(string ten)
{
	int length = strlen(ten.c_str());
	int i = 0;
	int answer = 0;
	int reback;
	string ret;
	while (true)
	{
		if (i < length)
		{
			ret = ten.substr(i, 1);//获取到了每一个位数上的具体值
			reback = callback(ret, i);
			answer = answer + reback;
		}
		else
		{
			break;
		}
		i = i + 1;
	}



	string result = "1";
	return answer;
}




/*Char*转TCHAR*/
LPWSTR ConvertCharToLPWSTR(const char* szString)

{

	int dwLen = strlen(szString) + 1;

	int nwLen = MultiByteToWideChar(CP_ACP, 0, szString, dwLen, NULL, 0);//算出合适的长度

	LPWSTR lpszPath = new WCHAR[dwLen];

	MultiByteToWideChar(CP_ACP, 0, szString, dwLen, lpszPath, nwLen);

	return lpszPath;

}

/*string转LPCWSTR*/
LPCWSTR stringToLPCWSTR(std::string orig)
{
	size_t origsize = orig.length() + 1;
	const size_t newsize = 100;
	size_t convertedChars = 0;
	wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(orig.length() - 1));
	mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
	return wcstring;
}

int main()
{
	cout << "请输入窗口标题:";
	string title;
	cin >> title;
	cout << "请输入特征码(如果不行可以试试切换大小写):";
	string special;
	cin >> special;
	char * specialcode = const_cast<char*>(special.c_str());
	cout << "请输入偏移量,如果没有请输入0:";
	int move;
	cin >> move;

	HWND hWnd;
	LPCWSTR  newititle = ConvertCharToLPWSTR(title.c_str());
	hWnd = FindWindow(NULL, newititle);//根据窗口标题获取窗口句柄

	DWORD PID;
	GetWindowThreadProcessId(hWnd, &PID);//存入PID

	HANDLE hprocess;
	hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);//获取进程

	ScanAddress(hprocess, specialcode, 0);//"获取地址值为多少"  如果输出的地址不对,可以试试特征码的大写和小写的替换
	//cout << hanshu_dizhi << endl;//输出地址(10进制)


	unsigned int num = hanshu_dizhi;
	num = num + move;//相对内存地址偏移量(10进制)
	string oversixdoc = tentosixteen(num);//这里已经转换为了16进制的地址
	cout << "地址为:" << oversixdoc << endl;//输出地址(10进制)
	while (true);
}


版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

评论