Easter Egg in APKs: What is Frosting

Author: Konstantin Molodyakov

The structure of the file is a fascinating world with its own history, secrets and its own circus of freaks, where crutch solutions are performed. If you delve into it, you can find a lot of interesting things.

I came across one feature of APK files – a special signature with a special block of metadata, Frosting… It allows you to unambiguously determine if the file has been distributed through Google Play. This signature will be useful for antivirus vendors and sandboxes when analyzing malware. In addition, it can assist forensic scientists in finding the source of the file.

There is practically no information about this. Only the section was found Security metadata in early 2018 in Android Developers Blog and the Avast utility, which allows you to verify this signature. I decided to study this thing, check the correctness of the Avast developers’ assumptions about the content of the Frosting block and share my findings.

Frosting and APK Signing Block

Google uses a special signature for APK files when publishing apps to Google Play. This signature lies in APK Signing Block, which is located before the central directory of the zip file and after its main content:

For identification APK Signing Block magic is used – APK Sig Block 42… Inside the signature block, there may be other blocks, the purpose of which is determined by the 4-byte ID. This results in a ZIP format extension with backward compatibility. If you are interested in reading more or see the source, the method ApkSigningBlockUtils.findSignature described here

Let’s take some file, for example 2124948e2b7897cd6fbbe5fbd655c26d… View block identifiers contained in APK Signing Block, you can use 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']

There are several blocks with different identifiers, which are officially described in documentation:

Some blocks can be found in the source Android:

There are also other blocks:

  • 0x504b4453 (DEPENDENCY_INFO_BLOCK_ID) – a block that apparently contains meta information about dependencies saved by the plugin Android Gradle to identify problems with them;
  • 0x71777777 (APK_CHANNEL_BLOCK_ID) – block of Chinese pribluda Walle for assembly, which contains JSON with the channel name;
  • 0xff3b5998 – the zero block that I met in file – I could not find any information about him;
  • 0x2146444e – a block with the necessary meta information from Google Play.

Frosting and “Play Market”

Let’s return to the analysis of the considered block 0x2146444e… First you should examine the insides Play Store applications

.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

The identifier of interest to us was found in two places. We look deeper. We quickly find the class responsible for parsing the block. Here, for the first time, the name of the Frosting block appears among the constants:

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);
    // ...
}

I compared different versions of the Play Store application and noticed the following: the code responsible for parsing this type of signature appeared around January 2018 with the release of version 8.6.X. The Frosting metadata block existed before, but it was during this period that it took the form in which it exists now.

To parse the data, we need a 4-byte number read primitive. The schema is a standard varint without any negative numbers tweaks:

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();
}

The block parsing function is quite large, although it is simple. It allows you to understand the data structure itself:

{
    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]}}

The hash and the key of the first field from the sequence are used to verify the signature validation_sequence, which one validation_strategy is zero. The signature itself is taken from the sequence signature_sequence with the same serial number as the entry from validation_sequence… The figure below shows the explanatory pseudocode:

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()

Value signing_key_index points to an index in an array finsky.peer_app_sharing_api.frosting_public_keyswhich is defined as follows and so far contains only one key:

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)));

Data is signed in size size_signed_datastarting at variable size_frosting, algorithm ECDSA_SHA256… In this case, the data being signed contains SHA-256 from file data:

1) data from the beginning of the file to the signature block;

2) data from central directory to end end of central directory, with replacement in end of central directory field values offset of start of central with respect to the starting disk number to offset the signature block.

If there is a signature block of the scheme version 2, then it is inserted between the data from points 1 and 2 with the addition of APK_SIGNATURE_SCHEME_V2_BLOCK_ID in front of him.

The function that calculates the hash in the Play Store application looks like this:

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 and ProtoBuf

This information is enough to check the validity of the signature. But, alas, I never managed to find out what is hidden in the data of the Frosting block. I was only able to determine that the data is in the ProtoBuf format and can vary greatly in size and presence of fields depending on the file.

Typically decoded data without a schema looks like this (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
}

But there are instances (471c589acc800135eb318057c43a8068) containing under five hundred fields.

Hidden text

{
  "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
}

Interesting lines occasionally come across in the data: android.hardware.ram.low, com.samsung.feature.SAMSUNG_EXPERIENCE, com.google.android.apps.photos.PIXEL_2018_PRELOAD… These lines are not very documented names functionsthat the device may have.

Description of functions, if any, can be viewed on the device in files in the folder /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>

As a documented example, check for the presence of a camera by requesting a function android.hardware.camera through method hasSystemFeature class PackageManager… But why these lines are needed is not clear in this context.

I was unable to guess, find or recover the data schema from the classes APK file “Play Market”. If someone tells what is there and how it turned out to be determined, it will be interesting. So far there is only assumptions developers utilities from Avast about the structure of ProtoBuf and that the line com.google.android.apps.photos.PIXEL_2018_PRELOAD indicates if the application is system / pre-installed:

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

I would like to leave a few comments in this regard.

1) About the line com.google.android.apps.photos.PIXEL_2018_PRELOAD: it is easy to prove that this is a wrong assumption. Download several imagesprovided by Google, and we will see that not only such lines are not there, but also not a single application that would contain a Frosting block.

You can see this in more detail on the image walleye for Pixel 2 9.0.0 (PQ3A.190801.002, Aug 2019)… Install the image and find that among all 187 APKs, there is not a single file containing a Frosting block. If all apps are updated, 33 out of 264 APKs show up with a Frosting block. Moreover, only five of them have lines:

  • 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

It can be assumed that these lines determine the need for functions on the device where the application is installed. But let’s ask for a complete list of features of the device on which the update was carried out and make sure that this is not the case.

Hidden text

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) C frosting versions I disagree, because you can find similar data, but with values ​​other than 1. The maximum value of this field that I came across was 26.

3) C timestamp of the frosting creation I disagree: I watched a specific application and noticed that with the release of new versions, the value of this field does not necessarily increase. It jumps and can be negative.

4) MinSdkLevel and VersionCode look believable.

Conclusion

So, the Frosting block in the signature helps to unambiguously determine if the file was distributed through an official store. It was not possible to extract any further benefit from this signature.

Finally, catch an example of using such information in a mobile sandbox report ApkLab:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *