📜 ⬆️ ⬇️

Ideal bug: Using Type Confusion in Flash. Part 1

Hello again! Tomorrow we will start classes in the new group in the course “Reverse Engineering” . Traditionally we share with you the translation of useful material on the topic. Go!

It is important for some attackers that the exploit is extremely reliable. It should always lead to the execution of the code when running on a system with a known platform and Flash version. To create it, you can use especially high-quality bugs. This article describes the use of one of these bugs, as well as factors that make it particularly suitable for reliable operation.


')
Bug

CVE-2015-3077 - the problem of type confusion in the Adobe Flash Button and MovieClip filter setters, which allows you to confuse any type of filter with any other. I reported it in early December 2015, and it was fixed in May. The bug occurs because a hacker can overwrite the constructor used to initialize the filter object. An example of code reproducing the problem is presented below:



This code is somewhat confusing due to the use of the operator [], necessary for compilation in Flash CS. Logically equivalent code (which is not a fact that will be compiled) is shown below:



This code sets the object's filter field: Button or MovieClip to BlurFilter, which is then stored directly in Flash. The BlurFilter constructor is then overwritten by the ConvolutionFilter constructor. After that, the getter is called and an ActionScript object is created to store the original BlurFilter. However, the constructor has already been rewritten, so ConvolutionFilter is called. This is an object of type ConvolutionFilter, supported by the return of the original BlueFilter.

Ultimately, the ConvolutionFilter fields can be accessed (read and written) as if they belonged to BlurFilter. Similarly for any other type of filter. This opens up a wide range of manipulations useful for exploitation.

The diagram below shows the location of the original objects in memory, which can potentially be confused using this vulnerability in 64-bit Linux.



In two cases, pointers are comparable to integers and floating point numbers that can be manipulated. This means that pointers can be read and written directly. In addition, since the fields of objects are ordered and sorted by size according to the definition of a class, they are always in predictable places, so that writing and reading do not fail. These properties are important to ensure the reliability of the exploit.

Exploit

Since exploiting this problem requires multiple types of type confusion, I started by creating a utility function for type confusion, FilterConfuse.confuse . It also brings order: it returns the ActionScript filter constructors back to the normal state to repeatedly call the vulnerable function without affecting the ActionScript behavior outside the function itself.
The first step was to bypass the ASLR by determining the address of the virtual function table (vtable for short). The ideal way to do this is to confuse an object with a vtable with an object in which there is an element that overlaps the vtable that can be manipulated. But the vtable of all filter objects have the same offset. Instead, I used the BitmapData object in the DisplacementMapFilter to determine the vtable address.

To determine the memory location of the BitmapData object, I mixed up DisplacementMapFilter with a BevelFilter. This caused the BitmapData pointer stored in DisplacementMapFilter to align with the properties of the BevelFilter color ( shadowColor , shadowAlpha , highlightColor, and highlightAlpha ). These properties are supported by two 32-bit integers (shown as scolor and hcolor at the top and bottom), and the color properties get access to 24 bits of each integer, while alpha properties get access to the top 8 bits. If you read these properties and combine them using bit arithmetic, you can extract the direct address of the BitmapData object.



Then, you need to read the vtable from the top of the BitmapData object. For this, I used the matrix property of the ConvolutionFilter object. It is stored as a pointer to an array of floating-point numbers for which memory is allocated when the property is set, and an ActionScript array containing these numbers is returned when the property is received. By setting the matrix pointer to a BitmapData object, you can read from memory the contents of this object as an array of floating point numbers.

To set the pointer, I confused the ConvolutionFilter object with the DisplacementMapFilter object (not the same DisplacementMapFilter that I used above!) And set the mapPoint property to the BitmapData property above. The mapPoint property is a point with integer x and y coordinates (p_x and p_y in the figure below) that corresponds to the matrix pointer in ConvolutionFilter, which made it easy to set this value. After that, it became possible to read the vtable from the BitmapData object using a matrix array from the ConvolutionFilter object (it is worth noting that for this you had to confuse the object with DisplacementBitmapFilter, and then confuse it with ConvolutionFilter).



