Yomihay 👋

欢迎来到我的个人博客。 这里记录我的技术折腾生活感悟学习笔记。 希望能与你通过文字相遇。 我对模糊测试、软件测试、网络安全、服务器、LLM感兴趣

Cargo-fuzz入门:对Symphonia进行模糊测试与PoC构造

这是一篇fuzzing日记…记录一下这两天用cargo-fuzz挖Rust库的过程,踩了不少坑,也有点收获。 使用环境:Windows11(WSL2虚拟机)、Ubuntu24.04LTS 工具:cargo-fuzz、Symphonia库、ffmpeg(生成种子用)、python3 1. 选目标库 随便找一个,我选了 Symphonia(github链接 https://github.com/pdeljanov/Symphonia)。 这是一个纯Rust写的音频解析库,支持MP3、AAC、FLAC、MKV等一堆格式。Star有3000多,用的人挺多。 音视频库天生就适合fuzzing,因为要解析各种奇怪的二进制格式,边界检查稍微不注意就容易出问题。 把库拉下来: git clone https://github.com/pdeljanov/Symphonia.git cd Symphonia 装一下cargo-fuzz(如果之前没装的话): cargo install cargo-fuzz 2. 分析攻击 进去一看,作者其实已经准备好了fuzz目录,省事了。 cd symphonia/fuzz/fuzz_targets ls 里面有两个现成的target: decode_any.rs: 会尝试自动探测文件格式,然后解封装+解码。覆盖面最广。 decode_mp3.rs: 专门针对MP3解码器,直接喂原始数据包,跳过格式探测。 看了一下 decode_any.rs 的代码,大概流程就是: 读取fuzzer传过来的 Vec<u8> -> 包装成 MediaSourceStream -> Probe 探测格式 -> 创建解码器 -> 循环 decode。 很标准的用法,跟正常用这个库没区别。所以直接用它就行,不用自己写harness了。 3. 种子和字典的问题 这里有个问题。如果直接用 cargo fuzz run decode_any 裸跑,直接喂字节流文件,效率特别低。 因为音频文件都有magic bytes(比如MP3是 0xFF 0xF1,WAV是 RIFF…),fuzzer生成的纯随机数据99.9%都会在Probe阶段就被拦截,根本进不到解码逻辑里。 所以要准备两个东西: (1) 种子库(corpus) 不要去网上下那种几MB的完整音频文件,fuzzer跑不动。最好的办法是用ffmpeg生成一堆小的文件,每个0.1秒就够了。 文件结构完整,但是体积极小,fuzzer变异起来效率高。 让AI帮我写了个python脚本,调ffmpeg生成了11种格式的种子(MP3、AAC、FLAC、OGG、MKV、MP4、WAV等等),每个文件就几十到几百字节。 脚本大概长这样: import subprocess import os import shutil # Configuration OUTPUT_DIR = "corpus" DURATION = "0.1" # Seconds Note = "sine=frequency=1000:duration=0.1" # Formats to generate # map: extension -> ffmpeg_encoding_args FORMATS = { "mp3": ["-c:a", "libmp3lame"], "wav": ["-c:a", "pcm_s16le"], "flac": ["-c:a", "flac"], "ogg": ["-c:a", "libvorbis"], "mkv": ["-c:a", "libvorbis"], # Matroska audio "mp4": ["-c:a", "aac", "-movflags", "+faststart"], "m4a": ["-c:a", "aac"], "aac": ["-c:a", "aac"], # ADTS "caf": ["-c:a", "pcm_s16be"], # Core Audio Format "aiff": ["-c:a", "pcm_s16be"], "wma": ["-c:a", "wmav2"], # Windows Media Audio } def check_ffmpeg(): try: subprocess.run(["ffmpeg", "-version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True) print("ffmpeg found.") except (subprocess.CalledProcessError, FileNotFoundError): print("Error: ffmpeg is not installed or not in PATH.") exit(1) def generate_seeds(): if os.path.exists(OUTPUT_DIR): print(f"Directory '{OUTPUT_DIR}' already exists. Skipping creation to avoid overwriting user data.") else: os.makedirs(OUTPUT_DIR) print(f"Created directory '{OUTPUT_DIR}'.") print(f"Generating seeds into '{OUTPUT_DIR}'...") for ext, args in FORMATS.items(): filename = os.path.join(OUTPUT_DIR, f"seed.{ext}") # Command: unique sine wave generation for minimal file size # ffmpeg -y -f lavfi -i sine=frequency=1000:duration=0.1 [args] filename cmd = ["ffmpeg", "-y", "-f", "lavfi", "-i", Note] + args + [filename] try: subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, check=True) print(f"Generated: {filename}") except subprocess.CalledProcessError as e: print(f"Failed to generate {ext}: {e.stderr.decode('utf-8')}") if __name__ == "__main__": check_ffmpeg() generate_seeds() 跑完之后corpus目录下就有11个微型文件了。 ...

January 3, 2026 · 6 min · Me

如何访问 ChatGPT

因为国内访问官网 ChatGPT 直接访问比较困难(被墙了),所以需要通过一些方法来访问。 准备工作 安装环境:Windows 11 & MacOS & Android 12 软件:Clash Verge (Windows/MacOS) & Clash Meta for Android (Android) 必备材料:一个 Clash 配置文件(订阅链接) Step 1: 下载软件 你需要下载 Clash Verge(如果你是 Windows/MacOS)或者 Clash Meta for Android(如果你是 Android)。 Clash Verge & Clash Meta for Android 是干什么的? 它们是代理工具,用于网络加速,功能上与 VPN 类似。但更准确地说是一个基于 Clash 内核的图形化代理客户端。如果你要访问国外的网站,就要用这两个软件来启动网络服务哦。 简而言之,你需要用这两个软件来启动网络服务(系统代理),然后才能访问国外的网站。 下载链接: Clash Verge 下载地址 Clash Meta for Android 下载地址 Step 2: 获取订阅链接 你需要一个 Clash 配置文件(订阅链接)。 ...

December 30, 2025 · 1 min · Yomihay

Hello World!

欢迎来到我的博客 把这个博客搭起来了。这里之后会记录我的技术心得和生活点滴。 为什么选择 Hugo Stack? 极简:卡片式设计很现代。 快速:静态页面加载飞快。 美观:原生支持暗黑模式。 上面是LLM的做的起始页 这里什么都没有。

December 29, 2025 · 1 min · Me