Пасхалка в APK-файлах: что такое Frosting

от автора

Автор: Константин Молодяков

Структура файла — увлекательный мир со своими историей, тайнами и собственным цирком уродов, где выступают костыльные решения. Если в ней покопаться, можно найти много интересного.

Я наткнулся на одну особенность APK-файлов — специальную подпись с особым блоком метаданных, Frosting. Она позволяет однозначно определить, распространялся ли файл через Google Play. Эта подпись будет полезна для антивирусных вендоров и песочниц при анализе вредоносов. Кроме того, она может помочь криминалистам при поиске источника файла.

Информации об этом практически нет. Удалось найти только раздел Security metadata in early 2018 в Android Developers Blog и утилиту Avast, которая позволяет проверить данную подпись. Я решил изучить эту штуку, проверить корректность предположений разработчиков Avast о содержании Frosting-блока и поделиться своими выводами.

Frosting и APK Signing Block

Google использует специальную подпись APK-файлов при публикации приложений в Google Play. Эта подпись лежит в APK Signing Block, который находится перед центральной директорией ZIP-файла и после его основного содержимого:

Для идентификации APK Signing Block используется magic — APK Sig Block 42. Внутри блока подписи могут лежать другие блоки, предназначение которых определяется 4-байтовым ID. Получается расширение ZIP-формата с обратной совместимостью. Если интересно почитать подробнее или увидеть исходники, метод ApkSigningBlockUtils.findSignature описан тут.

Возьмем какой-нибудь файл, например 2124948e2b7897cd6fbbe5fbd655c26d. Посмотреть идентификаторы блоков, содержащихся в APK Signing Block, можно с помощью androguard:

from androguard.core.bytecodes import apk apk_obj = apk.APK("2124948e2b7897cd6fbbe5fbd655c26d.apk") apk_obj.parse_v2_v3_signature() print(["0x%X" % key for key in apk_obj._v2_blocks.keys()])  ['0x7109871A', '0x2146444E']

Существует несколько блоков с разными индентификаторами, которые официально описаны в документации:

Некоторые блоки можно найти в исходниках Android:

  • 0x42726577 (VERITY_PADDING_BLOCK_ID) — блок, используемый для нулевого выравнивающего блока;
  • 0x6dff800d (SOURCE_STAMP_BLOCK_ID) — относительно новый вид блоков.

Встречаются и другие блоки:

  • 0x504b4453 (DEPENDENCY_INFO_BLOCK_ID) — блок, в котором, по всей видимости, содержится метаинформация о зависимостях, сохраняемая плагином Android Gradle для определения проблем с ними;
  • 0x71777777 (APK_CHANNEL_BLOCK_ID) — блок китайской приблуды Walle для сборки, который содержит JSON с именем канала;
  • 0xff3b5998 — нулевой блок, который встретился мне в файле — найти какую-либо информацию о нем я не смог;
  • 0x2146444e — блок с необходимой метаинформацией от Google Play.

Frosting и «Play Маркет»

Вернемся к анализу рассматриваемого блока 0x2146444e. Для начала следует изучить внутренности приложения «Play Маркет».

.method public static b(ByteBuffer)ByteBuffer         .registers 2     00000000  invoke-static       bny->a(ByteBuffer)aea, p0     00000006  move-result-object  p0     00000008  const               v0, 0x2146444E     0000000E  invoke-virtual      aea->a(I)Object, p0, v0     00000014  move-result-object  p0     00000016  check-cast          p0, bnx     0000001A  if-eqz              p0, :00000024     0000001E  iget-object         p0, p0, bnx->a:ByteBuffer     00000022  return-object       p0     00000024  new-instance        p0, SigBlockUtil$BlockNotFoundException     00000028  const-string        v0, "Block entry id (go/apk-structure-glossary) "                                       "not present in APK Signing Block"     0000002C  invoke-direct       SigBlockUtil$BlockNotFoundException->                                       <init>(String)V, p0, v0     00000032  throw               p0 .end method

Интересующий нас идентификатор обнаружен в двух местах. Смотрим глубже. Довольно быстро находим класс, отвечающий за разбор блока. Здесь же первый раз среди констант появляется название Frosting-блока:

public enum aysn implements avto {     UNKNOWN(0),     SUCCESS(81),     NO_FROSTING_BLOCK(1),     FROSTING_BLOCK_TOO_SHORT(2),     BAD_SIGNED_DATA_LENGTH_VARINT(3),     NON_POSITIVE_SIGNED_DATA_LENGTH(4),     SIGNED_DATA_LENGTH_TOO_LONG(5),     BAD_FROSTING_LENGTH_VARINT(6),     NON_POSITIVE_FROSTING_LENGTH(7),     FROSTING_LENGTH_BEYOND_SIGNED_DATA(8),     FROSTING_LENGTH_BEYOND_BLOCK(9),     MALFORMED_FROSTING(10),     // ...     INSTALLER_NO_ACCOUNT_WITH_MATCHING_REGION(74);     // ... }

Я сравнил разные версии приложения «Play Маркет» и заметил следующее: код, отвечающий за разбор такого вида подписи, появился примерно в январе 2018 года вместе с выходом версии 8.6.X. Блок с метаданными Frosting существовал и раньше, но именно в этот период он принял тот вид, в котором существует сейчас.

Для разбора данных нам понадобится примитив чтения 4-байтового числа. Схема представляет собой стандартный varint без каких-либо ухищрений с отрицательными числами:

private static int read_int32(ByteBuffer arg2) {     int v0 = arg2.get();     if(v0 >= 0) {         return v0;     }      int v0_1 = v0 & 0x7F;     int v1 = arg2.get();     if(v1 >= 0) {         return v1 << 7 | v0_1;     }      v0_1 |= (v1 & 0x7F) << 7;     int v1_1 = arg2.get();     if(v1_1 >= 0) {         return v1_1 << 14 | v0_1;     }      v0_1 |= (v1_1 & 0x7F) << 14;     int v1_2 = arg2.get();     if(v1_2 >= 0) {         return v1_2 << 21 | v0_1;     }      int v2 = arg2.get();     int v0_2 = v0_1 | (v1_2 & 0x7F) << 21 | v2 << 28;     if(v2 >= 0) {         return v0_2;     }      throw new IllegalArgumentException(); }

Функция разбора блока довольно большая, хоть и устроена просто. Она позволяет разобраться в самой структуре данных:

{     var_int32 size_signed_data,     var_int32 size_frosting,     byte frosting[size_frosting],     var_int32 size_validation_sequence,     array validation_sequence {         var_int32 size_validation_data,         var_int32 validation_strategy,         var_int32 signing_key_index,         byte sha256[0x20]},     var_int32 size_signature_sequence,     array signature_sequence {         var_int32 size_signature,         byte signature[size_signature]}}

Для проверки подписи используются хеш и ключ первого поля из последовательности validation_sequence, у которого validation_strategy равен нулю. Сама подпись забирается из последовательности signature_sequence с таким же порядковым номером, как у записи из validation_sequence. На рисунке ниже представлен поясняющий псевдокод:

def get_signing_data(frosting_block):     for i, validation in enumerate(frosting_block.validation_sequence):         if validation.validation_strategy != 0:             continue         return (             validation.sha256, validation.signing_key_index,             frosting_block.signature_sequence[i].signature)     raise AttributeError()

Значение signing_key_index указывает на индекс в массиве finsky.peer_app_sharing_api.frosting_public_keys, который определен следующим образом и пока содержит только один ключ:

gyd.iH = arip.a(     "finsky.peer_app_sharing_api.min_tos_version", v8); gyd.iI = arip.a(     "finsky.peer_app_sharing_api.frosting_public_keys",     "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZH2+1+E07dnErAD3L6BbTnaohU0bbXriNlJI7VxJU+LjdSwPyXR5pomARAMoyPkMksLz/gitUPtFuJoPL2ziEw=="); gyd.iJ = arip.a(     "finsky.peer_app_sharing_api.startup_package_blacklist",     "com.android.vending,com.google.android.gms,com.android.providers.downloads"); gyd.iK = arip.a(     "finsky.frosting_only_update_time_ms", Long.valueOf(TimeUnit.DAYS.toMillis(30L)));

Подписываются данные размером size_signed_data, начиная с переменной size_frosting, алгоритмом ECDSA_SHA256. При этом подписываемые данные содержат SHA-256 от данных файла:

1) данные от начала файла до блока подписи;

