#ifndef __SCANOPCODE_H__
#define __SCANOPCODE_H__
#include <cstdio>
#include <cstdlib>
using namespace std;
#include <windows.h>
union Mem
{
DWORD date32;
WORD date16[2];
BYTE data8[4];
};
/************************************************************************/
/* 函数说明:查找特征码
/* process: 要查找的进程
/* markCode: 特征码字符串,不能有空格
/* distinct:特征码首地址离目标地址的距离 负数在特征码在上
/* offset: 返回目标地址
/* size: 设置返回数据为几个BYTE 1 2 3 4
/* ordinal: 特征码出现的次数
/* beginAddr: 开始搜索地址
/* endAddr: 结束地址
/* ret:返回目标地址的内容
/************************************************************************/
DWORD ScanOpcode(HANDLE process, const char *markCode,
int distinct,
LPDWORD offset = NULL,
DWORD size = 4,
DWORD ordinal = 1,
DWORD beginAddr = 0x00400000, DWORD endAddr = 0x7FFFFFFF)
{
//每次读取游戏内存数目的大小
const DWORD pageSize = 4096;
////////////////////////处理特征码/////////////////////
//特征码长度不能为单数
if (strlen(markCode) % 2 != 0) return 0;
//特征码长度
int len = strlen(markCode) / 2;
//将特征码转换成byte型
BYTE *m_code = new BYTE[len];
for (int i = 0; i < len; i++){
char c[] = {markCode[i*2], markCode[i*2+1], '\0'};
m_code[i] = (BYTE)::strtol(c, NULL, 16);
}
/////////////////////////查找特征码/////////////////////
BOOL _break = FALSE;
//用来保存在第几页中的第几个找到的特征码
int curPage = 0;
int curIndex = 0;
//每页读取4096个字节
BYTE *page = new BYTE[pageSize+len-1];
DWORD tmpAddr = beginAddr;
DWORD ord = 0;
while (tmpAddr <= endAddr - len){
::ReadProcessMemory(process, (LPCVOID)tmpAddr, page, pageSize+len-1, 0);
//在该页中查找特征码
for (int i = 0; i < pageSize; i++){
for (int j = 0; j < len; j++){
//只要有一个与特征码对应不上则退出循环
if (m_code[j] != page[i + j])break;
//找到退出所有循环
if (j == len - 1){
ord++;
if(ord != ordinal)
break;
_break = TRUE;
curIndex = i; // 特征码的首地址偏移
break;
}
}
if (_break) break;
}
if (_break) break;
curPage++;
tmpAddr += pageSize;
}
// 一个也没找到
if(tmpAddr > endAddr - len)
return 0;
// 生成目标地址
DWORD offsetaddr = curPage * pageSize + curIndex + beginAddr + distinct;
if(offset != NULL){
*offset = offsetaddr;
}
// 返回地址内容
DWORD base;
::ReadProcessMemory(process, (LPVOID)offsetaddr, &base, 4, 0);
delete m_code;
delete page;
return base & 0xFFFFFFFF>>(4-size)*8;
}
// 查找内存地址
DWORD ScanAddr(HANDLE process, const char *markCode,
int distinct,
DWORD size = 4,
DWORD ordinal = 1,
DWORD beginAddr = 0x00400000, DWORD endAddr = 0x7FFFFFFF)
{
DWORD addr = NULL;
ScanOpcode(process, markCode, distinct, &addr, size, ordinal, beginAddr, endAddr);
return addr;
}
// 查找立即数
DWORD ScanImme(HANDLE process, const char *markCode,
int distinct,
DWORD size = 4,
DWORD ordinal = 1,
DWORD beginAddr = 0x00400000, DWORD endAddr = 0x7FFFFFFF)
{
return ScanOpcode(process, markCode, distinct, NULL, size, ordinal, beginAddr, endAddr);
}
// 查找地址call
DWORD ScanCall(HANDLE process, const char *markCode,
int distinct,
DWORD size = 4,
DWORD ordinal = 1,
DWORD beginAddr = 0x00400000, DWORD endAddr = 0x7FFFFFFF)
{
DWORD addr = NULL;
DWORD cont = ScanOpcode(process, markCode, distinct, &addr, size, ordinal, beginAddr, endAddr);
return addr - 1 + 5 + cont;
}
/*
汇编实例:
模块 - Game
005FC930 /$ 55 push ebp
005FC931 |. 8BEC mov ebp,esp
005FC933 |. 51 push ecx
005FC934 |. 56 push esi
005FC935 |. 8BF1 mov esi,ecx
005FC937 |. 8D86 EC000000 lea eax,dword ptr ds:[esi+0xEC]
005FC93D |. 50 push eax
005FC93E |. 8D4E 34 lea ecx,dword ptr ds:[esi+0x34]
005FC941 |. E8 AAC20600 call Game.00668BF0
005FC946 |. 50 push eax
005FC947 |. E8 A6F51600 call Game.0076BEF2
005FC94C |. 85C0 test eax,eax
005FC94E |. 74 6D je XGame.005FC9BD
005FC950 |. 83BE 3C040000 01 cmp dword ptr ds:[esi+0x43C],0x1
005FC957 |. 75 2B jnz XGame.005FC984
005FC959 |. 8B0D 4CF72501 mov ecx,dword ptr ds:[0x125F74C]
005FC95F |. 8B41 30 mov eax,dword ptr ds:[ecx+0x30]
005FC962 |. 8B96 44040000 mov edx,dword ptr ds:[esi+0x444]
005FC968 |. 50 push eax
假设特征码是绿色框部分
005FC933 |. 51 push ecx
005FC934 |. 56 push esi
005FC935 |. 8BF1 mov esi,ecx
005FC937 |. 8D86 EC000000 lea eax,dword ptr ds:[esi+0xEC]
005FC93D |. 50 push eax
005FC93E |. 8D4E 34 lea ecx,dword ptr ds:[esi+0x34]
char* opcode="51568BF18D86EC000000508D4E34" // 第二列连起来
要查找红色框内容:
005FC930 /$ 55 push ebp
即一个内存地址,也是函数的首地址,所以使用ScanAddr
先计算出目标到opcode首地址的偏移
005FC933 - 005FC930 = 0x3 因为目标是在opcode上面 所以是-0x3
调用 ScanAddr(process, opcode, -0x3); 就能获得
要查找黄色框内容:
005FC947 |. E8 A6F51600 call Game.0076BEF2
即一个调用call,使用ScanCall
同样要计算出目标地址到opcode的首地址偏移
首先这里目标0076BEF2的地址为 005FC947+1 因为call指令也占用了一个字节的内存
所以偏移 = 005FC948 - 005FC933 = 0x15 因为目标在opcode下面 所以是正的
(这里谁减谁不重要,主要看目标是在opcode之上还是下)
调用 ScanCall(process, opcode, 0x15)
要查找蓝色框的内容:
005FC959 |. 8B0D 4CF72501 mov ecx,dword ptr ds:[0x125F74C]
即一个立即数,也是一个基址,使用ScanImme
计算目标地址:005FC959 + 2 = 005FC95B
计算偏移:005FC95B - 005FC933 = 0x28 正值
调用 ScanImme(process, opcode, 0x28)
一般情况下使用前面3个参数就可以了
使用后面参数的情况:
size:
如果想查找白色框的内容0x1
005FC950 |. 83BE 3C040000 01 cmp dword ptr ds:[esi+0x43C],0x1
要设置 size=1 因为他在内存只占了一个字节
ordinal:
在你确定一个特征码时
使用Ctrl+s,Ctrl+l在OD中搜索这个特征码,假设他是第3次出现才是正确的位置
设置 ordinal=3
beginAddr,endAddr:
如果模块Game是一个dll,而你想从这个dll的基址开始搜索
设置 beginAddr = GetModuleHandle('Game')
当然也可以给他俩赋值任何可读地址
ordinal和beginAddr可以配合使用
*/
#endif // __SCANOPCODE_H__
没有合适的资源?快使用搜索试试~ 我知道了~
特征码搜索基址 c/c++源代码
共2个文件
mhtml:1个
h:1个
4星 · 超过85%的资源 需积分: 44 168 下载量 174 浏览量
2013-01-08
01:15:26
上传
评论 2
收藏 1.7MB ZIP 举报
温馨提示
游戏特征码搜索基址 c/c++源代码 有图有解释,拿来即可用 本人亲测,可用 代码来源于互联网:)
资源推荐
资源详情
资源评论
收起资源包目录
特征码搜索基址 源代码.zip (2个子文件)
特征码搜索基址 源代码
c++特征码搜索函数.mhtml 2.56MB
scan.h 6KB
共 2 条
- 1
gogogo8008
- 粉丝: 2
- 资源: 16
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页