应使用 std::search 进行二进制特征码匹配,配合 std::vector 存储特征码与目标数据,以 std::ios::binary 模式读写文件,修改内存前须正确设置页保护权限。

用 std::search 做二进制特征码匹配,别手写 KMP
直接用标准库的 std::search 最省事,它底层是优化过的搜索(通常为 Boyer-Moore 变种),对短特征码(几字节到几十字节)比手写循环快且安全。自己遍历比对容易漏掉边界、搞错有符号/无符号比较。
- 特征码必须是
std::vector<:byte></:byte>或std::array<:byte n></:byte>,不能用char*—— 否则遇到\xFF在有符号 char 平台上会变成 -1,和0xFF不等 - 目标数据也得是
std::vector<:byte></:byte>,读文件时用std::ios::binary打开,否则 Windows 下会把\r\n换成\n,破坏原始字节 - 匹配结果返回的是迭代器,不是偏移量,要算位置得用
std::distance(data.begin(), it)
替换前先验证内存可写,否则 memcpy 会崩
在 PE 文件或已加载模块里改字节,不检查页属性就直接写,大概率触发 ACCESS_VIOLATION。Windows 要调 VirtualProtect,Linux/macOS 用 mprotect,改完还得恢复原保护。
- PE 文件本地修改:用
std::fstream以std::ios::in | std::ios::out | std::ios::binary打开,定位到 offset 后直接write(),不用管内存保护 - 运行中 patch 进程内存:必须先
VirtualQuery查当前页权限,再用VirtualProtect设为PAGE_READWRITE,操作完立刻设回原值 - 别用
memcpy往只读段写 —— 它不会报错,但下一次访问该地址就崩,调试器里看到的是EXCEPTION_ACCESS_VIOLATION
std::byte 是唯一安全的二进制容器类型
用 unsigned char 看似能存 0–255,但它在某些编译器(如 MSVC 默认)是 signed,0xFF == -1,导致特征码 {0xFF, 0x00} 永远匹配不上 {0xFF, 0x00} —— 因为 -1 != 255。
- 声明特征码:用
std::vector<:byte>{std::byte{0xFF}, std::byte{0x90}}</:byte>,别用{0xFF, 0x90}初始化std::vector<uint8_t></uint8_t> - 读文件到内存:用
std::vector<:byte>(size)</:byte>分配,再用file.read(reinterpret_cast<char>(buf.data()), size)</char>——reinterpret_cast是必须的,因为read()只认char* - 打印调试时,强制转
uint32_t:static_cast<uint32_t>(b)</uint32_t>,否则std::cout 可能输出乱码或负数
特征码含通配符?自己写匹配逻辑绕不开
std::search 不支持 ?? 这类通配,真要支持就得手动扫。核心就一条:跳过值为 0xFF(或其他约定值)的位置,其余严格相等。
- 定义通配惯例:比如用
std::byte{0xFF}表示“任意字节”,匹配时遇到它直接continue - 不要在循环里反复调
std::search模拟通配 —— 效率极低,而且无法表达“第3字节任意,其余固定”这种结构 - 简单做法:写个
bool matches_pattern(const std::vector<:byte>& data, size_t pos, const std::vector<:byte>& pattern)</:byte></:byte>,内部逐字节比对,遇到0xFF就跳过
std::byte 当 char 直接 cout —— 这俩问题一出现,特征码看起来“明明一样却搜不到”,查半天才发现是类型隐式转换在捣鬼。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