2) данные от central directory до конца end of central directory, с заменой в end of central directory значения поля offset of start of central with respect to the starting disk number на оффсет блока подписи.

Если есть блок подписи схемы версии 2, то он вставляется между данными из пунктов 1 и 2 с добавлением APK_SIGNATURE_SCHEME_V2_BLOCK_ID перед ним.

Функция, вычисляющая хеш в приложении «Play Маркет», выглядит так:

private static byte[] get_frosting_hash(RandomAccessFile f_apk,          long offset_signing_block, ByteBuffer signature_scheme_v2_block,          long offset_zip_central_dir, long size_from_central_dir_to_end_central_dir,          ByteBuffer end_central_dir) {     MessageDigest v0;     try {         v0 = MessageDigest.getInstance("SHA-256");     }     catch(NoSuchAlgorithmException unused_ex) {         throw new FrostingUtil.FailureException(aysn.N);  // NO_SHA_256_ALGORITHM     }      mcc.update_digest(v0, f_apk, 0L, offset_signing_block);     if(signature_scheme_v2_block != null) {         v0.update(mcc.a);         v0.update(signature_scheme_v2_block);     }      mcc.update_digest(v0, f_apk, offset_zip_central_dir,             size_from_central_dir_to_end_central_dir);     bnz.a(end_central_dir, offset_signing_block);     end_central_dir.position(end_central_dir.position());     end_central_dir.limit(end_central_dir.limit());     v0.update(end_central_dir);     return v0.digest(); }

Frosting и ProtoBuf

Этой информации достаточно, чтобы проверить валидность подписи. Но, увы, мне так и не удалось узнать, что скрывается в данных Frosting-блока. У меня получилось лишь определить, что данные имеют формат ProtoBuf и могут сильно отличаться по размеру и наличию полей в зависимости от файла.

Обычно декодированные без схемы данные выглядят так (4b005c9e9ea0731330a757fcf3abeb6e):

cat ./ru.sberbankmobile_11.1.0_2020072413.protobuf | ./protodec -p  {   "1:0:varint": 2,   "2:1:varint": 0,   "3:2:varint": 1,   "4:3:varint": 1603811598348,   "5:4:embedded": {     "8:0:embedded": {       "1:0:embedded": {         "1:0:varint": 21       },       "6:1:varint": 3     },     "9:1:embedded": {       "1:0:embedded": {         "1:0:varint": 2020072413,         "4:1:varint": 3       },       "2:1:embedded": {         "1:0:varint": 2020072414,         "4:1:varint": 5       }     },     "10:2:embedded": {       "1:0:bytes": [         255, 255, 255, 255, 255, 255, 255, 255, 255,         255, 255, 255, 255, 255, 255, 255, 255, 7,         0, 40, 0, 16, 0, 0, 80, 5, 16, 64, 0, 56       ]     }   },   "8:5:varint": 1,   "9:6:varint": 2 }

Но встречаются экземпляры (471c589acc800135eb318057c43a8068), содержащие под пятьсот полей.

Скрытый текст

{   "1:0:varint": 1,   "2:1:varint": 1,   "3:2:varint": 1,   "4:3:varint": 1593452906098,   "5:4:embedded": {     "7:0:embedded": {       "1:0:varint": 1,       "2:1:varint": 1     },     "8:1:embedded": {       "1:0:embedded": {         "1:0:varint": 16       },       "6:1:varint": 3,       "6:2:varint": 2     },     "9:2:embedded": {       "1:0:embedded": {         "1:0:varint": 2021505050,         "4:1:varint": 3,         "4:2:varint": 2       }     },     "10:3:embedded": {       "1:0:bytes": [         221, 255, 227, 239, 247, 127, 255, 191, 239, 191, 255, 255, 255, 255,         247, 255, 255, 0, 0, 8, 0, 16, 0, 0, 16, 5, 16, 64, 0, 32],       "3:1:embedded": {         "1:0:bytes": [           137, 204, 247, 126, 103, 225, 96, 185, 11, 67, 239, 227, 193, 247,           248, 68, 8, 2, 37, 20, 197, 120, 249, 112, 81, 240, 131, 124, 231,           64, 45, 116, 60, 212, 47, 211, 175, 84, 218, 140, 61, 140, 116, 14,           9, 38, 64, 21, 87, 196, 128, 228, 201, 237, 248, 67, 96, 229, 131,           79, 217, 94, 223, 232, 73, 222, 177, 132, 162, 191, 144, 84, 83, 77,           253, 70, 207, 180, 53, 131, 75, 2, 111, 84, 212, 4, 33, 100, 160, 78,           253, 54, 63, 120, 67, 18, 92, 196, 101, 214, 245, 149, 11, 217, 102,           93, 243, 158, 87, 133, 135, 85, 179, 175, 58, 242, 217, 52, 37, 128,           81, 76, 10, 113, 96, 205, 150, 253, 12, 105, 74, 1, 25, 146, 160,           126, 93, 196, 179, 143, 145, 106, 135, 242, 136, 186, 96, 164, 61,           11, 56, 229, 113, 104, 68, 162, 179, 105, 25, 125, 27, 43, 162, 94,           238, 237, 75, 89, 0, 112, 98, 49, 129, 49, 208, 89, 163, 66, 174,           119, 27, 135, 109, 105, 204],         "2:1:varint": 13       }     },     "12:4:embedded": {       "1:0:embedded": {         "5:0:varint": 21       },       "2:1:embedded": {         "1:0:varint": 0,         "2:1:embedded": {           "1:0:bytes": [             41, 93, 201, 211, 27, 15, 203, 207, 160, 84, 10, 4, 65, 194, 92,             146, 191, 221, 207, 134, 150, 216, 77, 234, 223, 53, 187, 49, 207,             136, 84, 82]         },         "3:2:embedded": {           "1:0:bytes": [             80, 168, 41, 12, 177, 59, 101, 235, 150, 116, 174, 248, 213, 250,             72, 228, 35, 56, 11, 184, 197, 36, 206, 168, 225, 19, 221, 82, 213,             106, 206, 248],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 120             }           }         },         "3:3:embedded": {           "1:0:bytes": [             59, 234, 46, 139, 75, 154, 134, 17, 78, 53, 232, 182, 38, 151, 51,             63, 38, 71, 1, 189, 112, 252, 157, 201, 177, 179, 163, 159, 188,             22, 181, 221],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 160             }           }         },         "3:4:embedded": {           "1:0:bytes": [             202, 210, 137, 99, 138, 209, 74, 181, 118, 190, 8, 18, 68, 86, 137,             151, 223, 217, 226, 19, 248, 109, 240, 206, 216, 31, 232, 18, 87,             167, 17, 251],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 240             }           }         },         "3:5:embedded": {           "1:0:bytes": [             191, 119, 224, 30, 167, 161, 4, 135, 44, 155, 92, 208, 26, 168,             120, 198, 195, 65, 125, 110, 58, 168, 92, 171, 56, 41, 131, 172,             176, 171, 78, 223],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 320             }           }         },         "3:6:embedded": {           "1:0:bytes": [             246, 143, 161, 148, 32, 191, 55, 116, 35, 71, 23, 31, 83, 35, 218,             162, 116, 40, 111, 227, 122, 3, 151, 57, 45, 54, 156, 94, 171, 146,             185, 175],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 480             }           }         },         "3:7:embedded": {           "1:0:bytes": [             5, 217, 66, 174, 71, 16, 113, 53, 143, 20, 129, 142, 83, 16, 107,             217, 105, 193, 85, 234, 236, 46, 45, 168, 7, 17, 71, 171, 18, 239,             131, 23],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 640             }           }         },         "3:8:embedded": {           "1:0:bytes": [             134, 163, 146, 36, 137, 172, 95, 238, 205, 214, 71, 99, 209, 190,             16, 59, 205, 59, 201, 2, 146, 43, 117, 131, 131, 218, 64, 251, 108,             217, 37, 141],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 213             }           }         },         "3:9:embedded": {           "1:0:bytes": [             186, 26, 67, 178, 23, 52, 226, 60, 224, 196, 139, 119, 120, 246,             20, 110, 238, 52, 171, 50, 107, 40, 225, 89, 86, 93, 183, 41, 195,             150, 1, 234],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 7             }           }         },         "3:10:embedded": {           "1:0:bytes": [             58, 32, 81, 63, 166, 190, 81, 128, 63, 140, 253, 185, 32, 231, 65,             64, 145, 144, 158, 160, 114, 51, 147, 56, 145, 78, 131, 124, 155,             244, 135, 29],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 47             }           }         },         "3:11:embedded": {           "1:0:bytes": [             208, 138, 65, 103, 12, 44, 60, 179, 81, 117, 125, 125, 32, 171, 58,             255, 61, 9, 184, 59, 17, 165, 38, 250, 2, 126, 131, 206, 204, 106,             121, 122],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 172             }           }         },         "3:12:embedded": {           "1:0:bytes": [             31, 249, 92, 139, 0, 179, 127, 14, 76, 18, 118, 130, 116, 231, 107,             180, 104, 172, 152, 12, 126, 119, 18, 158, 162, 145, 126, 39, 92,             184, 71, 29],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 148             }           }         },         "3:13:embedded": {           "1:0:bytes": [             215, 70, 132, 253, 56, 142, 20, 226, 80, 118, 251, 124, 96, 236,             23, 198, 249, 38, 100, 213, 16, 125, 232, 138, 142, 127, 236, 127,             185, 25, 114, 190],           "2:1:embedded": {             "7:0:embedded": {               "1:0:string": "IW"             }           }         },         "3:14:embedded": {           "1:0:bytes": [             87, 151, 187, 223, 182, 225, 35, 238, 176, 44, 82, 149, 122, 132,             165, 219, 225, 29, 73, 188, 200, 85, 139, 102, 160, 115, 38, 107,             248, 236, 198, 127],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 153             }           }         },         "3:15:embedded": {           "1:0:bytes": [             41, 181, 59, 170, 70, 192, 248, 215, 162, 173, 176, 230, 98, 201,             85, 97, 46, 213, 204, 180, 97, 160, 104, 131, 96, 116, 115, 239,             75, 4, 152, 127],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 171             }           }         },         "3:16:embedded": {           "1:0:bytes": [             66, 31, 252, 95, 240, 235, 159, 130, 37, 247, 203, 210, 165, 40, 2,             37, 157, 33, 78, 114, 102, 214, 7, 15, 128, 103, 91, 63, 138, 113,             125, 119],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 3             }           }         },         "3:17:embedded": {           "1:0:bytes": [             38, 209, 2, 170, 201, 97, 61, 107, 59, 193, 146, 187, 51, 241, 22,             232, 147, 33, 169, 77, 71, 109, 213, 77, 47, 247, 160, 158, 111,             206, 156, 243],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 184             }           }         },         "3:18:embedded": {           "1:0:bytes": [             195, 229, 130, 114, 114, 109, 5, 1, 40, 156, 47, 239, 0, 169, 239,             211, 98, 138, 113, 182, 234, 23, 214, 125, 49, 107, 142, 168, 175,             253, 223, 124],           "2:1:embedded": {             "7:0:embedded": {               "1:0:string": "IN"             }           }         },         "3:19:embedded": {           "1:0:bytes": [             53, 252, 95, 223, 136, 114, 75, 101, 122, 251, 97, 128, 49, 203,             183, 223, 33, 50, 56, 209, 198, 238, 135, 15, 85, 128, 142, 242,             221, 17, 110, 219],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 77             }           }         },         "3:20:embedded": {           "1:0:bytes": [             31, 231, 69, 193, 155, 115, 41, 39, 125, 98, 164, 106, 101, 40, 15,             168, 63, 161, 40, 158, 119, 56, 170, 131, 97, 143, 204, 117, 219,             228, 115, 58],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 51             }           }         },         "3:21:embedded": {           "1:0:bytes": [             58, 114, 14, 110, 167, 28, 66, 253, 106, 5, 106, 130, 219, 199,             234, 73, 126, 0, 63, 102, 153, 172, 52, 224, 22, 145, 84, 42, 74,             216, 210, 58],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 154             }           }         },         "3:22:embedded": {           "1:0:bytes": [             3, 198, 55, 89, 63, 195, 67, 117, 23, 19, 208, 6, 64, 61, 55, 60,             106, 216, 150, 133, 175, 51, 211, 254, 106, 150, 250, 240, 10, 49,             163, 47],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 84             }           }         },         "3:23:embedded": {           "1:0:bytes": [             43, 113, 17, 252, 89, 90, 79, 80, 158, 159, 123, 186, 207, 137, 84,             186, 68, 155, 105, 111, 176, 215, 70, 107, 51, 237, 73, 155, 242,             122, 10, 46],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 325             }           }         },         "3:24:embedded": {           "1:0:bytes": [             163, 118, 101, 102, 1, 115, 201, 144, 237, 239, 117, 79, 163, 127,             173, 149, 33, 211, 90, 111, 82, 50, 146, 101, 80, 30, 22, 112,             153, 164, 19, 150],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 258             }           }         },         "3:25:embedded": {           "1:0:bytes": [             11, 171, 219, 11, 212, 240, 116, 80, 201, 168, 63, 75, 188, 168,             236, 220, 108, 157, 49, 226, 17, 158, 105, 188, 44, 180, 67, 196,             36, 31, 46, 149],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 161             }           }         },         "3:26:embedded": {           "1:0:bytes": [             233, 52, 162, 8, 5, 80, 139, 147, 172, 124, 252, 124, 75, 146, 182,             53, 109, 29, 220, 18, 52, 120, 53, 83, 255, 138, 143, 39, 194, 61,             163, 196],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 46             }           }         },         "3:27:embedded": {           "1:0:bytes": [             82, 61, 18, 192, 210, 218, 157, 38, 65, 86, 39, 30, 138, 32, 248,             114, 10, 148, 210, 251, 130, 23, 54, 116, 104, 206, 141, 102, 169,             191, 5, 233],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 38             }           }         },         "3:28:embedded": {           "1:0:bytes": [             47, 251, 190, 153, 104, 136, 52, 169, 146, 57, 29, 6, 153, 167, 3,             209, 5, 30, 100, 215, 240, 47, 96, 103, 114, 164, 131, 197, 69,             112, 4, 86],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 129             }           }         },         "3:29:embedded": {           "1:0:bytes": [             93, 192, 14, 10, 50, 59, 229, 14, 140, 132, 196, 12, 219, 149, 215,             224, 125, 6, 139, 61, 6, 144, 255, 96, 5, 37, 216, 91, 137, 135,             41, 24],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 25             }           }         },         "3:30:embedded": {           "1:0:bytes": [             10, 2, 142, 220, 179, 122, 72, 30, 24, 127, 28, 65, 31, 28, 73,             126, 198, 238, 62, 156, 228, 87, 163, 9, 38, 116, 106, 48, 25,             152, 159, 179],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 126             }           }         },         "3:31:embedded": {           "1:0:bytes": [             81, 12, 199, 94, 25, 57, 186, 111, 6, 142, 64, 231, 47, 149, 116,             21, 53, 34, 89, 104, 13, 47, 184, 121, 38, 4, 206, 64, 179, 247,             20, 137],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 156             }           }         },         "3:32:embedded": {           "1:0:bytes": [             171, 95, 184, 6, 120, 203, 22, 123, 134, 45, 181, 225, 90, 186,             233, 210, 8, 55, 43, 48, 169, 47, 10, 200, 161, 216, 118, 98, 61,             215, 124, 135],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 158             }           }         },         "3:33:embedded": {           "1:0:bytes": [             198, 24, 206, 30, 88, 136, 6, 128, 184, 53, 150, 247, 25, 79, 56,             60, 81, 143, 13, 123, 107, 35, 86, 162, 122, 7, 216, 27, 27, 249,             19, 47],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 63             }           }         },         "3:34:embedded": {           "1:0:bytes": [             230, 93, 108, 31, 194, 183, 82, 253, 244, 34, 6, 1, 7, 69, 80, 147,             131, 89, 158, 29, 236, 115, 92, 196, 44, 178, 254, 238, 121, 246,             113, 68],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 104             }           }         },         "3:35:embedded": {           "1:0:bytes": [             147, 204, 39, 33, 249, 108, 184, 249, 48, 14, 165, 120, 66, 9, 137,             134, 5, 48, 106, 48, 105, 140, 144, 159, 125, 179, 124, 71, 158,             117, 131, 210],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 19             }           }         },         "3:36:embedded": {           "1:0:bytes": [             89, 255, 33, 10, 191, 177, 183, 189, 245, 158, 109, 205, 126, 163,             104, 71, 57, 35, 124, 14, 130, 83, 188, 213, 129, 96, 249, 122, 39,             106, 120, 195],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 80             }           }         },         "3:37:embedded": {           "1:0:bytes": [             105, 92, 221, 66, 185, 181, 94, 19, 30, 129, 85, 145, 196, 110, 14,             125, 216, 251, 11, 186, 138, 194, 135, 243, 1, 172, 32, 128, 159,             113, 84, 87],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 106             }           }         },         "3:38:embedded": {           "1:0:bytes": [             157, 183, 189, 153, 219, 24, 43, 100, 235, 0, 132, 119, 215, 108,             236, 153, 22, 241, 252, 211, 231, 116, 33, 113, 123, 237, 138, 202,             213, 153, 43, 88],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 123             }           }         },         "3:39:embedded": {           "1:0:bytes": [             146, 229, 59, 43, 145, 105, 186, 201, 142, 14, 158, 90, 5, 28, 230,             197, 134, 18, 13, 219, 74, 209, 84, 214, 210, 54, 70, 1, 56, 31,             218, 54],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 58             }           }         },         "3:40:embedded": {           "1:0:bytes": [             220, 242, 61, 79, 217, 248, 85, 208, 85, 163, 104, 176, 88, 2, 114,             108, 131, 202, 204, 53, 110, 75, 239, 56, 136, 67, 248, 247, 12,             63, 191, 12],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 175             }           }         },         "3:41:embedded": {           "1:0:bytes": [             71, 68, 176, 15, 211, 98, 59, 27, 187, 227, 14, 91, 53, 120, 129,             50, 108, 107, 103, 66, 252, 217, 178, 77, 184, 147, 91, 90, 19,             111, 128, 53],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 134             }           }         },         "3:42:embedded": {           "1:0:bytes": [             201, 51, 220, 118, 187, 125, 87, 7, 246, 185, 155, 52, 220, 28, 12,             90, 48, 123, 202, 135, 233, 18, 3, 137, 10, 222, 223, 206, 111,             196, 255, 235],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 78             }           }         },         "3:43:embedded": {           "1:0:bytes": [             144, 123, 192, 106, 90, 212, 71, 96, 188, 5, 46, 223, 100, 12, 58,             99, 141, 127, 17, 14, 181, 44, 129, 224, 57, 134, 157, 34, 245, 78,             63, 60],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 130             }           }         },         "3:44:embedded": {           "1:0:bytes": [             21, 33, 78, 136, 74, 131, 86, 48, 170, 99, 67, 146, 12, 42, 119,             249, 70, 198, 221, 127, 241, 175, 42, 0, 12, 66, 71, 172, 59, 17,             27, 228],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 56             }           }         },         "3:45:embedded": {           "1:0:bytes": [             45, 178, 69, 5, 175, 52, 44, 90, 190, 94, 100, 180, 238, 153, 189,             58, 248, 181, 189, 134, 151, 53, 68, 244, 110, 252, 95, 156, 34,             248, 195, 141],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 90             }           }         },         "3:46:embedded": {           "1:0:bytes": [             91, 22, 185, 64, 72, 46, 38, 48, 20, 244, 241, 114, 1, 64, 97, 227,             136, 54, 169, 201, 133, 11, 182, 88, 154, 1, 142, 138, 24, 112,             166, 16],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 168             }           }         },         "3:47:embedded": {           "1:0:bytes": [             27, 146, 39, 199, 46, 197, 241, 106, 223, 55, 129, 191, 176, 123,             232, 151, 44, 180, 31, 142, 137, 201, 21, 52, 94, 201, 111, 170,             169, 93, 55, 131],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 76             }           }         },         "3:48:embedded": {           "1:0:bytes": [             193, 124, 22, 3, 213, 34, 101, 149, 246, 22, 8, 15, 68, 75, 165,             76, 38, 150, 247, 77, 2, 140, 154, 249, 2, 205, 73, 232, 130, 104,             69, 159],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 66             }           }         },         "3:49:embedded": {           "1:0:bytes": [             5, 193, 68, 1, 180, 40, 46, 163, 192, 112, 174, 29, 81, 223, 190,             244, 3, 142, 55, 211, 8, 2, 192, 194, 30, 20, 55, 42, 41, 68, 125,             127],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 136             }           }         },         "3:50:embedded": {           "1:0:bytes": [             83, 24, 100, 126, 8, 186, 138, 33, 95, 127, 89, 36, 2, 106, 137,             183, 242, 92, 104, 95, 122, 198, 162, 7, 255, 251, 123, 96, 225,             149, 63, 111],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 29             }           }         },         "3:51:embedded": {           "1:0:bytes": [             194, 142, 59, 4, 54, 96, 70, 2, 123, 91, 9, 252, 170, 235, 182, 98,             37, 143, 10, 210, 186, 173, 103, 165, 149, 47, 171, 59, 201, 209,             250, 66],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 107             }           }         },         "3:52:embedded": {           "1:0:bytes": [             99, 76, 68, 203, 167, 245, 211, 142, 143, 66, 189, 190, 254, 178,             37, 12, 61, 195, 104, 178, 165, 186, 113, 253, 215, 1, 169, 54,             129, 175, 212, 70],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 35             }           }         },         "3:53:embedded": {           "1:0:bytes": [             92, 240, 11, 68, 247, 15, 103, 182, 210, 65, 243, 114, 153, 230,             135, 241, 160, 60, 31, 140, 166, 85, 107, 163, 252, 119, 167, 35,             195, 207, 141, 18],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 20             }           }         },         "3:54:embedded": {           "1:0:bytes": [             52, 163, 30, 105, 147, 104, 203, 234, 85, 78, 118, 91, 238, 243,             81, 81, 183, 127, 166, 173, 2, 33, 111, 160, 93, 35, 4, 128, 97,             231, 134, 223],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 40             }           }         },         "3:55:embedded": {           "1:0:bytes": [             15, 45, 48, 189, 170, 219, 22, 126, 243, 217, 200, 106, 165, 165,             120, 108, 150, 111, 105, 150, 85, 8, 120, 155, 210, 148, 32, 198,             145, 49, 115, 16],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 26             }           }         },         "3:56:embedded": {           "1:0:bytes": [             27, 250, 155, 159, 74, 227, 46, 27, 185, 4, 150, 8, 184, 21, 240,             149, 45, 244, 81, 252, 85, 159, 50, 201, 247, 73, 42, 60, 127, 194,             238, 197],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 36             }           }         },         "3:57:embedded": {           "1:0:bytes": [             108, 3, 162, 113, 54, 72, 115, 18, 228, 40, 151, 67, 169, 226, 153,             58, 138, 252, 59, 67, 200, 53, 128, 160, 233, 148, 198, 100, 2,             236, 64, 76],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 127             }           }         },         "3:58:embedded": {           "1:0:bytes": [             49, 49, 177, 65, 227, 61, 198, 32, 171, 82, 125, 100, 152, 38, 31,             134, 206, 214, 41, 7, 221, 160, 238, 165, 79, 21, 214, 112, 178,             61, 11, 9],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 118             }           }         },         "3:59:embedded": {           "1:0:bytes": [             20, 105, 162, 168, 235, 1, 24, 192, 39, 86, 5, 217, 99, 35, 205,             139, 169, 93, 95, 58, 226, 208, 58, 100, 127, 228, 120, 31, 18, 41,             125, 188],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 24             }           }         },         "3:60:embedded": {           "1:0:bytes": [             34, 182, 106, 248, 174, 109, 85, 82, 233, 185, 158, 189, 109, 180,             122, 16, 147, 191, 174, 75, 237, 181, 28, 126, 154, 187, 117, 74,             222, 183, 40, 42],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 140             }           }         },         "3:61:embedded": {           "1:0:bytes": [             26, 231, 159, 209, 255, 47, 66, 73, 25, 159, 150, 146, 159, 24,             180, 147, 187, 127, 158, 136, 140, 26, 16, 163, 73, 22, 192, 248,             72, 201, 123, 70],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 160             }           }         },         "3:62:embedded": {           "1:0:bytes": [             203, 229, 192, 110, 98, 83, 18, 72, 171, 75, 44, 16, 145, 234, 53,             21, 92, 92, 252, 180, 147, 252, 134, 164, 131, 200, 84, 216, 173,             57, 215, 64],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 65             }           }         },         "3:63:embedded": {           "1:0:bytes": [             27, 37, 29, 129, 135, 60, 21, 21, 130, 47, 246, 84, 230, 29, 106,             8, 164, 126, 104, 33, 221, 10, 59, 198, 65, 59, 120, 175, 206,             115, 159, 192],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 150             }           }         },         "3:64:embedded": {           "1:0:bytes": [             247, 70, 240, 58, 235, 170, 216, 77, 82, 133, 127, 229, 69, 233,             41, 152, 29, 26, 140, 211, 60, 199, 111, 14, 228, 194, 135, 49,             207, 62, 100, 88],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:65:embedded": {           "1:0:embedded": {             "3:0:bytes": [               240, 189, 141, 59, 178, 229, 21, 207, 150, 181, 18, 214, 123,               229, 94, 213, 47, 55, 0, 35, 94, 176, 10, 239, 63, 91, 177, 203,               181, 232]           },           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:2:embedded": {         "1:0:varint": 1,         "2:1:embedded": {           "1:0:bytes": [             33, 255, 48, 173, 71, 120, 45, 62, 197, 131, 213, 202, 76, 94, 249,             217, 35, 187, 218, 99, 4, 123, 252, 140, 225, 146, 188, 168, 168,             162, 182, 43]         },         "3:2:embedded": {           "1:0:bytes": [             25, 141, 201, 30, 174, 20, 216, 191, 35, 48, 111, 202, 181, 109,             38, 200, 22, 81, 86, 189, 190, 86, 13, 133, 64, 168, 191, 133, 34,             39, 191, 224],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:3:embedded": {           "1:0:bytes": [             71, 158, 85, 141, 109, 205, 49, 21, 217, 217, 209, 39, 252, 123,             76, 99, 122, 134, 75, 8, 32, 224, 96, 181, 34, 239, 108, 110, 14,             13, 46, 205],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:3:embedded": {         "1:0:varint": 0,         "2:1:embedded": {           "1:0:bytes": [             203, 190, 37, 85, 163, 233, 86, 189, 68, 5, 138, 164, 64, 165, 54,             146, 237, 162, 128, 49, 148, 179, 51, 34, 217, 7, 38, 108, 182,             197, 160, 179]         }       },       "3:4:embedded": {         "1:0:varint": 0,         "2:1:embedded": {           "1:0:bytes": [             163, 159, 42, 53, 128, 115, 90, 161, 149, 19, 157, 15, 58, 113,             122, 238, 204, 104, 91, 216, 78, 131, 30, 240, 110, 166, 106, 159,             237, 125, 147, 82]         },         "3:2:embedded": {           "1:0:bytes": [             57, 32, 198, 203, 112, 159, 189, 236, 244, 113, 104, 205, 165,             135, 237, 217, 163, 184, 202, 45, 241, 164, 164, 78, 112, 12, 177,             124, 204, 213, 16, 78],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:3:embedded": {           "1:0:bytes": [             220, 184, 103, 130, 108, 220, 83, 140, 36, 238, 139, 5, 167, 253,             252, 136, 76, 43, 72, 36, 245, 92, 47, 147, 40, 134, 117, 179, 88,             9, 164, 70],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:5:embedded": {         "1:0:varint": 1,         "2:1:embedded": {           "1:0:bytes": [             240, 142, 243, 236, 188, 6, 32, 37, 148, 220, 19, 135, 176, 7, 175,             172, 234, 124, 152, 61, 115, 11, 68, 50, 219, 32, 182, 146, 2, 41,             153, 192]         },         "3:2:embedded": {           "1:0:bytes": [             245, 12, 255, 55, 29, 151, 184, 242, 250, 247, 191, 244, 52, 251,             172, 66, 40, 242, 47, 67, 168, 136, 224, 201, 229, 16, 64, 4, 36,             207, 164, 97],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:3:embedded": {           "1:0:bytes": [             98, 200, 36, 229, 239, 75, 96, 35, 195, 26, 180, 253, 4, 232, 178,             167, 173, 163, 171, 110, 154, 60, 20, 229, 82, 52, 201, 194, 199,             137, 188, 237],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:6:embedded": {         "1:0:varint": 1,         "2:1:embedded": {           "1:0:bytes": [             36, 1, 15, 223, 76, 25, 153, 9, 204, 90, 139, 114, 200, 122, 201,             226, 179, 79, 135, 58, 82, 134, 136, 184, 34, 249, 131, 132, 127,             38, 46, 245]         },         "3:2:embedded": {           "1:0:bytes": [             110, 242, 238, 199, 145, 159, 168, 178, 187, 136, 71, 7, 156, 155,             102, 157, 218, 30, 147, 63, 91, 89, 147, 79, 29, 133, 10, 154, 77,             107, 15, 23],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:3:embedded": {           "1:0:bytes": [             193, 203, 71, 244, 30, 18, 158, 188, 15, 77, 73, 13, 22, 120, 82,             107, 224, 130, 68, 135, 58, 123, 59, 135, 29, 86, 232, 139, 54, 74,             77, 121],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:7:embedded": {         "1:0:varint": 0,         "2:1:embedded": {           "1:0:embedded": {             "2:0:varint": 495613890054,             "192224:1:float32": 4.882061335059751e-12,             "13:2:float64": -1.0035307849984653e+45,             "14:3:float64": -9.42824039531738e+194           }         },         "3:2:embedded": {           "1:0:bytes": [             176, 193, 111, 217, 103, 210, 40, 38, 174, 253, 210, 197, 138, 118,             79, 56, 223, 186, 161, 214, 205, 215, 175, 9, 245, 199, 58, 188,             87, 17, 112, 187],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:3:embedded": {           "1:0:bytes": [             233, 74, 153, 41, 23, 225, 3, 244, 202, 119, 170, 143, 9, 6, 210,             63, 125, 169, 131, 143, 182, 92, 221, 250, 202, 54, 145, 84, 30,             120, 18, 91],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:8:embedded": {         "1:0:varint": 1,         "2:1:embedded": {           "1:0:bytes": [             168, 15, 228, 127, 125, 117, 127, 138, 147, 171, 112, 68, 159, 126,             29, 136, 159, 179, 53, 127, 49, 203, 4, 114, 246, 31, 236, 30, 138,             177, 114, 180]         },         "3:2:embedded": {           "1:0:bytes": [             175, 38, 148, 203, 5, 192, 218, 240, 99, 37, 193, 198, 171, 54,             171, 189, 43, 21, 47, 93, 178, 90, 122, 26, 84, 147, 81, 211, 72,             159, 117, 186],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 120             }           }         },         "3:3:embedded": {           "1:0:bytes": [             178, 168, 118, 168, 112, 230, 109, 168, 126, 135, 179, 184, 202,             71, 168, 52, 173, 232, 47, 90, 206, 58, 2, 36, 231, 168, 28, 159,             121, 169, 250, 225],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 160             }           }         },         "3:4:embedded": {           "1:0:bytes": [             27, 161, 172, 103, 148, 85, 34, 240, 54, 186, 19, 156, 128, 76,             161, 194, 205, 44, 121, 156, 95, 221, 165, 157, 48, 84, 171, 94,             213, 94, 38, 32],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 240             }           }         },         "3:5:embedded": {           "1:0:bytes": [             59, 22, 204, 77, 122, 25, 137, 251, 172, 27, 167, 105, 49, 28, 42,             101, 237, 95, 111, 59, 71, 48, 155, 192, 72, 229, 119, 45, 87, 83,             228, 126],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 320             }           }         },         "3:6:embedded": {           "1:0:bytes": [             8, 33, 151, 137, 172, 94, 16, 17, 78, 72, 18, 122, 33, 27, 94, 14,             210, 96, 130, 155, 222, 163, 85, 72, 14, 65, 157, 51, 80, 239, 102,             159],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 480             }           }         },         "3:7:embedded": {           "1:0:bytes": [             56, 238, 38, 244, 65, 33, 107, 152, 55, 119, 194, 4, 193, 171, 0,             161, 170, 76, 178, 1, 83, 171, 68, 124, 231, 251, 16, 58, 69, 140,             73, 27],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 640             }           }         },         "3:8:embedded": {           "1:0:bytes": [             234, 0, 220, 53, 6, 255, 39, 198, 77, 205, 185, 199, 74, 82, 77,             238, 19, 189, 175, 169, 229, 243, 213, 98, 178, 88, 114, 237, 130,             176, 18, 73],           "2:1:embedded": {             "1:0:embedded": {               "1:0:varint": 213             }           }         },         "3:9:embedded": {           "1:0:bytes": [             185, 165, 104, 89, 84, 74, 209, 29, 242, 21, 183, 113, 130, 246,             55, 41, 106, 125, 21, 102, 221, 45, 71, 190, 159, 70, 149, 140, 48,             167, 19, 193],           "2:1:embedded": {             "5:0:embedded": {               "1:0:varint": 40             }           }         },         "3:10:embedded": {           "1:0:bytes": [             220, 55, 196, 143, 179, 190, 76, 224, 62, 229, 56, 186, 142, 119,             251, 254, 170, 172, 89, 23, 229, 85, 169, 193, 135, 234, 5, 63, 19,             102, 182, 115],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 3             }           }         },         "3:11:embedded": {           "1:0:bytes": [             129, 101, 107, 114, 78, 83, 69, 51, 80, 76, 1, 218, 223, 168, 239,             110, 132, 179, 104, 145, 7, 183, 83, 83, 248, 208, 228, 139, 134,             120, 52, 26],           "2:1:embedded": {             "3:0:embedded": {               "1:0:varint": 2             }           }         }       },       "3:9:embedded": {         "1:0:varint": 0,         "2:1:embedded": {           "1:0:bytes": [             74, 175, 233, 99, 240, 93, 193, 197, 121, 201, 157, 138, 122, 204,             35, 17, 29, 212, 57, 239, 239, 42, 0, 122, 150, 248, 198, 205, 34,             3, 51, 162]         }       }     }   },   "7:5:varint": 1,   "8:6:varint": 2,   "9:7:varint": 2 }

