惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
博客园 - 【当耐特】
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
Check Point Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
IT之家
IT之家
T
Tailwind CSS Blog
月光博客
月光博客
Vercel News
Vercel News
V
V2EX
Engineering at Meta
Engineering at Meta
B
Blog
Stack Overflow Blog
Stack Overflow Blog
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
腾讯CDC
I
InfoQ

Alliot's blog

Codex第三方API使用生图接口 域名切换到blog.alliot.tech Docker 代理配置机制与作用域 Docker 代理配置机制与作用域 2025年底的安卓搞机备忘录 2025年底的安卓搞机备忘录 ArgoCD部署应用出现metadata.annotations过大问题 ArgoCD部署应用出现metadata.annotations过大问题 APC UPS更换电池校准容量 APC UPS更换电池校准容量 M1 Mac安装低版本Node.js M1 Mac安装低版本Node.js Ansible使用Bitwarden存储Vault密码 Ansible使用Bitwarden存储Vault密码 Cloudflare Tunnel前置代理支持 Cloudflare Tunnel前置代理支持 CDN场景下配置Vaultwarden启用fail2ban CDN场景下配置Vaultwarden启用fail2ban 中银香港丝滑开户总结 中银香港丝滑开户总结 从指定路径更新雷池WAF证书 从指定路径更新雷池WAF证书 AWS ECS使用EBS作为Volume AWS ECS使用EBS作为Volume 利用 APT Hook 在 PVE 更新后自动执行脚本 浅浅的调教一下国产智障电视 浅浅的调教一下国产智障电视 Nginx proxy_pass到AWS ALB的504问题 Nginx proxy_pass到AWS ALB的504问题 OpenV**手动指定路由规则
OSMO Action5Pro 解锁BL并开启adbd
Alliot · 2026-09-18 · via Alliot's blog

  不久前,某安上有大佬发现 Action 5 Pro 居然能通过 9008 打开 Bootloader,更意外的是它的 SoC 是骁龙 8 Gen 2(SM8550/QCS8550), 一台运动相机塞了颗旗舰 SoC,一下子就变得好玩了。此后某安和 B 站陆续有人放出解锁、常驻工厂模式打开 adbd 的教程。
  这篇就以 macOS 为例,手把手带你解锁并开启adbd

前置信息

  本文流程已经在我手上的实机完整走通,但不排除后续固件打补丁把这条路堵上。不过 Action 5 Pro 已经很久没更新固件、功能上毫无动静了,重心大概都压在 Action 6 上,个人判断疆子短期内下场补漏的概率不大。(这么快就固件停更,可恶!)

  我的实机环境:

  • 型号:DJI Osmo Action 5 Pro(AC204)
  • SoC:QCS8550/SM8550(KalamaP)
  • 固件:10.00.16.13

  9008 线就是某宝几块钱的高通二代工程线,带按钮、能进 EDL 的那种即可。

前言

  经过与 Codex 的一系列口喷,最终发现拿到开机自启的 root ADB,本质上只需要动两个分区,userdata 完全不用碰。

  1. 改本机 devinfo 的两个解锁标志,解除 Bootloader 锁定;
  2. 把工厂 ABL 写进当前活动槽,让系统以 engineering 模式启动,从而暴露 USB ADB。
1
2
3
9008
├─ devinfo 两字节补丁 → Bootloader unlocked
└─ 工厂 ABL → engineering 模式 → root ADB + Fastboot 入口

  实机走完全程后的验收标准:fastboot getvar unlocked 返回 yes,内核启动参数里能看到 mp_state=engineering androidboot.secure_debug=1adbd.service 开机自启,adb shell 直接是 uid=0(root)

  顺带说一句:最早某安有大佬分享了自己的 userdata.img,一度被当成“开 ADB 必刷”的东西。实际分析下来根本不用刷——从别的设备回读的 userdata 会带着人家的 UUID、Wi-Fi、蓝牙密钥、相机配置和校准数据,跨设备写进去只会覆盖你自己的信息,弊大于利。

为什么是这两个分区

  解包固件会发现,Action 5 Pro 其实自带了完整的 ADB 组件:

