scan4all 集成源码解析:simhash 算法原理及其在 httpx 指纹比对中的实战应用
2026/9/17 9:28:18 网站建设 项目流程

scan4all 集成源码解析:simhash 算法原理及其在 httpx 指纹比对中的实战应用

【免费下载链接】scan4allOfficial repository vuls Scan: 15000+PoCs; 23 kinds of application password crack; 7000+Web fingerprints; 146 protocols and 90000+ rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all

simhash(Charikar 相似哈希)是一种"相似文档产生相似指纹"的局部敏感哈希算法,其 64 位指纹间的汉明距离越小,说明两份内容越接近。scan4all 通过其内嵌的 httpx 探测模块引入了github.com/mfonda/simhash包,将其作为 JSON 输出时的默认指纹算法之一,用于对 HTTP 响应体与响应头做近似去重和内容相似度度量。读完本文,你能理解 simhash 从特征向量化到指纹生成的完整数学流程,掌握其 Go API(FeatureSet、Vectorize、Compare、Shingle)的正确用法,并能看懂 scan4all 中 simhash 指纹的实际调用链与输出位置。

一、simhash 是什么:相似文档的近似指纹

vendor/github.com/mfonda/simhash/README.md对该包的定位非常明确:它是 Charikar 论文中 simhash 算法的 Go 语言实现,其核心性质是——两份相似文档的 simhash 指纹,其汉明距离(Hamming distance)会很小

这与 MD5、SHA 等"雪崩效应"强的普通哈希形成鲜明对比:普通哈希中原文一个字符的差异就会导致摘要完全不同;而 simhash 刻意让指纹对原文的微小变化保持稳定,从而可以在海量文档中通过比较 64 位整数的位差异,快速筛出近似重复(near-duplicate)内容。README 同时指出,该包当前只实现了 simhash 算法本身,后续工作方向是利用它在大文档集合中快速识别近似重复文档——这也正是 scan4all 将其纳入 Web 探测工具链的动机:对大量站点响应做近似去重与聚类。

安装方式

README 给出的标准安装命令为:

go get github.com/mfonda/simhash

在 scan4all 中该依赖已被 vendor 进仓库(见 go.mod 中github.com/mfonda/simhash v0.0.0-20151007195837-79f94a1100d6),实现源码位于 vendor/github.com/mfonda/simhash/simhash.go,因此 scan4all 的交叉编译与离线构建无需再访问外部模块代理。

二、算法全流程:从分词到 64 位指纹

README 强调:使用 simhash 的第一步是把文档切分为特征集合(feature set),这一职责由FeatureSet接口承担;包内置了WordFeatureSet实现,按单词切分文档,README 也坦承更好的分词效果有改进空间。对照 vendor/github.com/mfonda/simhash/simhash.go 的源码,整个流程可以拆成四个环节:

  1. 特征提取与分词(Feature / FeatureSet)

    • Feature接口要求每个特征提供Sum() uint64(特征的 64 位哈希)与Weight() int(权重)。内置NewFeature用 FNV-64 计算字节序列哈希并默认权重为 1,NewFeatureWithWeight允许自定义权重(见 simhash.go 第 111-123 行)。
    • WordFeatureSet在构造时先把全文转小写(normalize),再用正则[\w']+(?:\://[\w\./]+){0,1}提取"单词 + 可选 URL"形式的特征,URL 会被完整保留为一个 token(第 166 行);另有UnicodeWordFeatureSet,配合golang.org/x/text/unicode/norm做 Unicode 正规化,用[\pL-_']+提取词元,适合非 ASCII 文本(第 179-198 行)。
  2. 向量化(Vectorize)64 维向量初始化为零;对每个特征,其 64 位哈希的第 i 位为 1 时,向量第 i 维加上该特征权重,为 0 时减去权重(第 40-55 行)。VectorizeBytes则是简化版:对一组等权[]byte特征直接用 FNV-64 计算,每步加减 1(第 63-80 行)。

  3. 指纹生成(Fingerprint)向量折叠为 64 位整数:第 i 维非负则置 1,否则置 0(第 86-94 行)。Simhash(fs FeatureSet)SimhashBytes(b [][]byte)两个便捷函数分别对应上述两条路径(第 141-148 行)。

  4. 相似度比较(Compare)Compare(a, b uint64) uint8计算两个指纹的汉明距离,源码注释说明目前采用的是 Kernighan 消最低位法(v &= v - 1循环计数),返回 0-64 的位差异数(第 131-138 行)。距离越小,文档越相似。

