rednaga/APKiD

[ENHANCEMENT] Improve rule `is_apk`

Opened this issue · 5 comments

We could improve the rule is_apk by checking that after 26 bytes from the magic bytes we got the AndroidManifest.xml. As shown below:

rule IsZIP {
  strings:
    $EOCD_magic = { 50 4B 05 06 }

  condition:
    $EOCD_magic in (0..filesize - 22)
}
rule HasZIPMagic {
  strings:
    $CDFH_magic = { 50 4B 01 02 }
    $LFH_magic = { 50 4B 03 04 }
    $EOCD_magic = { 50 4B 05 06 }
    $DD_magic = { 50 4B 07 08 }
  condition:
    $LFH_magic or $CDFH_magic or $EOCD_magic or $DD_magic
}
rule IsDOCX {
  strings:
    //                         P  K             [  C  o  n  t  e  n  t  _  T  y  p  e  s  ]  .  x  m  l
    $lfh_and_content_type = { 50 4B 03 04 [26] 5B 43 6F 6E 74 65 6E 74 5F 54 79 70 65 73 5D 2E 78 6D 6C }

  condition:
    IsZIP and $lfh_and_content_type
}
rule IsJAR {
  strings:
    //                 P  K             M  E  T  A  -  I  N  F  /  M  A  N  I  F  E  S  T  .  M  F
    $lfh_and_meta = { 50 4B 03 04 [26] 4D 45 54 41 2D 49 4E 46 2F 4D 41 4E 49 46 45 53 54 2E 4D 46 }
    // the file name must be 30 bytes after the beginning of the LFH (or the CFD)

  condition:
    IsZIP and $lfh_and_meta
}
rule IsAPK {
  strings:
  //                    P  K             A  n  d  r  o  i  d  M  a  n  i  f  e  s  t  .  x  m  l
  $lfh_and_android = { 50 4B 03 04 [26] 41 6E 64 72 6F 69 64 4D 61 6e 69 66 65 73 74 2E 78 6D 6C}
  
  condition:
    IsZIP and $lfh_and_android
}

APKiD is_apk rule

rule is_apk : file_type
{
  meta:
    description = "APK"

  strings:
    $zip_head = "PK"
    $manifest = "AndroidManifest.xml"

  condition:
    $zip_head at 0 and $manifest and #manifest >= 2
}

private rule is_signed_apk : internal
{
  meta:
    description = "Resembles a signed APK that is likely not corrupt"

  strings:
    $meta_inf = "META-INF/"
    $ext_rsa = ".RSA"
    $ext_dsa = ".DSA"
    $ext_ec = ".EC"

  condition:
    is_apk and
    for all of ($meta_inf*) : ($ext_rsa or $ext_dsa or $ext_ec in (@ + 9..@ + 9 + 100))
}

private rule is_unsigned_apk : internal
{
  meta:
    description = "Resembles an unsigned APK that is likely not corrupt"

  condition:
    is_apk and not is_signed_apk
}

Source - https://github.com/Polydet/polydet/blob/master/polydet/plugins/zip.py#L42

  • For IsAPK, AndroidManifest.xml is not always there, we rather can check if it exists at all
  • For is_signed_apk, we better add "APK Sig Block 42" + Central Directory Magic (0x02014b50) (41 50 4B 20 53 69 67 20 42 6C 6F 63 6B 20 34 32 50 4B 01 02) to cover V2 and V3 signed apks because when minimum sdk version is >=24 it doesn't have to be signed with V1

Can you give a (some?) examples of valid APKs which do not contain any AndroidManifest.xml files?

+2 on extending the different signature variations though. That would be neat and potentially nice to have as a secondary url tag.

  • For IsAPK, AndroidManifest.xml is not always there, we rather can check if it exists at all
  • For is_signed_apk, we better add "APK Sig Block 42" + Central Directory Magic (0x02014b50) (41 50 4B 20 53 69 67 20 42 6C 6F 63 6B 20 34 32 50 4B 01 02) to cover V2 and V3 signed apks because when minimum sdk version is >=24 it doesn't have to be signed with V1

Would you like to open a PR?

  • For IsAPK, AndroidManifest.xml is not always there, we rather can check if it exists at all
  • For is_signed_apk, we better add "APK Sig Block 42" + Central Directory Magic (0x02014b50) (41 50 4B 20 53 69 67 20 42 6C 6F 63 6B 20 34 32 50 4B 01 02) to cover V2 and V3 signed apks because when minimum sdk version is >=24 it doesn't have to be signed with V1

Would you like to open a PR?

Just created one
#379