1
2
3
4
/sbin/adbd
/sbin/launch_adbd
/lib/systemd/system/adbd.service
/sbin/usb/compositions/*

  而且 adbd.service 本身就处于 enabled 状态。所以问题从来不是“缺 adbd”,而是原厂 production 模式下的 ABL 没让系统进入工程调试状态,也没有暴露对应的 USB composition。

  这两个分区分工很清楚:devinfo 只保存 Bootloader 的锁状态;工厂 ABL 负责在启动时给内核塞进这两行参数:

1
2
mp_state=engineering
androidboot.secure_debug=1

  系统随后就会拉起早已存在的 adbd,给出一个无需改动 system 或 userdata 的 root shell。这也是整个流程能做到“最小改动”的原因。

风险与前提

  9008/Firehose 是直接对 UFS 裸写,地址写错、供电中断或者用错 loader,都可能让相机直接变砖,这时候你可能就得考虑「随心换」了(

  动手之前请逐条确认:

  • 能用工程线反复硬件进入 05c6:9008
  • 已经拿到匹配的 Firehose loader 和工厂 ABL;
  • 已经读过自己设备的 GPT;
  • 原始 devinfo、活动槽 ABL 和关键小分区都备份了;
  • 接受解锁 Bootloader 可能触发数据清除、失去保修、降低设备安全性;
  • 操作全程供电稳定,电池已装回。

  最重要的一条:本文出现的 LUN 和扇区都是我这台实机的示例值。你的 GPT 只要有一项对不上,就绝对不能照抄写入命令——地址必须以你自己 printgpt 读出来的为准。

准备文件

本文目录约定:

1
2
3
loader/RedMagicCommon_8Gen2_devprg
img-unlock/abl-factory.img
backup-action5pro/

本文只需要两个外来二进制:Firehose loader 和工厂 ABL。这两个文件都不含任何单台设备的身份数据,我已经打包好:

下载action5pro-unlock-files.zip

解压后应得到:

1
2
loader/RedMagicCommon_8Gen2_devprg
img-unlock/abl-factory.img

下载后先核对哈希再使用,与下面一致才继续:

1
2
b85fb0e651f88f12e3c9b7b56c0f7229449c410f87fc20c6bc35698516383297  loader/RedMagicCommon_8Gen2_devprg
658af73f3319af4c07c733fe6ad184f68c299b678819815bbdacbaaff3b12466 img-unlock/abl-factory.img

devinfo、备份和解锁后的 devinfo-minimal-unlocked.bin 不在压缩包里,也不该有——它们必须由你自己的设备现场读取和生成,附任何人的都会污染你的设备身份。

红魔 8 系列和 Action 5 Pro 都基于 SM8550/QCS8550(Kalama)平台。上述红魔 8 Gen2 programmer 已在 Action 5 Pro 上实测进入 Firehose,但“同 SoC”本身不保证任意 loader 都安全;只使用已经核验过的文件。

工厂 ABL 必须恰好为 1 MiB:

1
2
3

sha256sum loader/RedMagicCommon_8Gen2_devprg img-unlock/abl-factory.img
wc -c loader/RedMagicCommon_8Gen2_devprg img-unlock/abl-factory.img

预期 abl-factory.img 为:

1
2
1048576 bytes
SHA-256 658af73f3319af4c07c733fe6ad184f68c299b678819815bbdacbaaff3b12466

哈希或大小不同就停止。

安装 EDL 工具

以下命令适用于 macOS。Linux 安装对应发行版的 libusb、Python 和 Git 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

brew install libusb git coreutils


export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH"


python3 -m venv .edl-venv


git clone https://github.com/bkerler/edl.git edl-tool
git -C edl-tool checkout 2f8e89a848afaaef68997fcbcb5b178d958d497b


.edl-venv/bin/pip install ./edl-tool

定义本次终端会话使用的工具路径:

1
2
3
4
5
EDL_PY=.edl-venv/bin/python
EDL_SCRIPT=edl-tool/edl.py
LOADER=loader/RedMagicCommon_8Gen2_devprg
FACTORY_ABL=img-unlock/abl-factory.img
BACKUP=backup-action5pro

关闭终端后变量会消失;重新操作前需要再次执行这一段。

进入并确认 9008

  1. 相机关机并取下电池;
  2. 按住 9008 工程线按钮插入相机;
  3. 主机枚举出 Qualcomm 9008 后装回电池,避免刷写途中供电中断。

macOS 查看 USB:

1
2

ioreg -p IOUSB -l -w 0 | grep -i QUSB_BULK

应看到 Qualcomm QUSB_BULK 节点。若想确认 VID:PID,注意 ioreg 里 idVendor/idProduct 是十进制,05c6:9008 对应 1478/36872

1
ioreg -p IOUSB -l -w 0 | grep -iE "idVendor|idProduct"

9008 与 ADB/Fastboot 是不同模式,此时下面两项应为空:

1
2
adb devices -l
fastboot devices

第一步:只读 GPT

1
2
3
4

"$EDL_PY" "$EDL_SCRIPT" printgpt \
--memory=ufs \
--loader="$LOADER"

核对输出中的:

  • MemoryName=UFS
  • 逻辑块大小;
  • LUN 数量;
  • devinfo 所在 LUN、起始扇区和长度;
  • abl_aabl_b 的位置;
  • 哪个槽显示 Active True

本文实机布局为:

分区LUN起始扇区扇区数状态
devinfo42397521公共分区
abl_a466566256Active True
abl_b4190279256Active False

本文后续命令只适用于完全相同的布局且活动槽为 A。如果你的活动槽是 B,停止;不要自行把文中的 A/B 和扇区机械互换。

确认一致后定义地址:

1
2
3
4
5
6

LUN=4
DEVINFO_START=239752
DEVINFO_SECTORS=1
ABL_START=66566
ABL_SECTORS=256

第二步:备份自己的设备

备份关键小分区

1
2
3
4
5
6
7
8
mkdir -p "$BACKUP"



"$EDL_PY" "$EDL_SCRIPT" rl "$BACKUP" \
--memory=ufs \
--loader="$LOADER" \
--skip=system_a,system_b,emulated,userdata,blackbox,blackbox_upgrade,rawdump

确认目录中至少存在:

1
2
3
4

test -f "$BACKUP/lun4/devinfo.bin"
test -f "$BACKUP/lun4/abl_a.bin"
test -f "$BACKUP/lun4/abl_b.bin"

单独备份 userdata

先从你自己的 GPT 记录 userdata 的 LUN、起始扇区和扇区数。下方仍是本文实机示例:

1
2
3
4
5
6
7
8
9
10
11
12
USERDATA_LUN=0
USERDATA_START=15214715
USERDATA_SECTORS=25472


mkdir -p "$BACKUP/lun0"


"$EDL_PY" "$EDL_SCRIPT" rs "$USERDATA_START" "$USERDATA_SECTORS" \
"$BACKUP/lun0/userdata.bin" \
--memory=ufs --lun="$USERDATA_LUN" \
--loader="$LOADER"

建立完整性清单

1
2
3
4
5

sha256sum "$BACKUP"/lun*/* > "$BACKUP/SHA256SUMS"


