龙马谷

 找回密码
 立即注册

QQ登录

只需一步,快速开始

龙马谷VIP会员办理客服QQ:82926983(如果临时会话没有收到回复,请先加QQ好友再发。)
1 [已完结] GG修改器新手入门与实战教程 31课 2 [已完结] GG修改器美化修改教程 6课 3 [已完结] GG修改器Lua脚本新手入门教程 12课
4 [已完结] 触动精灵脚本新手入门必学教程 22课 5 [已完结] 手游自动化脚本入门实战教程 9课 6 [已完结] C++射击游戏方框骨骼透视与自瞄教程 27课
7 [已完结] C++零基础UE4逆向开发FPS透视自瞄教程 29课 8 [已完结] C++零基础大漠模拟器手游自动化辅助教程 22课 9 [已完结] C++零基础开发DXF内存脚本辅助教程 32课
以下是天马阁VIP教程,本站与天马阁合作,赞助VIP可以获得天马阁对应VIP会员,名额有限! 点击进入天马阁论坛
1 [已完结] x64CE与x64dbg入门基础教程 7课 2 [已完结] x64汇编语言基础教程 16课 3 [已完结] x64辅助入门基础教程 9课
4 [已完结] C++x64内存辅助实战技术教程 149课 5 [已完结] C++x64内存检测与过检测技术教程 10课 6 [已完结] C+x64二叉树分析遍历与LUA自动登陆教程 19课
7 [已完结] C++BT功能原理与x64实战教程 29课 8 [已完结] C+FPS框透视与自瞄x64实现原理及防护思路
查看: 5915|回复: 0

Sunday算法特征码搜索C++ 支持通配符

[复制链接]

11

主题

16

回帖

30

积分

编程入门

Rank: 1

龙马币
32
小子不忘记 | 显示全部楼层 |阅读模式