В данных изредка попадаются занятные строки: android.hardware.ram.low, com.samsung.feature.SAMSUNG_EXPERIENCE, com.google.android.apps.photos.PIXEL_2018_PRELOAD. Эти строки — не очень документированные имена функций, которые могут быть у устройства.

Описание функций, если они есть, можно посмотреть, на устройстве в файлах в папке /etc/sysconfig/:

adb shell cat /etc/sysconfig/pixel_experience_2017.xml  <?xml version="1.0" encoding="utf-8"?> <!-- These are configurations that should exist on Google's 2017 and newer Nexus devices. --> <config>     <!-- This is meant to be the canonical feature identifying 2017 and newer Nexus devices. -->     <feature name="com.google.android.feature.PIXEL_2017_EXPERIENCE" /> </config>  adb shell cat /etc/sysconfig/pixel_2017_exclusive.xml  <?xml version="1.0" encoding="utf-8"?> <!-- These are configurations that should exist on Google's 2017 devices (and not newer/older) --> <config>     <!-- This defines the Photos preload feature for specifically the 2017 Pixel devices. -->     <feature name="com.google.android.apps.photos.PIXEL_2017_PRELOAD" /> </config>

В качестве документированного примера можно привести проверку наличия камеры запросом функции android.hardware.camera через метод hasSystemFeature класса PackageManager. Но зачем нужны эти строки, в данном контексте непонятно.

