jtwc 发表于 2022-4-22 14:46

各位老师,C++用特征码读取内存地址(支持通配符“??”),速度太慢咋优化?

本帖最后由 jtwc 于 2022-4-22 14:51 编辑

各位老师,网上找了一个C++用特征码读取内存地址(支持通配符“??”)的源码,经过“HULANG-BTB”老师修改后完美解决了报错问题。但3-5分钟才读出一个地址,速度太慢咋优化?哪位老师有兴趣用算法优化一下?谢谢了。修改后源码如下:#include <Windows.h>
#include <iostream>
#include <vector>
#include <time.h>

using namespace std;

#define BLOCKMAXSIZE 409600//每次读取内存的最大大小
BYTE* MemoryData;//每次将读取的内存读入这里
short Next;

bool isHexCharacter(char c) {
    return (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9');
}

// 十六进制转10进制
// 1 2 3 4 5 6 7 8 9 A B C D E F
WORD hexToWord(char c) {
    if (c >= '0' && c <= '9') {
      return c - '0';
    }
    else if (c >= 'A' && c <= 'F') {
      return c - 'A' + 10;
    }
    else if (c >= 'a' && c<= 'f') {
      return c - 'a' + 10;
    }
    return -1;
};

// 十六进制转10进制
WORD hexToWord(char c1, char c2) {
    if (isHexCharacter(c1) && isHexCharacter(c2))
      return hexToWord(c1) * 16 + hexToWord(c2);
    return 256;
}

// 特征码转字节集
WORD GetTzmArray(char* Tzm, vector<WORD> & TzmArray)
{
    int TzmLength = strlen(Tzm);
    for (int i = 0; i < TzmLength; i += 3) {
      TzmArray.push_back(hexToWord(Tzm, Tzm));
    }
    return TzmArray.size();
}

//获取Next数组
void GetNext(short* next, vector<WORD> TzmArray)
{
    //特征码(字节集)的每个字节的范围在0-255(0-FF)之间,256用来表示问号,到260是为了防止越界
    for (int i = 0; i < 260; i++)
      next = -1;
    for (int i = 0; i < TzmArray.size(); i++)
      next] = i;
}

//搜索一块内存
void SearchMemoryBlock(HANDLE hProcess, vector<WORD> TzmArray, unsigned __int64 StartAddress, unsigned long size, vector<unsigned __int64>& ResultArray)
{
    if (!ReadProcessMemory(hProcess, (LPCVOID)StartAddress, MemoryData, size, NULL))
    {
      return;
    }

    for (int i = 0, j, k; i < size;)
    {
      j = i; k = 0;

      for (; k < TzmArray.size() && j < size && (TzmArray == MemoryData || TzmArray == 256); k++, j++);

      if (k == TzmArray.size())
      {
            ResultArray.push_back(StartAddress + i);
      }

      if ((i + TzmArray.size()) >= size)
      {
            return;
      }

      int num = Next];
      if (num == -1)
            i += (TzmArray.size() - Next);//如果特征码有问号,就从问号处开始匹配,如果没有就i+=-1
      else
            i += (TzmArray.size() - num);
    }
}

//搜索整个程序
int SearchMemory(HANDLE hProcess, char* Tzm, unsigned __int64 StartAddress, unsigned __int64 EndAddress, int InitSize, vector<unsigned __int64>& ResultArray)
{
    int i = 0;
    unsigned long BlockSize;
    MEMORY_BASIC_INFORMATION mbi;

    vector<WORD> TzmArray;
    GetTzmArray(Tzm, TzmArray);
    GetNext(Next, TzmArray);

    //初始化结果数组
    ResultArray.clear();
    ResultArray.reserve(InitSize);

    while (VirtualQueryEx(hProcess, (LPCVOID)StartAddress, &mbi, sizeof(mbi)) != 0)
    {
      //获取可读可写和可读可写可执行的内存块
      if (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE)
      {
            i = 0;
            BlockSize = mbi.RegionSize;
            //搜索这块内存
            while (BlockSize >= BLOCKMAXSIZE)
            {
                SearchMemoryBlock(hProcess, TzmArray, StartAddress + (BLOCKMAXSIZE * i), BLOCKMAXSIZE, ResultArray);
                BlockSize -= BLOCKMAXSIZE; i++;
            }
            SearchMemoryBlock(hProcess, TzmArray, StartAddress + (BLOCKMAXSIZE * i), BlockSize, ResultArray);

      }
      StartAddress += mbi.RegionSize;

      if (EndAddress != 0 && StartAddress > EndAddress)
      {
            return ResultArray.size();
      }
    }
    return ResultArray.size();
}

int main()
{
    //初始化MemoryData大小
    MemoryData = new BYTE;

    DWORD pid = 0;
    vector<unsigned __int64> ResultArray;

    cout << "请输入进程ID:" << endl;
    cin >> pid;

    //通过进程ID获取进程句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);

    int start = clock();
    SearchMemory(hProcess, (char*)"?? ?? ?? ?? ?? ?? ?? 40 05 00 00 00 38 AF 40 FF 76 02 00 00 ", 0x410000, 0xFFFFFFFF, 30, ResultArray);
    int end = clock();

    cout << "用时:" << end - start << "毫秒" << endl;
    cout << "搜索到" << ResultArray.size() << "个结果" << endl;

    for (vector<unsigned __int64>::iterator it = ResultArray.begin(); it != ResultArray.end(); it++)
    {
      printf("%x\n", *it);
    }

    return 0;
}

JuncoJet 发表于 2022-4-22 14:53

首先确定串的长度,匹配首字符,再匹配尾字符,不对的时候就可以长跳
多看看 kmp bm sunday算法

jtwc 发表于 2022-4-22 14:55

JuncoJet 发表于 2022-4-22 14:53
首先确定串的长度,匹配首字符,再匹配尾字符,不对的时候就可以长跳
多看看 kmp bm sunday算法

老师,谢谢了,这个目前对我来说有难度

有时候是好人 发表于 2022-4-22 14:55

能看到自己的资料嘛?

jtwc 发表于 2022-4-22 15:00

有时候是好人 发表于 2022-4-22 14:55
能看到自己的资料嘛?

老师,啥意思?

HULANG-BTB 发表于 2022-4-22 15:08

1、通配符不要放在特征值的头部和尾部
2、试用kmp和sunday算法进行模式匹配

天下一家 发表于 2022-4-22 15:08

电脑再跑得 慢,也不会 3-5分钟吧,3-5秒就应该 找到1个了。

jtwc 发表于 2022-4-22 15:20

天下一家 发表于 2022-4-22 15:08
电脑再跑得 慢,也不会 3-5分钟吧,3-5秒就应该 找到1个了。

老师,真没有夸张,CE秒出,下图还是速度比较快的

小小随 发表于 2022-4-22 15:33

jtwc 发表于 2022-4-22 15:20
老师,真没有夸张,CE秒出,下图还是速度比较快的

https://www.52pojie.cn/thread-1623689-1-1.html

jtwc 发表于 2022-4-22 16:27

小小随 发表于 2022-4-22 15:33
https://www.52pojie.cn/thread-1623689-1-1.html

谢谢老师,我试试
页: [1] 2
查看完整版本: 各位老师,C++用特征码读取内存地址(支持通配符“??”),速度太慢咋优化?