目录
Unpack guacamole_21_H.04_190416.ops
背景
严格意义上来说本文应该叫做: <<我本来只是想救个砖,但是却逆向了刷机工具尝试搞清楚android unlock
的原理>> :D
前段时间因为一些工作需求想给手里的测试机(一加7Pro)刷个ColorOS,因为之前想体验Android12,机器是刷了个userdebug的lineageos,遂尝试了卡刷、sideload等之后机器被我搞坏了,开机直接recovery,报错信息是什么 mount fs的时候失败了 :( 没办法只能救转了,逛了一圈论坛发现有人提供9008刷机工具(https://www.oneplusbbs.com/forum.php?mod=viewthread&tid=4730052),通过万能的9008救回来之后,我就想做点别的: 把他的firehose“偷”出来玩玩。
Unpack guacamole_21_H.04_190416.ops
刷机工具解压之后就几个文件,一个刷机工具 msmdownloadtoolv4.0.88,还有个guacamole_21_H.04_190416.ops
,一看就是固件包,然后就是一些完整性校验用的文件。
根据经验,这类刷机包里应该是内置了firehouse的,可以考虑两条路:
-
解包,直接把firehose提出来
-
内存dump,在刷机工具尝试给手机传输firehose的时候的时候内存dump,从内存里根据ELF文件头给截出来
方法2是我最开始尝试的办法,但是dump了几次,发现了好几个ELF,但是都不对,所以尝试方法1 :D 很显然这个包是厂商自己搞得加密,不过网上已经有大佬分析了(早用方法1就少走弯路了),所以根据 How to Extract/Decrypt OnePlus OPS Firmware(https://www.droidwin.com/how-to-extract-oneplus-ops-firmware/) 提供的工具,可以成功吧固件包解开,获取到firehose
# muhe @ muheMacBookAir in ~/Work/play_with_oneplus7pro on git:main x [22:01:37] $ ls -al prog_firehose_* -rw-r--r--@ 1 muhe staff 726400 Oct 28 22:46 prog_firehose_ddr.elf -rw-r--r--@ 1 muhe staff 726272 Oct 28 22:46 prog_firehose_lite.elf
随便试了一把读分区,是可以的,说明firehose是没问题的 :)
然后就想着顺手看点别的,研究研究Qual+Android平台的解锁BL是怎么实现的,遂有了后续的过程。
Unlock探究
开发者选项–允许解锁
参考android-9-r1, 因为现在用的一加的系统的是Android9的
没在开发这里允许解锁BL的话,直接fastboot oem unlock是不行的
-
onOemUnlockConfirmed
https://cs.android.com/android/platform/superproject/+/android-9.0.0_r1:packages/apps/Settings/src/com/android/settings/development/OemUnlockPreferenceController.java;l=132
public void onOemUnlockConfirmed() { mOemLockManager.setOemUnlockAllowedByUser(true); }
-
setOemUnlockAllowedByUser
https://cs.android.com/android/platform/superproject/+/android-9.0.0_r1:frameworks/base/core/java/android/service/oemlock/OemLockManager.java;drc=b45a2ea782074944f79fc388df20b06e01f265f7;l=114
@RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE) public void setOemUnlockAllowedByUser(boolean allowed) { try { mService.setOemUnlockAllowedByUser(allowed); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
-
setOemUnlockAllowedByUser
https://cs.android.com/android/platform/superproject/+/android-9.0.0_r1:frameworks/base/services/core/java/com/android/server/oemlock/OemLockService.java;l=156;drc=b45a2ea782074944f79fc388df20b06e01f265f7;bpv=0;bpt=1
// The user has the final say so if they allow unlock, then the device allows the bootloader // to OEM unlock it. @Override public void setOemUnlockAllowedByUser(boolean allowedByUser) { if (ActivityManager.isUserAMonkey()) { // Prevent a monkey from changing this return; } enforceManageUserOemUnlockPermission(); enforceUserIsAdmin(); final long token = Binder.clearCallingIdentity(); try { if (!isOemUnlockAllowedByAdmin()) { throw new SecurityException("Admin does not allow OEM unlock"); } if (!mOemLock.isOemUnlockAllowedByCarrier()) { throw new SecurityException("Carrier does not allow OEM unlock"); } mOemLock.setOemUnlockAllowedByDevice(allowedByUser); setPersistentDataBlockOemUnlockAllowedBit(allowedByUser); } finally { Binder.restoreCallingIdentity(token); } }
-
setPersistentDataBlockOemUnlockAllowedBit
https://cs.android.com/android/platform/superproject/+/android-9.0.0_r1:frameworks/base/services/core/java/com/android/server/oemlock/OemLockService.java;drc=b45a2ea782074944f79fc388df20b06e01f265f7;bpv=0;bpt=1;l=232
/** * Always synchronize the OemUnlockAllowed bit to the FRP partition, which * is used to erase FRP information on a unlockable device. */ private void setPersistentDataBlockOemUnlockAllowedBit(boolean allowed) { final PersistentDataBlockManagerInternal pdbmi = LocalServices.getService(PersistentDataBlockManagerInternal.class); // if mOemLock is PersistentDataBlockLock, then the bit should have already been set if (pdbmi != null && !(mOemLock instanceof PersistentDataBlockLock)) { Slog.i(TAG, "Update OEM Unlock bit in pst partition to " + allowed);