Мне не удалось угадать, найти или восстановить схему данных из классов APK «Play Маркет». Если кто-то расскажет, что там и как получилось это определить, будет интересно. Пока есть только предположения разработчиков утилиты от Avast о структуре ProtoBuf и о том, что строка com.google.android.apps.photos.PIXEL_2018_PRELOAD указывает, является ли приложение системным/предустановленным:

1 <varint> = 1  // frosting versions? 2 <varint> = 0 3 <varint> = 1 4 <varint> = 1541545744578  // Timestamp of the frosting creation? 5 <chunk> = message:     8 <chunk> = message:         1 <chunk> = message(1 <varint> = 22)  // minSdkLevel?         6 <varint> = 2     9 <chunk> = message:         1 <chunk> = message(1 <varint> = 2266, 4 <varint> = 2)  // versionCode         2 <chunk> = message(1 <varint> = 50003, 4 <varint> = 4)     10 <chunk> = message:         1 <chunk> = bytes (30)  // ?? only last byte changes across apks             0000   FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF             0010   FF FE FF FF FF FF FF FF FF FF FF FF FF 3F             '.............................?'         3 <chunk> = message:             1 <chunk> = bytes (32)  // sha256 of something?                 0000   16 F8 22 A6 93 26 89 34 D8 2A 88 BB 8C AD B6 68                 0010   2C EB 77 A8 AA E4 5F AA F9 3C CA 63 44 2A A4 B9                 '.."..&.4.*.....h,.w..._..<.cD*..'             2 <varint> = 20

