FastScan 是一款专为逆向工程和游戏分析设计的高性能内存指针链扫描工具。采用先进的多线程算法和优化的内存访问策略,能够在海量数据中快速定位和分析复杂的多级指针结构。
- 游戏修改与分析: 快速定位动态内存地址
- 逆向工程: 追踪复杂的指针链关系
- 内存分析: 深入理解程序内存结构
- 安全研究: 分析内存保护机制
- ⚡ 极速扫描: 多线程并行处理,支持TB级内存扫描
- 🎯 精准定位: 智能算法过滤无效指针,提高命中率
- 💾 低内存占用: 流式处理大文件,避免内存溢出
- 🔧 灵活配置: 丰富的参数选项,满足各种使用场景
- 📊 批量对比: 支持多文件同时对比,大幅提升效率
⚠️ 需要Root权限运行⚠️ 支持真机64位、虚拟机64位、模拟器64位⚠️ 支持PC对比(Ubuntu等Linux系统)⚠️ 二进制对比除外,主要功能支持64位⚠️ 支持4个二进制同时对比
- 多层级指针链搜索: 支持1-50层深度的指针链扫描
- 自定义扫描范围: 灵活设置偏移量范围(0x0 - 0xFFFFFFFF)
- 智能内存分区: 自动识别并筛选目标内存区域
- 多目标并行扫描: 同时搜索多个目标地址(最多2000个)
- 全内存遍历: 不限制起始模块,覆盖所有可能的指针路径
- 高并发处理: 利用多核CPU并行计算,性能提升数倍
- 内存优化: 流式处理避免内存占用过高
- 起点-终点分析: 指定起始地址和目标地址群,快速建立关联
- GG脚本支持: 导入GameGuardian保存的地址列表
- 关系可视化: 清晰展示指针链的跳转路径
- 二进制精确对比: 逐字节比较两个扫描结果
- 层级限制: 支持指定对比的起始层级和结束层级
- 模块过滤: 可选择是否比较模块基址和索引
- 结果输出: 自动生成格式化文本文件
- 多线程加速: 智能分块并发处理,速度提升10倍以上
- 动态负载均衡: 自动调整线程任务分配
- 内存缓存优化: 减少磁盘IO次数
- 进度实时显示: 查看对比进度和预计剩余时间
- 批量对比: 一次性对比3-8个扫描文件
- 交集提取: 找出所有文件中的共同指针链
- 差异分析: 识别不同文件间的差异指针
- 结果合并: 自动合并临时块文件
- 高速解析: 直接读取.out格式的扫描结果
- 内存筛选: 载入后可根据数值范围过滤指针
- 动态分析: 支持int和float类型的实时数值追踪
- 暴力模式: 跳过部分验证步骤,快速载入大量指针
- 智能解析: 自动识别文本格式的指针链
- 批量筛选: 多地址同时筛选,支持逗号/空格/分号分隔
- 缓存机制: 可选内存缓存加速重复查询
- 增量过滤: 支持多次筛选,逐步缩小范围
- 实时验证: 手动输入指针链,立即查看解析结果
- 负偏移支持: 完整支持正负偏移混合的指针链
- 分步显示: 展示每一级指针的解引用过程
- 类型转换: 同时显示int和float数值
- 哈希加速: 使用xxHash64快速构建索引
- 并行处理: 多线程分块读取和对比
- 内存优化: 适合1GB以下的文本文件
- 分桶外部哈希: 低内存占用,支持10GB+文件对比
- 流式处理: 不需要一次性加载整个文件
- 自动参数优化: 根据系统资源自动调整缓冲区大小
- Anonymous (匿名内存)
- C_alloc/C_heap (C堆内存)
- C_data/C_bss (C数据段)
- Java/Java_heap (Java堆)
- Stack (栈)
- Code_app/Code_system (代码段)
- Video (显存)
- Ashmem (共享内存)
- PPSSPP (模拟器内存)
- 全部/其他/损坏区域
- 字节对齐过滤: 跳过非4字节对齐的指针
- 分页对齐处理: 处理页边界对齐问题
- 缺页机制: 主动触发缺页加载未映射内存
- B4000处理: 特殊地址格式兼容
- 模块扩展: 允许0层偏移跨越相邻同名模块段
- 负偏移扫描: 支持双向偏移(base±offset)
- 详细模块: 按[名称][索引][段类型]精确选择
- 基础模块: 按模块名称批量选择所有相关段
- 自定义模块: 手动指定起始和结束地址
- SYSCALL: 默认系统调用,兼容性最好
- PREAD64: 备用读写方式,支持读取非r权限段
- KERNEL: 内核读写,需要驱动支持
# 自动检测运行中的进程
序号: 1 包名: com.example.game PID: 12345
序号: 2 包名: com.another.app PID: 67890
# 支持输入序号或完整包名
提示: 请设置目标进程包名或进程序号
$ 1 # 选择第一个进程内存范围选择:
- 绿色: 已选中
- 灰色: 未选中
输入模块序号 (支持多选, 如: 2,6,8)
$ 2,6,8 # 选择 Anonymous, C_bss, C_data
- 32位: 适用于32位应用或模拟器
- 64位: 适用于64位原生应用 (默认)
# 单地址模式
$ 7F8B4C2000
# 多地址模式 (逗号/空格/分号分隔)
$ 7F8B4C2000, 7F8B4C3000, 7F8B4C4000
# 从GG文件导入
$ gg
提示: 请输入GG保存指针文件路径
$ /sdcard/addresses.txt# 单层级 (扫描6层)
$ 6
# 范围层级 (从第3层开始扫描到第7层)
$ 3-7
# 指定每层固定偏移
$ offset
提示: 请输入指定层级(1-6)
$ 3
提示: 请输入第3层的固定偏移
$ 0x18 # 第3层固定偏移为0x18# 十六进制
$ 0x1000
# 十进制
$ 4096# 方式1: 详细模块选择
索引:1 libunity.so[1][Cd] 0x12345000 ~ 0x12346000
索引:2 libunity.so[1][Cdx] 0x12347000 ~ 0x12348000
提示: 请输入指定模块([1,2,3,4]勾选/取消/cls重置)
$ 1,2 # 选择libunity.so的Cd和Cdx段
# 方式2: 基础模块选择
索引:1 libunity.so
索引:2 libil2cpp.so
$ 1 # 选择libunity.so的所有段
# 方式3: 自定义模块
$ add
提示: 请输入新模块名称
$ custom_module
提示: 请输入模块开始地址
$ 7F8B4C0000
提示: 请输入模块结束地址 (回车默认开始地址+扫描范围)
$ [Enter]# 选择扫描方式
(1) 基础扫描 # 从指定模块开始搜索
(2) 暴力扫描 # 全内存搜索,不限制起始模块
(3) 指针关系 # 起点-终点分析
# 确认配置并扫描
请输入目标层数: (回车默认层数: 6)
$ [Enter]
请输入搜索范围: (回车默认范围: 2000)
$ [Enter]
提示: 请输入文件路径(回车自动生成)
$ scan_result.out # 或按Enter自动生成a1.out
是否进行扫描(y/n)(默认y)
$ y
# 扫描过程
进程总内存: 2.5 GB
开始扫描内存区间...
获取指针数量: 12458763条
获取指针耗时:1523ms
扫描到156278条锁链
已保存至scan_result.out索引:1 文件: a1.out 2025-01-13 14:23:45 125.32 MB
提示: 请输入文件索引1
$ 1
是否限制指针层数([层数]/[起始]-[结束])(默认n)
$ 5-6 # 只格式化第5-6层的指针
是否开始格式化指针(y/n)(默认y)
$ y
# 格式化结果示例
libunity.so[1][Cd]+0x25F78+0x18+0xB8+0x30+0x10
libunity.so[1][Cdx]+0x1A2C0+0x20+0x48+0x58+0x8
...
格式化指针成功,共32156条指针# 选择两个文件
索引:1 文件: a1.out 125.32 MB
索引:2 文件: a2.out 138.47 MB
提示: 请输入两文件下标(1,2逗号隔开)
$ 1,2
# 配置对比参数
是否限制指针层数([层数]/[起始]-[结束])(默认读取配置)
$ 6 # 只对比6层的指针
是否对比并写入(y/n)(默认n)
$ y # 对比并保存结果
是否对比指针(y/n)(默认y)
$ y
# 对比过程
当前使用64位基址对比...
对比进度: 25%... 50%... 75%... 100%
对比完成: 找到1523条相同指针
输出文件名: 文件1对比2.txt# 线程配置
当前可调用的CPU核心数: 8
提示: 请输入线程数
$ 7 # 使用7个线程
# 选择文件和配置 (同普通对比)
$ 1,2
# 多线程对比
使用须知: 写入配置目录的tmp下,最后需手动合并!
当前多线程分块数量为100
是否对比指针(y/n)(默认y)
$ y
# 对比进度
分块进度: [Thread 1] 15% [Thread 2] 12% ...
对比完成: 总耗时 25秒
文件数量: 73
总大小: 45.6 MB
是否合并文件(y/n)(默认y)
$ y
合并完成: 文件数 73, 总大小 45.60 MB, 总耗时 3 秒
输出文件: 文件1对比2.txt请输入需要对比的文件数量(最小3最大8)
$ 4
提示: 请输入4个文件下标(1,2...逗号隔开)
$ 1,2,3,4 # 对比文件1、2、3、4
# 配置和执行 (同极速对比)
...
# 结果
匹配指针: 所有4个文件中共有的指针
输出文件: 文件1-2-3-4对比.txt索引:1 文件: a1.out 125.32 MB
提示: 请输入文件索引1
$ 1
# 设置自定义头 (可选)
请输入自定义头:
$ 7F8B4C0000 # 或按Enter跳过
# 选择筛选类型
提示: 请输入筛选类型(1:int 2:float)
$ 1 # 筛选整数
# 设置偏移 (相对于指针目标地址的偏移)
提示: 请输入偏移(默认0x0)
$ 0x10
# 设置数值范围
提示: 请输入筛选最大值
$ 1000
提示: 请输入筛选最小值
$ 100
# 筛选结果
筛选耗时: 2.3s
符合条件的指针: 2356条
# 交互式操作
提示: 请输入操作(show查看/add增加了/sub减少了/exit退出)
$ show
地址: 0x7F8B4C2010 value: 256
地址: 0x7F8B4C3020 value: 512
...
$ add # 筛选数值增加的指针
数值增加了,共158个指针
$ sub # 筛选数值减少的指针
数值减少了,共89个指针
$ exit # 退出索引:1 文件: scan_result.txt 256.78 MB
提示: 请输入文件索引1
$ 1
# 缓存设置
提示: 该文件大于30MB 推荐使用缓存
是否临时使用缓存?(y/n)(默认y)
$ y
说明: 缓存可能会漏掉含有B4的部分指针
开始扫描内存区间...
扫描到指针12458763条
# 全数据加载 (显示所有指针及其当前值)
注意: 全部数据加载指的是,加载全部文本指针,显示地址
你想要全部数据加载出来吗?(默认y)
$ y
文本载入中... 15%... 50%... 85%... 100%
统计结果:35612条指针
0x7F8B4C2000 出现次数23 值[D] 1024 值[F] 0.000001
0x7F8B4C3000 出现次数18 值[D] 2048 值[F] 3.140000
...
# 筛选地址
请输入筛选地址:
$ 7F8B4C2000 # 筛选包含此地址的指针链
请输入第2条地址(不输入结束):
$ 7F8B4C3000 # 可以输入多个地址
请输入第3条地址(不输入结束):
$ [Enter] # 结束输入
# 筛选结果
统计结果:1523条指针
文件数量: 15
总大小: 8.5 MB
是否合并文件(y/n)(默认y)
$ y
保存文件名: scan_result[过滤1].txt
开始合并文件...
合并完成说明:请输入文本指针(支持负偏移)
例如: libunity.so[1][Cd]+0x25F78-0x50+0x245
请输入链条:
$ libunity.so[1][Cd]+0x25F78+0x18+0xB8-0x10
# 解析过程
起始模块地址:libunity.so[1][Cd][7F8B4C0000]
当前地址: 0x7F8B4E5F78 + 0x18
-> 0x7F8C2A1000 (已对齐)
当前地址: 0x7F8C2A1000 + 0xB8
-> 0x7F8C3E4200 (已对齐)
当前地址: 0x7F8C3E4200 - 0x10
-> 0x7F8C3E41F0 (已对齐)
最终地址: 0x7F8C3E41F0
结果: int-> 1024 float-> 3.14159索引: 1 文件: result1.txt 2025-01-13 14:23:45 450.32 MB
索引: 2 文件: result2.txt 2025-01-13 15:30:12 523.47 MB
提示: 请输入两文件下标(1,2逗号隔开)
$ 1,2
# 自动选择对比模式
# 文件总大小 < 1GB: 小文件对比 (哈希表)
# 文件总大小 >= 1GB: 大文件对比 (分桶外部哈希)
# 小文件对比
第一个文件处理完成。
处理耗时: 12.5 秒
文件共计: 2356789
第二个文件处理完成。
处理耗时: 8.3 秒
匹配的行数: 345678
文件数量: 28
总大小: 156.8 MB
是否合并文件(y/n)(默认y)
$ y
保存文件名: [result1]对比[result2].txt
开始合并文件...
# 大文件对比
参数(自动): 分桶缓冲=128MB 桶内缓冲=64MB 桶上限=512 并发线程=7
分桶数量: 512
阶段1: 按桶切分...
切分耗时: 45 秒
阶段2: 逐桶匹配...
进度: 16/512 已完成
进度: 32/512 已完成
...
进度: 512/512 已完成
匹配总数: 456789 总耗时: 180 秒
保存文件名: [分桶对比][result1]vs[result2].txt- 操作系统: Linux 5.0+ / Android 8.0+ (API 26+)
- 架构: x86_64 / ARM64
- 权限: Root权限
- 内存: 建议4GB+
- 存储: 建议10GB+可用空间
Android设备 (ARM64/x86_64):
# 1. 上传文件到设备
adb push FastScan /data/local/tmp/
# 2. 进入设备shell
adb shell
# 3. 切换到root
su
# 4. 赋予执行权限
chmod +x /data/local/tmp/FastScan
# 5. 运行程序
cd /data/local/tmp
./FastScanLinux系统 (x86_64/ARM64):
# 1. 赋予执行权限
chmod +x FastScan
# 2. Root权限下运行
sudo ./FastScan# 运行程序
./FastScan
# 进入主菜单
(1) 基础配置 (2) 指针搜索 (3) 指针对比
(4) 指针载入 (5) 文本对比 (999) 退出常用游戏: 0x1000 - 0x3000
大型游戏: 0x5000 - 0x10000
特殊情况: 0x20000+
目标: 找到游戏血量的稳定指针链
步骤:
1. 修改血量,获取当前地址: 0x7F8B4C2000
2. 重启游戏,血量地址变化: 0x7F9A5D3000
3. 第一次扫描: 目标=0x7F8B4C2000,层级=6,范围=0x2000
结果: a1.out (156278条)
4. 第二次扫描: 目标=0x7F9A5D3000,层级=6,范围=0x2000
结果: a2.out (142893条)
5. 对比两次结果: a1.out vs a2.out
结果: 找到523条相同指针
6. 第三次验证: 重启游戏再扫描 a3.out
对比: a1 vs a2 vs a3 (多文件对比)
结果: 最终找到18条稳定指针
最稳定的指针:
libunity.so[1][Cd]+0x25F78+0x18+0xB8+0x30+0x10+0x20
某些游戏引擎使用负偏移来优化内存访问:
libil2cpp.so[1][Cd]+0x1A2C0-0x8+0x48+0x10
解析:
1. 基址: libil2cpp.so[1][Cd] = 0x70000000
2. +0x1A2C0 -> 0x7001A2C0 (读取8字节) -> 0x80000000
3. -0x8 -> 0x7FFFFFF8 (负偏移)
4. +0x48 -> 0x80000040 (读取8字节) -> 0x90000000
5. +0x10 -> 0x90000010 (最终地址)
启用负偏移功能:
扫描配置 -> (11) 负偏移 -> 开启
处理跨段指针(cd/cdx/cdro):
不启用模块扩展:
libunity.so[1][Cd]+0x3000 # 只在Cd段内搜索
启用模块扩展:
libunity.so[1][Cd]+0x3000 # 可以跳转到Cdx、Cdro相邻段
启用方法:
扫描配置 -> (10) 模块扩展 -> 开启
| 优化项 | 说明 | 性能提升 |
|---|---|---|
| 多核并行 | 充分利用CPU多核 | 4-8倍 |
| 内存缓存 | 减少重复读取 | 2-3倍 |
| 字节对齐 | 过滤无效指针 | 30-50% |
| 分页对齐 | 智能页边界处理 | 10-20% |
| 缺页机制 | 主动触发缺页 | 5-15% |
| 对比模式 | 内存占用 | 速度 | 适用场景 |
|---|---|---|---|
| 普通对比 | 低 | 慢 | 小文件(<100MB) |
| 极速对比 | 中 | 快 | 中等文件(100MB-1GB) |
| 多文件对比 | 高 | 极快 | 大量文件同时对比 |
| 载入方式 | 速度 | 特点 |
|---|---|---|
| 二进制载入 | 极快 | 直接读取.out文件 |
| 文本载入(无缓存) | 中 | 实时解析,占用少 |
| 文本载入(有缓存) | 快 | 空间换时间 |
可能原因:
- 目标地址错误或已失效
- 扫描层级不够 (尝试增加到8-10层)
- 扫描范围太小 (尝试0x5000-0x10000)
- 模块选择错误 (检查是否选择了正确的内存区域)
- 字节对齐过滤过严 (尝试关闭字节对齐)
解决方法:
# 使用暴力扫描
(2) 暴力扫描 # 全内存搜索
# 或者使用全内存范围
内存范围 -> (15) All # 选择全部内存可能原因:
- 两次扫描的参数不一致 (层级、范围、模块)
- 目标地址在两次扫描间变化过大
- 层级限制设置错误
解决方法:
# 确保扫描参数一致
第一次: 层级=6, 范围=0x2000, 模块=libunity.so
第二次: 层级=6, 范围=0x2000, 模块=libunity.so # 完全相同
# 取消层级限制
对比配置 -> (1) 层级限制 -> 输入0清除限制可能原因:
- 进程未运行或已退出
- 文本中的模块名格式不正确
- 游戏更新导致模块名变化
解决方法:
# 查看当前进程的模块
$ debug vm_static_list
模块名: libunity.so
模块数量: 1
模块范围: 16
起始地址: 0x70000000
结束地址: 0x71000000
# 检查文本格式
正确: libunity.so[1][Cd]+0x25F78+0x18
错误: libunity.so+0x25F78+0x18 # 缺少[1][Cd]对于扫描:
// 设置扫描限制
扫描配置 -> (6) 扫描限制 -> 输入限制数量
建议: 5000万 - 2亿
// 减少核心数
扫描配置 -> (9) 扫描核心 -> 输入较小值
建议: 物理核心数 / 2对于对比:
// 增大分块数量
基础配置 -> (3) 多线程分块 -> 输入较大值
建议: 200 - 500
// 或使用普通对比
指针对比 -> (1) 普通对比 # 低内存占用对于载入:
# 关闭文本缓存
载入配置 -> (4) 缓存载入 -> 不缓存
# 或使用二进制载入
(1) 二进制载入 # 效率更高方法1: 硬件优化
- 使用更快的存储设备 (SSD优于HDD)
- 增加内存 (减少交换分区使用)
- 使用更多核心的CPU
方法2: 软件优化
# 启用极速扫描模式
基础配置 -> 选择扫描模式 -> 2 (极速扫描)
# 优化配置
扫描配置 -> (7) 字节对齐 -> 开启
扫描配置 -> (8) 分页对齐 -> 关闭
扫描配置 -> (9) 扫描核心 -> 最大值
# 精确模块选择
模块设置 -> 只选择必要的内存区域
避免选择: All, Code_system, Other方法3: 算法优化
# 使用指针关系分析
(3) 指针关系 # 比基础扫描快3-5倍
# 多次对比缩小范围
第一次: 全范围扫描
第二次: 对比结果重新扫描
第三次: 再次对比获得精确结果使用极速对比:
指针对比 -> (2) 极速对比
# 调整线程数
对比配置 -> (3) 线程数量 -> 输入CPU核心数-1
# 调整分块数量
基础配置 -> (3) 多线程分块 -> 输入10-50优化建议:
- 文件大小 < 200MB: 普通对比
- 文件大小 200MB-1GB: 极速对比
- 文件大小 > 1GB 或多文件: 多文件对比
原因: 某些自定义或动态加载的模块无法识别其类型标记。
显示格式:
已识别:
libunity.so[1][Cd] # C data段
libunity.so[1][Cdx] # C data可执行段
libunity.so[1][Cdro] # C data只读段
libunity.so[1][Cb] # C bss段
libunity.so[1][Xa] # 可执行区域
未识别:
libunity.so[1][12345] # 未知类型,显示数字
这不影响功能,指针仍然有效。
自动保存:
所有配置自动保存在 /sdcard/fscan/config/[包名].bin
手动备份:
# 备份配置
cp /sdcard/fscan/config/com.example.game.bin ~/backup/
# 恢复配置
cp ~/backup/com.example.game.bin /sdcard/fscan/config/跨设备迁移:
- 打包整个 /sdcard/fscan 目录
- 在新设备上解压到相同位置
- 阿夜 - 软件开发与维护
- 反馈邮箱: 1773714466@qq.com
- 用途: 仅接收与软件相关的反馈和建议
- 注意: 请勿发送无关信息,以免影响处理效率
- 使用问题请先查阅本文档的常见问题章节
- 未解决的问题可通过邮箱咨询
- 反馈Bug请详细描述复现步骤和系统环境
优化改进:
-
⚡ 优化二进制过滤新增不加载
-
⚡ 优化普通对比 和单线程对比
-
⚡ 优化进程监听不切换包名
-
⚡ 新增二进制过滤支持模糊
-
⚡ 新增文本过滤支持模糊
-
⚡ 新增全量对比
优化改进:
- ⚡ 优化文本过滤多线程竞争导致闪退的问题
新功能:
- ✨ 新增二进制过滤,输出二进制
优化改进:
- ⚡ 优化用户登录的逻辑,更换新验证系统
- ⚡ 二进制过滤自动识别两地址关系二进制
新功能:
- ✨ 新增二进制对比输出二进制
优化改进:
- ⚡ 优化二进制规则 修复了几个二进制对比的bug
- ⚡ 对比速度提升一个档次
新功能:
- ✨ 没有增加啥功能
优化改进:
- ⚡ 优化悬浮窗终端滑动事件
- ⚡ 调整滑动获取焦点事件逻辑
- ⚡ 更新最新libSea3优化获取时区函数
Bug修复:
- 🐛 修复其他时区导致的对比异常
新功能:
- ✨ 支持隐藏终端悬浮窗底部操作栏
- ✨ 新增独立悬浮窗小键盘(妈妈再也不担心档视野了)
优化改进:
- ⚡ 优化libSea3驱动版本,更新到最新版本
- ⚡ 优化部分菜单显示内容中描述信息
Bug修复:
- 🐛 本次无bug
新功能:
- ✨ 新增文本指针链一键转lua脚本的功能
优化改进:
- ⚡ 优化文本过滤选择目标地址为序号选择
- ⚡ 优化选择二进制文件和文本文件正则表达式,目前已经实现可以自定义名称的二进制
- ⚡ 优化更新逻辑,调整支持非强制更新
Bug修复:
- 🐛 修复文本对比完成后缓存文件不被及时清理的bug
- 🐛 修复软件版本第一次安装给予软件权限会导致软件崩溃的问题
优化改进:
- ⚡ 优化 Android 9 雷电模拟器使用悬浮窗时的回车交互体验
- ⚡ 优化文本载入性能与稳定性
- ⚡ 优化内核扫描在指针数量过大时的内存管理,避免崩溃
Bug修复:
- 🐛 修复负指针扫描最后一级无法进行负向扫描的问题
新功能:
- ✨ 优化悬浮窗终端调整模拟器复制功能
- ✨ 新增悬浮窗设置透明度(默认80%)
- ✨ 新增更强的文本对比功能
- ✨ 新增自定义toast避免弹窗被覆盖
优化改进:
- ⚡ 优化悬浮窗触摸焦点事件的监听
- ⚡ 优化点击设置为自动关闭悬浮窗
- ⚡ 优化点击用户和卡网为自动关闭悬浮窗
Bug修复:
- 🐛 修复文本对比读取配置文件目录异常
本软件仅供学习和研究使用。用户使用本软件从事的任何行为均与开发者无关。请确保你的使用符合当地法律法规。
FastScan v2.2.9 - 专业的指针链扫描工具
Made with ❤️ by 阿夜
参考青衫白衣的开源扫描引擎