我爱秘籍论坛

 找回密码
 加入论坛

QQ登录

只需一步,快速开始

扫一扫,访问微社区

CE:最优秀的游戏修改工具入门:修改器制作傻瓜教程说说:你最想要找的修改器以前游戏玩我们,现在我们玩游戏
进阶:游戏修改视频教程导航必备:超2400款游戏秘籍下载:超5000款游戏修改器必读:论坛金币获得方法
查看: 299869|回复: 41

[C/C++] C++实现的完整aobscan,速度很快

  [复制链接]
发表于 2010-10-3 02:25:56 | 显示全部楼层 |阅读模式
完整的aobscan实现,我在搜索部分使用了一个高速搜索算法。
貌似有点Bug- -,哪个高手能改正确呢?

实在看不懂的,就看main函数吧
#include <windows.h>
#include <Psapi.h>
#include <stdio.h>
#include <time.h>

/*这是一个很低效的算法*/
unsigned char *memstr(char * dst , int dst_len, char *src , int src_len )
{
   
int i;
   
char *cp = src;
   
if (src_len < dst_len)
    {
        
return NULL;
    }
   
for (i = 0; i <= src_len - dst_len; i++)
    {
        
if (memcmp(cp , dst , dst_len) == 0)
        {
            
return (unsigned char *)cp;
        }
        
cp++;
    }
   
return   NULL;
}

/*sunday算法*/
#define MAX_CHAR_SIZE 257
long
*setCharStep(const unsigned char *subStr, long subStrLen)
{
   
long i;
   
static long charStep[MAX_CHAR_SIZE];
   
for (i = 0; i < MAX_CHAR_SIZE; i++)
        
charStep[i] = subStrLen + 1;
   
for (i = 0; i < subStrLen; i++)
    {
        
charStep[(unsigned char)subStr[i]] = subStrLen - i;
    }
   
return charStep;
}
/*
   算法核心思想,从左向右匹配,遇到不匹配的看大串中匹配范围之外的右侧第一个字符在小串中的最右位置
   根据事先计算好的移动步长移动大串指针,直到匹配
*/
long sundaySearch(const unsigned char *mainStr, const unsigned char *subStr, long *charStep, long mainStrLen, int subStrLen)
{
   
long main_i = 0;
   
long sub_j = 0;
   
while (main_i < mainStrLen)
    {
        
//保存大串每次开始匹配的起始位置,便于移动指针
        
long tem = main_i;
        
while (sub_j < subStrLen)
        {
            
if (mainStr[main_i] == subStr[sub_j])
            {
               
main_i++;
               
sub_j++;
               
continue;
            }
            
else
            
{
               
//如果匹配范围外已经找不到右侧第一个字符,则匹配失败
               
if (tem + subStrLen > mainStrLen)
                    
return -1;
               
//否则 移动步长 重新匹配
               
unsigned char firstRightChar = mainStr[tem + subStrLen];
               
main_i += charStep[(unsigned char)firstRightChar];
               
sub_j = 0;
               
break;
//退出本次失败匹配 重新一轮匹配
            
}
        }
        
if (sub_j == subStrLen)
            
return main_i - subStrLen;
    }
   
return -1;
}
发表于 2015-4-23 02:04:19 | 显示全部楼层
给个建议 分级算法  比如特征码 DB  8e  9H (瞎写的)   先迅速遍历 D8  保存所有找到的B8位置 然后遍历 保存的位置里 8E  依次循环

回复 支持 反对

使用道具 举报

发表于 2016-2-14 10:18:44 | 显示全部楼层
Sunday在带通配符的匹配问题上比什么kmp快多了,核心思想就是将能跳过的步数放大,尽可能跳过多的没用的比较
回复 支持 反对

使用道具 举报

发表于 2016-2-14 10:16:10 | 显示全部楼层
我记得这是axdx(不知道名字有没有打错= =)大神写的吧,其实就是用sunday优化匹配
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-10-3 02:26:54 | 显示全部楼层
额,因为加了代码高亮,所以一次发不完。
unsigned char getHex(unsigned char hex)
{
   
if (hex >= '0' && hex <= '9') return hex - '0';
   
if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10;
   
if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10;
   
return 0;
}
int GetHexValue(char *src)
{
   
int i, j, flag;
   
static char temp[1024];
   
for (i = 0, j = 0; src[i] != 0; i++)
    {
        
if ((src[i] <= 'F' && src[i] >= 'A') || (src[i] <= 'f' && src[i] >= 'a') || (src[i] <= '9' && src[i] >= '0'))
        {
            
if (src[i] != ' ')
            {
               
temp[j++] = src[i];
            }
        }
    }
   
temp[j] = 0;
   
src[0] = 0;
   
for (i = 0, j = 0, flag = 1; temp[i] != 0; i++)
    {

        
char ch = getHex(temp[i]);
        
if (ch != -1)
        {
            
if (flag == 1) src[j] = ch << 4;
            
else src[j++] += ch;
            
flag *= -1;
        }
    }
   
src[j] = 0;
   
return j;
}
DWORD ReadPage(HANDLE m_hProcess, DWORD dwBaseAddr, char* Value)
{
   
//读取1页内存
   
BYTE arBytes[4096];
   
if (!::ReadProcessMemory(m_hProcess, (LPVOID)dwBaseAddr, arBytes, 4096, NULL))
    {
        
//此页不可读
        
return (DWORD) - 1;
    }
   
else
   
{
        
//
        //unsigned char key[] = {0x80, 0x7f, 0x49, 0x00};
        
unsigned char Value2[1024];
        
strcpy((char*)Value2, Value);
        
int len = GetHexValue((char*)Value2);
        
//getchar();
        //注释这两行是低效的算法
        //char key[] = {0x80, 0x7f, 0x49, 0x00};
        //int len = 4;
        //if (memstr(key, len, (char*)arBytes, 4096) != 0) return memstr(key, len, (char*)arBytes, 4096) - (unsigned char*)arBytes;
        //else return -1;

        //开始sunday算法
        
long *charStep = setCharStep(Value2, len);
        
return sundaySearch(arBytes, Value2, charStep, 4096, len);
    }
   
return (DWORD) - 1;   
//不会执行到此处
}
 楼主| 发表于 2010-10-3 02:27:31 | 显示全部楼层