sha256sum -c "$BACKUP/SHA256SUMS"

把整个备份目录复制到外置盘,并在外置盘再次运行校验。不要只保存教程作者的备份。

第三步:生成本机专属解锁 devinfo

先检查本机原始文件的结构,再生成副本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


python3 - "$BACKUP/lun4/devinfo.bin" img-unlock/devinfo-minimal-unlocked.bin <<'PY'
from pathlib import Path
import sys

src, dst = map(Path, sys.argv[1:])
original = src.read_bytes()
assert len(original) == 4096, f"unexpected devinfo size: {len(original)}"
assert original.startswith(b"ANDROID-BOOT!"), "unexpected devinfo magic"
assert original[0x10] == 0, f"unexpected is_unlocked: {original[0x10]}"
assert original[0x18] == 0, f"unexpected is_unlock_critical: {original[0x18]}"

patched = bytearray(original)
patched[0x10] = 1
patched[0x18] = 1
dst.write_bytes(patched)
PY

严格验证只有两个字节变化:

1
2
3
4
5
6
7
8

test "$(wc -c < img-unlock/devinfo-minimal-unlocked.bin)" -eq 4096


cmp -l "$BACKUP/lun4/devinfo.bin" img-unlock/devinfo-minimal-unlocked.bin


sha256sum "$BACKUP/lun4/devinfo.bin" img-unlock/devinfo-minimal-unlocked.bin

预期差异:

1
2
17   0   1
25 0 1

如果还有第三行差异,停止。

