Ghost AcademyGhostOffensive · Ghost Academy
GhostOffensiveMódulo 10SOLO SOLUCIÓN

Writeup — Nexus Robotics

← Volver al capítulo 10

Atención: contiene todas las flags. Inténtalo primero por tu cuenta.

Todos los errores y salidas son reales, obtenidos ejecutando los scripts tal como los trae el ZIP, y después ya corregidos, contra el contenedor desplegado (servicio en localhost:9000).

Script 1 — diag1_objetivo.py — objetivo equivocado

Fallo original★

kali@lab (salida real)
$ python3 exploits/diag1_objetivo.py
(se queda colgado; RHOST/RPORT no corresponden a este laboratorio)

El script trae la IP y el puerto de ejemplo del autor original. Se cambian por los del laboratorio:

kali@lab (salida real)
$ RHOST = "127.0.0.1"
RPORT = 9000
b'NEXUSDIAG 4.1 ready\r\n'
OK GO{el_objetivo_no_era_el_correcto}

Flag: GO{el_objetivo_no_era_el_correcto}

Script 2 — diag2_terminador.py — terminador de línea

Fallo original★

kali@lab (salida real)
$ python3 exploits/diag2_terminador.py
b'NEXUSDIAG 4.1 ready\r\n'
(sin respuesta; el programa se queda esperando)

El protocolo exige que cada línea termine en \r\n, no solo en \n. Se corrige el terminador:

kali@lab (salida real)
$ s.sendall(b"DIAG2\r\n")
b'NEXUSDIAG 4.1 ready\r\n'
OK GO{crlf_no_es_solo_un_salto_de_linea}

Flag: GO{crlf_no_es_solo_un_salto_de_linea}

Script 3 — diag3_comando.py — el comando cambió de nombre

Fallo original★★

kali@lab (salida real)
$ python3 exploits/diag3_comando.py
b'NEXUSDIAG 4.1 ready\r\n'
ERR comando renombrado en esta version

El propio servicio lo dice: el comando STATUS de la documentación antigua ahora se llama HEALTH:

kali@lab (salida real)
$ s.sendall(b"HEALTH\r\n")
b'NEXUSDIAG 4.1 ready\r\n'
OK GO{el_comando_cambio_de_nombre}

Flag: GO{el_comando_cambio_de_nombre}

Script 4 — diag4_banner.py — falta un paso previo

Fallo original★★

kali@lab (salida real)
$ python3 exploits/diag4_banner.py
ERR primero completa el saludo (HELLO)

El servicio exige un pequeño saludo (HELLO) antes de aceptar el comando de diagnóstico. El exploit original iba directo al grano:

kali@lab (salida real)
$ s.sendall(b"HELLO\r\n"); print(s.recv(1024))
s.sendall(b"DIAG4\r\n")
OK hola
OK GO{hay_que_leer_el_banner_primero}

Flag: GO{hay_que_leer_el_banner_primero}

Script 5 — diag5_bytes.py — mezcla de bytes y texto

Fallo original★★

kali@lab (salida real)
$ python3 exploits/diag5_bytes.py
TypeError: can't concat str to bytes

version_cliente es una cadena de texto; hay que convertirla a bytes antes de concatenar:

kali@lab (salida real)
$ version_cliente = b"toolkit-1.0"
b'NEXUSDIAG 4.1 ready\r\n'
OK GO{bytes_y_texto_no_se_mezclan}

Flag: GO{bytes_y_texto_no_se_mezclan}

Script 6 — diag6_python2.py — sintaxis de Python 2

Fallo original★

kali@lab (salida real)
$ python3 exploits/diag6_python2.py
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?

El script está escrito para Python 2. Se porta a Python 3: print(...) con paréntesis y range() en vez de xrange():

kali@lab (salida real)
$ print("Banner recibido:", banner)
for intento in range(1):
Banner recibido: b'NEXUSDIAG 4.1 ready\r\n'
OK GO{print_ya_no_es_una_sentencia}

Flag: GO{print_ya_no_es_una_sentencia}

Script 7 — diag7_connect.py — argumentos de connect()

Fallo original★

kali@lab (salida real)
$ python3 exploits/diag7_connect.py
TypeError: socket.connect() takes exactly one argument (2 given)

connect() espera una sola tupla (host, puerto), no dos argumentos sueltos:

kali@lab (salida real)
$ s.connect((RHOST, RPORT))
b'NEXUSDIAG 4.1 ready\r\n'
OK GO{connect_espera_una_tupla}

Flag: GO{connect_espera_una_tupla}

Script 8 — diag8_relleno.py — relleno con la longitud exacta

Fallo original★★

kali@lab (salida real)
$ python3 exploits/diag8_relleno.py
b'NEXUSDIAG 4.1 ready\r\n'
ERR relleno de 63 bytes, se esperaban 64

El propio servicio indica la longitud exacta que espera. El exploit traía 63 bytes de relleno (el valor usado en una demo con una versión distinta); se ajusta a 64:

kali@lab (salida real)
$ relleno = b"A" * 64
b'NEXUSDIAG 4.1 ready\r\n'
OK GO{el_relleno_tenia_la_medida_justa}

Flag: GO{el_relleno_tenia_la_medida_justa}

Resumen

#FalloCorrección
1Objetivo de ejemplo sin cambiarActualizar RHOST/RPORT
2Terminador de línea incompletoUsar \r\n
3Nombre de comando obsoletoUsar el nombre actual (HEALTH)
4Falta un paso de protocolo previoCompletar el saludo antes del comando
5Mezcla de bytes y strConvertir a bytes antes de concatenar
6Sintaxis de Python 2Portar a Python 3
7Argumentos de connect()Pasar una tupla, no dos valores sueltos
8Longitud de relleno incorrectaAjustar al valor exacto que exige el servicio