February 13, 2014

Data Flow Tracking in Flash Player: Undocumented Bytecodes and JIT

Undocumented Bytecodes

I did some analysis how the bytecodes in DoABC tag parsed, and compared the result against what I saw in the AVM2 documentation (May 2007). I found that Flash Player can parse certain bytecodes that are not mentioned in the documentation.

Bytecode Note Bytecode Note Bytecode Note Bytecode Note
0x00 RESERVED 0x40 newfunction 0x80 coerce 0xc0 increment_i
0x01 UNDOCUMENTED 0x41 call 0x81 UNDOCUMENTED 0xc1 decrement_i
0x02 nop 0x42 construct 0x82 coerce_a 0xc2 inclocal_i
0x03 throw 0x43 callmethod 0x83 UNDOCUMENTED 0xc3 declocal_i
0x04 getsuper 0x44 callstatic 0x84 UNDOCUMENTED 0xc4 negate_i
0x05 setsuper 0x45 callsuper 0x85 coerce_s 0xc5 add_i
0x06 dxns 0x46 callproperty 0x86 astype 0xc6 subtract_i
0x07 dxnslate 0x47 returnvoid 0x87 astypelate 0xc7 multiply_i
0x08 kill 0x48 returnvalue 0x88 UNDOCUMENTED 0xc8 RESERVED
0x09 label 0x49 constructsuper 0x89 UNDOCUMENTED 0xc9 RESERVED
0x0a RESERVED 0x4a constructprop 0x8a RESERVED 0xca RESERVED
0x0b RESERVED 0x4b RESERVED 0x8b RESERVED 0xcb RESERVED
0x0c ifnlt 0x4c callproplex 0x8c RESERVED 0xcc RESERVED
0x0d ifnle 0x4d RESERVED 0x8d RESERVED 0xcd RESERVED
0x0e ifngt 0x4e callsupervoid 0x8e RESERVED 0xce RESERVED
0x0f ifnge 0x4f callpropvoid 0x8f RESERVED 0xcf RESERVED
0x10 jump 0x50 UNDOCUMENTED 0x90 negate 0xd0 getlocal_0
0x11 iftrue 0x51 UNDOCUMENTED 0x91 increment 0xd1 getlocal_1
0x12 iffalse 0x52 UNDOCUMENTED 0x92 inclocal 0xd2 getlocal_2
0x13 ifeq 0x53 UNDOCUMENTED 0x93 decrement 0xd3 getlocal_3
0x14 ifne 0x54 RESERVED 0x94 declocal 0xd4 setlocal_0
0x15 iflt 0x55 newobject 0x95 typeof 0xd5 setlocal_1
0x16 ifle 0x56 newarray 0x96 not 0xd6 setlocal_2
0x17 ifgt 0x57 newactivation 0x97 bitnot 0xd7 setlocal_3
0x18 ifge 0x58 newclass 0x98 RESERVED 0xd8 RESERVED
0x19 ifstricteq 0x59 getdescendants 0x99 RESERVED 0xd9 RESERVED
0x1a ifstrictne 0x5a newcatch 0x9a RESERVED 0xda RESERVED
0x1b lookupswitch 0x5b RESERVED 0x9b RESERVED 0xdb RESERVED
0x1c pushwith 0x5c RESERVED 0x9c RESERVED 0xdc RESERVED
0x1d popscope 0x5d findpropstrict 0x9d RESERVED 0xdd RESERVED
0x1e nextname 0x5e findproperty 0x9e RESERVED 0xde RESERVED
0x1f hasnext 0x5f UNDOCUMENTED 0x9f RESERVED 0xdf RESERVED
0x20 pushnull 0x60 getlex 0xa0 add 0xe0 RESERVED
0x21 pushundefined 0x61 setproperty 0xa1 subtract 0xe1 RESERVED
0x22 RESERVED 0x62 getlocal 0xa2 multiply 0xe2 RESERVED
0x23 nextvalue 0x63 setlocal 0xa3 divide 0xe3 RESERVED
0x24 pushbyte 0x64 getglobalscope 0xa4 modulo 0xe4 RESERVED
0x25 pushshort 0x65 getscopeobject 0xa5 lshift 0xe5 RESERVED
0x26 pushtrue 0x66 getproperty 0xa6 rshift 0xe6 RESERVED
0x27 pushfalse 0x67 UNDOCUMENTED 0xa7 urshift 0xe7 RESERVED
0x28 pushnan 0x68 initproperty 0xa8 bitand 0xe8 RESERVED
0x29 pop 0x69 RESERVED 0xa9 bitor 0xe9 RESERVED
0x2a dup 0x6a deleteproperty 0xaa bitxor 0xea RESERVED
0x2b swap 0x6b RESERVED 0xab equals 0xeb RESERVED
0x2c pushstring 0x6c getslot 0xac strictequals 0xec RESERVED
0x2d pushint 0x6d setslot 0xad lessthan 0xed RESERVED
0x2e pushuint 0x6e getglobalslot 0xae lessequals 0xee RESERVED
0x2f pushdouble 0x6f setglobalslot 0xaf greaterequals 0xef debug
0x30 pushscope 0x70 convert_s 0xb0 UNDOCUMENTED 0xf0 debugline
0x31 pushnamespace 0x71 esc_xelem 0xb1 instanceof 0xf1 debugfile
0x32 hasnext2 0x72 esc_xattr 0xb2 istype 0xf2 UNDOCUMENTED
0x33 RESERVED 0x73 convert_i 0xb3 istypelate 0xf3 RESERVED
0x34 RESERVED 0x74 convert_u 0xb4 in 0xf4 RESERVED
0x35 UNDOCUMENTED 0x75 convert_d 0xb5 RESERVED 0xf5 RESERVED
0x36 UNDOCUMENTED 0x76 convert_b 0xb6 RESERVED 0xf6 RESERVED
0x37 UNDOCUMENTED 0x77 convert_o 0xb7 RESERVED 0xf7 RESERVED
0x38 UNDOCUMENTED 0x78 checkfilter 0xb8 RESERVED 0xf8 RESERVED
0x39 UNDOCUMENTED 0x79 RESERVED 0xb9 RESERVED 0xf9 RESERVED
0x3a UNDOCUMENTED 0x7a RESERVED 0xba RESERVED 0xfa RESERVED
0x3b UNDOCUMENTED 0x7b RESERVED 0xbb RESERVED 0xfb RESERVED
0x3c UNDOCUMENTED 0x7c RESERVED 0xbc RESERVED 0xfc RESERVED
0x3d UNDOCUMENTED 0x7d RESERVED 0xbd RESERVED 0xfd RESERVED
0x3e UNDOCUMENTED 0x7e RESERVED 0xbe RESERVED 0xfe RESERVED
0x3f RESERVED 0x7f RESERVED 0xbf RESERVED 0xff RESERVED