DWORD aobscan(DWORD dwPid, char* Value)
{
   
if (dwPid == 0) return (DWORD) - 1;

   
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
   
if (hProcess != NULL)
    {
        
//获得内存大小
        
PROCESS_MEMORY_COUNTERS pmc;
        
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
        ::
GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc));

        
//遍历内存
        
for (int i = 0; i < pmc.WorkingSetSize; i += 4096)
        {
            
DWORD dwValue = ReadPage(hProcess, i, Value);
            
if (dwValue != -1)
            {
               
printf("Found:0x%X\n", i + dwValue);
               
return i + dwValue;
            }
        }
        ::
CloseHandle(hProcess);
    }
   
printf("Nothing Found!\n");
   
return (DWORD) - 1;
}
DWORD GetGameID()
{
   
HWND hwnd = FindWindow("MainWindow", NULL);
   
if (hwnd)
    {
        
DWORD dwPid;
        
GetWindowThreadProcessId(hwnd, &dwPid);
        
return dwPid;
    }
   
return 0;
}
int main()
{
   
double begin = clock();

   
aobscan(GetGameID(), "807f49 00");

   
printf("time:%.0fms", clock() - begin);
   
getchar();
}

终于发完了,我真不是故意的
发表于 2010-10-3 02:39:01 | 显示全部楼层
弱弱的问一句,论坛上的代码高亮是如何实现的
发表于 2010-10-3 08:56:35 | 显示全部楼层
看不懂

点评

同感  发表于 2012-2-24 23:11
 楼主| 发表于 2010-10-3 08:56:42 | 显示全部楼层
回复 4# logkll2193

因为我那个记事本可以把代码复制成ubb代码
发表于 2010-10-15 14:12:46 | 显示全部楼层
高亮很简单啊,比如说用网页编辑软件好像也可以的,发帖时要勾选下面的html代码。应该可以吧
发表于 2010-10-15 14:45:11 | 显示全部楼层
nice~
发表于 2010-12-11 10:58:23 | 显示全部楼层
本帖最后由 pangshidaye 于 2010-12-11 11:46 编辑

LZ用的是BMH算法吧
发表于 2010-12-16 16:16:48 | 显示全部楼层
太深奥了  俺看不懂。。
发表于 2011-2-4 23:58:38 | 显示全部楼层
有意思。
发表于 2011-2-5 13:14:27 | 显示全部楼层
支持支持!!!!
发表于 2011-2-17 16:59:46 | 显示全部楼层
我out了  竟然还有Sunday算法,查了一下还快过KMP
发表于 2011-2-17 20:06:44 | 显示全部楼层
话说对C一向头晕。
发表于 2011-5-26 13:32:48 | 显示全部楼层
顶一个阿,MS不错样
发表于 2011-5-26 16:13:38 | 显示全部楼层
aobscan函数中
PROCESS_MEMORY_COUNTERS pmc;
        pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
        ::GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc));

        //遍历内存
        for (int i = 0; i < pmc.WorkingSetSize; i += 4096)
        {
            DWORD dwValue = ReadPage(hProcess, i, Value);
            if (dwValue != -1)
            {
                printf("Found:0x%X\n", i + dwValue);
                return i + dwValue;
            }
        }

编译出错,哎,我用的VC6.0,和你的编译器不同
发表于 2011-8-30 03:58:34 | 显示全部楼层
代码能看懂,对aobscan不了解也不知道你要实现什么所以不好帮你改,感觉挺乱的,有点一半像C#一半C++,其实代码可以省略好多的。。。写那么长太费墨水了又乱看的眼睛疼。。。。
发表于 2011-8-30 04:13:05 | 显示全部楼层
还可以的说  = =
头像被屏蔽
发表于 2011-10-4 23:28:00 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
发表于 2011-10-6 01:02:13 | 显示全部楼层
不错的教程
您需要登录后才可以回帖 登录 | 加入论坛

本版积分规则

QQ|Archiver|手机版|小黑屋|我爱秘籍论坛  

GMT+8, 2019-3-23 11:23 , Processed in 0.145945 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表