Error perfecto: uso de Type Confusion en Flash. Parte 1

Hola de nuevo Ma帽ana comenzaremos las clases en un nuevo grupo en el curso "Ingenier铆a inversa" . Tradicionalmente compartimos con usted la traducci贸n de material 煤til sobre el tema. Vamos!

Es importante para algunos atacantes que el exploit sea extremadamente confiable. Siempre debe conducir a la ejecuci贸n de c贸digo cuando se inicia en un sistema con una plataforma y versi贸n conocidas de Flash. Para crearlo, puede usar errores especialmente de alta calidad. Este art铆culo describe el uso de uno de estos errores, as铆 como los factores que lo hacen particularmente adecuado para una operaci贸n confiable.



Bug

CVE-2015-3077 es un problema de confusi贸n de tipos en los configuradores de filtros de Adobe Flash Button y MovieClip , que le permite confundir cualquier tipo de filtro con cualquier otro. Lo inform茅 a principios de diciembre de 2015 y en mayo se solucion贸. El error se produce porque el cracker puede sobrescribir el constructor utilizado para inicializar el objeto de filtro. A continuaci贸n se presenta un c贸digo de muestra que reproduce el problema:



Este c贸digo es algo confuso debido al uso del operador [], que es necesario para la compilaci贸n en Flash CS. El c贸digo l贸gicamente equivalente (que no es un hecho que compila) se da a continuaci贸n:



Este c贸digo establece el campo de filtro del objeto: Bot贸n o MovieClip en BlurFilter, que luego se almacena directamente en Flash. El constructor ConvolutionFilter sobrescribe el constructor BlurFilter. Despu茅s de eso, se llama al captador y se crea un objeto ActionScript para almacenar el BlurFilter original. Sin embargo, el constructor ya se ha sobrescrito, por lo que se llama ConvolutionFilter. Esto produce un objeto de tipo ConvolutionFilter, respaldado por la devoluci贸n del BlueFilter original.

Finalmente, se puede acceder a los campos de ConvolutionFilter (leer y escribir) como si pertenecieran a BlurFilter. De manera similar para cualquier otro tipo de filtro. Esto abre una amplia gama de manipulaciones 煤tiles para explotar.

El siguiente diagrama muestra la ubicaci贸n de los objetos originales en la memoria que podr铆an confundirse con esta vulnerabilidad en Linux de 64 bits.



En dos casos, los punteros son comparables a los enteros y los n煤meros de coma flotante que pueden manipularse. Esto significa que los punteros se pueden leer y escribir directamente. Adem谩s, dado que los campos de los objetos est谩n ordenados y ordenados por tama帽o de acuerdo con la definici贸n de la clase, siempre est谩n en lugares predecibles, de modo que la escritura y la lectura no fallan. Estas propiedades son importantes para garantizar la fiabilidad del exploit.

Explotar

Dado que la explotaci贸n de este problema requiere ejecutar repetidamente la confusi贸n de tipos, comenc茅 creando una funci贸n de utilidad para la confusi贸n de tipos, FilterConfuse.confuse . Tambi茅n ordena las cosas: devuelve los constructores de filtros de ActionScript a su estado normal para llamar repetidamente a una funci贸n vulnerable sin afectar el comportamiento de ActionScript fuera de la funci贸n misma.
El primer paso fue evitar ASLR definiendo la direcci贸n de la tabla de funciones virtuales (brevemente vtable). La forma ideal para esto es confundir un objeto con una tabla virtual con un objeto en el que hay un elemento que se superpone a la tabla virtual que se puede manipular. Pero la vtable de todos los objetos de filtro tiene el mismo desplazamiento. En cambio, utilic茅 el objeto BitmapData en DisplacementMapFilter para determinar la direcci贸n vtable.

