JesusFreke / smali

smali/baksmali
6.33k stars 1.07k forks source link

Seemingly illegal fill-array-data-payload is disassembled anyway #766

Open jackwpa opened 4 years ago

jackwpa commented 4 years ago

I recently encountered a dex file where a code portion of some initializer was disassembled as:

    :array
    nop
    .array-data 4
        0x123
        ....

That is, the fill-array-data-payload blob does not start with 0x300, as the specification says, but with a nop (so, 00 00), which is only then followed by 0x300. I did confirm this with a hex editor. So, it looks like baksmali skipped the NOP and parsed the subsequent array data as normal.

Is this legal? I crafted a similar file and ran it through dalvikvm on a production device. As expected, the verifier rejects it:

java.lang.VerifyError: Verifier rejected class ... [0xFFFFFFFF] unaligned array data table: at N, data offset N-1

So, which is right here? And does ART even apply the same verification that the dalvikvm tool does on a file?

JesusFreke commented 4 years ago

the "dalvikvm" executable on any modern phone with art is just a front-ent for art. There is no more dalvik.

So yes, the results from running the dalvikvm executable are correct, and it looks like this is a bug in baksmali. Although I think this used to be allowed by (the real) dalvikvm. So I'll need to figure out when/how this behavior changed, if it did.

JesusFreke commented 4 years ago

Oh, I just noticed that you didn't verify that the original dex file failed verification, but one that you generated. Can you share the file you created that failed verification?

Did the original dex file fail verification? What was the code offset of the :array label, when disassembling with the --code-offsets options.

jackwpa commented 4 years ago

Sorry for the delay, I missed the notification. Here's my sample file:

public class FillArray {
  public static void main(String[] args) throws Exception {
    int[] a = new int[]{0x11, 0x22};
    System.out.println("Placeholder");
  }
}

Compiles it to, for example (base-64 encoded) FillArray.dex: ZGV4CjAzNQAmgGZ0YXfcDpoPOuezERsnpPacfALQxGSsAwAAcAAAAHhWNBIAAAAAAAAAAOgCAAASAAAAcAAAAAoAAAC4AAAAAwAAAOAAAAABAAAABAEAAAQAAAAMAQAAAQAAACwBAABgAgAATAEAAM4BAADWAQAA5gEAAPMBAAAPAgAAJgIAAD0CAABRAgAAZQIAAHkCAACGAgAAiQIAAI0CAACRAgAApgIAAKwCAACxAgAAugIAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAKAAAADAAAAA0AAAAKAAAABwAAAAAAAAALAAAABwAAAMABAAALAAAABwAAAMgBAAAGAAIADwAAAAAAAAAAAAAAAAACAA4AAAACAAEAEAAAAAQAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAEAAACoAQAA1wIAAAAAAAABAAAAzwIAAAEAAQABAAAAwQIAAAQAAABwEAMAAAAOAAMAAQACAAAAxgIAABYAAAASICMACAAmAAsAAABiAAAAGgEJAG4gAgAQAA4AAAMEAAIAAAARAAAAIgAAAAAAAAAAAAAAAQAAAAAAAAABAAAATAEAAAEAAAAFAAAAAQAAAAkABjxpbml0PgAORmlsbEFycmF5LmphdmEAC0xGaWxsQXJyYXk7ABpMZGFsdmlrL2Fubm90YXRpb24vVGhyb3dzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5c3RlbTsAC1BsYWNlaG9sZGVyAAFWAAJWTAACW0kAE1tMamF2YS9sYW5nL1N0cmluZzsABG1haW4AA291dAAHcHJpbnRsbgAFdmFsdWUAAQAHDgAEAQAHDml4GwACAQERHAEYAwAAAgAAgYAE1AIBCewCAAAAEAAAAAAAAAABAAAAAAAAAAEAAAASAAAAcAAAAAIAAAAKAAAAuAAAAAMAAAADAAAA4AAAAAQAAAABAAAABAEAAAUAAAAEAAAADAEAAAYAAAABAAAALAEAAAMQAAABAAAATAEAAAEgAAACAAAAVAEAAAYgAAABAAAAqAEAAAEQAAACAAAAwAEAAAIgAAASAAAAzgEAAAMgAAACAAAAwQIAAAQgAAABAAAAzwIAAAAgAAABAAAA1wIAAAAQAAABAAAA6AIAAA==

In the modified version below, I NOP'ed the invoke println() instruction, and adjusted the offset of fill-array-data by -1 word, that is two bytes, which means the array data offset points to 1 NOP before the pseudo opcode marker 0x300, therefore array data is unaligned. dalvikvm will complain about it: Exception in thread "main" java.lang.VerifyError: Verifier rejected class FillArray: void FillArray.main(java.lang.String[]): [0xFFFFFFFF] unaligned array data table: at 3, data offset 10 (declaration of 'FillArray' appears in /sdcard/FillArray_modified_unaligned.dex)