此外源码还提供Shingle(w, b)工具(第 213-233 行):把词元序列滑动窗口拼接成 w-gram,例如输入{"this","is","a","test"}、w=2 时得到{"this is","is a","a test"}。w-gram 让指纹对词序变化更敏感,是 README 所说的"提升切分效果"的实用抓手;w<1 会 panic,w 超过序列长度时自动收缩为序列长度。

三、README 示例的完整复现

以下是 README 给出的官方示例,完整保留其三组测试文档:两组仅一个词形差异(phrasevsphrass)的近似文本,与一组完全无关文本:

package main import ( "fmt" "github.com/mfonda/simhash" ) func main() { var docs = [][]byte{ []byte("this is a test phrase"), []byte("this is a test phrass"), []byte("foo bar"), } hashes := make([]uint64, len(docs)) for i, d := range docs { hashes[i] = simhash.Simhash(simhash.NewWordFeatureSet(d)) fmt.Printf("Simhash of %s: %x\n", d, hashes[i]) } fmt.Printf("Comparison of `%s` and `%s`: %d\n", docs[0], docs[1], simhash.Compare(hashes[0], hashes[1])) fmt.Printf("Comparison of `%s` and `%s`: %d\n", docs[0], docs[2], simhash.Compare(hashes[0], hashes[2])) }

README 给出的运行输出:

Simhash of this is a test phrase: 8c3a5f7e9ecb3f35 Simhash of this is a test phrass: 8c3a5f7e9ecb3f21 Simhash of foo bar: d8dbe7186bad3db3 Comparison of `this is a test phrase` and `this is a test phrass`: 2 Comparison of `this is a test phrase` and `foo bar`: 29

这组结果直观验证了算法性质:近似文档的指纹仅相差 2 位(末两个 hex 字符3f35vs3f21),而无关文档相差 29 位。实际使用时,可在 64 位尺度上以经验阈值(如 ≤3~5 位)筛选近似重复文档。

四、scan4all 中的实战集成:httpx 的 simhash 指纹

simhash 在 scan4all 中并非摆设,而是被内嵌的 httpx 探测模块用作响应指纹算法,调用链如下:

  • 哈希封装层:pkg/httpx/common/hashes/hashes.go 中的Simhash(data []byte)函数直接调用simhash.Simhash(simhash.NewWordFeatureSet(data)),把 64 位结果以十进制字符串返回。它与Md5Sha1Sha256Sha512Mmh3(murmur3 摘要 base64 内容)并列,构成 httpx 的指纹工具箱。
  • 参数校验层:pkg/httpx/runner/options.go 中,用户通过--hash-type传入的每种哈希都会先做白名单校验,合法取值为md5sha1sha256sha512mmh3simhash,不在白名单内的类型会被记录为 "Unsupported hash type" 错误。
  • 输出层:pkg/httpx/runner/runner.go 中有两处关键逻辑:
    1. 当启用 JSON 输出且用户未显式指定哈希类型时,自动设置为md5,mmh3,sha256,simhash(第 1432-1434 行)——simhash 因此成为 JSON 模式的默认指纹之一
    2. 输出时case "simhash"分支会分别对响应体resp.Data与原始响应头resp.RawHeaders计算指纹,写入结果映射的body-simhashheader-simhash字段,并在控制台以品红色高亮显示(第 1460-1462 行)。

这一集成的实际意义在于:simhash 对响应体中脚本、统计计数等高频微小变化不敏感,适合作为站点页面"内容签名",与 mmh3(favicon 指纹等精确场景)互补;配合汉明距离思路可对扫描结果做二次聚类。使用时的注意事项:simhash 走的是英文/URL 分词(WordFeatureSet),对纯中文页面按unicodeBoundaries才更合理,但 httpx 当前封装固定使用NewWordFeatureSet,从源码结构看,若需对非拉丁文目标获得更稳定的指纹,可在上层改用UnicodeWordFeatureSet的调用路径。

五、小结

simhash 包用不到 250 行 Go 代码完整实现了 Charikar 相似哈希的分词、加权向量化、指纹折叠与汉明距离比较四个环节,API 设计(FeatureSet 接口 + 内置 WordFeatureSet/UnicodeWordFeatureSet + Shingle 工具)为自定义切分策略留出了扩展位。scan4all 将其 vendor 进 httpx 模块,使simhash成为 JSON 输出的默认响应指纹算法之一,为大规模 Web 扫描结果的近似去重与内容聚类提供了底层算法支撑。

【免费下载链接】scan4allOfficial repository vuls Scan: 15000+PoCs; 23 kinds of application password crack; 7000+Web fingerprints; 146 protocols and 90000+ rules Port scanning; Fuzz, HW, awesome BugBounty( ͡° ͜ʖ ͡°)...项目地址: https://gitcode.com/GitHub_Trending/sca/scan4all

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询