Несколько лет назад один из членов нашей команды заказал себе OnePlus 6T прямо из Китая. Телефон пришел в оригинальной упаковке и типовой комплектации: с зарядным устройством, кабелем и чехлом. Смартфон без проблем проработал год, ничем, на первый взгляд, не отличаясь от тех, что продаются в России.
Но однажды приложения начали предупреждать о наличии root-доступа, а некоторые, особенно банковские, вообще перестали запускаться. При этом прошивка никаким образом не модифицировалась, а обновления устанавливались исключительно из официальных источников, относящихся к ОС. Такое странное поведение смартфона побудило нас провести исследование, результаты которого описаны в этой статье.
0. Поиск причины
Какое-то время нам не удавалось понять, в чем причина такого поведения приложений. Устройство проходило проверку Play Integrity Strong, а также подтверждалась подлинность цепочки загрузки при проверке аттестации приложением Key Attestation.
Через некоторое время стало ясно, что причиной такого поведения стали установленные параметры ro.debuggable=1
и ro.adb.secure=0
. Разобраться в этом оказалось довольно просто: после множества тщетных попыток понять, в чем проблема, мы попытались выполнить команду adb root
. В результате adb shell
запустился с правами root без каких-либо ошибок:
Демон adbd осуществляет проверку параметра ro.debuggable при сбросе привилегий с root до shell (без него невозможно подключиться клиентом, сохранив права root), а параметр ro.adb.secure влияет на необходимость аутентификации при подключении adb-клиента.
OnePlus6T:/ # getprop|grep ro.debug
[ro.debuggable]: [1]
OnePlus6T:/ # getprop|grep ro.adb
[ro.adb.secure]: [0]
Встал вопрос: как такое возможно?
Наличие параметра androidboot.verifiedbootstate=green
в командной строке ядра свидетельствует о заблокированном с ключами производителя загрузчике, что в свою очередь исключает компрометацию посредством повторной блокировки устройства. Это подтверждается тем, что устройство успешно проходило проверку play integrity. В случае разблокировки параметр verifiedbootstate
изменяется на orange
(или yellow
после повторной блокировки), и при включении устройства отображается соответствующее окно .
При перезапуске устройства в режиме recovery, оно также предоставляло рутовый шел через adb – это и начинало наводить на определенные мысли.
1. Как прошивка с включенной возможностью отладки попала в release-сборку?
Для анализа ситуации с использованием root-доступа был получен лог загрузки устройства (/proc/bootloader_log
). Наиболее интересным в нем оказался фрагмент, содержащий командную строку запуска ядра:
OemCmdLine
OemInfo.OemCmdLine len 805
Cmdline: androidboot.hardware=qcom androidboot.console=ttyMSM0 video=vfb:640x400,bpp=32,memsize=3072000 msm_rtb.filter=0x237 ehci-hcd.park=3 lpm_levels.sleep_
Cmdline: disabled=1 service_locator.enable=1 swiotlb=2048 androidboot.configfs=true loop.max_part=7 androidboot.usbcontroller=a600000.dwc3 rootwait ro init=/i
Cmdline: nit buildvariant=user androidboot.verifiedbootstate=green androidboot.keymaster=1 dm="1 vroot none ro 1,0 5764704 verity 1 PARTUUID=58c917ed-d09f-07d
Cmdline: 1-c7af-88f6e15beec8 PARTUUID=58c917ed-d09f-07d1-c7af-88f6e15beec8 4096 4096 720588 720588 sha1 97af17c8d79629d048c11ad4058f343124279389 61efba56aa1fa
Cmdline: 6397190a518f0aa794bbd02a7f604536e1a402ccb5f173614b7 10 restart_on_corruption ignore_zero_blocks use_fec_from_device PARTUUID=58c917ed-d09f-07d1-c7af-
Cmdline: 88f6e15beec8 fec_roots 2 fec_blocks 726263 fec_start 726263" root=/dev/dm-0 androidboot.vbmeta.device=PARTUUID=c3e4fce8-096e-a707-d9d8-74da4faf0882 a
Cmdline: ndroidboot.vbmeta.device=PARTUUID=c3e4fce8-096e-a707-d9d8-74da4faf0882 androidboot.vbmeta.avb_version=1.0 androidboot.vbmeta.device_state=locked andr
Cmdline: oidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=7616 androidboot.vbmeta.digest=5ae631ed1c9936e5ea64c854419ef7d150b317798975bc7d94fe444267daeac
Cmdline: 2 androidboot.vbmeta.invalidate_on_error=yes androidboot.veritymode=enforcing androidboot.bootdevice=1d84000.ufshc androidboot.fstab_suffix=default a
Cmdline: ndroidboot.serialno=221e6695 androidboot.baseband=msm msm_drm.dsi_display0=dsi_samsung_s6e3fc2x01_cmd_display: androidboot.slot_suffix=_b skip_initra
Cmdline: mfs rootwait ro init=/init androidboot.dtbo_idx=21 androidboot.dtb_idx=1 panel_type=black androidboot.mode=normal androidboot.recoveryreason=000 andr
Cmdline: oidboot.project_name=18811 androidboot.project_codename=fajitat ddr_manufacture_info=Samsung ddr_row0_info=16 androidboot.hw_version=41 androidboot.r
Cmdline: f_version=11 androidboot.prj_version=0 androidboot.platform_id=321 androidboot.platform_name=SDM845 androidboot.startupmode=hard_reset androidboot.en
Cmdline: able_dm_verity=1 androidboot.at_location=factory androidboot.power_cut_test=0 androidboot.secboot=enabled androidboot.battery.absent=false androidboo
Cmdline: t.rpmb_enable=true androidboot.type=sdebug androidboot.product.hardware.sku=3 androidboot.logcat_log_level=49 androidboot.init_log_level=49 androidbo
Cmdline: ot.selinux_log_level=842348088 androidboot.cust=0 androidboot.prmec=true androidboot.opcarrier=none androidboot.bootcount=1919247457
В глаза бросился нестандартный параметр androidboot.type=sdebug
. Хотя сам по себе флаг androidboot.type
не является чем-то уникальным, упоминаний его выставления в sdebug
оказалось немного. В ходе поиска удалось найти скрипт init.oem.rc
, включающий adb (в том числе в режиме зарядки) в случае, если устройство запущено в режиме sdebug
:
on property:sys.boot_completed=1 && persist.vendor.usb.config=none && property:ro.boot.type=sdebug
setprop persist.sys.usb.config adb
...
on charger && property:ro.boot.type=sdebug
setprop sys.usb.config adb
Однако на исследуемом устройстве этот файл найти не удалось (позднее выяснилось, что он был встроен в бинарный файл init
). Тогда было принято решение изучить все элементы цепочки загрузки устройства в надежде найти место включения режима отладки. К этому моменту стало очевидно, что данный функционал устройства каким-то образом связан с оставленным производителем бэкдором.
В 2017 году в устройствах OnePlus уже находили бэкдор. Однако с того момента прошло уже 4 года (на устройстве стоит прошивка 2021 года).
Анализ процесса загрузки показал, что в бинарном файле init
присутствует логика обработки данного параметра.
В функции android::init::PropertyLoadBootDefaults
происходит обработка параметра ro.boot.type
. В случае, если он имеет значение sdebug
, выставляются параметры ro.debuggable=1
и ro.adb.secure=0
, что и можно наблюдать на устройстве. Кроме того, в приведенном ниже фрагменте кода видно, что параметр ro.boot.verifiedbootstate
при этом выставляется в orange
:
Фрагмент кода init загрузчика
...
std::string value = android::base::GetProperty("ro.boot.type", empty_str);
if(std::string::compare(value, 5, "debug")){
android::base::SetProperty("ro.secure", "0");
android::base::SetProperty("ro.adb.secure", "0");
android::base::SetProperty("ro.boot.verifiedbootstate", "orange");
android::base::SetProperty("ro.debuggable", "1");
android::base::SetProperty("ro.force.debuggable", "1");
}
if(std::string::compare(value, 6, "sdebug")){
android::base::SetProperty("ro.adb.secure", "0");
android::base::SetProperty("ro.boot.verifiedbootstate", "orange");
android::base::SetProperty("ro.debuggable", "1");
android::base::SetProperty("ro.force.debuggable", "1");
}
...
Но если проверить свойство ro.boot.verifiedbootstate
, его значение будет green
. Неужели этот код не выполняется, и выставление параметров осуществляется в каком-то другом месте?
OnePlus6T:/ # getprop ro.boot.verifiedbootstate
green
Как оказалось, все намного проще: свойства типа ro
в init
процессе с использованием функции android::base::SetProperty
можно выставить только один раз. Первоначально init
реализует обработку командной строки ядра в функции ProcessKernelCmdline, где и выставляет передаваемые с префиксом androidboot.
аргументы ядра в качестве параметров с префиксом ro.boot.
. В том числе выставляется параметр ro.boot.verifiedbootstate=green
, поскольку в командной строке было передано значение androidboot.verifiedbootstate
. И только после этого вызывается функция android::init::PropertyLoadBootDefaults
.
Не углубляясь в исходный код
init
, достаточно заметить, что в функцииandroid::init::PropertyLoadBootDefaults
уже используется параметрro.boot.type
. Следовательно он должен быть выставлен ранее.
Погрузимся глубже.
2. Как в командную строку ядра Android попала строка androidboot.type=sdebug?
Если вы не знакомы с тем, как устроен процесс загрузки современного Android-устройства, рекомендуем познакомиться с этой статьей.
Опустим детали и сразу перейдем к фрагменту реализации загрузчика LinuxLoader
, запускаемого на финальном шаге.
Данный загрузчик имеет GUID
F536D559-459F-48FA-8BBC-43B554ECAE8D
и, судя по всему, основан на предоставляемом qualcomm edk2 приложении.
При поиске по строкам значения sdebug
можно достаточно быстро обнаружить следующий участок кода:
boot_tag = get_boot_tag();
switch (boot_tag){
case 0xB8:
boot_type = "nonrelease";
break;
case 0xA9E:
boot_type = "sdebug";
break;
case 0xA0:
boot_type = "auto";
break;
case 0xB7:
boot_type = "debug";
break;
default:
boot_type = "normal";
break;
}
AsciiVSPrint(&buf, 64, " androidboot.type=%a", &boot_type);
set_sdebug_boot_type(&buf);
В зависимости от возвращаемого функцией get_boot_tag
значения выставляется аргумент androidboot.type
, который затем помещается в передаваемую ядру командную строку (детали этого процесса опустим).
Функция get_boot_tag
в свою очередь реализует получение параметра из хранилища param
(размещается в одноименном разделе прошивки). Для изменения этого значения в коде загрузчика реализована функция set_boot_tag
:
int get_boot_tag(){
int tmp;
get_param_by_index_and_offset(0x12Cu, 0x84u, &tmp, 4u);
return tmp;
}
void set_boot_tag(int* tag){
set_param_by_index_and_offset(0x12Cu, 0x84u, tag, 4u);
}
Парсер
param
секции устройств OnePlus реализован тут, более подробно с форматом можно ознакомиться там же.
Таким образом, приходим к выводу, что появление параметра androidboot.type=sdebug
в командной строке ядра напрямую связано с неким параметром, хранимым в секции param
устройства. Попробуем продолжить цепочку и разобраться, как же он туда попал.
Если взглянуть на вызовы функции set_boot_tag
, можно наткнуться на единственную ссылку из обработчика "секретной" команды ops boottype
:
int ops_boottype_handler(wchar_t *arg){
int tmp
get_param_intranet(&tmp);
if ( (get_boot_tag() != 0xA9E || !tmp)
&& !enable_advanced_ops )
{
fastboot_fail("unknown command");
return;
}
DebugPrint(0x80000000, "fastboot cmdlist: cmdname=%s\n", arg);
tmp = strcmp(arg, L" normal");
if ( tmp )
{
if ( !strcmp(arg, L" auto") )
{
tmp = 0xA0;
}
else if ( !strcmp(arg, L" debug") )
{
tmp = 0xB7;
}
else if ( !strcmp(arg, L" sdebug") )
{
tmp = 0xA9E;
}
else if ( !strcmp(arg, L" nonrelease") )
{
tmp = 0xB8;
}
else{
fastboot_fail((__int64)"unknown command");
return;
}
}
set_boot_tag(tmp);
fastboot_okay("");
return;
}
Команда "секретная", поскольку ее обработчик объявлен в общей таблице со всеми командами типа ops
, наименование которых хранится в закодированном виде. Полный список команд приведен под спойлером. Помимо безобидных команд также поддерживается изменение режима работы selinux (ops selinux
), отключение и включение dm verity (ops disable_dm_verity
и ops enable_dm_verity
). И все это – на заблокированном загрузчике без каких-либо следов вмешательства после восстановления оригинального значения параметров.
Таблица поддерживаемых команд ops
encoded_cmds_60720[] = {
"jqtxsth%xut", ops_console,
"jqtxsthsz%xut", ops_unconsole,
"yhjyji%pfjqrjrp%xut", ops_kmemleak_detect,
"yhjyjisz%pfjqrjrp%xut", ops_kmemleak_undetect,
"s|tiyzmx2yttgjw%xut", ops_reboot_shutdown,
"wjiftqyttg2yttgjw%xut", ops_reboot_bootloader,
"lsnsnfwydjhwtk%xut", ops_force_training,
"lsnsnfwydjhwtksz%xut", ops_unforce_training,
"xkfyfi%xut", ops_datafs,
"uqjm%xut", ops_help,
"urzi%xut", ops_dump,
"}zsnqjx%xut", ops_selinux,
"jitrdyttg%xut", ops_boot_mode,
"65K:IYXK<WYK=6WY5955:K9%xut", ops_4F50040TR18FTR7FSTD5F01,
"75K:IYXK<WYK=6WY5955:K9%xut", ops_4F50040TR18FTR7FSTD5F02,
"~ynwj{dridjqgfxni%xut", ops_disable_dm_verity,
"~ynwj{dridjqgfsj%xut", ops_enable_dm_verity,
"xkurjy%ysztr%xut", ops_mount_tempfs,
"xkurjy%ysztrsz%xut", ops_unmount_tempfs,
"lrndfyfidlsnlfjv%xut", ops_qeaging_data_img,
"gifdjhwtk%xut", ops_force_adb,
"yxzhdyjx%xut", ops_set_cust,
"ju~yyttg%xut", ops_boottype,
"lxrp{ji%xut", ops_devkmsg,
"qj{jqdltqdqjswjp%xut", ops_kernel_log_level,
"qj{jqdltqdyfhltq%xut", ops_logcat_log_level,
"qj{jqdltqdynsn%xut", ops_init_log_level,
"qj{jqdltqd}zsnqjx%xut", ops_selinux_log_level,
"kwd|mdowu%xut", ops_prj_hw_rf,
"tksn2jhn{ji%xut",ops_device_info,
"stnyfhtqdyf%xut",ops_at_location,
"yxjydyzhdwj|tu%xut",ops_power_cut_test,
"yjxjwdrwf|dhnru%xut",ops_pmic_warm_reset,
"owudxzqut%xut",ops_oplus_prj,
"nxyidxzqut%xut",ops_oplus_dtsi,
"lfqkiftqidwj{thjw%xut",ops_recover_dloadflag,
}
Все эти функции добавляются в связный список обработчиков команд `fastboot` в декодированном виде функцией `fastboot_add_encoded_cmd` (наименование автора). Декодирование наименований команд производится при помощи простого алгоритма:
def decode(cmd):
res = ""
for i in cmd[::-1]:
res += chr(ord(i)-5)
return res
В основном цикле обработки fastboot-команд можно видеть некоторые условия их выполнения. Для большей загадочности в функции `is_ops_commands` проверяемая команда предварительно кодируется и в таком виде сравнивается со значением `xut`:
if ( !is_ops_commands(cmd->prefix) || get_ops_allowed() || get_param_intranet_status())
{
cmd->handle(&input_cmd[cmd->prefix_len], download_base, download_size);
}
else
{
fastboot_fail("unknown command");
}
Остается разобраться с функцией get_ops_allowed
. Она возвращает некоторое значение op_token_count
, которое обнуляется в нескольких случаях: загадочной командой oem unoproot
, по истечении 10 загрузок устройства (не во всех случаях) или выполнения команды ops 4F50040TR18FTR7FSTD5F02
. Ненулевым значением данная переменная инициализируется только в случае выполнения команды flash:oproot
с некоторым подписанным на ключе платформы токеном. Куда интереснее непонятный параметр intranet
, выставление которого в значение 3
также приводит к разблокировке описанных выше команд.
3. Как выключить этот режим?
Целью было выключение неведомого режима, а поскольку стандартная реализация fastboot не позволяет отправлять команды типа ops
для взаимодействия с устройством, был использован пакет adb для python:
from adb import fastboot
fastboot_dev = fastboot.FastbootCommands()
fastboot_dev.ConnectDevice()
fastboot_dev._SimpleCommand(b"ops 4F50040TR18FTR7FSTD5F01")
fastboot_dev._SimpleCommand(b"ops boottype normal")
fastboot_dev._SimpleCommand(b"ops 4F50040TR18FTR7FSTD5F02")
В результате выполнения скрипта root-доступ на устройстве исчез, а выполнение команд ops
стало невозможным.
4. А как вернуть это режим?
После выполнения пункта 3 возник вопрос: а возможно ли вернуть этот режим?
Уже после блокировки данного режима выяснилось, что для его разблокировки необходимо иметь специальный подписанный на ключе производителя токен. Получить помещаемые в токен данные можно командой oem oproot
, а разблокируется данный режим путем прошивки специального файла oproot (flash:oproot
).
Дабы продолжить эксперименты с рутованным девайсом, было принято решение воспользоваться инструментом edl для прошивки на устройство модифицированного раздела param
. Путем выполнения нехитрых команд root-доступ был успешно восстановлен:
edl printgpt
edl r param param.bin
py op8t_param.py read -f param.bin
py op8t_param.py write -f param.bin -o param_patched.bin 16 2718
edl w param param_patched.bin
Также удивило и то, что в репозитории edl нашелся скрипт oneplus_param.py
, судя по всему основанный на результатах исследований APK-файла из выявленного в 2017 году бэкдора.
В скрипте подробно описаны варианты значений различных флагов этого раздела и перечислены команды ops
. Также в нем представлен код для генерации QR для разблокировки с использованием инженерного приложения. На прошивке 2021 года данная процедура не актуальна.
Послесловие
Точно выяснить историю включения этого режима на устройстве, увы, уже не представляется возможным. Предположительно его появление связано с перепрошивкой на глобальную версию с помощью MSM Download Tool, проведенной перед продажей устройства. Впоследствии смартфон получал обновления, но активированный режим продолжал функционировать и был замечен благодаря усилению antiroot-механизмов в банковских приложениях.
Надеемся, что данная статья позволила вам глубже погрузиться в особенности работы смартфонов OnePlus и осознать, что даже самые современные устройства могут таить в себе неожиданные сюрпризы. Дальнейшие исследования этого функционала вряд ли имеют смысл, так как сейчас он представляет больше исторический интерес и отсутствует на новых моделях (по крайней мере, проверялся OnePlus 12).
Если у вас есть схожий опыт или интересные мысли по теме, делитесь ими в комментариях!
Комментарии (10)
kenomimi
20.12.2024 09:02Это бекдор со знаком плюс.
Китайские вендоры днищевого эшелона знают, что их устройства почти все рутуют - иначе этим добром пользоваться сложно ввиду кривого софта. Запилить хороший софт мешает экономика - устройство будет дорогим, и его никто не купит. Но всякие нехорошие люди из сертификации не дают право выбора пользователю, как ему использовать устройство, там жесткая диктатура - жри чего дали, барину видней, что тебе надо. Потому китайцы оставляют довольно очевидные дыры, чтобы не мешать пользователю делать то, что он хочет, но при этом обманом пройти сертификации.
dartraiden
20.12.2024 09:02Никакая сертификация не запрещает предоставлять пользователю возможность разблокировки загрузчика. Собственно даже сама Google на своих Pixel эту возможность предоставляет.
Просто у нормальных вендоров это делается через что-то типа
fastboot flashing unlock
, а не вот так, как описано в статье.sngvy
20.12.2024 09:02Да не делается это так, как описано в статье. Для современных OnePlus разблокировка осуществляется через их же приложение, которое отдает с сервера ключ для разблокировки, после чего идём в фастбут и посылаем упомянутую выше команду
qw1
20.12.2024 09:02Google даёт разблокировать загрузчик самостоятельно.
Но другие производители делают разблокировку только через свои онлайн-сервисы.
Я недавно изучал ситуацию с Xiaomi (хорошее железо за небольшие деньги) по темам на 4pda, и оказалось, что для подачи заявки на разблокировку нужно иметь Mi-Account созданный минимум месяц назад, в среднем коды приходят за несколько суток, но некоторым счастливчикам не приходят вовсе. В телефоне должна стоять сим-карта местного оператора и интернет через неё, чтобы проверить географическое расположение.Я пока в больших раздумьях, нужны ли мне такие приключения, или лучше переплатить x3 и взять Pixel.
sngvy
20.12.2024 09:02С каких пор OnePlus относится к днищевому эшелону? Их устройства для глобального рынка вполне комфортные для использования из коробки без напильника
dartraiden
20.12.2024 09:02"Свободные" прошивки типа LineageOS тоже этим грешат. Пользователи в массе своей не знают, что официальные билды LOS идут в варианте userdebug, что позволяет атакующему получить права суперпользователя, даже если смартфон не рутован, и даёт пользователю ложное чувство защищённости.
kenomimi
20.12.2024 09:02Для "свободных" прошивок важно больше то, что из них вырезаны мусорные маркетинговые сервисы, которые что-то куда-то отправляют (оставляют след), жрут батарею и для пользователя бесполезны. Возможность отобрать у приложения права, или подсунуть ему левые данные, если оно эти права требует в обязательном порядке. Именно это понимается под безопасностью. Бытовая безопасность, так сказать цифровая гигиена, но никак не игра в супершпиона.
Если кто-то настолько интересен органам некой страны, что ради него будут в том же аэропорту держать "на стреме" бригаду безумно дорогих специалистов по взлому - штош, такой купит нормальное защищеное решение, либо ему выдадут оное по службе.
LuigiVampa
20.12.2024 09:02Спасибо за интереснейшее исследование и отличную статью! Нечасто увидишь материал такого качества. В очередной раз убеждаюсь в том, насколько мутно и ненормально многие производители устройств реализуют логику загрузки операционной системы.
Если говорить в целом, то у Гугла предусмотрен интерфейс, через который предполагается управление статусом блокировки загрузчика и сопутствующих этому изменений. Это то самое "fastboot flashing unlock/lock". Предполагалось, что производители устройств будут интегрировать свои загрузчики именно с ним.
Тем не менее, несложно обратить внимание на то, что в реальности абсолютное большинство устройств, за единичными исключениями вроде Гугл Пикселей, где Гугл честно и по правилам реализовал эту интеграцию, используют для управления статусом блокировки загрузчика команды в духе "fastboot oem unlock/lock". Кажется, что "ну какая разница? просто по другому команда называется", но нет, на самом деле разница очень серьёзная.
В то время как "fastboot flashing" - это специально определённый механизм для блокировки/разблокировки загрузчика, то "fastboot oem" - это интерфейс для передачи произвольных команд, которые определяет производитель устройства сам. Производитель сам определяет формат, сам определяет состав, сам определяет логику реализации этих команд. В принципе там может быть реализовано что угодно и как угодно. По изначальной задумке, этот механизм нужен для реализации на уровне fastboot протокола разной нестандартной логики, специфичной для аппаратной платформы, что вообще-то вполне логично. Однако, производителям также очень легко злоупотребить этим и реализовать в нём также и то, реализация чего предполагается в совершенно другом месте.
Производители, конечно, реализуют блокировку/разблокировку именно через "fastboot oem", потому что это даёт им очень многое. Во-первых, это позволяет не соблюдать полные требования интерфейса "fastboot flashing" которые включают довольно большой набор разных состояний, включая, например, поддержку доверенной загрузки с определяемым пользователем корнем доверия - а это значит что и работы нужно сделать меньше, и контроля на стороне пользователя меньше - проще огородить от исследователей свою систему. Во-вторых, это позволяет производителям устройств уклоняться от требований по возможности предоставления пользователю разблокировки загрузчика - например неоправданно усложнять процесс, делать его нестандартным, к примеру, требовать дополнительный код разблокировки или отсылать в процессе на свои сервера кучу разных данных о том кто, где, как, когда, на каком устройстве запросил разблокировку и т.д. (привет Ксяоми). А дальше, видимо, это вполне можно использовать чтобы ссылаясь на это отказать в гарантийном обслуживании (или понизить социальный рейтинг как слишком умному /s). В-третьих, и это самое главное, Гугл для прохождения сертификации устройства не требует прохождения тестов правильной реализации интерфейса "fastboot flashing" от сторонних производителей. Это рекомендуется, но обязательным для сертификации не является, в результате практически никто этого и не делает, а все с удовольствием срезают углы на "oem" вариантах.
Честно говоря, я так глубоко как автор статьи не копал, но судя по информации в статье, ВанПлюсы пошли ещё дальше и вообще реализовали ещё один дополнительный кастомный слой команд "ops", в который ещё дополнительных мутных возможностей накрутили. В общем то, после такого и перестаёшь удивляться успехам инструментов по извлечению данных для криминалистики типа Cellebrite, "Мобильный Криминалист" и подобных им, которые какой-то очень существенный процент существующих на рынке моделей устройств ломают именно через незадокументированные возможности на уровне fastboot. И фаззеры для поиска незадокументированных команд в fastboot режиме тоже не просто так пишутся.
LuigiVampa
20.12.2024 09:02Кстати, добавлю ещё интересный момент конкретно про устройства OnePlus. Когда несколько лет назад я готовил упомянутую в тексте статью, я все действия производил на OnePlus 5T, который по своей низкоуровневой начинке очень похож на 6Т. Насколько я понимаю, модели OnePlus 5/5T/6/6T имеют вообще достаточно небольшие различия между собой.
Одной из интереснейших их особенностей является то, что на некоторых OnePlus-ах, в которые входят как раз вышеупомянутые модели, есть возможность закрывать загрузчик на нестоковой прошивке (на xda энтузиасты обнаружили), т.к. у них то ли частично, то ли может быть как-то отдельно, по своему, была реализована возможность поддержки определяемого пользователем корня доверия. Сильно точнее детали не подскажу, но у них был выделен доступный к прошивке из fastboot раздел "avb_custom_key". Насколько я понимаю, кстати, эта возможность сохранилась и на некоторых других, более поздних устройствах производителя.
Механизм этот, видимо, также эволюционировал со временем, от более старых моделей устройств к более новым, т.к. требовал определённой минимальной версии firmware, которую нужно было скачать с сайта производителя и зашить на устройство, а также имел свои особенности. Так для модели 5Т было достаточно просто сгенерировать RSA ключ, преобразовать его в специальный формат, подписать внешним инструментом разделы, после чего прошить их как обычно, а ключ прошить в вышеупомянутый раздел "avb_custom_key", то для более поздних моделей OnePlus уже необходимо было немного попатчить сорцы, например того же LineageOS или AOSP, и собирать уже сборку с включёнными хэшами разделов и небольшой дополнительной для сборки логикой, чтобы всё корректно заработало.
Я тогда тоже, благодаря удачному устройству на руках, довольно много поэкспериментировал с тем, чтобы получить на устройстве "жёлтый" статус, когда операционная система установлена не стоковая, разделы подписаны не аппаратными ключами, а ключами из раздела, которые зашил сам пользователь, но загрузчик при этом закрыт, avb работает, и т.д. И у меня это получилось, конкретно - на том самом OnePlus 5T. Я запускал LineageOS на заблокированном загрузчике и даже портировал ради интереса тогда ещё riru модуль xposed, который у меня также работал на системе, чтобы завести "из системы" XPrivacyLua, и это тоже всё работало, с заблокированным загрузчиком.
Я обратил внимание вот на какую штуку, которую тогда в материале не упомянул. Однажды я решил поэкспериментировать и посмотреть как вживую работает dm-verity. Собрал сборку LineageOS с функционалом рута из коробки (дело было давненько, тогда ещё поддерживался addonsu), с подписью системы, разделов, своим корнем доверия и вот это всё. Прошил, заблокировал загрузчик, перезагрузился - всё хорошо, устройство вошло в "жёлтый" режим, система загрузилась. Подключился по adb и вызвал su - получил рутовый шелл. Перемонтировал system в rw, и поменял там кое-что из файлов, т.е. явно нарушил целостность рид-онли раздела. И... ничего не произошло! Т.е. по идее, система должна была обнаружить изменение целостности раздела system, и dm-verity должен быть немедленно прекратить работу системы и, более того, не дать ей загрузиться в дальнейшем, пока раздел не вернётся в изначальное состояние, но этого НЕ произошло, ни сразу, ни после перезагрузки устройства.
Тогда я понял, что, вероятно, что-то очень сильно не так с реализацией этих вещей у OnePlus. И кто знает что это было? Попалось устройство в каком-то незадокументированном режиме? Сборка у меня была "user", т.е. релизная, специально собирал LineageOS именно не в стандартном для них "userdebug". Свойства ro.secure и ro.debuggable точно были в значениях соответствующих релизной сборке. Глубже я тогда копать не стал, т.к. к сожалению, не было достаточно свободного времени. Допускаю что может быть я что-то не так сделал или понял, но, возможно, это тоже было что-то из незадокументированных особенностей устройств производителя, которые автор происследовал в статье. И кто его знает сколько их ещё? И в ВанПлюсах, и не только.
Такие дела
electrofetish
Можно взять средний китайский смартфон с их же сборкой Android и посмотреть на сколько он фонит в сеть интернет.
Чистых смартфонов фактически нет.