Para determinar la ubicaci贸n en la memoria BitmapData del objeto, confund铆 DisplacementMapFilter con BevelFilter. Esto hizo que el puntero BitmapData almacenado en DisplacementMapFilter se alineara con las propiedades de color BevelFilter ( shadowColor , shadowAlpha , highlightColor y highlightAlpha ). Estas propiedades son compatibles con dos enteros de 32 bits (mostrados como scolor y hcolor arriba y abajo), y las propiedades de color acceden a 24 bits de cada entero, mientras que las propiedades alfa acceden a los 8 bits superiores. Si lee estas propiedades y las combina utilizando aritm茅tica de bits, puede extraer la direcci贸n inmediata BitmapData del objeto.



Luego, debe leer la vtable desde la parte superior del objeto BitmapData. Para esto, utilic茅 la propiedad de matriz del objeto ConvolutionFilter. Se almacena como un puntero a una matriz de n煤meros de coma flotante, bajo la cual se asigna memoria al establecer la propiedad, y una matriz de ActionScript que contiene estos n煤meros se devuelve cuando se recibe la propiedad. Al establecer el puntero matricial en un objeto BitmapData, puede leer el contenido de este objeto de la memoria como una matriz de n煤meros de punto flotante.

Para configurar el puntero, confund铆 el objeto ConvolutionFilter con el objeto DisplacementMapFilter (隆no es el mismo DisplacementMapFilter utilizado anteriormente!) Y configur茅 la ubicaci贸n de BitmapData del objeto arriba en la propiedad mapPoint . La propiedad mapPoint es un punto con coordenadas enteras x e y (p_x y p_y en la figura a continuaci贸n) que corresponden al puntero de matriz en ConvolutionFilter, lo que facilit贸 la configuraci贸n de este valor. Despu茅s de eso, se hizo posible leer la vtable del objeto BitmapData usando una matriz de matriz del objeto ConvolutionFilter (vale la pena se帽alar que para esto el objeto tuvo que confundirse con DisplacementBitmapFilter, y luego confundirse nuevamente con ConvolutionFilter).



En este punto, se hace m谩s dif铆cil mantener la confiabilidad del exploit debido al uso de n煤meros de coma flotante. Los valores vtable_low y vtable_high se leen de la matriz ConvolutionFilter como n煤meros de punto flotante, ya que este es un tipo de matriz. Pero, desafortunadamente, no todos los valores de puntero v谩lidos son n煤meros de coma flotante v谩lidos. Esto significa que leer el valor devolver谩 NaN, o peor, un valor num茅rico no del todo correcto.

Idealmente, para resolver este problema, debe acceder a vtable_low y vtable_high a trav茅s de un getter, que los interpreta como enteros, pero esto no se debe a que los elementos de filtro suelen ser flotantes debido a su funcionalidad.

Afortunadamente, la m谩quina virtual AS2 es lo suficientemente floja como para interpretar n煤meros de coma flotante: solo convierte un valor en flotante cuando se realiza una operaci贸n en ActionScript. Las operaciones originales generalmente no requieren interpretaci贸n, excepto las especiales como la aritm茅tica. Esto significa que al copiar un n煤mero de coma flotante de una matriz de matriz a vtable_low o vtable_high, retendr谩 su valor en la memoria, incluso si no es v谩lido para flotante, mientras que la variable en la que se copi贸 no se usa en ActionScript o para realizar operaciones aritm茅ticas en el nativo c贸digo Por lo tanto, si el valor de una variable se confunde instant谩neamente con otro tipo que admite el rango completo de valores de 32 bits, por ejemplo int, se garantiza que ser谩 el mismo que el valor original en la memoria de la matriz. Por lo tanto, para evitar la falta de fiabilidad en el exploit, es importante llevar a cabo la confusi贸n de tipos antes de manipular flotantes en ActionScript.