第四步:写入 devinfo

写前最后回读

1
2
3
4
5
6
7
8
9
10
11
PRE_DEVINFO=$(mktemp /tmp/action5-devinfo-pre.XXXXXX)


"$EDL_PY" "$EDL_SCRIPT" rs "$DEVINFO_START" "$DEVINFO_SECTORS" \
"$PRE_DEVINFO" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"


test "$(wc -c < "$PRE_DEVINFO")" -eq 4096
cmp "$PRE_DEVINFO" "$BACKUP/lun4/devinfo.bin"

单扇区写入并回读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


"$EDL_PY" "$EDL_SCRIPT" ws "$DEVINFO_START" \
img-unlock/devinfo-minimal-unlocked.bin \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"

POST_DEVINFO=$(mktemp /tmp/action5-devinfo-post.XXXXXX)


"$EDL_PY" "$EDL_SCRIPT" rs "$DEVINFO_START" "$DEVINFO_SECTORS" \
"$POST_DEVINFO" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"


test "$(wc -c < "$POST_DEVINFO")" -eq 4096
sha256sum "$POST_DEVINFO" img-unlock/devinfo-minimal-unlocked.bin
cmp "$POST_DEVINFO" img-unlock/devinfo-minimal-unlocked.bin

后文所有写入后的回读校验都是这个套路:cmp 的退出码为准——无输出且返回 0 才算与目标镜像逐字节一致,一旦有差异 cmp 会直接打印首个不同字节的位置。旁边的 sha256sum 行只是把哈希打出来供你肉眼留档,不需要手动逐位比对。

分阶段启动验证

安全起见,先只验证 devinfo,不同时写 ABL:

1
2

"$EDL_PY" "$EDL_SCRIPT" reset --resetmode=reset --loader="$LOADER"

设备断开时工具可能报告 USB I/O error;如果 9008 已从 USB 消失,这通常只是复位导致的断连。相机没有自动启动时按电源键。

本文实测此时相机可正常进入系统,但仍没有 ADB。这一步的价值是确认两字节 devinfo 没破坏正常启动。

第五步:重新进入 9008,刷工厂 ABL

再次通过工程线进入 05c6:9008,重新执行变量定义,并重新读取 LUN4 GPT。确认仍为相同布局和活动槽 A 后继续。

写前检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PRE_ABL=$(mktemp /tmp/action5-abl-pre.XXXXXX)


"$EDL_PY" "$EDL_SCRIPT" rs "$ABL_START" "$ABL_SECTORS" \
"$PRE_ABL" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"


test "$(wc -c < "$PRE_ABL")" -eq 1048576
cmp "$PRE_ABL" "$BACKUP/lun4/abl_a.bin"


test "$(wc -c < "$FACTORY_ABL")" -eq 1048576
printf '%s %s\n' \
658af73f3319af4c07c733fe6ad184f68c299b678819815bbdacbaaff3b12466 \
"$FACTORY_ABL" | sha256sum -c -

写入活动槽 ABL 并回读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

"$EDL_PY" "$EDL_SCRIPT" ws "$ABL_START" "$FACTORY_ABL" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"

POST_ABL=$(mktemp /tmp/action5-abl-post.XXXXXX)


"$EDL_PY" "$EDL_SCRIPT" rs "$ABL_START" "$ABL_SECTORS" \
"$POST_ABL" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"

test "$(wc -c < "$POST_ABL")" -eq 1048576
sha256sum "$POST_ABL" "$FACTORY_ABL"
cmp "$POST_ABL" "$FACTORY_ABL"

只有全部成功才重启:

1
"$EDL_PY" "$EDL_SCRIPT" reset --resetmode=reset --loader="$LOADER"

若没有自动开机,按电源键正常启动。

第六步:验证 root ADB

1
2
3
4
5
6
7
8

adb kill-server
adb start-server


adb wait-for-device
adb devices -l
adb shell id

正确结果应包含:

1
2
<serial>  device  product:qcs8550_ac204
uid=0(root)

如果状态为 offline,重新插拔普通 USB 线后重试;如果没有设备,不要刷 userdata,先检查工厂 ABL 是否真的写入活动槽且回读哈希一致。

确认工程启动参数和服务状态:

1
2
3
4
5
6
7