At this stage, it becomes more difficult to maintain the reliability of the exploit due to the use of floating point numbers. The values ​​of vtable_low and vtable_high are read from the ConvolutionFilter matrix as floating point numbers, since this is an array type. But, unfortunately, not every valid pointer value is a valid floating point number. This means that reading a value will return NaN, or worse, a not entirely correct numeric value.

Ideally, to solve this problem, you need to access vtable_low and vtable_high through the getter, which interprets them as whole numbers, but this is not, because filter elements usually float because of their functionality.

Fortunately, the AS2 virtual machine is rather lazy with regard to the interpretation of floating-point numbers — it converts the value to float only when it is operated on in ActionScript. Original operations usually do not require interpretation, except special ones, such as arithmetic. This means that when copying a floating-point number from a matrix array to vtable_low or vtable_high, it will retain its value in memory, even if it is invalid for a float, while the variable to which it was copied is not used in ActionScript or to perform arithmetic operations in its native code. Thus, if a variable's value is instantly confused with another type that supports a full range of 32-bit values, for example int, it is guaranteed to be the same as the original value in the memory of the matrix array. Therefore, in order to avoid the appearance of insecurity in an exploit, it is important to conduct type confusion before manipulating floats in ActionScript.

To do this, I wrote a conversion class, FloatConverter , that uses type confusion in filters to implement integer-to-float and float-to-integer functions. It confuses the matrix property ColorMatrixFilter (not to be confused with the matrix property ConvolutionFilter), which is a set of embedded floats, with the GlowFilter color and alpha properties that refer to different int bytes.



So you can implement a reliable conversion float'a in int, but, unfortunately, in the opposite direction it does not work reliably. To access the color array in ColorMatrix in ActionScript, the entire array is copied, even if you refer only to the first one. When copying an array, each element is converted to a Number, which includes accessing pointers (for example, calling the object's valueOf). Since the color array is the longest of the GlowFilter class, it gets into a heap when tangled with GlowFilter. This means that converting unknown values ​​from this heap can occur, which will crash if they refer to invalid pointers when converting to Number. Therefore, for int-to-float, I implemented a float converter that uses another confusion, ConvolutionFilter and DisplacementMapFilter, which is a direct caste and does not cause unknown values ​​from the heap.



This solves the problem of crashes caused by referring to unfamiliar values ​​from the heap, but unfortunately, there is another reliability issue associated with this float exploit. It is due to the implementation of the ConvolutionFilter matrix getter. All numeric values ​​in ActionScript 2 are of type Number, which is the union of an integer and a pointer into a double precision number (double). The original ConvolutionFilter matrix is ​​stored as an array of floating-point numbers, but is copied into an ActionScript array to maintain access when the matrix getter is called, and the values ​​in the process are converted to double. Then, when calling the float converter, they are converted back to floating point numbers.

Reducing a floating-point number to a double-precision number and vice versa usually preserves its value, but not if the float value is SNaN. According to the floating point specification, there are two types of NaNs: silent NaN (QNaN) and signaling NaN (SNaN). When QNaN appears, nothing happens, but SNaN in some cases throws a floating point exception. In x86, double conversion to float always results in QNaN (even if double is obtained from SNaN) to avoid unexpected exceptions.

Therefore, if the lower bits of the pointer are SNaN, it will be converted to QNaN, which means the first bit (the first bit of the mantissa, bit 22) will be set when it should not. This problem can be avoided by reading vtable - the third pointer byte containing the first bit can be read without alignment to confirm the present value. So the code will read without alignments (after reading vtable again with the Bitmap pointer increased by one) and will adjust the int value if the float turns out to be SNaN.

Using the float converters described above, the vtable address can be converted to an integer. Now you need to achieve code execution using this address. An easy way to move the instruction pointer is to overwrite the vtable of the object (or a pointer to an object that has a vtable). This can be done by using the confusion matrix ConvolutionFilter and BitmapData of the DisplacementFilter pointer.

The end of the first part. The second part of the translation will be published a little later, and now we are waiting for your comments and we invite everyone to the “Reverse Engineering” course from OTUS.

Source: https://habr.com/ru/post/442640/


All Articles