Vulnerable Systems:
* Adobe Flash Player version 10.0.22.87
Immune Systems:
* Adobe Flash Player version 10.0.32.18
When intrf_count is larger than 0x10000000, it is nullified due to an integer overflow.
This results in an out of bounds pointer dereference. The out of bounds object contains arbitrary values (in the context of the code which handles the interfaces count element) which are manipulated in a way so that an arbitrary memory overwrite with an attacker supplied destination and value is possible.
Since the out of bounds object contains arbitrary values, the attacker may spray the heap so he/she would have control over ArbitraryObjectA and ArbitraryObjectB (they would be located at addresses which contain data controlled by the attacker). This may allow him/her to pass all aforementioned conditions and also control the value which is written in the arbitrary memory MOV and the target of it. Achieving this may allow him the execute arbitrary code.
During the research of this vulnerability I ve managed to create a functional exploit (URL of the demo can be found in the references section of this advisory)
It should be denoted that the vulnerable code is wrapped by an SEH handler which doesn't crash the application on Access Violation. This means that the exploitation process may try different base addresses and offsets in case of a failure.
The following is a detailed run trace which explains the vulnerability. Irrelevant instructions are omitted. Flash10b.ocx is assumed to be loaded at VA 10000000h.
let <intrf_count> be 0x10000000
.text:10206B03 mov edi, [esp+50h+var_2C] ; EDI=<intrf_count>=0x10000000
.text:10206B14 lea edx, [edi+edi] ;
EDX=<intrf_count*2>=0x20000000, may not overflow (verified elsewhere) .text:10206B1B call sub_101EAC30
.text:101EAC45 call sub_101EAB90
.text:101EAB98 call sub_101D1FF0 ; this method calculates
the nearest power of 2 for <intrf_count*2> (i.e: stays 0x20000000)
.text:101EABA0 add eax, eax ; doubles that value (i.e:
EAX=0x40000000)
.text:101EABCC lea ecx, ds:0[eax*4] ; multiplies it by 4 (i.e:
ECX=0x00000000) =>OVERFLOW<=
.text:101EABDA call sub_10224C62
.text:10224C62 jmp sub_10224363
.text:10224363 mov edx, [esp+arg_0] ; arg_0 is the overflown
value (i.e: EDX=00000000)
.text:10224367 lea eax, [edx+7]
.text:10224376 and eax, 0FFFFFFF8h ; EAX=00000000
.text:1022437A mov esi, eax ; ESI=00000000
.text:102243A4 mov ecx, esi ; ECX=00000000
.text:102243A9 mov eax, [eax+ecx*4-4]
; the overflown value is used as an index into pointer table, starting at EAX.
; since we can cause ECX to become 0x0000000, we may select an out of bounds ; pointer (eax-4). Tests show that it always contains a valid pointer to some ; object, with arbitrary values. i.e: EAX=&OutOfBoundsObject
.text:102243AD mov ecx, eax ; ECX=&OutOfBoundsObject
.text:102243C8 call sub_10226D4D
.text:10226D53 mov ebx, ecx ; EBX=&OutOfBoundsObject
.text:10226D6C mov esi, [ebx+8] ; ESI=&ArbitraryObjectA
(usually: 0x55555555)
.text:10226D76 test byte ptr [esi+2Ah], 1 ; <PathConditionA >-
must pass this in order to continue
.text:10226D7A jz short loc_10226DA5
.text:10226D7C mov eax, [ebx+38h] ;
EAX=&ArbitraryObjectB, (usually 0x55555557)
.text:10226D7F cmp byte ptr [eax+33Ch], 0 ; <PathConditionB> -
must pass this in order to continue
.text:10226D86 mov ecx, ebx ; ECX=&OutOfBoundsObject
.text:10226D88 jnz short loc_10226D9D
.text:10226D8A push esi
.text:10226D8B call sub_10226CAF
.text:10226CB0 mov esi, [esp+4+arg_0] ;
ESI=&ArbitraryObjectA, (usually 0x55555555)
.text:10226CB5 push esi
.text:10226CB6 mov edi, ecx ; EDI=&OutOfBoundsObject
.text:10226CB8 call sub_102266CA
.text:102266CA mov eax, [esp+arg_0] ;
EAX=ESI=&ArbitraryObjectA (usually 0x55555555)
.text:102266DB mov ecx, [eax+1Ch] ; ECX=arbitrary value
- usually *(0x55555571)
.text:102266CE mov edx, [eax+20h] ; EDX=arbitrary value
- usually *(0x55555575)
.text:102266DE mov [ecx+20h], edx; ; JACKPOT - a write of
an arbitrary DWORD to an arbitrary VA
The following is an illustration of the pointer table and the out of bounds pointer which may be dereferenced:
Background
ActionScript code is compiled into ActionScript Byte Code segments, loaded by AVM2 (ActionScript Virtual Machine 2).
These segments are described by the abcFile structure:
The value of class_count element is the number of entries in the instance and class arrays.
Each instance entry is a variable length instance_info structure which specifies the characteristics of object instances created by a particular class:
The value of the intrf_count field is the number of entries in the interface array.
The interface array contains indices into the multiname array of the constant pool; the referenced names specify the interfaces implemented by this class.