6.1 KMP算法搜索机器码

水军大提督  金牌会员 | 2023-9-27 08:12:55 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 896|帖子 896|积分 2688

KMP算法是一种高效的字符串匹配算法,它的核心思想是利用已经匹配成功的子串前缀的信息,避免重复匹配,从而达到提高匹配效率的目的。KMP算法的核心是构建模式串的前缀数组Next,Next数组的意义是:当模式串中的某个字符与主串中的某个字符失配时,Next数组记录了模式串中应该回退到哪个位置,以便继续匹配。Next数组的计算方法是找出模式串每一个前缀中最长的相等前缀和后缀,并记录下来它们的长度,作为Next数组中的对应值。
在字符串匹配时,KMP算法从主串和模式串的开头开始逐个字符比较,若发现匹配失败,则根据Next数组中的值进行回退,从失配位置的下一位重新开始比较。这样回退的次数比暴力匹配方式要少得多,因此匹配效率得到了大幅提升。
6.1.1 遍历输出进程内存

首先需要实现取进程PID的功能,当用户传入一个进程名称时则输出该进程的PID号,通过封装GetPidByName函数,该函数用于根据指定的进程名称,获取该进程的进程PID,以便于后续针对进程进行操作。函数参数name为指定的进程名称字符串。该函数通过调用CreateToolhelp32Snapshot函数创建一个系统快照,返回系统中所有进程的快照句柄。然后使用该快照句柄,通过进程快照函数Process32First和Process32Next函数逐个对比进程的名称,找到进程名称匹配的PID,返回该PID。若无法找到匹配的进程名称,则返回0。读者需要注意,当使用进程遍历功能时通常需要引入库作为支持;
  1. // 根据进程名得到进程PID
  2. DWORD GetPidByName(const char* name)
  3. {
  4.     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  5.     PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
  6.     DWORD pid = 0;
  7.     if (Process32First(snapshot, &pe32))
  8.     {
  9.         do
  10.         {
  11.             if (_stricmp(pe32.szExeFile, name) == 0)
  12.             {
  13.                 pid = pe32.th32ProcessID;
  14.                 break;
  15.             }
  16.         } while (Process32Next(snapshot, &pe32));
  17.     }
  18.     CloseHandle(snapshot);
  19.     return pid;
  20. }
复制代码
在开始使用KMP枚举特征码之前我们需要实现简单的内存读写功能,通过封装一个MemoryTraversal函数,该函数接收三个参数分别是,进程PID,进程开始内存地址,以及进程结束内存地址,该函数输出当前进程内存机器码,每次读入4096字节,然后每16个字符换一次行,遍历内存0x00401000 - 0x7FFFFFFF这篇内存区域,这段代码实现如下所示;
[code]// 遍历并输出进程内存VOID MemoryTraversal(DWORD PID, const DWORD beginAddr, const DWORD endAddr){    const DWORD pageSize = 4096;    // 打开并获取进程句柄    HANDLE process = ::OpenProcess(PROCESS_ALL_ACCESS, false, PID);    BOOL _break = FALSE;    BYTE page[pageSize];    DWORD tmpAddr = beginAddr;    // 循环枚举进程    while (tmpAddr = 0 && ch
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!

标签云

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