FillArray_modified_unaligned.dex: ZGV4CjAzNQCFf2chYXfcDpoPOuezERsnpPacfALQxGSsAwAAcAAAAHhWNBIAAAAAAAAAAOgCAAASAAAAcAAAAAoAAAC4AAAAAwAAAOAAAAABAAAABAEAAAQAAAAMAQAAAQAAACwBAABgAgAATAEAAM4BAADWAQAA5gEAAPMBAAAPAgAAJgIAAD0CAABRAgAAZQIAAHkCAACGAgAAiQIAAI0CAACRAgAApgIAAKwCAACxAgAAugIAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAKAAAADAAAAA0AAAAKAAAABwAAAAAAAAALAAAABwAAAMABAAALAAAABwAAAMgBAAAGAAIADwAAAAAAAAAAAAAAAAACAA4AAAACAAEAEAAAAAQAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAEAAACoAQAA1wIAAAAAAAABAAAAzwIAAAEAAQABAAAAwQIAAAQAAABwEAMAAAAOAAMAAQACAAAAxgIAABYAAAASICMACAAmAAoAAABiAAAAGgEJAA4AAAAAAAAAAAMEAAIAAAARAAAAIgAAAAAAAAAAAAAAAQAAAAAAAAABAAAATAEAAAEAAAAFAAAAAQAAAAkABjxpbml0PgAORmlsbEFycmF5LmphdmEAC0xGaWxsQXJyYXk7ABpMZGFsdmlrL2Fubm90YXRpb24vVGhyb3dzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5c3RlbTsAC1BsYWNlaG9sZGVyAAFWAAJWTAACW0kAE1tMamF2YS9sYW5nL1N0cmluZzsABG1haW4AA291dAAHcHJpbnRsbgAFdmFsdWUAAQAHDgAEAQAHDml4GwACAQERHAEYAwAAAgAAgYAE1AIBCewCAAAAEAAAAAAAAAABAAAAAAAAAAEAAAASAAAAcAAAAAIAAAAKAAAAuAAAAAMAAAADAAAA4AAAAAQAAAABAAAABAEAAAUAAAAEAAAADAEAAAYAAAABAAAALAEAAAMQAAABAAAATAEAAAEgAAACAAAAVAEAAAYgAAABAAAAqAEAAAEQAAACAAAAwAEAAAIgAAASAAAAzgEAAAMgAAACAAAAwQIAAAQgAAABAAAAzwIAAAAgAAABAAAA1wIAAAAQAAABAAAA6AIAAA==

With the mod below, I inserted 2 NOPs before the 0x300 magic. The payload therefore remains aligned, and dalvikvm complains differently this time, as said in my original message: Exception in thread "main" java.lang.VerifyError: Verifier rejected class FillArray: void FillArray.main(java.lang.String[]) failed to verify: void FillArray.main(java.lang.String[]): [0x3] invalid magic for array-data (declaration of 'FillArray' appears in /sdcard/FillArray_modified.dex)

FillArray_modified.dex: ZGV4CjAzNQCEfz8fYXfcDpoPOuezERsnpPacfALQxGSsAwAAcAAAAHhWNBIAAAAAAAAAAOgCAAASAAAAcAAAAAoAAAC4AAAAAwAAAOAAAAABAAAABAEAAAQAAAAMAQAAAQAAACwBAABgAgAATAEAAM4BAADWAQAA5gEAAPMBAAAPAgAAJgIAAD0CAABRAgAAZQIAAHkCAACGAgAAiQIAAI0CAACRAgAApgIAAKwCAACxAgAAugIAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAKAAAADAAAAA0AAAAKAAAABwAAAAAAAAALAAAABwAAAMABAAALAAAABwAAAMgBAAAGAAIADwAAAAAAAAAAAAAAAAACAA4AAAACAAEAEAAAAAQAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAEAAACoAQAA1wIAAAAAAAABAAAAzwIAAAEAAQABAAAAwQIAAAQAAABwEAMAAAAOAAMAAQACAAAAxgIAABYAAAASICMACAAmAAkAAABiAAAAGgEJAA4AAAAAAAAAAAMEAAIAAAARAAAAIgAAAAAAAAAAAAAAAQAAAAAAAAABAAAATAEAAAEAAAAFAAAAAQAAAAkABjxpbml0PgAORmlsbEFycmF5LmphdmEAC0xGaWxsQXJyYXk7ABpMZGFsdmlrL2Fubm90YXRpb24vVGhyb3dzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5c3RlbTsAC1BsYWNlaG9sZGVyAAFWAAJWTAACW0kAE1tMamF2YS9sYW5nL1N0cmluZzsABG1haW4AA291dAAHcHJpbnRsbgAFdmFsdWUAAQAHDgAEAQAHDml4GwACAQERHAEYAwAAAgAAgYAE1AIBCewCAAAAEAAAAAAAAAABAAAAAAAAAAEAAAASAAAAcAAAAAIAAAAKAAAAuAAAAAMAAAADAAAA4AAAAAQAAAABAAAABAEAAAUAAAAEAAAADAEAAAYAAAABAAAALAEAAAMQAAABAAAATAEAAAEgAAACAAAAVAEAAAYgAAABAAAAqAEAAAEQAAACAAAAwAEAAAIgAAASAAAAzgEAAAMgAAACAAAAwQIAAAQgAAABAAAAzwIAAAAgAAABAAAA1wIAAAAQAAABAAAA6AIAAA==

I ran the tests on a phone running Android 10. Haven't got a chance to try that on a pre-ART image.

baksmali does not like the second mod (aligned) file. fill-array-data will is generated as a comment along with #invalid payload reference. Strangely, baksmali is fine with the unligned mod: fill-array-data is there and the payload offset points to the single nop before 0x300.

FYI I also tried things with JEB, and things are disassembled and decompiled okay, the offset was adjusted, but a warning was generated: "Padding detected before pseudo-opcode data (fill-array-data)"

FillArray_modified.dex with JEB 3.19 w/ standard settings: image

jackwpa commented 4 years ago

Any update?