DanielCohen197/Conex
GitHub: DanielCohen197/Conex
一个 C++ 单头文件库,通过自定义 lambda 条件实现语义化的二进制数据模式匹配与搜索。
Stars: 2 | Forks: 0
# Conex
一个基于条件的二进制模式匹配 C++ 单头文件库。
Conex 允许你使用类似正则表达式的模式语法搜索二进制数据,其中每个分组由一个条件定义——即一个检查原始字节并返回 true 或 false 的 lambda。
```
auto result = conex::search_first(blob, "(c0:4)(c1:8)",
[](std::span s) { /* signature check */ },
[](std::span s) { /* address check */ }
);
```
## 环境要求
- C++17 或更高版本
- 除标准库外无其他依赖
## 安装说明
将 `conex.hpp` 复制到你的项目中并包含它。
```
#include "conex.hpp"
```
## 模式语法
模式是一系列分组:
```
(cN:W)Q
```
| 部分 | 含义 |
|------|---------|
| `N` | 要使用的 lambda 索引(从 0 开始,与你的可变参数对应) |
| `:W` | 每次匹配消耗的字节宽度(默认值:1) |
| `Q` | 量词:`*` 零次或多次,`+` 一次或多次,`?` 零次或一次,无 = 恰好一次 |
### 示例
| 模式 | 含义 |
|---------|---------|
| `(c0:4)` | 恰好 4 个满足 lambda 0 的字节 |
| `(c0:4)(c1:8)` | 4 个满足 c0 的字节,紧接着 8 个满足 c1 的字节 |
| `(c0:4)*` | 零个或多个满足 c0 的 4 字节序列 |
| `(c0:4)+(c1:2)` | 一个或多个 4 字节序列,然后恰好 2 个字节 |
| `(c0:8)(c0:8)(c1:4)*(c2:2)(c3:8)` | 两个 8 字节地址,任意数量的 4 字节记录,两个字节,八个字节 |
## API
### `conex::search_first`
扫描数据块并返回第一个匹配项。
```
conex::MatchResult conex::search_first(
std::span blob,
std::string_view pattern,
Conds&&... conditions
);
```
### `conex::search_all`
返回所有不重叠的匹配项。
```
std::vector conex::search_all(
std::span blob,
std::string_view pattern,
Conds&&... conditions
);
```
### `conex::match`
尝试在给定 span 的起始位置进行匹配。要在特定偏移量处匹配,请传递 `blob.subspan(offset)`。
```
conex::MatchResult conex::match(
std::span blob,
std::string_view pattern,
Conds&&... conditions
);
```
## 匹配结果
```
struct MatchResult {
bool matched;
size_t start; // byte offset where match begins
size_t end; // byte offset after match ends
std::vector> captures; // captures[group][repetition]
};
struct Capture {
size_t offset; // byte offset in original blob
std::span bytes; // the matched bytes
};
```
`captures[i]` 包含由分组 `i` 匹配到的每次重复。对于非重复分组,它将始终只有一个条目(如果匹配成功)。
## 示例
通过签名和页对齐的地址成员在二进制数据块中查找结构体:
```
#include "conex.hpp"
bool is_page_aligned_address(std::span bytes) {
uint64_t addr;
std::memcpy(&addr, bytes.data(), 8);
return (addr & 0xFFF) == 0; // page-aligned
}
auto result = conex::search_first(
std::span(blob),
"(c0:4)(c1:8)",
// c0: match the struct signature
[](std::span s) {
uint32_t sig;
std::memcpy(&sig, s.data(), 4);
return sig == 0xDEADBEEF;
},
// c1: match page aligned address condition
[](std::span s) {
return is_page_aligned_address(s);
}
);
if (result) {
auto* s = reinterpret_cast(blob.data() + result.start);
}
```
在特定偏移量处匹配:
```
auto result = conex::match(std::span(blob).subspan(offset, 4), "(c0:4)", my_lambda);
```
遍历重复分组中捕获的记录:
```
auto result = conex::search_first(blob, "(c0:8)(c1:4)*(c2:2)", c0, c1, c2);
for (auto& capture : result.captures[1]) { // group 1 = (c1:4)*
uint32_t val;
std::memcpy(&val, capture.bytes.data(), 4);
printf("record at offset %zu: 0x%08X\n", capture.offset, val);
}
```
更多示例,请查看示例文件。
标签:C++, C++17, DAST, DNS 反向解析, Header-Only, HTTP头分析, IP 地址批量处理, URL发现, 二进制数据, 云安全监控, 云资产清单, 内存扫描, 单头文件库, 字节流解析, 安全工具开发, 安全检测, 恶意软件分析, 数据擦除, 数据结构, 无第三方依赖, 条件匹配, 模式匹配, 正则表达式风格, 特征码搜索, 签名匹配, 网络信息收集, 自动化资产收集, 逆向工程, 静态分析