Я бы хотел оставить несколько комментариев на этот счет.

1) По поводу строки com.google.android.apps.photos.PIXEL_2018_PRELOAD: легко доказать, что это неверное предположение. Скачаем несколько образов, предоставляемых Google, и увидим, что там нет не только таких строк, но и ни одного приложения, которое бы содержало блок Frosting.

Можно рассмотреть это более детально на образе walleye for Pixel 2 9.0.0 (PQ3A.190801.002, Aug 2019). Установим образ и обнаружим, что среди всех 187 APK-файлов нет ни одного файла, содержащего блок Frosting. Если обновить все приложения, блок Frosting обнаружится у 33 из 264 APK-файлов. При этом только у пяти из них присутствуют строки:

  • com.google.android.as:
    • com.google.android.feature.DPS
    • com.google.android.feature.PIXEL_EXPERIENCE
    • com.google.android.feature.PIXEL_2017_EXPERIENCE
    • com.google.android.feature.PIXEL_2019_EXPERIENCE
    • com.google.android.feature.ANDROID_ONE_EXPERIENCE
    • com.google.android.feature.PIXEL_2018_EXPERIENCE
    • com.google.android.feature.PIXEL_2020_EXPERIENCE
  • google.android.inputmethod.latin:
    • android.hardware.ram.low
  • google.android.dialer:
    • com.google.android.apps.dialer.GO_EXPERIENCE
    • com.google.android.feature.PIXEL_2020_EXPERIENCE
  • google.android.GoogleCamera:
    • android.hardware.camera.level.full
  • google.android.apps.photos:
    • com.google.android.feature.PIXEL_2020_EXPERIENCE

