RealFlex RealWin Server [SCADA] Reverse y Exploit

Miguel Méndez Z.
Oct 17, 2018 · 7 min read
Image for post
Image for post
CrackSLatinoS

Primero que todo esta vulnerabilidad ya tiene un par de años exactamente es del 2010 su CVE-2010–4142. Mi objetivo es volver a escribir el exploit ¿y esto porque?. Bueno la motivación de resolverlo es porque se publico como ejercicio en CrackSLatinoS buena comunidad.

Bueno antes de empezar de lleno con el análisis quiero aclarar algunas dudas que tenia sobre el binario y eso es lo que explicare en este post ya que necesitaba ciertas cosas para que el BoF se ejecutase y saber que función es la culpable. Ahora desarrollar el exploit es relativamente fácil no tenia ninguna complejidad, pero si habían algunas cosas que se daban por entendido que no se explicaban y eso es lo que necesitaba saber.

RealFlex 6.4 SCADA tiene un servidor que se ejecuta en un sistema operativo QNX Neutrino y utiliza un protocolo cifrado dinámicamente entre el servidor y los clientes para asegurar una comunicación segura, ademas de una interfaz grafica HMI (Human Machine Interface).

Image for post
Image for post
HMI

Voy a tratar que no sea tan extenso este post bueno empecemos ️👽.

Lo primero que veremos es que están corriendo unos servicios como el 910, 912, 917. Donde podemos crear un Socket y probar algunos Fuzzer conocidos o utilizar Python For Life en esos puertos abiertos . Para resumir la vulnerabilidad se encuentra en el servicio 912, entonces lo primero que hago es un script en python bien simple que me genere una conexión Socket y enviar una gran cantidad de bytes \x41 al servidor.

Image for post
Image for post
service
Image for post
Image for post
simple socket

Que es lo que ocurre aquí al enviar la data al servidor lo único que recibimos es un mensaje de error “FlexSim protocol header corruption detected” que nos quiere decir esto que la conexión se realizo pero no obtuvimos el crash y eso es por una simple razón lo que estamos enviando como paquete esta mal formado y eso nos lleva a reversiar para ver que es lo que pasa y que necesitamos 💡.

Image for post
Image for post
Image for post
Image for post
error de protocolo

Empiezo a ver por donde llega la conexión así que probé con WSARecv de WS2_32.DLL y vemos que obtenemos el largo del Buffer y la data que envié de solo A’s.

Image for post
Image for post
wsarecv

Luego la siguiente rutina por flecha Roja de WSARecv donde utiliza un MOV EDX, [ESI] como base para aplicar un desplazamiento de 18h y hacer una llamada a esa función.

Image for post
Image for post
Image for post
Image for post
desplazamiento 18h = 24

Entonces al llegar a sub_413630 encuentro lo que necesitaba, primero compara que el largo 21F0h sea mayor a 0xC dec(12) que eso ya seria el largo del header, cumpliendo eso llegamos a unos valores que se comparan 6A541264h si no se cumple la primera condición valida la siguiente 6A541266h de lo contrario entra a la función donde imprime el mensaje de header corrupto.

El flujo es así, EAX+18h es el puntero al Buffer con A’s y lo mueve a ESI para que compare los primero bytes con el string hardcode 6A541264h. Entonces ya se que debe contener los primeros bytes de mi data enviada.

Image for post
Image for post

ESI apunta al inicio del buffer, al sumar ESI+8 nos posicionamos en unos de los bytes que ingresamos, el cual esos byte serán sumados y comparados con EAX+1Ch que es el tamaño del Buffer 21F0h.

Entonces debo calcular el desplazamiento de los bytes y poner unos que sean menor a 21F0h así que pondré \x00*4 que ayudaran para el desplazamiento luego \x1D*2 estos son utilizados para que al sumar con 0xC no sea mayor a 21F0h y \x00*2 para que se fusione con 1D quedando de la siguiente manera 0x00001D1D.

Image for post
Image for post

Por el momento la estructura nuestro del header va de la siguiente manera:

Header : \x64\x12\x54\x6A\x00\x00\x00\x00\x1D\x1D\x00\x00