adb shell 'cat /proc/cmdline'


adb shell 'systemctl is-enabled adbd.service'
adb shell 'systemctl is-active adbd.service'
adb shell 'systemctl status adbd.service --no-pager'

预期关键字段:

1
2
3
4
mp_state=engineering
androidboot.secure_debug=1
enabled
active

进入交互式 root shell:

1
adb shell

第七步:验证 Fastboot 和 Bootloader 状态

1
2
3
4
5
6
7
8

adb reboot bootloader


fastboot devices
fastboot getvar unlocked
fastboot getvar current-slot
fastboot getvar product

预期:

1
2
3
4
<serial>       fastboot
unlocked: yes
current-slot: a
product: kalama

返回系统并确认 ADB 自动恢复:

1
2
3
fastboot reboot
adb wait-for-device
adb shell id

以后正常开机、连接普通 USB 线后直接使用:

1
2
adb devices -l
adb shell

回退:恢复原始 ABL 和 devinfo

前提:仍能通过工程线进入 9008。恢复前重新读取 GPT,重新定义变量,并确认布局未变。

如果两项都要撤销,先恢复原厂 ABL,再恢复原始 devinfo;全部回读成功后再重启。

恢复原厂 ABL A

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

"$EDL_PY" "$EDL_SCRIPT" ws "$ABL_START" "$BACKUP/lun4/abl_a.bin" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"

RESTORED_ABL=$(mktemp /tmp/action5-abl-restored.XXXXXX)
"$EDL_PY" "$EDL_SCRIPT" rs "$ABL_START" "$ABL_SECTORS" \
"$RESTORED_ABL" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"


test "$(wc -c < "$RESTORED_ABL")" -eq 1048576
sha256sum "$RESTORED_ABL" "$BACKUP/lun4/abl_a.bin"
cmp "$RESTORED_ABL" "$BACKUP/lun4/abl_a.bin"

恢复原始 devinfo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

"$EDL_PY" "$EDL_SCRIPT" ws "$DEVINFO_START" "$BACKUP/lun4/devinfo.bin" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"

RESTORED_DEVINFO=$(mktemp /tmp/action5-devinfo-restored.XXXXXX)
"$EDL_PY" "$EDL_SCRIPT" rs "$DEVINFO_START" "$DEVINFO_SECTORS" \
"$RESTORED_DEVINFO" \
--memory=ufs --lun="$LUN" \
--loader="$LOADER"


test "$(wc -c < "$RESTORED_DEVINFO")" -eq 4096
sha256sum "$RESTORED_DEVINFO" "$BACKUP/lun4/devinfo.bin"
cmp "$RESTORED_DEVINFO" "$BACKUP/lun4/devinfo.bin"

两项均验证成功后再复位:

1
"$EDL_PY" "$EDL_SCRIPT" reset --resetmode=reset --loader="$LOADER"

OTA 和日常安全

工厂 ABL 让 root ADB 开机暴露。连接不可信主机前应认识到:这比普通量产系统的攻击面更大。

OTA 可能覆盖活动槽 ABL,使系统恢复 production 模式并关闭 ADB。升级后先检查:

1
adb devices -l

不要为了恢复 ADB 直接重复盲刷。重新进入 9008,读取当前 GPT、活动槽和 ABL 哈希后再决定。

立即停止的情况

出现任一情况就停止写入:

  • loader 无法稳定进入 Firehose;
  • 型号、固件或 GPT 与本文适用范围不一致;
  • 活动槽不是 A;
  • devinfo 不是 4096 B,或没有 ANDROID-BOOT! 魔数;
  • 原始解锁字段不是预期的 0
  • 工厂 ABL 大小或 SHA-256 不匹配;
  • 写前备份没有第二份副本;
  • 写后回读的尺寸、哈希或 cmp 不通过;
  • 相机异常发热、供电不稳或 USB 反复掉线;
  • 操作要求写 GPT、XBL、校准或设备身份分区。

最小且已验证的路径只有:

1
2
3
4
5
6
读取本机 GPT并备份
→ 本机 devinfo 两字节解锁
→ 当前活动槽 A 写入已核验的工厂 ABL
→ engineering 模式启动
→ root ADB
→ Fastboot unlocked: yes

结语

  搞机有风险,折腾需谨慎,一定要记得备份!