The loop and the big switch statement parsing DoABC bytecode is near 0x6087e9. Instruction near 0x58f25d also reads bytecode. The documentation certainly needs an update on Adobe's side so developers can add the currently undocumented bytecodes to their decompiler/disassembler.

JIT

After adding new functionalities to my pintool I run it against Flash Player. Here is my observation.

When executing a flash file containing DoAction tag in Flash Player no memory page allocated with or set to *EXECUTE* flag. Thus no dynamically generated code was executed with the most common method. Therefore I think DoAction works with interpreted execution. Meaning every single bytecode run on isolation rather than a set of bytes compiled&run (JIT).

When executing a flash file containing DoABC tag in Flash Player I observed increased usage of VirtualAlloc. The page was allocated with PAGE_READWRITE flag. Later on the execution the page was set to PAGE_EXECUTE_READ and the execution flow was transferred to the page. When the execution was returned to the caller the page was set back to PAGE_READWRITE. I knew this was a part of how JIT works. Change of the memory protection flags is the mitigation for DEP.

0x5205a6 is a VirtualProtect call to change the memory protection flags. When it's called with PAGE_READWRITE it's called via 0x5fc39c. When it's called with PAGE_EXECUTE_READ it's called via 0x5fc2e9.

During my experiment I figured out that instruction at 0x5d20ef calls into the JIT-compiled code. Though this might not be the only address to call JIT-compiled code from. I observed many call backs in the JIT-compiled code. One of the callback might be to give continuous feedback to the caller for example if a long loop is being executed. I observed that constants are encrypted with xor instructions to make memory spraying more difficult. This is not new but first time for me to see. This is how 0x41414141 looks like when it's encrypted.
03af1f67 b83a7c1959      mov     eax,59197C3Ah
03af1f6c 357b3d5818      xor     eax,18583D7Bh
All offsets in this post are RVAs, that is relative to Flash Player's image base. Offsets are appropriate in Flash Player 12.0.0.38 (flashplayer_12_sa.exe has a size of 10,339,208).
  This blog is written and maintained by Attila Suszter. Read in Feed Reader.