Para hacer esto, escrib铆 una clase de conversi贸n, FloatConverter , usando la confusi贸n de tipos en los filtros para implementar funciones de entero a flotante y de flotante a entero. Confunde la propiedad de matriz ColorMatrixFilter (no la confunda con la propiedad de matriz ConvolutionFilter), que es un conjunto de flotadores incorporados, con las propiedades de color y alfa GlowFilter que acceden a diferentes bytes int.



De esta manera, puede implementar una conversi贸n confiable de un flotante a un int, pero, desafortunadamente, esto no funciona de manera confiable en la direcci贸n opuesta. Para acceder a la matriz de colores en ColorMatrix en ActionScript, se copia toda la matriz, incluso si solo accede a la primera. Al copiar una matriz, cada elemento se convierte en N煤mero, que incluye una llamada a punteros (por ejemplo, llamar al valor de un objeto). Dado que la matriz de colores es la m谩s larga de toda la clase GlowFilter, se acumula cuando se confunde con GlowFilter. Esto significa que puede producirse la conversi贸n de valores desconocidos de este mont贸n, lo que provocar谩 un bloqueo si se refieren a punteros no v谩lidos al convertir a N煤mero. Por lo tanto, para int-to-float, implement茅 un convertidor flotante usando otra confusi贸n ConvolutionFilter y DisplacementMapFilter, que es una conversi贸n directa y no causa valores desconocidos del mont贸n.



Esto resuelve el problema de los bloqueos causados 鈥嬧媝or el acceso a valores desconocidos desde el mont贸n, pero, desafortunadamente, hay otro problema de confiabilidad asociado con flotantes en este exploit. Se debe a la implementaci贸n del captador de matriz ConvolutionFilter. Todos los valores num茅ricos en ActionScript 2 son del tipo N煤mero, que es la uni贸n de un n煤mero entero y un puntero en un n煤mero doble. La matriz original de ConvolutionFilter se almacena como una matriz de n煤meros de coma flotante, pero se copia a la matriz de ActionScript para preservar el acceso cuando se llama al captador de matriz, y los valores se convierten en dobles en el proceso. Luego, cuando se llama al convertidor flotante, se convierten nuevamente a n煤meros de coma flotante.

Lanzar un n煤mero de coma flotante a un n煤mero de doble precisi贸n y viceversa generalmente guarda su valor, pero no si el valor flotante es SNaN. Seg煤n la especificaci贸n de coma flotante, hay dos tipos de NaN: NaN silencioso (QNaN) y NaN de se帽al (SNaN). Cuando aparece QNaN, no sucede nada, pero SNaN en algunos casos arroja una excepci贸n de punto flotante. En x86, la conversi贸n de doble a flotante siempre da como resultado QNaN (incluso si el doble proviene de SNaN) para evitar excepciones inesperadas.

Por lo tanto, si los bits m谩s bajos del puntero son SNaN, se convertir谩 a QNaN, lo que significa que el primer bit (el primer bit mantisa, bit 22) se establecer谩 cuando no deber铆a. Este problema se puede evitar al leer vtable: el tercer byte del puntero que contiene el primer bit se puede leer sin alineaci贸n para confirmar el valor presente. Por lo tanto, el c贸digo se leer谩 sin alineaciones (despu茅s de leer la vtable nuevamente con el puntero de mapa de bits aumentado en uno) y ajustar el valor int si el flotador resulta ser SNaN.

Usando los convertidores flotantes descritos anteriormente, la direcci贸n vtable se puede convertir en un entero. Ahora necesita obtener el c贸digo para ejecutar usando esta direcci贸n. Una manera f谩cil de mover el puntero de instrucciones es sobrescribir la vtable del objeto (o un puntero a un objeto que tenga una vtable). Esto se puede hacer confundiendo la matriz de matriz ConvolutionFilter y el BitmapData del puntero DisplacementFilter.

El final de la primera parte. La segunda parte de la traducci贸n se publicar谩 un poco m谩s tarde, y ahora estamos esperando sus comentarios e invitamos a todos al curso de ingenier铆a inversa de OTUS.

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


All Articles