|
发表于 2022-12-28 16:22:12
|
查看: 6302 |
回复: 0
BytesToHexStr.h
BytesToHexStr.cpp
HexStrToBytes.h
HexStrToBytes.cpp
CFind_Offset.h
CFind_Offset.cpp
CFind_Offset_GetBaseOfffset.cpp
CFind_Offset_MatchSearch.cpp
//以下是调用例子
基址偏移.h
OFFSET_所有对象数组.cpp
定位所有基址偏移.cpp
//main.cpp是入口函数所在
main.cpp
//BytesToHexStr.h
- #pragma once
- #include <stdio.h>
- #include <string.h>
- #include <Windows.h>
- char* ByteToHexChar(unsigned char c);
- void BytesToHexStr(IN char *pBytes,IN SIZE_T nSize,OUT char*pOutBufHexStr,IN SIZE_T nBufSize);
复制代码
//BytesToHexStr.cpp
- #include <windows.h>
- #include "BytesToHexStr.h"
- char* ByteToHexChar(unsigned char c)
- {
- static char szRet[3]={0}; //FF 0F 00 1A 11
- unsigned char szhigh=c/16;
- unsigned char szlow=c-szhigh*0x10;
- if (szhigh>=0&&szhigh<=9)
- {
- szRet[0]='0'+szhigh; //30+9//'9'
- }else
- {
- //10..15
- szRet[0]='A'+szhigh-10;
- }
- if (szlow>=0&&szlow<=9)
- {
- szRet[1]='0'+szlow; //30+9//'9'
- }else if (szlow>=10&&szlow<=15)
- {
- //10..15
- szRet[1]='A'+szlow-10;
- }
- return (char*) szRet;
- }
- void BytesToHexStr(IN char *pBytes,IN SIZE_T nSize,OUT char*pOutBufHexStr,IN SIZE_T nBufSize)
- {
- DWORD n=0;
- if (nBufSize/3<nSize)
- {
- n=nBufSize/3;
- }else
- {
- n=nSize;
- }
- pOutBufHexStr[0]='\0';
- for (UINT32 i=0;i<n;i++)
- {
- strcat_s(pOutBufHexStr,nBufSize, ByteToHexChar(pBytes[i]));
- strcat_s(pOutBufHexStr,nBufSize,","); //×Ö½Ú·Ö¸ô·û
- }
- strcat_s(pOutBufHexStr,nBufSize,"\0"); //½áÊø·û
- return ;
- }
复制代码
//HexStrToBytes.h
- #pragma once
- #include <stdio.h>
- #include <string.h>
- #include <Windows.h>
- //1、szHexStr 为待转换字16进制字串
- //2、szBytesbuf 是存放转换后的数据
- //3、nBufSize是szBytesbuf缓冲区的大小
- //4、返回成功转换的字节数量
- SIZE_T HexStrToBytes(const char*szHexStr, OUT BYTE*szBytesbuf, SIZE_T nBufSize);
- //带分隔符
- SIZE_T HexStrToBytesNew(const char*szHexStr, OUT BYTE*szBytesbuf, SIZE_T nBufSize);
- SIZE_T HexStrToBytesEx(IN const char*szHexStr, OUT BYTE*szBytesbuf, SIZE_T nBufSize, OUT BYTE*szStar);
-
-
复制代码
//HexStrToBytes.cpp
- #include <windows.h>
- #include "HexStrToBytes.h"
- #include <stdio.h>
- #include <string>
- using namespace std;
-
- unsigned char charToByte(char c)
- {
- //0..9
- //a..f
- //A..F
- unsigned char cret=0;
- if (c>='0'&&c<='9')
- {
- cret=c-'0';//'1'
- }else if (c>='a'&&c<='f')
- {
- cret=c-'a'+10;//'1'
- }else if (c>='A'&&c<='F')
- {
- cret=c-'A'+10;//'1'
- }
- return cret;
- }
- //1、szHexStr 为待转换字16进制字串
- //2、szBytesbuf 是存放转换后的数据
- //3、nBufSize是szBytesbuf缓冲区的大小
- SIZE_T HexStrToBytes(const char*szHexStr,OUT BYTE*szBytesbuf,SIZE_T nBufSize)
- {
- int dwHexLen=(int)strlen(szHexStr);
- unsigned char OneByte=0;
- int j=0;
- int nBytes=0;
- for (int i=0;i<=dwHexLen;i++)
- {
-
- //判断,分隔符
- if (i&&i%2==0)
- {
- nBytes++;
- szBytesbuf[j++]=OneByte;
- //检测缓冲是否溢出
- if (j>=nBufSize)
- {
- //溢出了 返回
- break;
- }
- OneByte=0;//初始化 以备下一字节的转换
- }
- {
- OneByte=OneByte*16+charToByte(szHexStr[i]);
- }
- }
- if(nBytes>68) {MessageBoxA(0,"特征码过长","警示",1);};
- return nBytes;
- };
- //带分隔符
- SIZE_T HexStrToBytesNew(const char*szHexStr,OUT BYTE*szBytesbuf,SIZE_T nBufSize)
- {
- int dwHexLen=(int)strlen(szHexStr);
- unsigned char OneByte=0;
- int j=0;
- int nBytes=0;
- for (int i=0;i<=dwHexLen;i++)
- {
-
- //判断,分隔符
- if (szHexStr[i]==','||szHexStr[i]=='\0')
- {
- nBytes++;
- szBytesbuf[j++]=OneByte;
- //检测缓冲是否溢出
- if (j>=nBufSize)
- {
- //溢出了 返回
- break;
- }
- OneByte=0;//初始化 以备下一字节的转换
- }else
- {
- OneByte=OneByte*16+charToByte(szHexStr[i]);
- }
- }
- return nBytes;
- };
- bool 是通配符(BYTE c)
- { //自己定义通配符 可以是所有的非数字符号
- bool flag = false;
- if (c == '*'||c == '?')
- {
- flag = true;
- }
- else if (c == '?') //全角状态的问号
- {
- flag = true;
- }
- return flag;
- }
- bool 是数字(IN BYTE c,OUT BYTE &num)
- {
- bool flag = false;
- //0..9
- //a..f
- //A..F
- //unsigned char cret = 0;
- if (c >= '0'&&c <= '9')
- {
- num = c - '0';//'1'
- flag = true;
- }
- else if (c >= 'a'&&c <= 'f')
- {
- num = c - 'a' + 10;//'1'
- flag = true;
- }
- else if (c >= 'A'&&c <= 'F')
- {
- num = c - 'A' + 10;//'1'
- flag = true;
- }
- return flag;
- }
- bool 是分隔符(BYTE c)
- {
- bool flag = false;
- if (c == ',' || c == ' ')
- {
- flag = true;
- }
- else if (c == ';')
- {
- flag = true;
- }
- return flag;
-
- }
- //str是待处理的字符串
- //to_replaced 是被替换的字符串
- //newchars是新的字符串
- string& replace_str(string& str, const string& to_replaced, const string& newchars)
- {
- for(string::size_type pos(0); pos != string::npos; pos += newchars.length())
- {
- pos = str.find(to_replaced,pos);
- if(pos!=string::npos)
- str.replace(pos,to_replaced.length(),newchars);
- else
- break;
- }
- return str;
- }
- //带分隔符,通配符处理
- SIZE_T HexStrToBytesEx(IN const char*szHexStr, OUT BYTE*szBytesbuf, SIZE_T nBufSize,OUT BYTE*szStar)
- {
- char tmpstr[256] = { 0 };
- strcpy_s(tmpstr, szHexStr );
- //printf("szHexStr=%s\r\n", szHexStr);
- int dwHexLen = (int)strlen(szHexStr);
- {
- //替换所有0x前缀0X
- //替换所有分隔符
- //不是数字的全当通配符
- //所有小写字母转大写
- for (int i = 0; i <= dwHexLen; i++)
- {
- if (tmpstr[i] >= 'a'&&tmpstr[i] <= 'z')
- {
- //转大写
- tmpstr[i] = tmpstr[i] + 'A' - 'a'; //'a'>'A' 'A' - 'a'=-32
- }
- }
- std::string newHexStr = tmpstr;//这里不直接赋值为szHexStr,是为防止缓冲区重叠
- //替换所有0x前缀0X
- replace_str(newHexStr, "0X", "");//小写的0x已经在上边被转换
- //替换所有分隔符
- replace_str(newHexStr, ",", "");//中文逗号
- replace_str(newHexStr, ",", "");//英文逗号
- replace_str(newHexStr, " ", "");//英文逗号
- replace_str(newHexStr, "\t", "");//英文逗号
- strcpy_s(tmpstr, newHexStr.c_str());
- }
- unsigned char OneByte = 0;
- int j = 0;
- int nBytes = 0;
- BYTE num=0;
- dwHexLen =(int) strlen(tmpstr);
- for (int i = 0; i <= dwHexLen; i++)
- {
- // 2个字符一组处理
- // if (是数字(tmpstr[i],num))
- if (i&&i % 2 == 0)
- { //i=2,4,6,8,10 偶数才会走到这里
- // printf("[%03d]=%02X <%03d>\r\n",j, OneByte, OneByte);
- nBytes++;
- szBytesbuf[j++] = OneByte;
-
- //检测缓冲是否溢出
- if (j >= nBufSize|| tmpstr[i]=='\0')
- {
- //遇到字符口中结束 或者 溢出了返回
- break;
- }
- OneByte = 0;//初始化 以备下一字节的转换
- }
- { //i=0,1,2,3,4,5,6
- bool flag=是数字(tmpstr[i], num); // 1A,3F
- if (flag)
- {
- OneByte = OneByte * 16 + num;// charToByte(tmpstr[i]);
- }else
- {
- //不是数字 全当通配符处理了 ** ?? ??
- //通配符 也必须是成对出现 否则格式就是错误的
- if (tmpstr[i] != tmpstr[i + 1])
- {
- char buf[512];
- sprintf_s(buf, "szHexStr=%s,tmpstr=%s通配符未成对出现", szHexStr, tmpstr);
- MessageBoxA(0, buf, "ERROR HexStrToBytesEx", 0);
- }
- //printf("[%03d]=<%c,%c>\r\n", j, tmpstr[i], tmpstr[i+1]);
-
- szStar[j+0] = 1; //保存通配符位置
- i = i + 1; //一次性跳过一对通配符 需要的是i=i+2 这里加1是因为for循环那里还有个i++
- }
-
- }
- }
- //printf("\r\n");
- return nBytes;
- };
复制代码
//CFind_Offset.h
- #pragma once
- #include <stdio.h>
- #include <windows.h>
- #include <psapi.h>
- #include <tchar.h>
- char* GetBjTime(IN OUT char*buf, size_t nBufSize);
- typedef class _CFind_Offset
- {
- public:
-
- static HWND GetHwnd();//获取目标窗口句柄
- static DWORD GetPID(); //获取目标PID
- static HANDLE GetProcessHandle();//获取目标进程句柄
- static UINT_PTR GetExeBase();//获取目标进程主模块基址
- static BOOL GetExeData(OUT PBYTE &pbuf,OUT size_t &nReadSize);
- static BOOL FindOffset(IN BYTE* buf, IN size_t bufSize, IN BYTE* 特征码, IN BYTE 特征码长度, OUT DWORD &nOffset);
- static INT_PTR GetBaseOfffset(IN INT_PTR 指令地址,IN INT_PTR 指令长度,IN INT_PTR 指令前缀长度);
- static INT_PTR GetBaseOfffset(const char*特征码, INT_PTR 特征码偏移, BYTE 指令长度, BYTE 指令前缀长度);
- static INT_PTR GetBaseOfffsetEx(IN const char*特征码, IN INT_PTR 特征码偏移, IN BYTE 指令长度, IN BYTE 指令前缀长度);
- static INT_PTR MatchSearch(IN const char*特征码带通配符, IN INT_PTR 特征码偏移, IN BYTE 指令长度, IN BYTE 指令前缀长度); //
- static INT_PTR MatchSearch(IN const char *变量名,
- IN const char*特征码带通配符,
- IN INT_PTR 特征码偏移,
- IN BYTE 指令长度,
- IN BYTE 指令前缀长度); // CFind_Offset
- static void printfCmdAndFile(const char*buf);
- }CFind_Offset;
复制代码
//CFind_Offset.cpp
- #include "CFind_Offset.h"
- //buf 是目标进程的代码数据
- //bufSize 代码段数据的大小
- //特征码
- //特征码长度
- //nOffset返回找到的偏移 =目标进程特征地址-目标进程主模块地址
- static char tmpbuf[0x6247000] = { 0 };//根据文件大小设置本地的缓冲区 100MB
- BOOL CFind_Offset::FindOffset(IN BYTE* buf, IN size_t bufSize,IN BYTE* 特征码,IN BYTE 特征码长度,OUT DWORD &nOffset)
- {
- for (size_t i=0;i<bufSize- 特征码长度;i++)
- {
- if (memcmp(buf + i, 特征码, 特征码长度) == 0) //内存比较
- {
- nOffset =(DWORD)i;
- return TRUE;
- break;
- }
- }
- return FALSE;
- };
- INT_PTR CFind_Offset::GetBaseOfffset(IN INT_PTR 指令地址, IN INT_PTR 指令长度, IN INT_PTR 指令前缀长度)
- {
- INT_PTR p1 = 指令地址/*Mir4G.exe*/ + 指令前缀长度;
- if ((p1+4) > sizeof(tmpbuf))
- {
- MessageBoxA(NULL, "错误的参数", "ERROR", 0);
- return 0;
- }
- else
- {
- //000000013F59223D | 48 8B 0D EC D8 9A 05 | mov rcx,qword ptr ds:[144F3FB30] | Mir4G.exe+5E0FB30 //13F130000+ 5E0FB30
- //$-2C | 48 8B 0D EC D8 9A 05 | mov rcx,qword ptr ds:[145D7FB30] | Mir4G.exe+5E0FB30 mov rcx qword ptr[????] EC D8 9A 05 //059AD8EC
- INT_PTR 偏移 = *(DWORD*)(tmpbuf+p1);
- //目标地址=指令地址+指令长度+偏移
- //144F3FB30=000000013F59223D+7+059AD8EC
- //13F130000+ 5E0FB30 = 13F130000+46223D+7+059AD8EC //EXE基址=13F130000
- // exe基址+ 5E0FB30 = exe基址+46223D+7+059AD8EC
- // exe基址+ 5E0FB30 = exe基址+指令地址+7+059AD8EC
- // exe基址+ 5E0FB30 = exe基址+指令地址+指令长度+偏移
- // 5E0FB30= 指令地址+指令长度+偏移
-
- INT_PTR 目标地址 = 指令地址 + 指令长度 + 偏移;
-
- return 目标地址;
- }
-
- };
- //只读取一次
- BOOL CFind_Offset::GetExeData(OUT PBYTE &pbuf, OUT size_t &nReadSize)
- {
-
- static size_t nsize = 0; //用于保存实际读取的字节大小
- if (nsize)
- {
- nReadSize = nsize;
- pbuf = (PBYTE)tmpbuf;
- return TRUE;
- }
- //顺利的情况下 以下代码只会执行一次
- HANDLE hp = GetProcessHandle(); //获取目标进程句柄权限
- UINT_PTR exebase = GetExeBase(); //获取目标进程的 主模块基址
- BOOL br=ReadProcessMemory(hp, (PVOID)exebase, tmpbuf, sizeof(tmpbuf), &nsize);
- if (br == FALSE)
- {
- printf("hp=%p Error GetLastError()=%d line=%d\r\n", hp, GetLastError(),__LINE__);
- getchar();
- }
- else
- {
- nReadSize = nsize;
- pbuf =(BYTE*) tmpbuf;
-
- }
- return br;
- };
- HWND CFind_Offset::GetHwnd()
- {
- HWND h = FindWindowA("UnrealWindow", NULL); //"UnrealWindow" // "Mir4G[1]" "Mir4G[2]"
- if (h)
- {
- return h;
- }
- else
- {
- printf("Error line=%d FindWindowA ret NULL 游戏未打开 \r\n", __LINE__);
- getchar();
- }
- return 0;
- };
- DWORD CFind_Offset::GetPID()
- {
- HWND h = GetHwnd();
- DWORD pid = 0;
- GetWindowThreadProcessId(h, &pid);
- return pid;
- };
- HANDLE CFind_Offset::GetProcessHandle()
- {
- DWORD pid = GetPID();
- static HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, false, pid);//如失败,返回值为空,可调用GetLastError获得错误代码。
- if (hp==NULL )
- {
- printf("Error line=%d OpenProcess ret NULL GetLastError()=%d \r\n", __LINE__, GetLastError());
- getchar();
- }
- return hp;
- };
- UINT_PTR CFind_Offset::GetExeBase()
- {
- //return(UINT_PTR) GetModuleHandleA(NULL);//代码已经注入到目标进程空间
- static UINT_PTR exeBase64 = NULL;
- HMODULE hMods[1024]; //20*sizeof(HMODULE ) //160
- DWORD cbNeeded;
- unsigned int i;
- HANDLE 进程句柄 = GetProcessHandle();
- if (exeBase64) return exeBase64;
- // Get a list of all the modules in this process.
- BOOL br = EnumProcessModules(进程句柄, hMods, sizeof(hMods), &cbNeeded);
- if (br)
- {
- UINT32 模块数量 = cbNeeded / sizeof(HMODULE);
- for (i = 0; i < 模块数量; i++)
- {
- TCHAR szModName[MAX_PATH] = { 0 };
- DWORD iret= GetModuleFileNameEx(进程句柄, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR));
-
- // Get the full path to the module's file.
- //printf("i=[%d],szModName=%s hMods[%d]=%p>>>\r\n",i, szModName,i,hMods[i]);
- if (iret)
- {
- //如果是 .exe模块 直接返回基址
- if (strstr(szModName, ".exe")) //*.bin *.dat //Mir4G.exe
- {
- exeBase64 = (UINT_PTR)hMods[i]; //hMods[0]
- printf("//主模块Mir4G.exe地址=%llX i=%d\r\n", exeBase64, i);
- }
-
- }
- }
- }
- else
- {
- /*
- 〖0〗-操作成功完成。
- 〖1〗-功能错误。
- 〖2〗-系统找不到指定的文件。
- 〖3〗-系统找不到指定的路径。
- 〖4〗-系统无法打开文件。
- 〖5〗-拒绝访问。
- 〖6〗-句柄无效。
- */
- printf("Error EnumProcessModules line=%d GetLastError=%d 进程句柄=%p", __LINE__,GetLastError(), 进程句柄);
- getchar();
- }
- // Release the handle to the process.
- //CloseHandle(进程句柄);
- return exeBase64;
- }
-
复制代码
//CFind_Offset_GetBaseOfffset.cpp
- #include "CFind_Offset.h"
- #include "HexStrToBytes.h"
- //buf 是目标进程的代码数据
- //bufSize 代码段数据的大小
- //特征码
- //特征码长度
- //nOffset返回找到的偏移 =目标进程特征地址-目标进程主模块地址
- //static char tmpbuf[0x6247000] = { 0 };//根据文件大小设置本地的缓冲区 100MB
- INT_PTR CFind_Offset::GetBaseOfffsetEx(IN const char*特征码, IN INT_PTR 特征码偏移, IN BYTE 指令长度, IN BYTE 指令前缀长度)
- {
- OUT INT_PTR nOffset = 0;
- BYTE 字节集[256] = { 0 };
- BYTE 通配符[256] = { 0 };//备用
- size_t 特征码长度 = strlen(特征码);
- if (特征码长度 > 128)
- {
- MessageBoxA(0, "最大支持128字节特征码长度", "ERROR", 0);
- return 0;
- }
- //16进制字符串转 字节集数组
- 特征码长度 = HexStrToBytes(IN 特征码, OUT 字节集, IN 特征码长度);
- BYTE* exebuf = 0;
- size_t exebufsize = 0;
- GetExeData(exebuf, exebufsize);
- if (exebuf == NULL)
- {
- MessageBoxA(0, "未成功获取目标进程代码段", "ERROR", 0);
- }
- BYTE*pexebuf = (BYTE*)exebuf;
- for (size_t i = 0; i < exebufsize; i++)
- {
- if (memcmp(pexebuf + i, 字节集, 特征码长度) == 0)
- {
- nOffset = i;
- break;
- }
- }
- //找到了特征码位置
- if (nOffset)
- {
- INT_PTR 指令地址 = nOffset + 特征码偏移;
- DWORD *偏移 = (DWORD*)(pexebuf + 指令地址 + 指令前缀长度);
- nOffset = 指令地址 + 指令长度 + 偏移[0];
- printf("指令地址=%llX nOffset=%llX\r\n", 指令地址, nOffset);
- }
- return nOffset;
- }
- INT_PTR CFind_Offset::GetBaseOfffset(const char*特征码, INT_PTR 特征码偏移, BYTE 指令长度, BYTE 指令前缀长度)
- {
- OUT INT_PTR nOffset = 0;
- BYTE 字节集[256] = { 0 };
- //BYTE 通配符[256] = { 0 };//备用
- size_t 特征码长度 = strlen(特征码);
- if (特征码长度 > 128)
- {
- MessageBoxA(0, "最大支持128字节特征码长度", "ERROR", 0);
- return 0;
- }
- //16进制字符串转 字节集数组
- 特征码长度=HexStrToBytes(IN 特征码, OUT 字节集, IN 特征码长度);
- BYTE* exebuf = 0;
- size_t exebufsize = 0;
- GetExeData(exebuf, exebufsize);
- if (exebuf==NULL)
- {
- MessageBoxA(0, "未成功获取目标进程代码段", "ERROR", 0);
- }
- BYTE*pexebuf = (BYTE*)exebuf;
- for (size_t i=0;i< exebufsize;i++)
- {
- if (memcmp(pexebuf + i, 字节集, 特征码长度) == 0)
- {
- nOffset = i;
- break;
- }
- }
- //找到了特征码位置
- if (nOffset)
- {
- INT_PTR 指令地址 = nOffset + 特征码偏移;
- DWORD *偏移 = (DWORD*) (pexebuf+指令地址 + 指令前缀长度);
- nOffset = 指令地址 + 指令长度 + 偏移[0];
- printf("指令地址=%llX nOffset=%llX\r\n", 指令地址, nOffset);
- }
- return nOffset;
- };
复制代码
//CFind_Offset_MatchSearch.cpp
-
- #include "CFind_Offset.h"
- #include "HexStrToBytes.h"
- //相等时返回0
- int MatchCmp(const BYTE* s1, const BYTE*s2, const BYTE* star1, size_t len)
- {
- #ifdef _DEBUG
- if (!s1 || !s2 || !star1)
- {
- MessageBoxA(0,"Error指针参数为NULL","MatchCmp", 0);
- }
- #endif
- size_t i = 0;
- for (i = 0; i < len; i++)
- {
- if (star1[i] || (s1[i] == s2[i])) //是通配符 memcmp
- {
- // printf("star1[%d]=%02X s1,s2<02X,%02X>\r\n", star1[i], s1[i], s2[i]);
- continue;
- }else
- {
- break;
- }
- }
- //printf("i=%zd len=%zd\r\n",i,len);
- if (i==len)
- {
- return 0; //相等
- }
- else
- {
- return(int)i+1; //不等
- }
-
- }
- INT_PTR CFind_Offset::MatchSearch(IN const char*特征码带通配符, IN INT_PTR 特征码偏移, IN BYTE 指令长度, IN BYTE 指令前缀长度)
- {
- UINT_PTR base = GetExeBase();
- PBYTE pexebuf = 0;
- size_t nSizeExe = 0;
- GetExeData(pexebuf, nSizeExe);
- // // CFind_Offset_MatchSearch
- INT_PTR nOffset = 0;
- {
- //char 特征码带通配符[] = "48 8B 15ZZ**??**FF 90 48080000 48 83 BF C8040000 00"; //11223355667788AAXX88
- BYTE features[256];
- BYTE star1[256] = { 0 };
- size_t nsize1 = HexStrToBytesEx(特征码带通配符,OUT features, sizeof(features), OUT star1);
-
- if (nSizeExe&&nsize1)
- {
- for (size_t i = 0; i < nSizeExe- nsize1; i++)
- { //int MatchCmp(const BYTE* s1, const BYTE*s2, const BYTE* star1, size_t len)
- int iret = MatchCmp(pexebuf + i, features, star1, nsize1);
- if (iret == 0)
- {
- nOffset = i;
- break;
- }
- }
- }
-
- }
- //找到了特征码位置
- if (nOffset)
- {
- INT_PTR 指令地址 = nOffset + 特征码偏移;
- DWORD *偏移 = (DWORD*)(pexebuf + 指令地址 + 指令前缀长度);
- //printf("//nOffset=%zX 特征码偏移=%zX <%zX,%d,%X>=%zX\r\n", nOffset, 特征码偏移, 指令地址,指令长度 , 偏移[0]
- //, 指令地址 + 指令长度 + 偏移[0]);
- nOffset = (DWORD)(指令地址 + 指令长度 + 偏移[0]); //会存在溢出的情况
- //#ifdef _DEBUG
- // printf("//%s> 搜索结果<%zX,%zX>\r\n", 特征码带通配符, base + nOffset, nOffset);
- // printf("//指令地址=<%zX,%zX> nOffset=<%zX,%zX>\r\n", base + 指令地址, 指令地址, base + nOffset, nOffset);
- //#endif // _DEBUG
- }
-
- return nOffset;
- }
- int WriteToFile(const char* szLine)
- {
- const char* sFilePath = "基址偏移.h";
- //printf("sFilePath=%s line=%d \n", sFilePath,__LINE__);
- //FileRename(sFilePath);
- FILE* fp = 0;
- fopen_s(&fp,sFilePath, "ab+"); //w+ 清新后写 a+ 在文件尾追加写
- if (fp == NULL)
- {
- return -1;
- }
- fwrite(szLine, strlen(szLine), 1, fp);
- fclose(fp);
- return 0;
- }
- void CFind_Offset::printfCmdAndFile(const char*buf)
- {
- printf(buf);
- WriteToFile(buf);
- };
- INT_PTR CFind_Offset::MatchSearch(
- IN const char *变量名,
- IN const char*特征码带通配符,
- IN INT_PTR 特征码偏移,
- IN BYTE 指令长度,
- IN BYTE 指令前缀长度)
- {
- char buf[512];
- UINT_PTR exeBase=GetExeBase();
- INT_PTR nOffset = MatchSearch(特征码带通配符, 特征码偏移, 指令长度, 指令前缀长度);
- sprintf_s(buf,"const UINT_PTR %s =0x%zX; // %zX >%s<%zd,%d,%d>\r\n",
- 变量名,
- nOffset,
- exeBase+nOffset,特征码带通配符 ,特征码偏移, 指令长度, 指令前缀长度);
- //写文件
- printf(buf);
- WriteToFile(buf);
- return nOffset;
- }
复制代码
//基址偏移.h
- //#pragma once
- const UINT_PTR CALL02_OFFSET_取任务对象 =F431D0; // 1401431D0 >488D8FE0020000488B01FF5030<31,5,1>
- const UINT_PTR CALL01_RCX_OFFSET_取任务对象 =12072E0; // 1404072E0 >488D8FE0020000488B01FF5030<18,5,1>
- const UINT_PTR CALL_OFFSET_明文包 =12FE530; // 1404FE530 >41B888130000488D542430488B4808<15,5,1>
- const UINT_PTR CALL_RCX_OFFSET_明文包 =5D29FE8; // 144F29FE8 >41B888130000488D542430488B4808<-7,7,3>
- const UINT_PTR CALL_OFFSET_背包物品使用 =1178980; // 140378980 >440FB68710030000488B93B0000000488BCBE8<18,5,1>
- const UINT_PTR CALL_OFFSET_使用背包物品01 =9C7010; // 13FBC7010 >488BC8450FB6CD41B801000000488BD3E8<16,5,1>
- const UINT_PTR CALL_RCX_OFFSET_使用背包物品01 =6E4400; // 13F8E4400 >488BC8450FB6CD41B801000000488BD3E8<-5,5,1>
- const UINT_PTR CALL_OFFSET_选怪CALL01 =8FDA40; // 13FAFDA40 >0F28B424F0000000488B8338030000<-5,5,1>
- const UINT_PTR CALL_OFFSET_选怪CALL02 =8E7BC0; // 13FAE7BC0 >0F28B424F0000000488B8338030000<-16,5,1>
- const UINT_PTR CALL_OFFSET_取控件对象 =1D67F00; // 140F67F00 >4C8B4310488BD7488BC8488B5C24304883C4205F49FFE0<-5,5,1>
- const UINT_PTR CALL_OFFSET_寻路 =A06A60; // 13FC06A60 >C6442428028944242CF20F10833C060000<60,5,1>
- const UINT_PTR CALL_OFFSET_按键 =1DA30E0; // 140FA30E0 >33C04889BEF00100004889BEF8010000898611010000<48,7,3>
- const UINT_PTR CALL_OFFSET01_采集 =6E4400; // 13F8E4400 >4488642428C7442420000000004533C941B001<-8,5,1>
- const UINT_PTR CALL_OFFSET02_采集 =9AE9D0; // 13FBAE9D0 >4488642428C7442420000000004533C941B001<22,5,1>
- const UINT_PTR OFFSET_怪物人物采集物对象ID数组 =5D2AF30; // 144F2AF30 >32C04D85C07408410FB68080060000<-7,7,3>
- const UINT_PTR OFFSET_所有对象数组 =5E0FB30; // 14500FB30 >33C08B4008C1E81DA8010F85<-23,7,3>
- const UINT_PTR OFFSET_人物属性对象A =5D29B18; // 144F29B18 >488B01FF50283D5E240000<17,7,3>
- const UINT_PTR OFFSET_人物角色坐标基址 =5D2A540; // 144F2A540 > 48 8B 05 ********48 85 C0 74 **80 B8 88 03 00 00 0D <0,7,3>
- const UINT_PTR OFFSET_NPC_ID_LIST =55A2CB0; // 1447A2CB0 >488D3CD04885FF0F84A5<-7,7,3>
- //#pragma once
- const UINT_PTR CALL02_OFFSET_取任务对象 =F431D0; // 1400431D0 >488D8FE0020000488B01FF5030<31,5,1>
- const UINT_PTR CALL01_RCX_OFFSET_取任务对象 =12072E0; // 1403072E0 >488D8FE0020000488B01FF5030<18,5,1>
- const UINT_PTR CALL_OFFSET_明文包 =12FE530; // 1403FE530 >41B888130000488D542430488B4808<15,5,1>
- const UINT_PTR CALL_RCX_OFFSET_明文包 =5D29FE8; // 144E29FE8 >41B888130000488D542430488B4808<-7,7,3>
- const UINT_PTR CALL_OFFSET_背包物品使用 =1178980; // 140278980 >440FB68710030000488B93B0000000488BCBE8<18,5,1>
- const UINT_PTR CALL_OFFSET_使用背包物品01 =9C7010; // 13FAC7010 >488BC8450FB6CD41B801000000488BD3E8<16,5,1>
- const UINT_PTR CALL_RCX_OFFSET_使用背包物品01 =6E4400; // 13F7E4400 >488BC8450FB6CD41B801000000488BD3E8<-5,5,1>
- const UINT_PTR CALL_OFFSET_选怪CALL01 =8FDA40; // 13F9FDA40 >0F28B424F0000000488B8338030000<-5,5,1>
- const UINT_PTR CALL_OFFSET_选怪CALL02 =8E7BC0; // 13F9E7BC0 >0F28B424F0000000488B8338030000<-16,5,1>
- const UINT_PTR CALL_OFFSET_取控件对象 =1D67F00; // 140E67F00 >4C8B4310488BD7488BC8488B5C24304883C4205F49FFE0<-5,5,1>
- const UINT_PTR CALL_OFFSET_寻路 =A06A60; // 13FB06A60 >C6442428028944242CF20F10833C060000<60,5,1>
- const UINT_PTR CALL_OFFSET_按键 =1DA30E0; // 140EA30E0 >33C04889BEF00100004889BEF8010000898611010000<48,7,3>
- const UINT_PTR CALL_OFFSET01_采集 =6E4400; // 13F7E4400 >4488642428C7442420000000004533C941B001<-8,5,1>
- const UINT_PTR CALL_OFFSET02_采集 =9AE9D0; // 13FAAE9D0 >4488642428C7442420000000004533C941B001<22,5,1>
- const UINT_PTR OFFSET_怪物人物采集物对象ID数组 =5D2AF30; // 144E2AF30 >32C04D85C07408410FB68080060000<-7,7,3>
- const UINT_PTR OFFSET_所有对象数组 =5E0FB30; // 144F0FB30 >33C08B4008C1E81DA8010F85<-23,7,3>
- const UINT_PTR OFFSET_人物属性对象A =5D29B18; // 144E29B18 >488B01FF50283D5E240000<17,7,3>
- const UINT_PTR OFFSET_人物角色坐标基址 =5D2A540; // 144E2A540 > 48 8B 05 ********48 85 C0 74 **80 B8 88 03 00 00 0D <0,7,3>
- const UINT_PTR OFFSET_NPC_ID_LIST =55A2CB0; // 1446A2CB0 >488D3CD04885FF0F84A5<-7,7,3>
- //>>完成所有遍历
-
复制代码
//OFFSET_所有对象数组.cpp
- #include <windows.h>
- /*
- //#define OFFSET_所有对象数组 0x5DE7C70 // 49 8B C6 81 60 08 FF FF FF BF //向上找第一个地址
- $-2E | 7D 2C | jge mir4g.1403D2269 |
- $-2C | 48 8B 0D EC D8 9A 05 | mov rcx,qword ptr ds:[145D7FB30] | Mir4G.exe+5E0FB30 mov rcx qword ptr[????] EC D8 9A 05 //059AD8EC
- $-25 | 99 | cdq |
- $-24 | 0F B7 D2 | movzx edx,dx |
- $-21 | 03 C2 | add eax,edx |
- $-1F | 44 8B C0 | mov r8d,eax |
- $-1C | 0F B7 C0 | movzx eax,ax |
- $-19 | 2B C2 | sub eax,edx |
- $-17 | 41 C1 F8 10 | sar r8d,10 |
- $-13 | 48 98 | cdqe |
- $-11 | 49 63 D0 | movsxd rdx,r8d |
- $-E | 4C 8B 04 D1 | mov r8,qword ptr ds:[rcx+rdx*8] |
- $-A | 48 8D 0C 40 | lea rcx,qword ptr ds:[rax+rax*2] |
- $-6 | 49 8D 04 C8 | lea rax,qword ptr ds:[r8+rcx*8] |
- $-2 | EB 03 | jmp mir4g.1403D226C |
- $ ==> | 49 8B C6 | mov rax,r14 | 0x49,0x8B,0xC6,0x81,0x60,0x08,0xFF,0xFF,0xFF,0xBF
- $+3 | 81 60 08 FF FF FF BF | and dword ptr ds:[rax+8],BFFFFFFF |
- $+A | 48 8D 15 E6 59 94 03 | lea rdx,qword ptr ds:[143D17C60] | 143D17C60:L"ExtendedFacebook"
- */
- #include <windows.h>
- #include "CFind_Offset.h"
- const INT_PTR 特征码偏移 = -0x2C;
- const DWORD 指令长度 = 7;
- const DWORD 指令前缀长度 = 3;
- void OFFSET_所有对象数组()
- {
- INT_PTR exeBase = CFind_Offset::GetExeBase();
- BYTE* buf = NULL;
- size_t nSize = 0;
- CFind_Offset::GetExeData(buf, nSize);
- printf("ExeDataBuf=%p nSize=%zx \r\n", buf, nSize);
- //char 特征码2[] = { 0x49,0x8B,0xC6,0x81,0x60,0x08,0xFF,0xFF,0xFF,0xBF };
- BYTE 特征码[] = { 0x49,0x8B,0xC6,0x81,0x60,0x08,0xFF,0xFF,0xFF,0xBF };
- DWORD 特征码地址偏移 = 0;
- BOOL 是否找到 = CFind_Offset::FindOffset((BYTE*)buf, nSize, 特征码, sizeof(特征码), OUT 特征码地址偏移);
- if (是否找到)
- {
- printf("特征码长度=%zd 找到的偏移=0x%X 游戏特征地址=0x%llX\r\n", sizeof(特征码), 特征码地址偏移, exeBase + 特征码地址偏移);
- {
- INT_PTR 指令地址 = 特征码地址偏移 + 特征码偏移;
- //指令地址 指令长度 指令前缀长度
- INT_PTR 最终偏移= CFind_Offset::GetBaseOfffset(指令地址, 指令长度, 指令前缀长度);
- printf("OFFSET_所有对象数组->(最终偏移=%zx 真实地址=%zx)\r\n", 最终偏移, exeBase+ 最终偏移);
- }
- }
- else
- {
- printf("Error 相应特征码 未定位到 是否找到=%d\r\n", 是否找到);
- getchar();
- }
- }
- // "498BC6816008FFFFFFBF" //0x49,0x8B,0xC6,0x81,0x60,0x08,0xFF,0xFF,0xFF,0xBF
- //INT_PTR CFind_Offset::GetBaseOfffset(const char*特征码, INT_PTR 特征码偏移, BYTE 指令长度, BYTE 指令前缀长度)
- void OFFSET_所有对象数组02()
- { //498BC6816008????FFBF
- INT_PTR exeBase = CFind_Offset::GetExeBase();
- INT_PTR 最终偏移 = CFind_Offset::GetBaseOfffset("498BC6816008FFFFFFBF", -0x2C, 7,3);
- printf("OFFSET_所有对象数组02->(最终偏移=%zx 真实地址=%zx)\r\n", 最终偏移, exeBase + 最终偏移);
- }
复制代码
//定位所有基址偏移.cpp
- #include "CFind_Offset.h"
- #include <time.h>
- int WriteToFile(const char* szLine);
- char* GetBjTime(IN OUT char*buf,size_t nBufSize)
- {
- //GetSystemTime(&sysTm); //获取格林威治标准时间,与北京时间相差8小时
- time_t t = time(NULL);
- tm tp;
- localtime_s(&tp, &t); // 北京时间
- sprintf_s(buf, nBufSize,"%d/%d/%d->", tp.tm_year + 1900, tp.tm_mon + 1, tp.tm_mday);
- sprintf_s(buf, nBufSize,"%s%d:%d:%d\n",buf,tp.tm_hour, tp.tm_min, tp.tm_sec);
- return buf;
- }
- int 定位所有基址并输入到文件()
- {
- { const char strline0[] = "\r\n#pragma once\r\n";
- printf(strline0);
- WriteToFile(strline0);
- }
- {
- char sz特征码[] = "488D8FE0020000488B01FF5030"; //+0x1F
- CFind_Offset::MatchSearch("CALL02_OFFSET_取任务对象", sz特征码, 0x1F, 5, 1);
- CFind_Offset::MatchSearch("CALL01_RCX_OFFSET_取任务对象", sz特征码, 0x12, 5, 1);
- }
- //return 1;
- {
- char sz特征码[] = "41B888130000488D542430488B4808";
- {
- char sz变量名[] = "CALL_OFFSET_明文包";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x0F, 5, 1);
- }
- {
- char sz变量名[] = "CALL_RCX_OFFSET_明文包";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -0x7, 7, 3);
- }
- }
- //CALL_OFFSET_背包物品使用
- {
- char sz特征码[] = "440FB68710030000488B93B0000000488BCBE8"; // +0x12
- char sz变量名[] = "CALL_OFFSET_背包物品使用";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x12, 5, 1);
- }
- {
- char sz特征码[] = "488BC8450FB6CD41B801000000488BD3E8"; // +0x10
- char sz变量名[] = "CALL_OFFSET_使用背包物品01";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x10, 5, 1);
- }
- {
- char sz特征码[] = "488BC8450FB6CD41B801000000488BD3E8"; // -0x05
- char sz变量名[] = "CALL_RCX_OFFSET_使用背包物品01";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -0x05, 5, 1);
- }
- //CALL_OFFSET_选怪
- {
- char sz特征码[] = "0F28B424F0000000488B8338030000"; //-5
- char sz变量名[] = "CALL_OFFSET_选怪CALL01";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -0x05, 5, 1);
- }
- {
- char sz特征码[] = "0F28B424F0000000488B8338030000"; //-0x10
- char sz变量名[] = "CALL_OFFSET_选怪CALL02";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -0x10, 5, 1);
- }
- //CALL_OFFSET_取控件对象
- {
- char sz特征码[] = "4C8B4310488BD7488BC8488B5C24304883C4205F49FFE0"; //-0x05
- char sz变量名[] = "CALL_OFFSET_取控件对象";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -0x05, 5, 1);
- }
- //CALL_OFFSET_寻路
- {
- char sz特征码[] = "C6442428028944242CF20F10833C060000"; //+0x3C
- char sz变量名[] = "CALL_OFFSET_寻路";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x3C, 5, 1);
- }
- //CALL_OFFSET_按键
- {
- char sz特征码[] = "33C04889BEF00100004889BEF8010000898611010000";
- char sz变量名[] = "CALL_OFFSET_按键";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x30, 7, 3);
- }
- //CALL_OFFSET_采集
- {
- char sz特征码[] = "4488642428C7442420000000004533C941B001"; //-8
- char sz变量名[] = "CALL_OFFSET01_采集";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -8, 5, 1);
- } {
- char sz特征码[] = "4488642428C7442420000000004533C941B001"; //+0x16
- char sz变量名[] = "CALL_OFFSET02_采集";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x16, 5, 1);
- }
- //OFFSET_怪物人物采集物对象ID数组
- {
- char sz特征码[] = "32C04D85C07408410FB68080060000"; // -0x07
- char sz变量名[] = "OFFSET_怪物人物采集物对象ID数组";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -7, 7, 3);
- }
- //OFFSET_所有对象数组
- {
- char sz特征码[] = "33C08B4008C1E81DA8010F85"; // -0x17
- char sz变量名[] = "OFFSET_所有对象数组";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -0x17, 7, 3);
- }
- //OFFSET_人物属性对象A
- {
- char sz特征码[] = "488B01FF50283D5E240000"; //+11
- char sz变量名[] = "OFFSET_人物属性对象A";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0x11, 7, 3);
- }
- //OFFSET_人物角色坐标基址
- {
- char sz特征码[] = " 48 8B 05 ********48 85 C0 74 **80 B8 88 03 00 00 0D "; //+9
- char sz变量名[] = "OFFSET_人物角色坐标基址";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, 0, 7, 3);
- }
- {
- char sz特征码[] = "488D3CD04885FF0F84A5"; //-07
- char sz变量名[] = "OFFSET_NPC_ID_LIST";
- CFind_Offset::MatchSearch(sz变量名, sz特征码, -7, 7, 3);
- }
-
- {
- const char strline0[] = "//>>完成所有遍历-->>OK %t\r\n";
- printf(strline0);
- WriteToFile(strline0);
- char buf[256];
- GetBjTime(buf, sizeof(buf));
- CFind_Offset::printfCmdAndFile(buf);
- }
- return 1;
- }
复制代码
//main.cpp
- // FindBaseOffset.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
- //
- #include <time.h>
- #include <iostream>
- #include "CFind_Offset.h"
- #include "HexStrToBytes.h"
- char* GetBjTime(IN OUT char*buf, size_t nBufSize);
- void 测试带通配符的特征转换()
- {
- {
- char s1[] = "0x11,0x22,0x33,0x44,0x55,0xFF,0x1A,0x1b,0x1c,0x330x66"; //11223355667788AAXX88
- char s2[] = "ABCD112233**55??66";
- BYTE b1[256];
- BYTE b2[256];
- BYTE star1[256] = { 0 };
- BYTE star2[256] = { 0 };
- size_t nsize1 = HexStrToBytesEx(s1, b1, sizeof(b1), star1);
- size_t nsize2 = HexStrToBytesEx(s2, b2, sizeof(b2), star2);
- printf("nsize1=%zd,nsize2=%zd\r\n", nsize1, nsize2);
- getchar();
- }
- {
- char s1[] = "48 8B 15ZZ**??**FF 90 48080000 48 83 BF C8040000 00"; //11223355667788AAXX88
- char s2[] = "48 89 05**??****BE 3F000000 80 78 08 000F84";
- BYTE b1[256];
- BYTE b2[256];
- BYTE star1[256] = { 0 };
- BYTE star2[256] = { 0 };
- size_t nsize1 = HexStrToBytesEx(s1, b1, sizeof(b1), star1);
- size_t nsize2 = HexStrToBytesEx(s2, b2, sizeof(b2), star2);
- printf("nsize1=%zd,nsize2=%zd\r\n", nsize1, nsize2);
- getchar();
- }
- }
- void OFFSET_所有对象数组();
- void OFFSET_所有对象数组02();
- int 定位所有基址并输入到文件();
- int main()
- {
- 定位所有基址并输入到文件();
-
- getchar();
- }
复制代码
|
游戏安全课程 学员办理咨询联系QQ150330575 手机 139 9636 2600 免费课程 在 www.bilibili.com 搜 郁金香灬老师
|
|