Можно предположить, что эти строки определяют необходимость функций на устройстве, куда устанавливается приложение. Но запросим полный список функций устройства, на котором проводилось обновление, и убедимся, что это не так.

Скрытый текст

adb shell pm list features  feature:reqGlEsVersion=0x30002 feature:android.hardware.audio.low_latency feature:android.hardware.audio.output feature:android.hardware.audio.pro feature:android.hardware.bluetooth feature:android.hardware.bluetooth_le feature:android.hardware.camera feature:android.hardware.camera.any feature:android.hardware.camera.ar feature:android.hardware.camera.autofocus feature:android.hardware.camera.capability.manual_post_processing feature:android.hardware.camera.capability.manual_sensor feature:android.hardware.camera.capability.raw feature:android.hardware.camera.flash feature:android.hardware.camera.front feature:android.hardware.camera.level.full feature:android.hardware.faketouch feature:android.hardware.fingerprint feature:android.hardware.location feature:android.hardware.location.gps feature:android.hardware.location.network feature:android.hardware.microphone feature:android.hardware.nfc feature:android.hardware.nfc.any feature:android.hardware.nfc.hce feature:android.hardware.nfc.hcef feature:android.hardware.opengles.aep feature:android.hardware.ram.normal feature:android.hardware.screen.landscape feature:android.hardware.screen.portrait feature:android.hardware.sensor.accelerometer feature:android.hardware.sensor.assist feature:android.hardware.sensor.barometer feature:android.hardware.sensor.compass feature:android.hardware.sensor.gyroscope feature:android.hardware.sensor.hifi_sensors feature:android.hardware.sensor.light feature:android.hardware.sensor.proximity feature:android.hardware.sensor.stepcounter feature:android.hardware.sensor.stepdetector feature:android.hardware.telephony feature:android.hardware.telephony.carrierlock feature:android.hardware.telephony.cdma feature:android.hardware.telephony.euicc feature:android.hardware.telephony.gsm feature:android.hardware.touchscreen feature:android.hardware.touchscreen.multitouch feature:android.hardware.touchscreen.multitouch.distinct feature:android.hardware.touchscreen.multitouch.jazzhand feature:android.hardware.usb.accessory feature:android.hardware.usb.host feature:android.hardware.vr.headtracking feature:android.hardware.vr.high_performance feature:android.hardware.vulkan.compute feature:android.hardware.vulkan.level feature:android.hardware.vulkan.version=4198400 feature:android.hardware.wifi feature:android.hardware.wifi.aware feature:android.hardware.wifi.direct feature:android.hardware.wifi.passpoint feature:android.hardware.wifi.rtt feature:android.software.activities_on_secondary_displays feature:android.software.app_widgets feature:android.software.autofill feature:android.software.backup feature:android.software.cant_save_state feature:android.software.companion_device_setup feature:android.software.connectionservice feature:android.software.cts feature:android.software.device_admin feature:android.software.device_id_attestation feature:android.software.file_based_encryption feature:android.software.home_screen feature:android.software.input_methods feature:android.software.live_wallpaper feature:android.software.managed_users feature:android.software.midi feature:android.software.picture_in_picture feature:android.software.print feature:android.software.securely_removes_users feature:android.software.sip feature:android.software.sip.voip feature:android.software.verified_boot feature:android.software.voice_recognizers feature:android.software.vr.mode feature:android.software.webview feature:com.google.android.apps.dialer.SUPPORTED feature:com.google.android.apps.photos.PIXEL_2017_PRELOAD feature:com.google.android.feature.EXCHANGE_6_2 feature:com.google.android.feature.GOOGLE_BUILD feature:com.google.android.feature.GOOGLE_EXPERIENCE feature:com.google.android.feature.PIXEL_2017_EXPERIENCE feature:com.google.android.feature.PIXEL_EXPERIENCE feature:com.google.android.feature.TURBO_PRELOAD feature:com.google.android.feature.WELLBEING feature:com.google.android.feature.ZERO_TOUCH feature:com.google.hardware.camera.easel feature:com.verizon.hardware.telephony.ehrpd feature:com.verizon.hardware.telephony.lte

2) С frosting versions я не согласен, так как можно найти похожие данные, но со значениями, отличными от 1. Максимальное значение этого поля, которое мне попадалось, –– 26.

3) С timestamp of the frosting creation я не согласен: я понаблюдал за конкретным приложением и заметил, что с выходом новых версий значение этого поля не обязательно растет. Оно скачет и может быть отрицательным.

4) MinSdkLevel и VersionCode выглядят правдоподобно.

Заключение

Итак, блок Frosting в подписи помогает однозначно определить, распространялся ли файл через официальный магазин. Больше никакой пользы из этой подписи извлечь не удалось.

Ловите напоследок пример использования такой информации в отчете мобильной песочницы ApkLab:

ссылка на оригинал статьи https://habr.com/ru/company/bizone/blog/531712/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *