做完硬件断点记录器后就开始研究如何隐藏Android的Bootloader锁了,当然最近没啥兴趣继续研究了,把目前为止的思路发出来
首先想到的一个方向是要先spoof安卓Setting里的oemlock status
在aoxpxref网站上搜索
bootloader unlocked
看到一个可疑的文件
/frameworks/base/core/java/android/service/oemlock/OemLockManager.java
xref 找到
/frameworks/base/services/core/java/com/android/server/oemlock/OemLockService.java
看到函数
可以看到Setting检测的是系统属性 ro.boot.flash.locked 来判断Bootloader是否解锁
AOSP搜索ro.boot.flash.locked,发现/system/core/init/init.cpp 有初始化该属性值的代码
ro.boot.flash.locked 的值是受到 ro.boot.verifiedbootstate 的值影响
google搜了一下后面的这个属性,发现这个属性可能的值有red,orange,yellow,green
看到一个隐藏bl锁的github项目
b25K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6@1L8%4m8B7L8$3S2F1N6%4g2Q4x3V1k6y4j5h3N6A6M7$3E0Q4x3V1k6T1L8r3!0T1i4K6u0r3x3$3x3H3y4r3c8S2j5U0b7%4x3U0M7@1k6e0W2T1j5X3u0X3j5U0y4V1k6r3b7I4k6X3y4X3y4K6q4U0z5e0t1&6j5K6S2W2k6o6m8U0x3q4)9J5c8X3&6S2N6r3W2$3k6g2)9J5c8X3A6F1K9g2)9J5c8X3#2S2k6$3W2K6K9$3S2A6k6r3g2Q4x3V1k6Z5K9h3c8W2i4K6g2X3M7r3!0D9K9h3y4&6i4K6u0W2j5%4m8H3i4K6t1K6e0o6p5J5
看到替换表
可以确定green是bl未解锁,还有一个 ro.boot.vbmeta.device_state 要改成locked状态,实机看这个属性解锁bl状态下是unlocked,除了前三个之外其他属性解bl之后没变
还有 googleplay service 的验证
9d7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2S2L8X3c8J5L8$3W2V1i4K6u0W2j5$3!0E0i4K6u0r3N6s2u0S2K9h3&6A6L8X3N6Q4x3V1k6K6j5h3k6W2N6s2W2F1k6i4c8Q4x3V1k6S2N6s2c8W2M7%4c8S2N6r3W2G2L8R3`.`.
011K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2S2L8X3c8J5L8$3W2V1i4K6u0W2j5$3!0E0i4K6u0r3k6$3!0G2k6$3I4W2i4K6u0r3M7r3I4S2P5g2)9J5c8X3W2F1N6r3g2Y4M7X3W2@1P5g2)9J5c8X3!0$3k6i4u0$3K9h3g2%4
对应的解决方案是
0d6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6C8k6s2u0S2k6K6m8F1i4K6u0r3M7$3q4X3k6i4c8&6L8X3g2@1i4K6u0V1k6X3W2^5
这个问题不大,国内又不用googleplay service
按照上述总结一下,隐藏bl锁需要修改以下属性
Java层最终会调用native_get方法获取Property的值
顺着native_get 找到函数__system_property_find 这个是用户层标准的获取property值的函数,来自libc.so,往下翻就是android property系统的实现了,可以看这篇文章
https://bbs.kanxue.com/thread-274100.htm
进用户层初始化property service的地方
/system/core/init/property_service.cpp
找到函数 PropertyInit 从名字猜测这是init进程初始化系统基本property值的地方,ProcessBootconfig和ProcessKernelCmdline最后是通过读取/proc/bootconfig和/proc/cmdline调用_system_property_add来设置ro.boot.verifiedbootstate和ro.boot.vbmeta.device_state的值
cat一下这两个设备文件,确实有相关信息
我想到了三个思路
kernel版本 5.10.168 路径/common/fs/proc/bootconfig.c 中的proc_boot_config_init 函数初始化了/proc/bootconfig的输出,顺着全局变量 xbc_data 找到系统获取bootconfig的地方/common/init/main.c -> setup_bootconfig , 可以看到bootconfig是从initrd里拿的

将返回的data copy进全局变量,然后由驱动打印出来看到数据
尝试文本替换
实验发现替换 uuid 和 vbmeta.device_state 系统正常启动,一旦修改 verifiedbootstate 系统就无法启动了,第一个思路就结束在这里了
先说结果: 成功了!!!!!!
安卓的linker使用的是mmap映射的elf文件,hook do_mmap的返回处,判断pgoff和filepath就能拦截到init进程加载libc.so,在这个时机里对_system_property_add函数下execute hook,
hook回调里对参数进行简单处理
修改成功

