最近刚开学,事情很多,所以博客也有很久没有更新了,很久没有写博客,好像心态也变了
由于游戏更新,我们不得不去更新游戏的基址,如果每次都手动去找基址,那肯定是相当麻烦的,所以我们要做的就是利用编程来实现基址的动态更新。
需要写的函数:
HexStrCmp(IN const char* szpHexStr1 , IN const char* szpHexStr1);
ScanFeatureCode();等一系列函数。
然后再实现通配符支持就可以实现基址的自动更新了。
下面直接给出源码:
#pragma once
#include<Windows.h>
void HexStrToX(IN OUT CHAR* szpHexbuf);//通配符的支持
DWORD BytesToHexStr(IN BYTE* nbData, DWORD nbDataSize, OUT char* szpHexBuf); //字节集转十六进制
BOOL HexStrCmp(IN const char*Hexstr1, IN const char* Hexstr2);// 十六进制字符串比较
char IsLowToBigCase(char c);//如果c是小写字母则返回大写字母
BOOL HexStrToBigCase(IN OUT char* szHexStr); //将16进制字符串转化为大写
BOOL CharToHex(OUT char* szpHexbuf, BYTE c);//将字符转化为十六进制
DWORD ScanFeatureCode(HANDLE hProcess,
IN OUT char* szpFeatureCode,
DWORD ndStartAddress = 00400000,
DWORD ndEndAddress = 0x7FFFFFFF); //扫描特征码的函数
void OneKeyUpdateBaseAddr(HANDLE hProcess); //一键更新基址
#include "stdafx.h"
#include "ScanFeatureCode.h"
#include<stdio.h>
char IsLowToBigCase(char c)//如果c是小写字母则返回大写字母
{
if (c >= 'a' && c <= 'z'){
//转化为大写字母
return c = c + 'A' - 'a';
}
return c;
}
BOOL HexStrToBigCase(IN OUT char* szHexStr) //将16进制字符串转化为大写
{
DWORD ndStrlen = strlen(szHexStr);
for (DWORD i = 0; i < ndStrlen; i++){
szHexStr[i] = IsLowToBigCase(szHexStr[i]);
}
return TRUE;
}
DWORD BytesToHexStr(IN BYTE* nbData, DWORD nbDataSize, OUT char* szpHexBuf) //字节集转十六进制
{
//1 --- 01
for (DWORD i = 0; i < nbDataSize; i++){
//sprintf_s(&szpHexBuf[i * 2], 3, "%02X", nbData[i]);
CharToHex(&szpHexBuf[i * 2], nbData[i]);
}
return TRUE;
}
BOOL HexStrCmp(IN const char*Hexstr1, IN const char* Hexstr2)// 十六进制字符串比较
{
DWORD ndHexlen1 = strlen(Hexstr1);
DWORD ndHexlen2 = strlen(Hexstr2);
if (ndHexlen1 > ndHexlen2)
ndHexlen1 = ndHexlen2;
for (DWORD i = 0; i < ndHexlen1; i++){
if (Hexstr1[i] == 'X' || Hexstr2[i] == 'X')
continue;
if (Hexstr1[i] == Hexstr2[i])
continue;
return FALSE;
}
return TRUE;
}
#define PAGESIZE 0x1024 //每次读取的大小
DWORD ScanFeatureCode(HANDLE hProcess,
IN OUT char* szpFeatureCode,
DWORD ndStartAddress,
DWORD ndEndAddress) //扫描特征码的函数
{
//支持通配符
HexStrToX(szpFeatureCode);
//特征码如果存在小写字母,则转化为大写
HexStrToBigCase(szpFeatureCode);
DWORD ndLenHexCode = strlen(szpFeatureCode); //0xaF 占用两个字节 所以到除2才是16进制的长度
BYTE *nbDataBuf = new BYTE[PAGESIZE + ndLenHexCode / 2 + 2];
DWORD RealSize = 0;//实际读取的缓冲区的大小
for (DWORD ndCurAddr = ndStartAddress; ndCurAddr < ndEndAddress - ndLenHexCode / 2; ndCurAddr += PAGESIZE){
ReadProcessMemory(hProcess, (LPVOID)ndCurAddr, (LPVOID)nbDataBuf, PAGESIZE + ndLenHexCode / 2 + 2, &RealSize);
//将nbDataBuf逐字节的比较
for (DWORD i = 0; i < PAGESIZE; i++){
char szpTempHex[256] = "";
BytesToHexStr(&nbDataBuf[i], ndLenHexCode/2, szpTempHex);
if (HexStrCmp(szpTempHex, szpFeatureCode) != FALSE){
return ndCurAddr + i;
}
}
}
return NULL;
}
BOOL CharToHex(OUT char* szpHexbuf, BYTE c)//将字符转化为十六进制
{
BYTE bLow = 0;
BYTE bHigh = 0;
bLow = c % 16; //低位
bHigh = c / 16; //高位
if (bHigh > 9){
szpHexbuf[0] = 'A' + bHigh - 10;
}
else{
szpHexbuf[0] = '0' + bHigh;
}
if (bLow > 9){
szpHexbuf[1] = 'A' + bLow - 10;
}
else{
szpHexbuf[1] = '0' + bLow;
}
szpHexbuf[2] = '\0';
return TRUE;
}
BOOL IsHexStr(char c){ //判断字符是否是十六进制字符串
if (c >= '0' && c <= '9')
return TRUE;
else if (c >= 'a' && c <= 'z')
return TRUE;
else if (c >= 'A' && c <= 'Z')
return TRUE;
else
return FALSE;
}
void HexStrToX(IN OUT CHAR* szpHexbuf)//通配符的支持
{
DWORD ndStrlen = strlen(szpHexbuf);
for (DWORD i = 0; i < ndStrlen; i++){
if (IsHexStr(szpHexbuf[i]) == FALSE)
szpHexbuf[i] = 'X';
}
return;
}
DWORD ReadBaseAddr(HANDLE hProcess , DWORD ndCurAddr , DWORD ndSize ){
DWORD ndTemp = NULL;
ReadProcessMemory(hProcess, (LPVOID)ndCurAddr, &ndTemp, ndSize, NULL);
return ndTemp;
}
void OneKeyUpdateBaseAddr(HANDLE hProcess) //一键更新基址
{
DWORD ndCurAddr = NULL;
DWORD ndBaseAddr = NULL;
//人物属性
char szpFeatureCode[256] = "C745FCFFFFFFFF8D47D0B9";
ndCurAddr = ScanFeatureCode(hProcess, szpFeatureCode);
ndBaseAddr= ReadBaseAddr(hProcess, ndCurAddr + 0xb, 4);
printf("#define Base_RoleProperty 0x%X //人物属性基址 \n", ndBaseAddr);
//背包基址A1********8B8498100400008BB0C40C00000BB0C80C0000
strcpy_s(szpFeatureCode,"A1********8B8498100400008BB0C40C00000BB0C80C0000");
ndCurAddr = ScanFeatureCode(hProcess, szpFeatureCode);
ndBaseAddr = ReadBaseAddr(hProcess, ndCurAddr+1, 4);
printf("#define Base_BackPacketList 0x%X //背包列表基址 \n", ndBaseAddr);
//背包CALL 8B87081600008B8FD01B00005350518BCFE8
strcpy_s(szpFeatureCode, "8B87081600008B8FD01B00005350518BCFE8");
ndCurAddr = ScanFeatureCode(hProcess, szpFeatureCode);
ndBaseAddr = ReadBaseAddr(hProcess, ndCurAddr+ 18, 4);
ndBaseAddr = ndBaseAddr + ndCurAddr + 18 + 4;
printf("#define Base_BackPacketCall 0x%X //背包物品使用call \n", ndBaseAddr);
return;
}
以上代码就完成了对基址更新,其他的就在mian函数中调用这个接口就可以了,具体代码就不给出了