感谢论坛sunday算法和特征码搜索的参考,在原来基础上增加功能进行了少许的修改。

  1. DWORD aobScan(HANDLE hProcess, HMODULE hModule, string 特征码,int CallOffset=0,DWORD* outCallAddre=0,int BaseAddreOffset=0, DWORD* outBaseAddr=0)
  2.         {//进程PID,模块句柄,特征码,CallOffset:找call偏移-上负下正,BaseAddreOffset:找基址偏移;偏移是从特征码地址算起
  3.                 string tzm = DeletStringPace(特征码);//删除特征码所有空格
  4.                 int tzmLen = tzm.length() / 2;//特征码长度
  5.                 if (tzm.length() % 2 != 0)/*特征码长度不能为单数*/ return 0;
  6.                 byte* tzmByte = new byte[tzmLen];//定义一个字节变量并开辟指定长度的内存空间
  7.                 int 通配符首次位置 = StringToByte(tzm, tzmByte);

  8.                 MODULEINFO mMoudleInfo;
  9.                 GetModuleInformation(hProcess, hModule, &mMoudleInfo, sizeof(mMoudleInfo));
  10.                 DWORD  ModuleBeginAddr = (DWORD)hModule;//模块开始地址
  11.                 DWORD  ModuleSize =mMoudleInfo.SizeOfImage;//模块大小
  12.                 DWORD  ModuleEndAddr = ModuleBeginAddr + ModuleSize;//模块结束地址

  13.                 BYTE *pMemBuffer = NULL;//存放读取的内存数据的缓冲区               
  14.                 MEMORY_BASIC_INFORMATION mbi;//内存信息
  15.                 clock_t nBeginTime = clock();//记录起始搜索时间

  16.                 while (ModuleBeginAddr < ModuleEndAddr)//结束条件
  17.                 {//开始扫描内存
  18.                         memset(&mbi, 0, sizeof(MEMORY_BASIC_INFORMATION));//查询地址空间中内存地址的信息
  19.                         if (VirtualQueryEx(hProcess, (LPCVOID)ModuleBeginAddr, &mbi, sizeof(mbi)) == 0)break;;
  20.                        
  21.                         if (MEM_COMMIT == mbi.State && PAGE_READWRITE == mbi.Protect || PAGE_EXECUTE_READWRITE == mbi.Protect)
  22.                         {//过滤内存空间, 根据内存的状态和保护属性进行过滤
  23.                                 if (pMemBuffer) {// 申请动态内存
  24.                                         delete[] pMemBuffer; pMemBuffer = NULL;
  25.                                 }
  26.                                 pMemBuffer = new BYTE[mbi.RegionSize];
  27.                                 if (!ReadProcessMemory(hProcess, (LPCVOID)ModuleBeginAddr, pMemBuffer, mbi.RegionSize, 0))continue;
  28.                                 UINT deviation = SundayCmp(pMemBuffer, mbi.RegionSize, tzmByte, tzmLen, 通配符首次位置);
  29.                                 if (-1 != deviation)//deviation是偏移
  30.                                 {//-1为没有找到
  31.                                         clock_t nEndTime = clock();//记录结束时间
  32.                                         printf(" %x  用时:%d 毫秒\r\n", ModuleBeginAddr + deviation, nEndTime - nBeginTime);
  33.                                         if (0!=CallOffset)
  34.                                         {//如果是找call
  35.                                                 DWORD temp;
  36.                                                 memcpy(&temp, &pMemBuffer[deviation  + CallOffset + 1], 4);//拷贝出对应地址上的机器码,复制4个字节
  37.                                                 printf(" 返回call: %X  用时:%d 毫秒\r\n", ModuleBeginAddr + deviation+ CallOffset + temp +5, nEndTime - nBeginTime);
  38.                                                 *outCallAddre= ModuleBeginAddr + deviation + CallOffset + temp +5;//下一条指令地址(也就是目标地址 + 5)
  39.                                         }
  40.                                         if (0!=BaseAddreOffset)
  41.                                         {//如果是找基址
  42.                                                 DWORD temp;
  43.                                                 memcpy(outBaseAddr, &pMemBuffer[deviation + BaseAddreOffset], 4);//拷贝出对应地址上的机器码,复制4个字节
  44.                                                 printf(" 返回基址: %X \r\n", outBaseAddr);//
  45.                                         }
  46.                                         return ModuleBeginAddr + deviation;//返回特征码地址
  47.                                 }
  48.                         }
  49.                         ModuleBeginAddr += mbi.RegionSize; //取下一块内存地址
  50.                 }
  51.                 return -1;//没找到返回
  52.         }


  53. int StringToByte(string &markCode,byte* pMarkCode)
  54.         {//带通配符的string字符串转byte字节数组
  55.                 int markCodeLen = markCode.length() / 2;
  56.                 int 通配符第1次出现的位置 = 0;
  57.                 //pMarkCode = new BYTE[markCodeLen];
  58.                 for (int i = 0; i < markCodeLen; i++)
  59.                 {
  60.                         string tempStr = markCode.substr(i * 2, 2);
  61.                         if (tempStr == "??")
  62.                         {
  63.                                 pMarkCode[i] = 0x3F;
  64.                                 if (通配符第1次出现的位置 == 0) 通配符第1次出现的位置 = i;
  65.                         }
  66.                         else {
  67.                                 pMarkCode[i] = strtoul(tempStr.c_str(), 0, 16);
  68.                         }
  69.                 }
  70.                 return 通配符第1次出现的位置;
  71.         }



  72. int SundayCmp(byte* dest, int destLen, byte* pattern, int patternLen, int 通配符第1次出现的位置)
  73.         {
  74.                 int nOffset = 0;//偏移量
  75.                 int i = 0, j = 0, nCount = 0;//数组下标:内存、特征码、返回地址

  76.                 int Shift[0xFF + 1] = { 0 };//Sunday算法模板数组赋值,+1防止特征码出现FF时越界
  77.                 for (int i = 0; i < 通配符第1次出现的位置; i++) {
  78.                         Shift[pattern[i]] = i + 1;
  79.                 }

  80.                 while (j < patternLen)
  81.                 {//以特征码长度进行循环
  82.                         if (dest[i] == pattern[j] || pattern[j] == 0x3F)//0x3F代表通配符
  83.                         {//如果相等
  84.                                 i++; j++;
  85.                         }
  86.                         else
  87.                         {
  88.                                 nOffset = i - j + 通配符第1次出现的位置;
  89.                                 if (nOffset > destLen - patternLen)/*判断偏移量是否大于缓冲区*/ break;
  90.                                 if (Shift[dest[nOffset]])
  91.                                 {//判断 Shift模板数组 里有没有 内存偏移后的值,有则回溯,否则+1
  92.                                         i = nOffset - Shift[dest[nOffset]] + 1;
  93.                                         j = 0;
  94.                                 }
  95.                                 else
  96.                                 {
  97.                                         i = nOffset + 1;
  98.                                         j = 0;
  99.                                 }
  100.                         }
  101.                 }
  102.                 if (j == patternLen)
  103.                 {//计算找到的目标地址://特征码地址 = 当前内存块基址 + i偏移 - 特征码长度
  104.                         return  i - patternLen;
  105.                 }
  106.                 return -1;
  107.         }
复制代码

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

龙马谷| C/C++辅助教程| 安卓逆向安全| 论坛导航| 免责申明|Archiver|
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表龙马谷立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2018-2021 All Right Reserved.
在线客服
快速回复 返回顶部 返回列表