Image for post
Image for post

Ya pudimos pasar los filtros y nos queda poco al parecer 😃 . Ahora lo que vemos es que al registro EAX quedara con la dirección del inicio de nuestra data que son las A’s, en realidad nuestra data enviada parte desde el header pero con el desplazamiento de 0Ch saltamos el header quedando en las A’s.

Image for post
Image for post

Aquí lo dejo mas claro si no se entendió ESI es nuestro header y EAX es el inicio de las A’s.

Image for post
Image for post

En esta rutina lo que hace es enviar al stack la dirección de las A’s y un byte obtenido del header pero cual sera?. Bueno fácil si sabemos que ESI es el inicio de nuestra data enviada que se compone de header+A’s, entonces seria de la siguiente manera header+4

Header : \x64\x12\x54\x6A\x00\x00\x00\x00\x1D\x1D\x00\x00

Tomamos el valor del primer byte \x00 y lo enviamos a la función calculada EDX+28h.

Image for post
Image for post

Ahora la ultima parte del header para que quede funcional es saber que valor debe ir en ese byte y porque. Bueno explicare para que se utiliza ese byte.

Pondré un ejemplo imaginemos que el byte que debemos cambiar lo dejamos con el valor de 15h esto se mueve a ESI el valor es comparado y debe ser menor que 62h si este es menor seguimos por el camino correcto.

Image for post
Image for post

Después de pasar la condición la siguiente instrucción a ejecutar es movzx eax, ds:byte_415108[edi] lo que realizara es tomar un byte de un array, pero eso sera según el valor que hemos introducido como probamos con 15h que en decimal seria 21 caeríamos en el 12 del array y ese sera multiplicado por 4 y ejecutaría el salto.

Image for post
Image for post
Image for post
Image for post

Si utilizamos un numero el cual tome un valor incorrecto del array seremos redireccionados a esta función donde imprimirá un mensaje de “Unknown scanner protocol message recieved: FUNCTION=1”.

Image for post
Image for post
Image for post
Image for post
message

Ahora yo utilice los valores \x02 y \x20 que serian validos para ocasionar el overflow. Tener en cuenta que cada uno de estos byte redireccionan por distintos flujos pero llegan al mismo resultado.

Ahí tenemos los 2 flujos que llevan al crash, para ir por el flujo de la derecha utilizamos el valor \x20 y el \x02 el de la izquierda.

Image for post
Image for post

Ahora vamos a utilizar la opción de la derecha. Ahí podemos observar que el byte \x20 tomo el valor de 0Ch del array que corresponde a 12 en decimal.

Image for post
Image for post

El calculo que realiza para seguir por el flujo que necesitamos es el siguiente:

  • Ingresamos \x20 este toma el valor 0Ch del array
Image for post
Image for post

Seguimos por ese flujo y llegamos a estas instrucciones donde obtenemos el mensaje a mostrar y lo imprime “Scanner (ID=%p) connection detected.”. Ademas de enviar los parámetros a la función que nombre como Bummmm.

Image for post
Image for post
Image for post
Image for post
mensaje impreso

Ya dentro de 0x00414958 -> Bummmm vemos 2 rutinas pintadas en verde la de arriba llegamos con el byte \x20 y la de abajo se la pueden imaginar :) con la \x02 en las 2 tenemos un lindo y famoso sprintf().

Image for post
Image for post

Ya en el final podemos ver los parámetros que se pasan a la función vulnerable quedando de la siguiente manera.

Parametros:

  • Data = A’s

sprintf(Buffer, Str, Data)

Image for post
Image for post

y al pasar por la función de sprintf() vemos que ya tenemos el control de SEH Bummm ahora solo queda escribir el exploit que no es complicado.

Image for post
Image for post

Header Validos:

  • \x64\x12\x54\x6A\x20\x00\x00\x00\x1D\x1D\x00\x00

Video de ejecución del exploit:

Link: https://www.youtube.com/watch?v=DhhIv93p--M

Code Exploit:

https://ricardo.crver.net/WEB/OTROS/EXPLOIT/Realflex-realwin-server-scada-reverse-y-exploit_By_s1kr10s.pdf

By3…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store