Otro Capture The Flag como todos en el mundillo conocemos o "Reto de Ciberseguridad" de esta serie de CTF con el Nivel 6 al que hemos llamado "El reactor".
Podéis bajaros el ejecutable pinchando en la imagen:
Resolución CTF - Nivel 6 : El reactor
¡Nunca dejes de desafiarte a ti mismo! ¡Nunca pierdas el entusiasmo! - Haider Ackermann.
Si ejecutamos el binario vemos como tiene apariencia de un entorno scada. Aparece una luz verde intermitente y a simple vista ninguna caja, etiqueta, etc. que se pueda utilizar o modificar.
Si abrimos un analizador de procesos como Process Explorer de Sysinternals, podemos ver como del programa original “Reactor.exe” cuelga otro llamado “Client1.exe”.
Podemos ver en las propiedades del mismo que escucha conexiones en un puerto, el 21337.
Y que hay una conexión establecida. Esa conexión pertenece a “Client1.exe” que puede verse con el mismo programa.
Podemos “atacharlo” al Ollydbg y ver qué ocurre.
Ponemos una serie de Breakpoint en la dll “wsock32.dll” encargada de las conexiones con sockets y en funciones de lo que podríamos pensar se utilizan para recibir datos.
Por ejemplo en “recv”. Puse en otros para asegurarme que no hacía nada más.
Y vemos como para en uno de ellos.
De momento no se ve nada, pulsamos F9 si queremos continuar hasta el siguiente Breakpoint o F8/F7 según convenga para ir paso a paso.
Y ya vemos como comienza a verse los datos que el servidor recibe, en este caso:
“status=OK,time=10”, unas cuantas veces. Eso es debido, lo adelanto, que mientras estás depurando, “Client1.exe” lo envía un OK cada 10 segundos y se acumulan.
Ya tenemos claro lo que recibe el servidor y lo que envía el cliente. Jugaremos primero con el servidor. Vamos a la parte de código (F8) en donde recibe el OK.
Lo cambiamos por NO, por ejemplo.
Suspendemos el proceso “Client1.exe” ya que envía cada 10 segundos un OK y nos molestará a la hora de realizar esta modificación.
Y pulsamos F9 quitando los breakpoints anteriores para que ya no pare.
¡ERROR GENERADO! Y mirad como después del 10 aparece la palabra status. Por lo tanto, esto también es modificable, es una caja de texto, no visible fácilmente.
Ahora le toca a la parte del cliente.
Lo mismo para funciones de envío, por ejemplo “send”. Podríamos también buscar “status=” en la memoria para ver donde se llama:
Podemos utilizar un simple editor hexadecimal para realizar algún cambio:
Por ejemplo, OK por NO.
Y generar el error de nuevo:
O bien, podríamos cambiar el tiempo de envío, por ejemplo, cada 20 segundos.
Y ver como el error anterior desaparace ya que envía un OK, cada 20 segundos.
Si ejecutáis el programa en una sandbox de análisis podríais ver rápidamente lo que hemos visto de los puertos:
Processes:
PID ParentPID User Path
--------------------------------------------------
1300 1556 KevinM C:\Users\KevinM\Desktop\Download\Reactor.exe
1948 1300 KevinM C:\Users\KevinM\AppData\Local\Temp\Client1.exe
Ports:
Port PID Type Path
--------------------------------------------------
21337 1300 TCP C:\Users\KevinM\Desktop\Download\Reactor.exe
49175 1948 TCP C:\Users\KevinM\AppData\Local\Temp\Client1.exe
Y como es llamado, las API que utiliza:
514,e94,4051bb RegOpenKeyExA (HKCU\Software\Borland\Locales)
514,e94,4051d9 RegOpenKeyExA (HKLM\Software\Borland\Locales)
514,e94,4051f7 RegOpenKeyExA (HKCU\Software\Borland\Delphi\Locales)
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=0, sz=100000,type=2000, prot=1) = 160000
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=160000, sz=4000,type=1000, prot=4) = 160000
514,e94,6ce7b717 IsDebuggerPresent() = 0
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=0, sz=1000,type=1000, prot=40) = 3c0000
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=164000, sz=4000,type=1000, prot=4) = 164000
514,e94,4017ab VirtualFree(addr=164000, sz=4000, type=4000) (region_sz=4000)
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=168000, sz=4000,type=1000, prot=4) = 168000
514,e94,4017ab VirtualFree(addr=168000, sz=4000, type=4000) (region_sz=4000)
514,e94,77e35141 CloseHandle(h=d4)
514,e94,77e35147 CloseHandle(h=d0)
514,e94,456024 socket(family=2,type=1,proto=0) = ec
514,e94,455c72 bind(ec, port=21337)
514,e94,455ca6 listen(h=ec )
514,e94,4083d4 Skipping DeleteFileA(C:\Users\KevinM\AppData\Local\Temp\Client1.exe)
514,e94,77e2caa4 CloseHandle(h=100)
514,e94,46b7ba WinExec(C:\Users\KevinM\AppData\Local\Temp\Client1.exe,1)
514,e94,77e37107 CloseHandle(h=110)
514,e94,77e2caa4 CloseHandle(h=110)
514,e94,77e2caa4 CloseHandle(h=114)
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=16c000, sz=4000,type=1000, prot=4) = 16c000
514,e94,dce7a17 VirtualAllocEx(h=ffffffff, addr=170000, sz=4000,type=1000, prot=4) = 170000
514,e94,4017ab VirtualFree(addr=170000, sz=4000, type=4000) (region_sz=4000)
514,e94,4017ab VirtualFree(addr=16c000, sz=4000, type=4000) (region_sz=4000)
514,e94,456c25 accept(ec,12fd88,12fda0) = 114
514,e94,455dd0 gethostbyaddr()
Espero que os haya gustado.