成功 Spoof Setting

第三个方法暂时没试过,感兴趣的可以试试看
有空就把第二个思路用kprobe来实现hook,包装成驱动连带硬件断点记录器分别开源到github上
刚入坑安卓,如有不对的地方或者有其他方法检测bl锁请大佬们在评论区指出!!!
private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
private static final String FLASH_LOCK_UNLOCKED = "0"
public boolean isDeviceOemUnlocked() {
enforceOemUnlockReadPermission();
String locked = SystemProperties.get(FLASH_LOCK_PROP);
switch (locked) {
case FLASH_LOCK_UNLOCKED:
return true;
default:
return false;
}
}
private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
private static final String FLASH_LOCK_UNLOCKED = "0"
public boolean isDeviceOemUnlocked() {
enforceOemUnlockReadPermission();
String locked = SystemProperties.get(FLASH_LOCK_PROP);
switch (locked) {
case FLASH_LOCK_UNLOCKED:
return true;
default:
return false;
}
}
static void export_oem_lock_status() {
if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
return;
}
SetProperty(
"ro.boot.flash.locked",
android::base::GetProperty("ro.boot.verifiedbootstate", "") == "orange" ? "0" : "1");
}
static void export_oem_lock_status() {
if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
return;
}
SetProperty(
"ro.boot.flash.locked",
android::base::GetProperty("ro.boot.verifiedbootstate", "") == "orange" ? "0" : "1");
}
static const char *prop_key[] =
{ "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked",
"ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
"ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags",
"ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit",
"vendor.boot.vbmeta.device_state", nullptr };
static const char *prop_val[] =
{ "locked", "green", "1",
"enforcing", "0", "0",
"0", "1", "user", "release-keys",
"0", "0",
"locked", nullptr };
static const char *prop_key[] =
{ "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked",
"ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
"ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags",
"ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit",
"vendor.boot.vbmeta.device_state", nullptr };
static const char *prop_val[] =
{ "locked", "green", "1",
"enforcing", "0", "0",
"0", "1", "user", "release-keys",
"0", "0",
"locked", nullptr };
| Property |
Value |
| ro.boot.flash.locked |
1 |
| ro.boot.verifiedbootstate |
green |
| ro.boot.vbmeta.device_state |
locked |
adb shell su -c cat /proc/bootconfig
androidboot.hardware = "qcom"
androidboot.memcg = "1"
androidboot.usbcontroller = "a600000.dwc3"
androidboot.bootdevice = "1d84000.ufshc"
androidboot.boot_devices = "soc/1d84000.ufshc"
androidboot.prjname = "22803"
androidboot.startupmode = "pwrkey"
androidboot.mode = "normal"
androidboot.product.hardware.sku = "0"
androidboot.hw_region_id = "1"
androidboot.serialno = "xxxxxxx"
androidboot.baseband = "msm"
androidboot.dtbo_idx = "12"
androidboot.dtb_idx = "1"
androidboot.force_normal_boot = "0"
androidboot.fstab_suffix = "default"
androidboot.verifiedbootstate = "orange"
androidboot.keymaster = "1"
androidboot.vbmeta.device = "PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
androidboot.vbmeta.avb_version = "1.0"
androidboot.vbmeta.device_state = "unlocked"
androidboot.vbmeta.hash_alg = "sha256"
androidboot.vbmeta.size = "23232"
androidboot.vbmeta.digest = "xxxxx"
androidboot.vbmeta.invalidate_on_error = "yes"
androidboot.veritymode = "enforcing"
androidboot.slot_suffix = "_a"
adb shell su -c cat /proc/bootconfig
androidboot.hardware = "qcom"
androidboot.memcg = "1"
androidboot.usbcontroller = "a600000.dwc3"
androidboot.bootdevice = "1d84000.ufshc"
androidboot.boot_devices = "soc/1d84000.ufshc"
androidboot.prjname = "22803"
androidboot.startupmode = "pwrkey"
androidboot.mode = "normal"
androidboot.product.hardware.sku = "0"
androidboot.hw_region_id = "1"
androidboot.serialno = "xxxxxxx"
androidboot.baseband = "msm"
androidboot.dtbo_idx = "12"
androidboot.dtb_idx = "1"
androidboot.force_normal_boot = "0"
androidboot.fstab_suffix = "default"
androidboot.verifiedbootstate = "orange"
androidboot.keymaster = "1"
androidboot.vbmeta.device = "PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
androidboot.vbmeta.avb_version = "1.0"
androidboot.vbmeta.device_state = "unlocked"
androidboot.vbmeta.hash_alg = "sha256"
androidboot.vbmeta.size = "23232"
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2023-8-17 23:40
被cslime编辑
,原因: 修复图片