c++怎么从庞大的二进制资源包中通过特征码扫描提取图片【进阶】

陌静君_9514

陌静君_9514

2026-03-30

454人浏览

原创

特征码扫描需先用mmap或CreateFileMapping映射资源包至内存,避免跨块漏检;再分层试探原始/异或特征码并验证JPEG/PNG结构与完整性;多线程须只读共享映射,配合原子操作记录结果。

c++怎么从庞大的二进制资源包中通过特征码扫描提取图片【进阶】

特征码扫描前必须预处理资源包的内存映射

直接用 fread 逐块读取几百 MB 的资源包,不仅慢,还容易漏掉跨块边界的特征码(比如图片头 \xFF\xD8\xFF 刚好落在两个 4KB 缓冲区交界处)。更稳妥的做法是用 mmap(Linux/macOS)或 CreateFileMapping + MapViewOfFile(Windows)把整个文件映射进虚拟内存——这样你能像操作一大段连续内存一样用指针遍历,且内核自动处理分页和边界对齐。

注意:Windows 上如果资源包超过 2GB,必须用 FILE_MAP_LARGE_PAGES 或确保进程启用大地址空间(/LARGEADDRESSAWARE),否则 MapViewOfFile 可能返回 NULL 而不报错;Linux 下则要检查 /proc/sys/vm/max_map_count 是否足够,否则 mmap 会失败并设 errno = ENOMEM。

匹配 JPEG/PNG 特征码时别只盯文件头

资源包里图片常被加密、压缩或加壳,原始 \xFF\xD8\xFF(JPEG SOI)或 \x89PNG\r\n\x1a\n(PNG signature)可能被异或、位移或偏移。实际扫描得做多层试探:

  • 先按未修改的原始特征码扫一遍,记录所有命中位置
  • 对每个命中点,向后读 64 字节,检查是否满足 JPEG 的 APP0/APP1 段结构(长度字段是否合理、是否有 JFIF 或 Exif 标识)
  • 若全无匹配,尝试对整段数据逐字节异或 0x55、0xAA 等常见密钥再扫描——很多游戏资源包就用单字节 XOR 混淆
  • PNG 还要注意 zlib 数据流校验:用 zlib::uncompress 尝试解压紧随 signature 后的 IDAT 块前 16 字节,失败则跳过

提取出的二进制块要验证完整性再落盘

光靠特征码定位只能保证“开头像”,不能保证后面是完整图片。直接写入 .jpg 文件,很可能得到一堆打不开的损坏文件。

验证逻辑必须包含:

  • JPEG:从 SOI 开始,用 jpeg_read_header(libjpeg)或手动解析 SOF0/SOF2 段,确认 width/height 非零且图像数据长度(从 SOS 到 EOI)在合理范围(比如不超过剩余缓冲区大小)
  • PNG:用 libpng 的 png_sig_cmp 校验前 8 字节,再调 png_create_read_struct + png_set_sig_bytes 尝试解析 IHDR,失败则丢弃
  • 通用兜底:计算整个候选块的 CRC32,若与资源包元数据中记录的校验值一致(如有),才视为可信

没这些验证,你扫出来的“图片”里可能混着半截纹理、音频 header、甚至引擎脚本片段。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

多线程扫描时共享内存区域必须只读映射

想提速?开 4 个线程各扫 1/4 地址空间。但千万别让线程去 mmap 同一份文件为 PROT_READ | PROT_WRITE——哪怕你没写,现代 CPU 的 speculative execution 也可能触发写保护异常(尤其在 ARM64 上),导致随机崩溃。

正确做法:

  • 主线程用 MAP_PRIVATE 或 MAP_SHARED + PROT_READ 映射一次
  • 子线程直接复用该指针,切勿重复 mmap
  • 若需记录匹配结果,用 std::atomic 计数器或无锁队列写入,避免对共享内存区域加锁

另外,std::string_view 指向映射内存是安全的,但绝不能把它传给任何可能内部调用 realloc 或 memcpy 的函数(比如某些 JSON 库的解析器),那些操作会试图拷贝不可写内存,触发 SEGV_ACCERR。

特征码扫描真正难的不是算法,而是资源包格式不公开、混淆方式不固定、验证逻辑要贴合实际引擎行为——你得先搞清它怎么塞进去,才能准确定位怎么掏出来。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

2235

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

3582

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

1196

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

4119

7

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

379

31

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6467

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2688

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习