App-zipdetails

 view release on metacpan or  search on metacpan

bin/zipdetails  view on Meta::CPAN


    seekTo($offset) ;

    my $buffer;
    myRead($buffer, $len);

    length $buffer == $len
        or return '';

    return $buffer;
}

sub readSignatureFromOffset
{
    my $offset = shift ;

    # catch use case where attempting to read past EOF
    # sub is expecting to return a 32-bit value so return 54-bit out-of-bound value
    return MAX64
        if $offset + 4 > $FILELEN ;

    my $here = $FH->tell();
    my $buffer = readFromOffset($offset, 4);
    my $gotSig = unpack("V", $buffer) ;
    seekTo($here);

    return $gotSig;
}


sub chckForAPKSigningBlock
{
    my $fh = shift;
    my $cdOffset = shift;
    my $cdSize = shift;

    # APK Signing Block comes directly before the Central directory
    # See https://source.android.com/security/apksigning/v2

    # If offset available is less than 44, it isn't an APK signing block
    #
    #   len1     8
    #   id       4
    #   kv with zero len 8
    #   len1     8
    #   magic   16
    #   ----------
    #           44

    return (0, 0, '')
        if $cdOffset < 44 || $FILELEN - $cdSize < 44 ;

    # Step 1 - 16 bytes before CD is literal string "APK Sig Block 42"
    my $magicOffset = $cdOffset - 16;
    my $buffer = readFromOffset($magicOffset, 16);

    return (0, 0, '')
        if $buffer ne "APK Sig Block 42" ;

    # Step 2 - read the second length field
    #          and check that it looks ok
    $buffer = readFromOffset($cdOffset - 16 - 8, 8);
    my $len2 = unpack("Q<", $buffer);

    return (0, 0, '')
        if $len2 == 0 || $len2 > $FILELEN;

    # Step 3 - read the first length field.
    #          It should be identical to the second one.

    my $startApkOffset = $cdOffset -  8 - $len2 ;

    $buffer = readFromOffset($startApkOffset, 8);
    my $len1 = unpack("Q<", $buffer);

    return (0, 0, '')
        if $len1 != $len2;

    return ($startApkOffset, $cdOffset - 16 - 8, $buffer);
}

sub scanApkBlock
{
    state $IDs = {
            0x7109871a  => "APK Signature v2",
            0xf05368c0  => "APK Signature v3",
            0x42726577  => "Verity Padding Block", # from https://android.googlesource.com/platform/tools/apksig/+/master/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
            0x6dff800d  => "Source Stamp",
            0x504b4453  => "Dependency Info",
            0x71777777  => "APK Channel Block",
            0xff3b5998  => "Zero Block",
            0x2146444e  => "Play Metadata",
    } ;


    seekTo($FH->tell() - 4) ;
    print "\n";
    out "", "APK SIGNING BLOCK";

    scanApkPadding();
    out_Q "Block Length Copy #1";
    my $ix = 1;

    while ($FH->tell() < $APK - 8)
    {
         my ($bytes, $id, $len);
        ($bytes, $len) = read_Q ;
        out $bytes, "ID/Value Length #" . sprintf("%X", $ix), Value_Q($len);

        ($bytes, $id) = read_V;

        out $bytes, "  ID", Value_V($id) . " '" . ($IDs->{$id} // 'Unknown ID') . "'";

        outSomeData($len-4, "  Value");
        ++ $ix;
    }

    out_Q "Block Length Copy #2";

    my $magic ;
    myRead($magic, 16);



( run in 1.058 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )