Seguridad OT: S5/S7, la maquina virtual MC7 y la ausencia de logs en ICS

De STEP5/AWL a STEP7, la maquina virtual MC7 y su reversing de bytecodes, exploit development sobre PLC, un sandbox escape con ejecucion nativa en kernel, ROP sobre MC7 y por que las ICS carecen estructuralmente de registro de auditoria.

1. Fundamentos del PLC

¿Qué es un PLC?

Un Controlador Lógico Programable (PLC) es una computadora industrial que acepta entradas desde emisores de señales, las evalúa de acuerdo a un programa almacenado en memoria y genera salidas para el control de máquinas y procesos. A diferencia de una computadora de propósito general, está diseñado para operar en ambientes hostiles con alta fiabilidad y determinismo temporal. Esta especialización implica una arquitectura interna optimizada para operaciones de control en tiempo real, donde el ciclo de scan (lectura de entradas → ejecución del programa → escritura de salidas) debe completarse en tiempos predecibles.

Tipos de estructuras externas

Del laboratorio al campo: una instantánea del hardware real

Antes de sumergirnos en instrucciones AWL y bytecodes, conviene recordar que todo sistema de control tiene una capa física. La imagen a continuación muestra el interior de un tablero de control industrial típico, donde conviven el PLC con los componentes de potencia y protección que le dan interfaz con el mundo real.

Interior de tablero eléctrico industrial con interruptor termomagnético, relés y contactor

Sobre el riel DIN se aprecian un interruptor termomagnético Merlin Gerin (curva C, 16A), una fila de relés de interfaz enchufables Finder capaces de conmutar cargas de hasta 250V, un contactor industrial Siemens serie 3TF42, y las borneras de conexión. Estos elementos actúan como puente entre las salidas electrónicas del PLC y los actuadores de potencia: bombas, válvulas, motores. Sin esta etapa de acondicionamiento, el autómata no podría gobernar el proceso físico.

Lenguaje STEP5

STEP5 es el entorno de programación clásico para la familia Siemens S5. Distingue dos tipos de programas:

Lenguajes contenidos en STEP5:

2. Bloques del Programa de Usuario

BloqueNombreFunción
OBBloque de OrganizaciónControla la secuencia de ejecución del programa. Define puntos de entrada e interrupciones. Esencial para la estructura del programa.
PBBloque de ProgramaContiene el programa principal de control. Puede llamar a otros bloques de funciones y datos.
FBBloque de FuncionesContiene funciones reutilizables que se pueden llamar desde otros bloques. Permite modularizar el programa.
SBBloque SecuencialUtilizado para programar secuencias de pasos. Define transiciones entre pasos y acciones asociadas.
DBBloque de DatosAlmacena datos variables utilizados en el programa. Facilita el intercambio de datos entre diferentes bloques.

Operandos en STEP5

3. AWL: Un Assembly para Autómatas

La sintaxis de AWL guarda un paralelismo notable con el Assembly de arquitecturas como x86. Se compone de un operador (la instrucción), un indicador de operando (el tipo de dato sobre el que se opera) y un operando (la dirección o valor concreto). El resultado de cada operación lógica se almacena en el registro RLO (Result of Logic Operation), que cumple una función análoga al registro EAX en x86: actúa como acumulador donde se deposita el resultado de la última evaluación.

// Estructura de una instrucción AWL:
direccion_relativa : operacion indicador_operando parametro

// Ejemplo con marcas de memoria y entradas:
U M 0.5 // AND entre RLO y el bit 5 del byte 0 de marcas
U M 254.0 // AND con el bit 0 del byte 254 de marcas
O // OR sin operando: une los dos extremos
U E 2.1 // AND con la entrada 2.1
U E 2.2 // AND con la entrada 2.2
= A 3.2 // Asigna el RLO a la salida 3.2

En el ejemplo anterior, el operando M hace referencia a las "marcas de memoria", un espacio en la memoria interna del PLC. La sintaxis M [byte].[bit] es notable: el número a la izquierda del punto representa el byte de la dirección y el número a la derecha representa el bit dentro de ese byte (0-7). En el PLC utilizado para las pruebas prácticas, se dispone de un máximo de 255 bytes de marcas (2048 bits).

El entorno de programación STEP5 en acción

Para entender cómo se materializan estas instrucciones en un proyecto real, la siguiente captura muestra el software de programación de la familia Simatic S5. Es el tipo de entorno —ejecutado aquí sobre una herramienta compatible con Windows como PG-2000— que aún hoy se utiliza para mantener sistemas heredados en plantas industriales.

Software de programación STEP5 para PLC Siemens S5 mostrando bloques OB1, PB25, FB1, FB2 en AWL

En la imagen se distinguen los bloques de organización y función (OB1, PB25, FB1, FB2) con código escrito íntegramente en AWL. Las instrucciones aparecen en alemán —herencia de la documentación original de Siemens— y se observan operaciones de incremento (INC) y decremento (DEC) directamente sobre bytes de memoria (MB0). Esta forma de programar, donde el desarrollador manipula direcciones de memoria con absoluta transparencia, es la que convierte al AWL en un lenguaje tan poderoso como peligroso: un simple puntero mal calculado puede corromper regiones enteras del programa.

A diferencia de las marcas, cuyas direcciones son lógicas y definidas por el fabricante, el direccionamiento de entradas y salidas depende de la ranura física en el RACK donde se encuentre el módulo de E/S. En el S5 esta asignación es fija: ranura 0 = byte 0, ranura 1 = byte 1, etc. En versiones más modernas como el S7, esta correspondencia puede configurarse por software.

La instrucción de asignación = cumple una función similar al RET en x86: copia el último resultado almacenado en el RLO y lo transfiere al operando designado, ya sea una salida física o una posición de memoria.

Instrucciones de fin de bloque

NOTA: RLO (VKE)

El RLO (Resultado Lógico de Operación), denominado VKE en la documentación alemana, es el equivalente funcional a RAX/EAX en x86_64. Almacena el resultado de cada operación lógica y es sobrescrito por cada nueva instrucción que produce un resultado booleano. Esta característica de acumulador es fundamental para entender el flujo de ejecución del programa.

4. Compuertas Lógicas y Operaciones

AND (AWL = U)

OR (AWL = O)

XOR (AWL = X)

Agrupación con paréntesis: las operaciones encerradas entre paréntesis se evalúan antes que la operación que las precede.

U(
  O E 2.1
  O E 2.2
)
U E 2.5
// Primero evalúa OR entre E2.1 y E2.2, luego AND con E2.5

OR sin operandos: permite evaluar extremos de forma independiente para luego encontrarse en una evaluación OR. Es una construcción sintáctica particularmente útil para simplificar expresiones complejas.

U E 2.1
U E 2.2
O // Sin operando: une los dos extremos evaluados
U E 2.3
U E 2.4

Diferencia S5 vs S7

El S5 no posee instrucciones para la detección de flancos de subida/bajada. El S7 sí incorpora esta capacidad de forma nativa mediante las instrucciones FP (flanco positivo) y FN (flanco negativo). En S5, la detección de flancos debe implementarse manualmente mediante lógica de muestreo con marcas de memoria, lo que introduce complejidad adicional.

5. Arquitectura de Registros

BitRegistroFunción
0ERIndica si la instrucción es la primera de una cadena lógica (inhibida). En este estado, la consulta se almacena directamente en RLO.
1RLORegistro donde se realizan las operaciones a nivel de bit. Almacena el resultado lógico (acumulador).
2STAGestión de errores.
3ORRequerido para el proceso AND delante de OR. Indica si la operación AND ha dado valor 1.
4OVSe activa si durante una operación aritmética o de comparación de coma flotante se produce un error de desbordamiento, operación no admisible o relación incorrecta.
5OSSe activa a la par de OV. Indica que previamente se ha producido un error. Solo cambia a 0 con la instrucción SPS o al alcanzar el fin de módulo.
6-7A0, A1Códigos de condición: resultados de operaciones aritméticas, comparaciones, operaciones digitales, bits desplazados.
8RBResultado binario. Permite interpretar el resultado de una operación de palabras como resultado binario e integrarlo en la cadena lógica.

6. Direccionamiento de Entradas/Salidas

Las direcciones de entrada/salida se estructuran de la siguiente manera: el número de la izquierda representa el byte y el número de la derecha representa los bits pertenecientes a este byte (máximo 7, ocupando 8 posiciones desde el 0 al 7).

En la configuración usada en el curso, el 2do byte designa los 8 switches de entrada (E 2.0, E 2.1, ..., E 2.7) y los 8 LED's de salida están en el byte 3 (A 3.0, A 3.1, ..., A 3.7).

Regla de direccionamiento en S5

El byte de un módulo de entrada/salida depende de su ubicación en el RACK. La dirección es orientada a bytes: Ranura 0 = byte 0, Ranura 1 = byte 1, Ranura 2 = byte 2, y así sucesivamente. En versiones más recientes como el S7, esta asignación puede configurarse mediante el software de programación.

Marcas de Memoria (M)

Las direcciones de marcadores no dependen de la dirección física en el RACK sino de la configuración interna del PLC. Podemos pensar en ellas como un arreglo de 255 bytes que actúan como "flags" o variables para almacenar el estado de alguna operación. Hablamos de un espacio de 2048 bits disponibles en un área de la memoria interna para almacenar datos binarios intermedios.

Un caso de uso interesante es la creación de Flip-flop S/R lógicos a nivel de software, sin necesidad de componentes físicos independientes. Esto permite recordar si un dispositivo está encendido o apagado, o memorizar el estado del paso anterior en una secuencia.

7. Ejemplo: Mando Condicional (Flip-Flop S/R por Software)

Implementación de un pulsador que enciende/apaga un LED utilizando marcas de memoria para detectar flancos:

// 1er Estado: ¿pulsador presionado y LED apagado?
UN E 2.1
UN A 3.3
S M 0.0

// 2do Estado: flanco de subida detectado
U E 2.1
U M 0.0
S M 0.1
R M 0.0

// 3er Estado: pulsador liberado
UN E 2.1
U M 0.1
S M 0.2
R M 0.1

// ... continúa el ciclo de muestreo ...

// Evaluación final: encender o apagar LED
O M 0.1
O M 0.2
= A 3.3

La lógica del programa depende del segmento de muestreo que se hace en el 2do y 3er estado, que es cuando el pulsador emite un alto. Si el LED ya está encendido, el 1er estado almacenará 0 en M0.0, provocando una reacción en cadena de ceros hasta apagar el LED.

Diagrama de tiempos del flip-flop S/R
Gráfica de estados del pulsador

8. Temporizadores en Siemens S5

TipoNemónicoComportamiento
S_EVERZSERetardo a la conexión. La salida se activa solo después de transcurrido el tiempo TV, siempre que la entrada S permanezca activa. Si S se desactiva antes, el temporizador se reinicia.
S_SEVERZSSRetardo a la conexión con memoria. Una vez activada la salida, permanece activa incluso si la entrada S se desactiva. Requiere entrada de reset (R) para reiniciar.
S_IMPULSSIGenera un pulso de salida de duración definida (TV) cuando la entrada S se activa. La duración del pulso es independiente de la duración de la señal de entrada.
S_VIMPSVPulso prolongado. Solo genera el pulso si la señal de entrada se mantiene activa durante un tiempo mínimo.
S_PULSSPGenera un pulso de duración definida (TV). La duración es independiente de cuánto tiempo se mantenga activa la entrada.
S_AVERZSARetardo a la desconexión. La salida se activa inmediatamente con S y comienza a contar TV cuando S se desactiva. La salida se desactiva después de transcurrido TV.

Constante de tiempo (KT):

L  KT  0001.2
// 1 (izquierda) = valor de tiempo
// 2 (derecha) = base de tiempo: 0=0.01s, 1=0.1s, 2=1s, 3=10s
// Resultado: 1 segundo

Los temporizadores disponibles dependen del modelo: CPU-90: máximo 32, CPU-95: máximo 128.

Dificultades con S5 vs S7

Gran parte de la documentación disponible sobre temporizadores corresponde al S7, que incorpora registros e instrucciones que no existen en los S5 utilizados en prácticas. Esto provoca errores de sintaxis al intentar ejecutar código de S7 en un S5 real. La solución práctica fue recurrir a un emulador de S5 para realizar pruebas, ya que el simulador PC Simu descartaba la instrucción de transferencia que toma el contenido de AKKU1 y lo envía a memoria.

9. Contadores y Operaciones de Cómputo

Permiten contar y/o descontar impulsos entre 0 y 999. Parámetros:

10. Operaciones de Comparación y Saltos

Comparaciones

Un comparador relaciona dos datos del mismo formato (BYTE o WORD). Tipos disponibles:

Notación S5 vs S7

En S5, F hace referencia a números enteros (Integer 16 bits). En S7 esto cambia por I (mnemónicos en inglés). También existen: D (Double Integer 32 bits) y G (Floating Point 32 bits IEEE-FP).

Instrucciones de Salto (Jump)

InstrucciónCondición
SPASalto Incondicional
SPBSalta si RLO = 1 (True)
SPNSalta si RLO = 0 (False)
SPZSalta si AKKU1 = 0
SPPSalta si AKKU1> 0
SPMSalta si AKKU1 < 0
SPOSalta si OV = 1 (desbordamiento)
SPSSalta si OS = 1 (error persistente)
SPRSalta si BR = 1 (operación aritmética sin errores)

Limitación detectada

En las pruebas realizadas, SPA y SPB son las únicas instrucciones de salto que funcionan consistentemente en el hardware disponible. Las demás requieren validación adicional.

11. Transición de STEP5 a STEP7

Es importante aclarar que S5-95 es comparable con S7-200 (ambos de gama baja). La transición real es del S5-95 usado en el curso al S7-300 usado en la mayoría de simulaciones y proyectos modernos.

Diferencias de hardware

CaracterísticaS5-95S7-300
RAM16 KB (STEP5) + 64 KB (ejecución)Mayor capacidad, dependiente del modelo
Puerto de programaciónAS511Interfaces MPI
Memoria de trabajoRAMRAM
Memoria de cargaRAM o EPROMRAM, Flash o tarjeta de memoria
Datos localesNo existenSí (datos temporales dentro de un bloque)
Datos remanentesMenor capacidadMayor capacidad de conservación ante pérdida de energía

12. Tipos de Datos, Constantes y Direccionamiento en STEP7

Formatos de constantes: equivalencia S5 → S7

Formato S5Ejemplo S5Formato S7Ejemplo S7Tipo de dato
KBL KB 10B#16#L B#16# ABYTE (8 bits)
KFL KF 10—L 10INT (16 bits)
KHL KH FFFW#16#L W#16# FFFFWORD (16 bits)
KML KM 11111111111111112#L 11111111_11111111WORD (16 bits)
KYL KY 10,12B#L B#(10,12)2xBYTE (8+8 bits)
KTL KT 10.0S5TIME#L S5TIME# 100msTIME (S5TIME)
KZL KZ 30C#L C#30COUNTER (BCD)
DHL DH FFFF FFFFDW#16#L DW#16#FFFF_FFFFDWORD (32 bits)
KCL KC WW' xx 'L ' WW 'CHAR (8 bits por carácter)
KGL KG +234 +09REALL +2.34 E+08REAL (32 bits, coma flotante)

Direccionamiento completo de operandos de datos

Novedad en STEP7: indicación conjunta del bloque de datos y del operando. Esto no era posible en S5. No se permite mezclar direccionamiento absoluto y simbólico en una misma instrucción.

L DB100.DBW6
L DB_MOTOR.REVOLUCIONES
// DB_MOTOR = símbolo del DB 100 en la tabla de símbolos
// REVOLUCIONES = operando declarado dentro del bloque de datos

Riesgos del direccionamiento incompleto

Situaciones en las que se sobrescribe el registro DB:
  • Acceso a datos con direccionamiento completo.
  • Llamada a un FB (sobrescribe el registro DB del bloque invocante).
  • Llamada a un FC que transfiere un parámetro de tipo compuesto (STRING, ARRAY, STRUCT, UDT).
  • Asignación a una FC de un parámetro depositado en un DB.
  • Direccionamiento de un parámetro de entrada/salida de tipo compuesto en un FB o FC.

13. Direccionamiento Indirecto

Formato de los punteros

En S5 el puntero para la operación indizada de elaboración ocupa una palabra. En S7 los punteros pueden tener dos formatos: palabra y palabra doble.

Formato de puntero en S5
Formato de puntero en S7 - palabra
Formato de puntero en S7 - palabra doble

Direccionamiento indirecto por memoria

Corresponde al direccionamiento indirecto de S5. El operando indica la dirección del valor que deberá procesar la operación. El puntero se puede encontrar en: Marcas (M), Bloque de datos (DB), Bloque de datos de instancia (DI), Datos locales (L). Una ventaja fundamental de este mecanismo es que permite modificar el operando de la instrucción dinámicamente durante la ejecución del programa.

// Ejemplo: puntero en formato de palabra doble en S7
L P#8.7
T MD 2
U E [MD 2]
= A [MD 2]
// Lee la entrada E8.7 y escribe su estado en la salida A8.7

14. Interfaces de Bus y Protocolos Industriales

Buses de campo

Sistemas de comunicación ideados para conectar sensores, actuadores y otros dispositivos E/S a un PLC:

Protocolos de comunicación

Sistemas SCADA, DCS y HMI

15. Hallazgos en Infraestructuras Venezolanas

Divulgación responsable

Toda la información presentada en esta sección proviene de fuentes públicas: trabajos de grado universitarios, documentos académicos, reportes de organismos oficiales y artículos de divulgación. El objetivo es estrictamente académico y de concienciación sobre la importancia de la seguridad en infraestructuras críticas.

CorpoElec y el ecosistema Schneider Electric

Investigaciones basadas en documentos públicos indican que CorpoElec utiliza PLCs de la serie Schneider Electric Modicon Quantum en sus sistemas de control. Estos dispositivos, programados mediante Unity Pro, son ampliamente utilizados en el sector eléctrico venezolano.

Un hallazgo particularmente relevante es la existencia de una vulnerabilidad en el Modicon Quantum que permite paralizar la CPU sin autenticación previa si se tiene acceso al puerto Modbus TCP. El aviso ICS-ALERT-12-020-03B de CISA documenta esta falla, y existen fundadas dudas sobre si fue efectivamente parcheada a tiempo en las infraestructuras afectadas. Adicionalmente, se han reportado configuraciones que exponían acceso remoto a estos sistemas, aunque la veracidad de estos reportes no ha sido confirmada de forma independiente.

Schneider Electric también ha enfrentado vulnerabilidades significativas en su Serial Modbus Driver (ModbusDrv.exe), un componente que se activa al conectar una PC al PLC vía puerto serial. El desbordamiento de búfer basado en pila identificado por Risk-Based Security afectó a 11 productos, incluyendo Unity Pro, TwidoSuite, PowerSuite, SoMove, SoMachine y OPC Factory Server. Esta vulnerabilidad era explotable remotamente.

Venalum: 15 años de historia tecnológica documentada

Las plantas de procesamiento de aluminio de Venalum representan un caso de estudio singular sobre cómo la documentación académica puede revelar la evolución tecnológica de una infraestructura crítica. Un trabajo de grado de 2016 documenta el uso de PLC S7-400 junto con Wonderware SCADA en los sistemas de control de la planta. Lo más significativo es que en 2019 se iniciaron oficialmente las migraciones de STEP5 a STEP7, lo que confirma que hasta fechas muy recientes se seguían utilizando PLCs S5 en la infraestructura de producción.

Un trabajo de grado anterior, fechado en 2006, documenta el sistema de control de los hornos de retención implementado con un PLC S7-300, utilizando OPC Simatic Net como servidor de comunicaciones y MATLAB 7 como cliente. La conexión OPC con MATLAB es particularmente interesante porque sugiere un procesamiento de datos industriales con herramientas de computación científica.

En 2021, otro trabajo de grado sobre el mismo horno de retención confirma que el S7-300 seguía en operación 15 años después, manteniendo probablemente la misma lógica de comunicación con MATLAB. Aunque el trabajo menciona una aplicación Android —que requeriría algún módulo inalámbrico—, esta se menciona una sola vez, lo que sugiere que nunca se implementó y fue incluida para dar formato académico al documento. La conclusión es clara: el sistema ha recibido mantenimiento sin cambios arquitectónicos significativos en más de una década y media.

El plano que lo cuenta todo: cuando un P&ID es mapa y confesión

Los trabajos de grado no solo enumeran equipos; incluyen diagramas de ingeniería que detallan la topología del proceso. La imagen a continuación es un P&ID (Diagrama de Tuberías e Instrumentación) real, fechado entre 1996 y 1997, correspondiente a una estación de proceso con tanque, serpentín de calentamiento y múltiples instrumentos.

Diagrama P&ID de una estación de proceso con tanque, serpentín e instrumentación ISA

En el diagrama se leen con claridad las líneas de flujo —"AIRE DESDE ESTACION 2", "H2O DESDE ESTACION E"—, la instrumentación con simbología ISA (válvulas solenoides, transmisores de nivel LIT02, sensores de temperatura TE03, indicadores de presión) y el cajetín de revisiones con fechas de mediados de los noventa. Este plano es el mapa de vuelo para un atacante: le dice qué variables se miden, qué actuadores se controlan y cómo está interconectado el sistema. Y sin embargo, en la misma tesis que incluye este diagrama, no hay un solo párrafo sobre cómo registrar quién modificó esas variables.

Implicaciones de seguridad de la documentación pública

Existe un debate legítimo sobre si los trabajos de grado y tesis universitarias que documentan infraestructuras críticas deberían ser de acceso público. Literalmente, con solo recopilar trabajos de grado, un atacante podría formarse una idea detallada de todas las tecnologías presentes en una empresa. Sin embargo, el problema de fondo no es la disponibilidad de esta información —una nación con recursos de inteligencia podría obtenerla por otros medios—, sino la falta de personal calificado en seguridad informática dentro de estas organizaciones.

La realidad es que en muchos casos no existe un modelo de amenazas formalmente definido, y la inversión en seguridad suele producirse después del incidente, no antes. Esta aproximación reactiva es particularmente peligrosa en entornos OT/ICS, donde una interrupción puede tener consecuencias físicas y económicas catastróficas. La misma lógica de descuido interno —invertir en el perímetro y olvidar la auditoría del núcleo— es la que permite vulnerabilidades como las documentadas en la auditoría a la Web API financiera con IDOR por validación incompleta de JWT. El patrón se repite: sin logs ni autorización interna, el sistema está ciego.

16. Malware y Tácticas de Compromiso en ICS

Havex RAT y el vector OPC

Havex es un Remote Access Tool documentado en Malpedia que introdujo una táctica particularmente insidiosa: una vez instalado en un sistema, analizaba la red en busca de dispositivos SCADA o ICS. Para ello, aprovechaba el estándar OPC (Open Platform Communication), un protocolo de comunicación universal utilizado por componentes ICS de diversos fabricantes que facilita la conectividad abierta y la interoperabilidad.

Havex utilizaba el Modelo de Objetos de Componentes Distribuidos (DCOM) para conectarse a servidores OPC dentro de la red ICS y recopilar información detallada: CLSID, nombre del servidor, ID del programa, versión de OPC, información del proveedor, estado de ejecución, número de grupos y ancho de banda del servidor. La entrada inicial era un simple email, tras lo cual el malware realizaba un sondeo en busca de la presencia del protocolo OPC y comenzaba a enumerar los dispositivos de la infraestructura.

Panorama de amenazas ICS

El ecosistema de amenazas para sistemas de control industrial incluye casos emblemáticos como Stuxnet (dirigido a centrifugadoras iraníes), Triton (ataque a sistemas de seguridad instrumentada), Pipedream (toolkit modular para PLCs) y Havex (reconocimiento vía OPC). Estos casos demuestran que los atacantes han desarrollado capacidades sofisticadas para comprender, enumerar y comprometer entornos OT.

Vector de entrada común

En la mayoría de los casos documentados, el vector de entrada inicial es un simple email. A partir de ahí, el malware realiza un reconocimiento lateral buscando protocolos ICS como OPC, Modbus o Profinet. Esta simplicidad aparente es engañosa: la sofisticación está en el conocimiento del dominio OT que demuestra el malware una vez dentro de la red.

17. Ingeniería Inversa del Bytecode MC7

La arquitectura subyacente: ¿VM o microprogramación?

Una de las cuestiones más fascinantes que emergen del estudio de los PLCs Siemens es la naturaleza de su arquitectura de ejecución. Los opcodes de las instrucciones AWL no se ejecutan directamente sobre el procesador físico (ARM o MIPS, según el modelo), sino que corren sobre una capa intermedia que algunos investigadores denominan "VM" o "pseudo-CPU".

Sin embargo, existe un debate sobre si esta capa constituye realmente una máquina virtual en el sentido tradicional o si se trata más bien de una arquitectura microprogramada. El concepto de microprogramación, definido por Matloff y Franklin, describe un escenario donde una máquina A (el CPU real) ejecuta un programa intérprete almacenado en ROM que le permite comportarse como una máquina B (la que entiende el set de instrucciones AWL). La máquina A está especialmente adaptada para esta tarea y es muy rápida, y al programa intérprete se le denomina firmware o microprograma.

Bajo esta óptica, MC5 (en S5) y MC7 (en S7) serían los microprogramas que permiten que un procesador ARM/MIPS se comporte como un CPU especializado en automatización industrial. Esta interpretación es consistente con la observación de que el objetivo final para lograr un impacto significativo en seguridad es trascender el limitado conjunto de instrucciones AWL y alcanzar el procesador real.

Herramientas de reversing: JEB Decompiler

JEB Pro, de PNF Software, ofrece soporte específico para PLC Siemens S7 con capacidad para decompilar bytecode MC7 a STL (AWL). Los screenshots de la herramienta revelan información crucial sobre la codificación de instrucciones:

Del código AWL al hexdump: el laboratorio de reversing

Para entender cómo se traduce el AWL a nivel de bytes, monté un entorno de análisis sobre una máquina virtual Windows 7 corriendo en QEMU/KVM. La siguiente captura muestra la correlación entre el volcado hexadecimal del firmware y las instrucciones que ejecuta el PLC.

Entorno de ingeniería inversa con hexdump, rizin y WinSPS-S7 mostrando código AWL

En la ventana superior izquierda se ejecuta cat test.wld | hexdump -C, mostrando el volcado hexadecimal del archivo de firmware. A la derecha, la herramienta de desensamblado rizin analiza el código estructurado y localiza direcciones simbólicas como I 124.0 (entrada) y Q 124.0 (salida). En la ventana inferior, el software WinSPS-S7 V6 exhibe el bloque de función FC23 programado en AWL: la lógica mínima U E 124.0 seguida de = A 124.0. Esta práctica de correlacionar binario con nemónicos es exactamente el tipo de arqueología digital que se necesita para desarrollar shellcode funcional sobre entornos MC7. Es la misma metodología de reversing que aplico en el análisis de malware PE con Capstone y x64dbg, pero trasladada al dominio OT.

Enlaces de referencia para reversing MC7

  • JEB — Simatic S7 STL Opcodes
  • JEB — PLC Decompiler
  • Ingeniería inversa en PLC Siemens S7-300 (Habr)
  • Mitsubishi PLC: desmontar el protocolo de red y encontrar vulnerabilidades (Habr)
  • Siemens S7 Bootloader — Ejecución no invasiva de código (RUB-SysSec)
  • Estructura en memoria de MC7 (TIB AV-Portal)
  • 18. Exploración de Shellcode y Binary Exploitation en PLCs

    Del reversing a la explotación

    El estudio de la codificación de instrucciones MC7 tiene aplicaciones prácticas inmediatas en seguridad ofensiva/defensiva. Entre los objetivos de investigación se encuentran:

    Puntos de entrada para fuzzing

    Los vectores potenciales para realizar fuzzing en un entorno PLC incluyen:

    Limitaciones de los simuladores

    Un obstáculo significativo es que los simuladores disponibles (PC Simu, WinSPS S7, PG2000) se centran en simular la VM de MC7 sin modelar cómo se traducen los bytecodes a instrucciones ARM/MIPS en el hardware real. Esto significa que la validación de shellcode a nivel de procesador solo puede realizarse con equipo físico. La filosofía de los fabricantes de mantener cerradas las especificaciones de sus CPUs agrava esta dificultad.

    Falta de herramientas de debugging profundo

    No existe una herramienta que funcione como un debugger paso a paso para PLCs, mostrando en tiempo real el estado de los registros (AKKU1, AKKU2, RLO, VKE) y la instrucción en ejecución. Las versiones más recientes de los entornos de programación han abandonado el AWL en favor de lenguajes de alto nivel, sin ofrecer una visualización del equivalente en código de bajo nivel. Esta opacidad deliberada dificulta enormemente la investigación de seguridad.

    19. La Caja Negra que Nunca se Instaló: Por Qué las Plantas No Pueden Contar su Propia Historia

    El hallazgo en las tesis universitarias

    La investigación de este post comenzó por curiosidad técnica: entender la máquina virtual que ejecuta bytecode MC7, cómo se codifican las instrucciones AWL y qué vectores de ataque pueden explotarse desde la red. Pero al cruzar ese trabajo con tesis de grado que detallan sistemas de control en infraestructuras reales, surgió un hallazgo más urgente que cualquier exploit de Modbus.

    Revisé múltiples trabajos académicos accesibles en repositorios universitarios venezolanos como el de la Universidad Central de Venezuela (saber.ucv.ve). Todos describen con lujo de detalles arquitecturas de control: marcas y modelos de PLC, planos de red, configuración de tópicos OPC, protocolos de comunicación, listados de tags, estrategias de redundancia. Información suficiente para que un atacante dedicado se forme una idea muy precisa del sistema.

    Pero en ninguno de esos documentos —ni uno solo— aparece un sistema de registro centralizado de eventos. No hay descripción de cómo se capturan los comandos del operador. No hay un párrafo sobre retención de logs. No existe la figura de un SIEM industrial ni nada que se le parezca.

    En cambio, aparece esto: el registro de fallas se hace a mano, en planillas Excel que cada ingeniero guarda en su computadora personal. Cito textual de uno de los trabajos: "cada Ingeniero de planta guarda en su computadora las data-paro que ha realizado durante todo el año".

    El eslabón perdido: cuando la HMI muestra interrogantes

    Para ilustrar la fragilidad de la monitorización sin registro, nada mejor que la imagen de una interfaz SCADA antigua. La siguiente captura corresponde al software Intellution FIX View ejecutándose en un monitor CRT.

    Monitor CRT mostrando software SCADA Intellution FIX View con pérdida de comunicación

    La pantalla representa una estación de proceso con un tanque vertical y un serpentín de calentamiento. Los campos de temperatura, presión y nivel muestran "???? °C", "??? Bar" y "???? %" respectivamente, acompañados de un indicador "COMM" que denota pérdida de comunicación con los instrumentos de campo o con el propio PLC. Esta es la paradoja visual: el operador puede ver que algo falla, pero el sistema no está registrando esa falla de forma estructurada. Si el operador no está mirando en ese momento, el evento simplemente desaparece.

    Lo que las tesis documentan (y lo que omiten)

    Para ilustrar la magnitud de esta omisión, presento ejemplos concretos extraídos del repositorio de la Universidad Central de Venezuela (saber.ucv.ve). Estos trabajos de grado documentan sistemas SCADA reales o propuestos para infraestructuras venezolanas, y en todos ellos se puede verificar el mismo patrón: exhaustivo detalle técnico sobre la arquitectura de control, silencio absoluto sobre la arquitectura de registro y auditoría.

    Trabajo de GradoTecnologías Documentadas¿Menciona Sistema de Registro de Eventos?Enlace
    Automatización de la planta de gases especiales AGA Gas (2004) PLC Siemens, SCADA, DFP, DTI, DLF No saber.ucv.ve/handle/10872/15373
    Estudio técnico para actualización de SCADA en planta de Total, Jusepin (2006) Wonderware Intouch 7.0, PLCs Modicon, HIMA, Modbus TCP, base de datos histórica SQL No saber.ucv.ve/handle/10872/2450
    Diseño de SCADA para estaciones de radares meteorológicos INAMEH (2012) Siemens WinCC Advanced V11, Modbus RTU, PLC, HMI con historiador de eventos Parcial (historiador SCADA, no logs de seguridad) saber.ucv.ve/handle/10872/4281
    Diseño de automatización para estación de bombeo de agua Ciudad Universitaria (2008) PLC Siemens, SCADA, diagramas P&ID No saber.ucv.ve/handle/10872/7010
    Ampliación y actualización del SCADA del laboratorio de redes de distribución EIE-UCV (2011) Wonderware ArchestrA, PLC, RTUs, SCADA iFix No saber.ucv.ve/handle/10872/...

    La consecuencia forense: imposibilidad de distinguir error de ataque

    Cuando ocurre un incidente —una parada imprevista, una sobrepresión, una explosión— lo primero que se necesita es una línea de tiempo. ¿Qué variable se descontroló primero? ¿Hubo un comando de parada desde el SCADA? ¿Se recibió una orden por Modbus desde un nodo externo? ¿Fallo lógico del programa o acción manual? Sin logs, la diferencia entre error técnico y acción maliciosa es imposible de establecer.

    En el mundo IT esto sería impensable. Un servidor web registra cada petición. Un firewall anota cada conexión. En entornos industriales, el PLC que controla un compresor de alta presión no registra quién le dio la orden de parar, ni cuándo, ni desde qué IP. Simplemente la ejecuta.

    Este hallazgo fue documentado originalmente en dos publicaciones de LinkedIn que desarrollo a continuación, expandidas con referencias académicas y casos de estudio globales.

    20. Por Qué los PLCs No Generan Logs: Una Propiedad del Diseño

    El determinismo como prioridad absoluta

    El problema no es solo que falten registros. El problema es que el PLC nunca fue pensado para generarlos. Su diseño responde a una exigencia distinta: ejecutar un ciclo de scan determinista, leer entradas, procesar el programa y escribir salidas en tiempos predecibles. Cada milisegundo de retraso puede ser inaceptable. En ese contexto, la memoria se reservó para la lógica de control, no para la auditoría. Lo que se ganó en fiabilidad se perdió en trazabilidad.

    Esta limitación no es un defecto del fabricante, sino una consecuencia directa del diseño de los sistemas de control industrial. Como señala la tesis doctoral de Feras Shahbi en la Universidad de Bristol (2026), "los PLCs están diseñados para un tiempo de actividad, seguridad y fiabilidad óptimos, siendo la defensa cibernética y la preparación forense, en el mejor de los casos, ideas tardías". Las características que hacen que los PLCs sean fiables y deterministas —arquitecturas propietarias, firmware cerrado, protocolos diversos y restricciones operativas estrictas— son precisamente las que impiden la aplicación directa de prácticas forenses estándar.

    Barreras técnicas concretas

    La RAM disponible en equipos como el S5-95 —16 KB para programa STEP5 y 64 KB para ejecución— se volatiliza ante un corte de energía. Los controladores carecen de un sistema operativo sobre el cual instalar agentes de monitoreo; la máquina virtual de MC7 es un entorno cerrado, sin hooks para instrumentación externa. A esto se suma la fragmentación de formatos propietarios entre fabricantes y la ausencia de sincronización horaria confiable mediante NTP nativo. Cualquier intento de normalizar lo poco que se registra se convierte en un ejercicio de arqueología industrial.

    Lo que dice la investigación académica

    El artículo "A Forensic Logging System for Siemens Programmable Logic Controllers" (Yau, Chow & Yiu, 2018) es contundente: "las investigaciones forenses de controladores lógicos programables son una tarea desafiante debido a la falta de sistemas de registro efectivos". Los autores señalan que, si bien existen herramientas para generar registros de auditoría con fines de diagnóstico, la información registrada es inadecuada para investigaciones forenses. Para abordar esta limitación, proponen un sistema que extrae datos del tráfico del protocolo de comunicaciones S7 de Siemens y los guarda en un archivo de auditoría estructurado.

    El caso de los data logs que nunca se activan

    Existen capacidades de diagnóstico que casi nunca se activan: los buffers de eventos de los S7-300/400, los data logs de las gamas más recientes, o los propios registros del SCADA. Pero en los proyectos documentados por las tesis revisadas, la recolección de logs no aparece como requisito. No está en el alcance ni en las pruebas FAT (Factory Acceptance Test). La seguridad se considera un costo, no una característica, y la auditoría forense simplemente no figura en el pliego de condiciones.

    Esta ausencia es particularmente grave si consideramos que los protocolos industriales como Modbus TCP carecen de autenticación por diseño. Como señala un análisis técnico, "Modbus TCP no tiene autenticación. Si alguien puede enviar un paquete a la IP del PLC en el puerto 502, el PLC obedecerá". Sin logs que registren quién envió cada comando, cualquier manipulación es indistinguible de una operación legítima.

    21. Casos Globales: Cuando la Falta de Evidencia Impide la Atribución

    Ucrania 2015: el primer apagón cibernético confirmado

    El 23 de diciembre de 2015, la red eléctrica en dos óblast del oeste de Ucrania fue hackeada, resultando en cortes de energía para aproximadamente 230,000 consumidores. Los atacantes utilizaron el malware BlackEnergy 3 para comprometer los sistemas de tres compañías de distribución de energía y abrir interruptores en más de 50 subestaciones. El análisis forense posterior, documentado en el artículo "Ukrainian Power Grids Cyberattack - A Forensic Analysis Based on ISA/IEC 62443", reveló que la investigación fue posible gracias a la existencia de algunos registros en los sistemas SCADA, pero la ausencia de logs a nivel de PLC y RTU dificultó la reconstrucción completa de la secuencia de eventos. La atribución al grupo Sandworm se basó más en inteligencia externa que en evidencia forense recopilada de los propios controladores.

    Oldsmar 2021: cuando el operador vio el ataque en tiempo real

    El 5 de febrero de 2021, un atacante accedió remotamente al sistema de la planta de tratamiento de agua de Oldsmar, Florida, y modificó los niveles de hidróxido de sodio de 100 partes por millón a 11,100 partes por millón —un nivel potencialmente letal. El ataque solo fue detectado porque un operador observó en tiempo real cómo el cursor se movía en la pantalla sin su intervención. Si el operador hubiera estado ausente, el sistema habría ejecutado la orden sin cuestionarla. La investigación posterior reveló que la planta carecía de un sistema de registro de eventos que permitiera determinar exactamente qué comandos se enviaron, desde qué dirección IP y con qué credenciales. La atribución del incidente sigue sin resolverse, y la lección es clara: sin logs, la diferencia entre un error de configuración y un ciberataque es imposible de establecer.

    TRITON 2017: el ataque que apuntó a los sistemas de seguridad

    En 2017, el malware TRITON (también conocido como TRISIS) atacó los controladores de seguridad Triconex de Schneider Electric en una planta petroquímica en Oriente Medio. Lo que hace único a TRITON es que no apuntaba al sistema de control de producción, sino al Sistema Instrumentado de Seguridad (SIS), diseñado para detener la planta en condiciones inseguras. Al reprogramar la lógica del SIS, los atacantes podían haber causado una catástrofe física. La investigación forense posterior, documentada por FireEye y Dragos, enfrentó un desafío monumental precisamente por la limitada capacidad de registro de los controladores de seguridad. Determinar si una modificación fue resultado de una acción maliciosa o de un error de ingeniería requirió semanas de análisis, y la atribución final dependió en gran medida de inteligencia externa y correlación de eventos en la red corporativa, no de los logs del propio sistema atacado.

    22. Qué Se Puede Hacer: Monitoreo Basado en Red y Forensic Readiness

    La alternativa viable: monitoreo pasivo de red

    Para cerrar esta brecha, la alternativa más viable hoy es el monitoreo basado en red: capturar tráfico con switches con mirroring y herramientas como Zeek permite registrar cada paquete Modbus u OPC sin tocar el PLC. Este enfoque tiene la ventaja de no interferir con el ciclo de scan determinista del controlador: la captura de tráfico ocurre fuera del PLC, en la capa de red, sin consumir recursos del dispositivo de control. Es, en esencia, una capa de auditoría externa que no estaba prevista en el diseño original pero que puede añadirse sin modificar la infraestructura existente.

    Los SIEM industriales como Nozomi o Dragos analizan ese tráfico y crean una capa de visibilidad que antes no existía. Pueden detectar comandos anómalos, cambios en la lógica de control y patrones de comunicación sospechosos, generando alertas que un operador humano puede investigar. No reemplazan los logs nativos que el PLC debería generar, pero ofrecen un paliativo inmediato para infraestructuras que hoy operan completamente a ciegas desde el punto de vista forense. Esta arquitectura de monitoreo pasivo es conceptualmente similar al laboratorio SOC/Honeypot con Wazuh, Zabbix y Grafana que desplegué para entornos IT, pero adaptada a las restricciones del mundo OT.

    Forensic readiness: diseñar para la evidencia desde el día uno

    La verdadera solución, sin embargo, pasa por incorporar la capacidad de registro desde la fase de diseño —lo que se conoce como forensic readiness— definiendo qué eventos importan, cómo capturarlos y cómo protegerlos contra manipulación. Esto implica:

    Mientras sigamos diseñando plantas que no pueden contar su propia historia, la diferencia entre error técnico y sabotaje seguirá dependiendo de la suerte, no de la evidencia. Y en infraestructuras críticas, apostar a la suerte no es una estrategia de seguridad aceptable.

    23. Perspectivas Futuras y Líneas de Investigación

    Desarrollo de herramientas propias

    La escasez de herramientas para reversing de PLCs hace necesario el desarrollo de una suite propia, inspirada en las librerías y artículos disponibles. Los objetivos incluyen:

    Montaje de un laboratorio ICS

    Para validar experimentalmente las hipótesis de seguridad, es necesario montar un laboratorio que simule una infraestructura ICS real. Esto implica:

    La meta final es una recopilación exhaustiva de conocimientos sobre reversing, escritura de shellcode y prácticas de explotación con objetivos S7-300, que pueda servir tanto para fines defensivos como para concienciar sobre los riesgos reales en infraestructuras industriales.

    Nota sobre la capacidad de comunicación del S5-95

    Queda pendiente determinar si los S5-95 tienen capacidades de comunicación suficientes para realizar prácticas significativas de análisis de protocolos. Sería una limitación considerable estudiar estos sistemas de forma aislada sin poder experimentar con el proceso de comunicación, el formato de los paquetes y las reglas de negociación. El costo de los PLCs modernos sigue siendo una barrera de entrada significativa para la investigación independiente.

    24. Conclusiones y Superficie de Ataque

    El análisis exhaustivo de la arquitectura Siemens S5/S7 y su contexto en infraestructuras reales revela múltiples vectores de seguridad que merecen atención urgente en entornos OT:

    La ingeniería inversa aplicada a estos sistemas no solo permite comprender su funcionamiento interno, sino también anticipar vectores de ataque y diseñar defensas adecuadas para entornos OT/ICS. En un contexto donde la inversión en seguridad suele ser reactiva y posterior al incidente, la investigación proactiva se convierte en una herramienta esencial para la protección de infraestructuras críticas.

    25. Referencias

    /¿Te interesa la seguridad en infraestructuras críticas?

    Este análisis de PLC es parte de una investigación más amplia que abarca reversing de malware, threat intelligence y despliegue de infraestructura defensiva. La ausencia de logs en OT es el mismo patrón de descuido interno que permite vulnerabilidades IDOR en APIs financieras.

    Pentesting Web API → Laboratorio SOC/Honeypot → Triage de Malware →

    Continuidad. Y lo que pasa cuando el reversing se convierte en explotacion.

    26. Prefacio: Por qué Exploit Development en OT

    El desarrollo de exploits para entornos de tecnología operativa (OT) no es una extensión trivial del exploit development tradicional. Los controladores lógicos programables (PLC) ejecutan código en arquitecturas propietarias, utilizan lenguajes de bajo nivel como AWL que se traducen a bytecode para una máquina virtual —MC5 en S5, MC7 en S7-300/S7-400, y MC7+ en S7-1200/S7-1500— que corre sobre procesadores ARM o MIPS bajo el kernel ADONIS. La carrera hacia la ejecución de código nativo en PLCs, documentada por Claroty Team82 en CVE-2020-15782, demostró que es posible escapar del sandbox de la VM y escribir shellcode directamente en regiones protegidas de memoria.

    Este artículo documenta la convergencia de cuatro líneas de investigación que he desarrollado en el portafolio:

    1. El reversing de AWL y la arquitectura MC5/MC7 documentado en PLC Siemens S5/S7: Arquitectura MC7 y AWL, donde diseccioné la máquina virtual, los registros (RLO, AKKU1, AKKU2), las instrucciones de salto y la estructura de los bloques de programa. Este análisis se complementa ahora con la documentación oficial de JEB Decompiler (Nicolas Falliere, PNF Software) sobre el formato binario de bloques S7, las convenciones de llamada __FC_CC y __FB_CC, y los tipos de datos MC7 (POINTER, ANY, S5TIME, DATE_AND_TIME).
    2. El laboratorio de exploit development tradicional de Windows Internals, ROP y Shellcode, donde construí cadenas ROP en 64 bits, analicé CVEs en Chrome V8, y monté un entorno con VirtualBox + fakedns + INetSim. La metodología de búsqueda de gadgets con ROPgadget se traslada ahora a binarios ARM/MIPS de firmware de PLCs.
    3. El ecosistema de herramientas de reversing de MC7, que incluye rz-libmc7 (plugin de rizin para desensamblar bytecode MC7 de S7-300/S7-400) y JEB Pro (soporte nativo para decompilar MC7 a pseudo-C). Ambas herramientas permiten analizar bytecode sin depender exclusivamente de hardware físico.
    4. La infraestructura ofuscada de WireGuard + udp2raw + Proxy Residencial, que proporciona el entorno blindado desde donde operar sin revelar la IP de origen. Esta infraestructura es crítica cuando se realizan pruebas contra PLCs reales conectados a Internet.

    El resultado es este documento: una guía que toma el AWL como lenguaje de partida, lo traduce a conceptos de explotación binaria, construye laboratorios prácticos con hardware simulado y real, analiza el bypass de sandbox de CVE-2020-15782 como caso de estudio central, y propone una metodología replicable para cualquiera que quiera adentrarse en la seguridad ofensiva de sistemas de control industrial.

    Divulgación Responsable

    Todas las técnicas descritas se aplican sobre entornos de laboratorio controlados o sobre vulnerabilidades ya parcheadas y documentadas públicamente (CVE-2020-15782 fue parcheada por Siemens en 2021). El objetivo es estrictamente académico y de concienciación sobre la necesidad de hardening en infraestructuras críticas.

    27. Fundamentos de AWL como Lenguaje de Explotación

    AWL (Anweisungsliste, también conocido como STL —Statement List— en la documentación de Siemens) es el equivalente en el mundo PLC al ensamblador en el mundo de la computación de propósito general. Es un lenguaje de bajo nivel que utiliza nemónicos para representar operaciones sobre registros y operandos. Para un desarrollador de exploits, AWL ofrece un control preciso sobre el flujo de ejecución del autómata, exactamente como lo hace el Assembly sobre un procesador x86 o ARM.

    Independientemente del lenguaje de programación utilizado —Ladder (LAD), Diagrama de Bloques (FBD), Structured Control Language (SCL), o el propio AWL—, el compilador STEP5/STEP7/TIA Portal genera bytecode MC5/MC7/MC7+ que es interpretado por la VM del PLC. Esto significa que el bytecode es el target real del exploit developer: podemos inyectar bytecode directamente sin pasar por el compilador, siempre que conozcamos la codificación de las instrucciones.

    1.1 El Modelo de Registros del PLC como Superficie de Explotación

    Los registros del PLC son el equivalente a los registros de la CPU en explotación binaria tradicional. Conocer su función es el primer paso para manipular el flujo de ejecución:

    Registro AWLBitFunciónEquivalente en Explotación
    FC (First Check)0Indica si la instrucción es la primera de una cadena lógica. Si FC=0, la consulta se almacena directamente en RLO sin evaluar el estado anterior.Similar al flag ZF (Zero Flag) en x86 — controla el inicio de cadenas lógicas
    RLO (VKE)1Resultado de operación lógica: acumulador principal de operaciones booleanas. Cada operación lógica (U, UN, O, ON, X, XN) sobrescribe este registro.EAX/RAX en x86 — acumulador principal. Controlarlo es controlar las decisiones del programa.
    STA2Estado del bit direccionado. Refleja el valor del operando consultado.Similar al flag CF (Carry Flag) — indica el estado de la última operación
    OR3Indica si una operación AND previa dio 1, necesario para combinar AND con OR en cadenas lógicas.Flag auxiliar para operaciones compuestas
    OV4Desbordamiento aritmético: se activa en operaciones de coma flotante o enteros con overflow.OF (Overflow Flag) en x86
    OS5Overflow Stored: latch del bit OV. Persiste hasta que se ejecuta una instrucción de fin de bloque o SPS.Indicador de error almacenado (persistente)
    CC0, CC16-7Códigos de condición: actualizados por operaciones aritméticas, comparaciones y desplazamientos.Similares a SF (Sign Flag) y PF (Parity Flag)
    BR8Binary Result: permite interpretar el resultado de una operación de palabra como resultado binario e integrarlo en la cadena lógica.Usado por SFC/SFB como indicador de éxito/error
    AKKU1, AKKU232 bits c/uAcumuladores para operaciones aritméticas y de carga/transferencia. AKKU1 es el principal; AKKU2 se usa en comparaciones y operaciones binarias.Equivalentes a EAX:EBX en x86 — fundamentales para operaciones de 32 bits
    AR1, AR232 bits c/uRegistros de direccionamiento: contienen punteros MC7 de 4 bytes (área + offset + bit). Usados para direccionamiento indirecto intra-área e inter-área.Equivalentes a ESI:EDI en x86 — controlan el acceso a memoria
    DB1, DB216 bits c/uRegistros de bloque de datos: DB1 apunta al bloque de datos global (DB), DB2 al bloque de datos de instancia (DI). No son directamente accesibles.Similares a los registros de segmento DS:ES en x86 real mode

    Implicación para Explotación: Control del RLO

    El registro RLO es el acumulador principal de operaciones booleanas. Cada operación lógica (U, UN, O, ON, X, XN) sobrescribe su valor. Si un atacante puede controlar el flujo de instrucciones AWL —por ejemplo, inyectando bytecode MC7 a través de S7comm (puerto TCP 102) o Modbus TCP (puerto 502) sin autenticación— puede manipular el RLO para forzar evaluaciones booleanas que el programa original no contempla. Esto es análogo a controlar EAX en un exploit x86: una vez que controlás el acumulador, controlás las decisiones del programa.
    Entorno de programación PG 2000 con emulador de PLC S5

    1.2 Instrucciones de Salto como Primitivas de Control de Flujo

    Las instrucciones de salto en AWL son las primitivas básicas para construir exploits. Su comportamiento es directamente análogo a los JMP, JE, JNE del ensamblador x86:

    AWL S5AWL S7CondiciónEquivalente x86Uso en Exploit
    SPASPAIncondicionalJMPRedirigir ejecución a shellcode
    SPBSPBRLO = 1JNE / JNZSalto condicional tras evaluación
    SPNSPNRLO = 0JE / JZBypass de verificaciones de seguridad
    SPZSPZAKKU1 = 0JZ (tras CMP)Control post-aritmética
    SPPSPPAKKU1> 0JGValidación de contadores
    SPMSPMAKKU1 < 0JLDetección de underflow
    SPOSPOOV = 1JOCaptura de desbordamiento aritmético
    SPSSPSOS = 1—Detección de error persistente (latch)
    SPRSPRBR = 1—Validación de operaciones aritméticas sin error

    Durante las pruebas prácticas con hardware S5-95U, verifiqué que SPA y SPB son las únicas instrucciones de salto que funcionan consistentemente en el equipo disponible. En S7-300/S7-400, todas las instrucciones de salto documentadas son funcionales. Esto no es una limitación menor para S5: significa que cualquier exploit para esta plataforma debe construirse exclusivamente con saltos incondicionales y saltos condicionados al RLO.

    1.3 El Desbordamiento de Pila de Módulos (STUEB) como Vector de Ataque

    AWL permite un máximo de 16 niveles de anidamiento en llamadas a módulos (UC, CC). Si se supera este límite, se produce un desbordamiento de pila de módulos (STUEB). Este es un vector de ataque clásico: un atacante que logre inyectar llamadas recursivas no controladas puede provocar un comportamiento indefinido en el PLC, potencialmente corrompiendo la pila de ejecución y redirigiendo el flujo del programa.

    // Exploit conceptual: desbordamiento de pila de módulos (STUEB)
                // FB 100: función recursiva sin condición de parada controlada por el atacante
                FB 100
                // Si el atacante mantiene E 2.0 activa, cada ciclo de scan llama a FB 100
                // incrementando el contador de anidamiento hasta STUEB
                U  E  2.0
                SPB FB 100     // Salto recursivo controlado por entrada
                BE

    Limitación Práctica

    En mis pruebas con el S5-95U, no pude verificar experimentalmente el comportamiento tras STUEB porque el simulador PC Simu descartaba la instrucción de transferencia que toma el contenido de AKKU1 y lo envía a memoria. La validación de este vector requiere hardware real o un emulador más preciso. Esta es una de las tareas pendientes en el roadmap de la Sección 14.

    28. Arquitectura ARM/MIPS Subyacente y el Kernel ADONIS

    Los PLCs modernos de Siemens —en particular la familia S7-1200 y S7-1500— no ejecutan AWL directamente sobre el silicio. Utilizan procesadores ARM o MIPS que corren el kernel propietario ADONIS. El bytecode MC7 (S7-300/S7-400) o MC7+ (S7-1200/S7-1500) es interpretado por una capa de firmware que actúa como máquina virtual. Sin embargo, el trabajo de Claroty Team82 demostró que esta VM puede ser vulnerada: la vulnerabilidad CVE-2020-15782 permitió escapar del sandbox y escribir shellcode ARM/MIPS directamente en regiones protegidas de memoria del kernel.

    2.1 VM vs Microprogramación: El Debate que Define la Estrategia de Explotación

    El debate académico sobre si MC5/MC7/MC7+ constituye una máquina virtual o una arquitectura microprogramada tiene consecuencias directas para el exploit development:

    La evidencia —especialmente el caso de CVE-2020-15782— apoya un modelo híbrido: MC7/MC7+ es una capa de abstracción que traduce bytecodes a instrucciones ARM/MIPS, pero esta capa corre en un espacio de usuario restringido (sandbox) sobre el kernel ADONIS. El sandbox limita el acceso a memoria y recursos del sistema. La vulnerabilidad de Claroty permitió romper esa restricción: escribir fuera de los límites del sandbox y parchar un opcode de la VM para que, cuando el sistema operativo lo ejecutara, saltara al shellcode del atacante.

    Placa base de un PLC S7-1200 y análisis hexadecimal de su firmware .upd

    2.2 CVE-2020-15782: El Caso de Estudio Definitivo

    La vulnerabilidad CVE-2020-15782 (CVSS 8.1, CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer) afectó a los PLCs SIMATIC S7-1200 y S7-1500. Descubierta por Tal Keren de Claroty Team82 y parcheada por Siemens en 2021, permitió a un atacante remoto con acceso de red al puerto TCP 102 (S7comm) y sin autenticación:

    1. Escapar del sandbox de la VM: escribir datos arbitrarios en regiones de memoria protegidas que normalmente están fuera del alcance del bytecode MC7+.
    2. Parchar un opcode de la VM: modificar una instrucción de la máquina virtual en memoria para que, al ser ejecutada por el sistema operativo, redirija el flujo a shellcode controlado por el atacante.
    3. Ejecutar código ARM/MIPS nativo: inyectar shellcode directamente en una estructura interna del kernel ADONIS, obteniendo ejecución de código a nivel de kernel.
    4. Persistir indetectable: el código inyectado a nivel de kernel es invisible para el sistema operativo y para cualquier herramienta de diagnóstico estándar.
    Diagrama del escape de sandbox en PLC S7-1200/1500 relacionado con CVE-2020-15782

    Implicación para el Laboratorio

    CVE-2020-15782 es el caso de estudio central de este artículo porque demuestra que la VM es vulnerable. No es una barrera infranqueable. La estrategia de explotación en PLCs modernos debe considerar dos capas: (1) la capa de bytecode MC7/MC7+ para la inyección inicial, y (2) la capa ARM/MIPS nativa para el sandbox escape y la ejecución de código arbitrario. En el Workshop 4 se detalla un laboratorio para replicar esta cadena de explotación en un entorno controlado.

    2.3 El Flujo de Compilación: Del Código Fuente al Bytecode

    Entender cómo el código fuente (AWL, SCL, LAD, FBD) se transforma en bytecode es esencial para un exploit developer. El proceso es el siguiente:

    Diagrama del flujo de compilación de código lógico de usuario a bytecode MC7/MC7+

    Como se observa en el diagrama, todos los lenguajes de programación convergen en el mismo bytecode MC7/MC7+. Esto significa que un exploit basado en bytecode es independiente del lenguaje original. Podemos escribir shellcode directamente en bytecode MC7 sin pasar por el compilador, siempre que conozcamos la codificación de las instrucciones. Esta codificación ha sido documentada parcialmente por:

    Terminal ejecutando Rizin para análisis de ingeniería inversa de un archivo binario MC7
    Vista de código fuente desensamblado o listado de instrucciones de bajo nivel para un PLC

    2.4 ARM vs x86: Lo que Cambia para el Exploit Developer

    La transición de explotación x86 a ARM introduce diferencias fundamentales que afectan la construcción de shellcode y cadenas ROP:

    Característicax86/AMD64ARMImpacto en Explotación
    Conjunto de instruccionesCISC (instrucciones complejas, longitud variable)RISC (instrucciones simples, longitud fija de 32 bits en ARM, 16/32 en Thumb)Shellcode más largo en ARM, pero más predecible y sin bytes prohibidos por diseño
    Convención de llamadaArgumentos en pila (x86) o RCX,RDX,R8,R9 (AMD64 Windows)Argumentos en R0-R3, retorno en R0. Stack para argumentos adicionalesLos gadgets ROP deben manipular registros diferentes. Pop {r0, pc} es el gadget universal de ARM
    Ejecución condicionalSolo saltos condicionales (Jcc)Casi todas las instrucciones pueden ser condicionales (sufijos -eq, -ne, -gt, etc.)Mayor densidad de gadgets útiles. Instrucciones como MOVEQ, ADDNE pueden ser gadgets
    PC como registroRIP/EIP no es directamente accesible como registro de propósito generalR15 (PC) es de propósito general. Se puede leer y escribir como cualquier registroLectura/escritura directa del contador de programa facilita el control de flujo
    EndiannessLittle-endianBi-endian (típicamente little-endian en PLCs Siemens)Shellcode debe verificar endianness del target. Los firmwares .upd de Siemens son little-endian
    Modos de ejecuciónRing 0 (kernel) / Ring 3 (usuario)EL0 (usuario) / EL1 (kernel) / EL2 (hypervisor) / EL3 (secure monitor)El sandbox de MC7+ corre en EL0. El kernel ADONIS en EL1. El sandbox escape busca escalar de EL0 a EL1

    Referencia de Instrucciones ARM para Explotación

    Para construir shellcode ARM, es indispensable tener a mano la referencia de instrucciones. Además de Felix Cloutier para x86, recomiendo el ARM Instruction Set Reference Guide y x64.syscall.sh para las llamadas al sistema en Linux/ARM. Para MIPS, la referencia es el MIPS Architecture Reference Manual.

    29. Del AWL al Shellcode: Traducción, Ofuscación y Herramientas

    El shellcode para PLCs presenta desafíos únicos. A diferencia del shellcode para sistemas operativos de propósito general —donde el objetivo típico es ejecutar /bin/sh o establecer una reverse shell—, en un PLC el shellcode debe interactuar con el proceso físico: abrir/cerrar válvulas, modificar setpoints, falsear lecturas de sensores, o simplemente paralizar la CPU. Además, debe operar dentro de las restricciones de la VM: registros limitados, áreas de memoria segmentadas (I, Q, M, L, DB, DI, T, C), y un conjunto de instrucciones optimizado para control industrial, no para computación general.

    3.1 Shellcode AWL Mínimo: Encender una Salida Digital

    El shellcode más simple en AWL consiste en forzar una salida independientemente de la lógica del programa original. Esto es análogo al shellcode clásico de x86 que ejecuta exit(0): no hace nada espectacular, pero demuestra que tenemos control de la ejecución.

    // Shellcode AWL #1: Forzar salida A 3.0 independientemente de la lógica
                // Longitud: 6 instrucciones. Objetivo: encender LED en byte 3, bit 0
                // Equivalente en explotación: mov eax, 1; mov [output], eax; ret
                // ------------------------------------------------------------
                SET          // RLO = 1 (fuerza true sin depender de entradas)
                S   A 3.0    // Setea la salida A 3.0 a 1 (LED encendido)
                SET          // RLO = 1
                S   A 3.1    // Setea la salida A 3.1 a 1 (segundo LED)
                SET          // RLO = 1
                S   A 3.2    // Setea la salida A 3.2 a 1 (tercer LED)
                BE           // Fin del bloque (equivalente a ret en x86)

    Este shellcode no depende de ninguna entrada. Al inyectarlo en un bloque de programa (PB/FC) o bloque de función (FB) y redirigir la ejecución hacia él, las salidas se activan sin que el programa original pueda evitarlo. Es la prueba de concepto mínima: si podemos ejecutar esto, tenemos control del PLC.

    3.2 Shellcode AWL Condicional: Puerta Trasera con Contador

    Un shellcode más sofisticado puede implementar una puerta trasera condicional: modificar el comportamiento del PLC solo cuando se recibe una señal específica. El siguiente ejemplo implementa una puerta trasera que se activa al recibir un pulso específico en una entrada, usando contadores como mecanismo de activación:

    // Shellcode AWL #2: Puerta trasera condicional con contador
                // Si E 2.0 se activa 3 veces, forzar A 3.0 (bypass de seguridad)
                // ------------------------------------------------------------
                U  E  2.0    // Verifica entrada de activación
                ZV Z 10     // Incrementa contador Z10
                L  Z 10     // Carga valor del contador en AKKU1
                L  KZ 3    // Carga constante 3 en AKKU2
                != F         // ¿AKKU1 != 3? (comparación de enteros 16 bits)
                SPB SKIP     // Si no es 3, saltar a SKIP
                SET          // RLO = 1
                S   A 3.0    // Activar salida (puerta trasera ejecutada)
                L   KZ 0   // Resetear contador para evitar detección
                S   Z 10    // Cargar 0 en Z10
                SKIP: BE      // Continuar ejecución normal

    3.3 Herramientas para el Reversing de Bytecode MC7

    El ecosistema de herramientas para analizar bytecode MC7 ha madurado significativamente. Las tres principales son:

    HerramientaDesarrolladorFuncionalidadLicenciaTarget
    JEB ProPNF SoftwareDesensamblador y decompilador de MC7 a pseudo-C. Adquisición de bloques desde STEP7. Soporte para formatos de bloque binario (interno LE y red BE). Recuperación de interfaces (IN/OUT/IN_OUT/STATIC/TEMP). Análisis de tipos de datos (POINTER, ANY, S5TIME, DATE_AND_TIME, ARRAY, STRING).Comercial (demo disponible)S7-300, S7-400
    rz-libmc7rizinorg (wargio, Jegeva)Plugin para rizin que implementa desensamblador de MC7 bytecode. Decodifica instrucciones aritméticas, lógicas, de salto y de acceso a memoria.Open Source (GitHub)S7-300, S7-400
    GhidraNSAFramework de ingeniería inversa con soporte para múltiples arquitecturas. Requiere desarrollo de extensiones para MC7, pero ofrece soporte nativo para ARM y MIPS (análisis de firmware).Open SourceFirmware ARM/MIPS de PLCs

    La combinación de rz-libmc7 para desensamblado rápido y JEB Pro para decompilación a alto nivel cubre el flujo completo de análisis de bytecode. Para el análisis del firmware ARM/MIPS subyacente, Ghidra es la herramienta de elección, especialmente con los scripts de análisis de firmware que permiten identificar la capa de traducción de MC7 a instrucciones nativas.

    Documento técnico que detalla la estructura de memoria de un PLC S7-300 y la ubicación del bloque de contraseñas

    Bytes Prohibidos en MC7

    A diferencia del shellcode x86 donde el byte nulo (0x00) es problemático, en MC7 el formato de instrucción es de longitud fija o semi-fija (máximo 4 bytes por instrucción con operando). Esto significa que no hay "bytes prohibidos" en el sentido tradicional. Sin embargo, ciertas combinaciones de opcodes pueden ser rechazadas por el firmware del PLC si no corresponden a instrucciones válidas. La ofuscación en MC7 consiste más en camuflar la lógica del shellcode —usando instrucciones redundantes, saltos indirectos, o codificación condicional— que en evadir filtros de bytes.

    30. ROP sobre MC7/MC7+: Gadgets en la VM del PLC

    La Programación Orientada al Retorno (ROP) es la técnica estándar para evadir DEP/NX/XN. En el contexto de un PLC, donde el firmware puede marcar regiones de memoria como no ejecutables, ROP permite construir cadenas de ejecución utilizando únicamente instrucciones existentes en el binario.

    4.1 Adaptación de ROP al Entorno MC7

    En MC7, el equivalente a los gadgets ROP son secuencias de instrucciones AWL que terminan en BE (fin de bloque), BEB (fin condicional si RLO=1) o BEA (fin incondicional). Estas instrucciones cumplen la función del RET en x86: devuelven el control al llamante. Una cadena ROP en MC7 consistiría en encadenar múltiples bloques de función (FB) o bloques de programa (FC) que terminen en BE, utilizando la pila de módulos para controlar el flujo.

    // Gadget ROP #1 en AWL: pop RLO; set salida; ret
                // FB 200: Equivalente a "pop eax; ret" en x86
                FB 200
                U  M 100.0   // "Pop" del stack lógico: carga M 100.0 en RLO
                =  A 3.0     // Escribe RLO en salida (side effect controlado)
                BE            // "Ret": vuelve al llamante

    La limitación práctica es que no existe un debugger paso a paso para PLCs que muestre el estado de los registros en tiempo real. Las versiones modernas de los entornos de programación han abandonado el AWL en favor de lenguajes de alto nivel, sin ofrecer visualización del código de bajo nivel. Esto dificulta enormemente la búsqueda automatizada de gadgets, que en x86 se hace con herramientas como ROPgadget o ropper.

    4.2 Estrategia Híbrida: ROP en ARM/MIPS Subyacente

    Dado que el firmware del PLC corre sobre ARM o MIPS, una estrategia más viable —y la utilizada por Claroty en CVE-2020-15782— es buscar gadgets ROP en el binario ARM/MIPS del firmware, no en el bytecode MC7. Esto requiere:

    1. Extraer el firmware del PLC: mediante la actualización de firmware (.upd), ingeniería inversa del protocolo de descarga, o acceso físico (JTAG/UART). El firmware contiene el kernel ADONIS y todas las bibliotecas del sistema.
    2. Analizar el binario ARM/MIPS con herramientas estándar: ROPgadget, ropper, o Ghidra con scripting en Python.
    3. Construir una cadena ROP que, combinada con la vulnerabilidad de sandbox escape, permita ejecutar código arbitrario en el procesador real.
    // Búsqueda de gadgets ARM en firmware de PLC Siemens S7-1200
                // Uso de ROPgadget sobre un volcado de firmware .upd
                $ ROPgadget --binary s7_1200_firmware.upd --arch ARM --thumb
                // Gadgets encontrados (ejemplos representativos):
                // 0x00014a7c: pop {r0, pc}        → Control de R0 (argumento 1) + salto
                // 0x00023b18: mov r0, r4; pop {r4, pc} → Movimiento entre registros + ret
                // 0x000105e0: str r0, [r1]; pop {r4, pc} → Escritura en memoria (útil para parchar)
                // 0x0000c894: bx lr               → Retorno simple (útil para encadenar gadgets)

    Barrera de Entrada

    Extraer el firmware de un PLC real requiere acceso físico al dispositivo y, frecuentemente, habilidades de hardware hacking (JTAG, UART, extracción de chips de memoria). Esta es una barrera significativa para la investigación independiente. En el laboratorio propuesto en la Sección 7, comenzamos con simuladores y firmwares públicos para luego escalar a hardware real.

    31. Superficie de Ataque en Entornos ICS Reales

    La superficie de ataque en un entorno ICS no se limita al PLC. Incluye todos los componentes que interactúan con él: protocolos de comunicación, estaciones de ingeniería, interfaces HMI, y sistemas SCADA. Mapear esta superficie es el primer paso para identificar vectores de explotación.

    ComponenteProtocolo/PuertoVector de AtaqueImpactoCaso Documentado
    PLC Siemens S7-300/400S7comm (TCP 102)Inyección de comandos STOP/RUN, descarga/inyección de firmwareParada de planta, modificación de lógica de controlStuxnet (2010)
    PLC Siemens S7-1200/1500S7comm+ (TCP 102)Sandbox escape, escritura en memoria protegida, ejecución de código nativo ARM/MIPSControl total del PLC a nivel de kernelCVE-2020-15782 (Claroty, 2021)
    Modbus TCPTCP 502Escritura en coils/registers sin autenticación por diseñoManipulación de E/S, falseo de sensores, activación/desactivación de actuadoresMúltiples incidentes no atribuidos
    ProfinetEthernet industrial (capa 2)Inyección de tramas, denegación de servicio en tiempo realInterrupción de comunicación determinista entre PLCsInvestigaciones académicas
    OPC UA/DATCP 4840, DCOM (135, 445)Enumeración de tags, lectura/escritura remota de variables de procesoFuga de información del proceso industrial, modificación de setpointsHavex RAT (2013-2014)
    HMI Magelis/HarmonyHTTP/HTTPS, VNC (5900)Contraseñas por defecto, vulnerabilidades web, exposición de pantalla de operadorControl visual del operador comprometido, comandos no autorizadosAuditorías de seguridad
    Estación de Ingeniería (TIA Portal)SMB (445), RDP (3389), WinRM (5985)Compromiso del equipo que programa todos los PLCs de la plantaAcceso total a toda la red OT, modificación de lógica en todos los PLCsPatrón de ataque recurrente
    Schneider Modicon QuantumModbus TCP (502), Serial Modbus DriverParalización de CPU sin autenticación, buffer overflow en driver serialDenegación de servicio, potencial ejecución de códigoICS-ALERT-12-020-03B (CISA)

    El caso de Modbus TCP es paradigmático: es un protocolo sin autenticación por diseño. Si un atacante puede enviar un paquete a la IP del PLC en el puerto 502, el PLC obedece. No hay usuario, no hay contraseña, no hay token. La única defensa es la segmentación de red. Y sin embargo, los trabajos de grado universitarios revisados en el análisis de infraestructuras venezolanas documentan configuraciones donde la red OT no está adecuadamente segmentada de la red corporativa.

    32. Casos Reales: De TRITON a CVE-2020-15782, Lecciones para el Atacante

    El estudio de ataques reales a infraestructuras ICS proporciona lecciones invaluables sobre vectores de entrada, persistencia y objetivos. Los casos que analizo a continuación no son teóricos: son incidentes documentados por agencias gubernamentales y empresas de ciberseguridad.

    6.1 TRITON (2017): El Ataque al Sistema de Seguridad

    TRITON (también conocido como TRISIS) atacó los controladores de seguridad Triconex de Schneider Electric en una planta petroquímica en Oriente Medio. Lo que lo hace único es que no apuntaba al sistema de control de producción, sino al Sistema Instrumentado de Seguridad (SIS). El SIS es la última línea de defensa: si el proceso sale de parámetros seguros, el SIS debe detener la planta. Al reprogramar la lógica del SIS, los atacantes podían haber causado una catástrofe física.

    Lección para el exploit developer: El objetivo más valioso no siempre es el PLC de producción. Los sistemas de seguridad, al ser los menos monitoreados y los que menos actualizaciones reciben, son objetivos ideales. Un shellcode que modifique la lógica de seguridad puede permanecer latente hasta que las condiciones del proceso activen la condición de peligro, momento en el cual el SIS —ya comprometido— no actuará.

    6.2 Havex RAT (2013-2014): Enumeración vía OPC

    Havex introdujo una táctica que revolucionó el reconocimiento en entornos ICS: una vez instalado en un sistema corporativo (vector inicial: email de phishing), utilizaba el estándar OPC para enumerar dispositivos industriales en la red. Havex se conectaba a servidores OPC vía DCOM y recopilaba: CLSID, nombre del servidor, ID del programa, versión de OPC, información del proveedor, estado de ejecución, número de grupos y ancho de banda del servidor.

    Lección para el exploit developer: La fase de reconocimiento no requiere acceso al PLC. Los protocolos estándar como OPC son una mina de información sobre la arquitectura de control. Un exploit que incluya un módulo de enumeración OPC puede mapear toda la red OT antes de lanzar el ataque principal.

    6.3 CVE-2020-15782 (2021): El Sandbox Escape Definitivo

    La vulnerabilidad descubierta por Tal Keren de Claroty Team82 marca un antes y un después en la explotación de PLCs. Demostró que:

    Estado Actual de CVE-2020-15782

    Siemens parcheó esta vulnerabilidad en 2021 mediante actualizaciones de firmware para S7-1200 y S7-1500. Sin embargo, el caso demuestra que la arquitectura de seguridad de los PLCs modernos —sandbox + VM + kernel— es vulnerable a ataques sofisticados. La lección para el defensor es clara: mantener los firmwares actualizados, segmentar la red OT, y monitorear el tráfico S7comm en busca de anomalías.

    33. Guía de Laboratorio ICS: Hardware, Simuladores y Red OT

    Montar un laboratorio ICS funcional es el paso más importante —y el más costoso— para practicar exploit development en entornos OT. Aquí propongo una arquitectura escalable que comienza con software gratuito y crece hasta incluir hardware real, todo ello operando desde la infraestructura ofuscada documentada en WireGuard + udp2raw.

    7.1 Arquitectura del Laboratorio

    // Topología del laboratorio ICS (4 niveles de profundidad)
                // ------------------------------------------------------------
                // Nivel 0: Internet → [Nodo A: VPS Puerta de Enlace]
                //                      ↓ WireGuard + udp2raw (faketcp:443, XOR)
                // Nivel 1: [Nodo B: Hipervisor del Laboratorio ICS]
                //                      ↓ redsocks + SOCKS5 residencial (salida a Internet)
                // Nivel 2: Red OT Virtual (192.168.100.0/24, Host-Only VirtualBox)
                //           ├── VM Kali Linux       .10 (estación de ataque)
                //           ├── VM Windows 10       .20 (estación de ingeniería + TIA Portal)
                //           ├── VM QEMU ARM/MIPS    .30 (emulador de PLC S7-1200)
                //           ├── VM REMnux           .40 (INetSim + fakedns)
                //           └── PLC Simulado        .50 (WinSPS-S7 V6 / PC Simu)
                //
                // Nivel 3: Hardware Físico (opcional, expansión del laboratorio)
                //           ├── Siemens S5-95U + módulos E/S (MC5, CPU 16-bit)
                //           ├── Siemens S7-300 + MPI adapter (MC7, CPU 32-bit)
                //           └── Siemens S7-1200 (MC7+, ARM, kernel ADONIS)

    7.2 Componentes del Laboratorio y Costos

    ComponenteSoftware/HardwarePropósito en el LaboratorioCosto Aprox. (USD)
    Nodo A (VPS)Ubuntu 22.04 LTS + WireGuard + udp2rawPuerta de enlace ofuscada. Único punto de entrada desde Internet.~$6/mes (VPS mínimo 1GB RAM)
    Nodo B (Hipervisor)PC con 32GB RAM + VirtualBox 7.xHost de todas las VMs del laboratorio. Corre redsocks + dnscrypt-proxy + dnsmasq.Hardware propio (~$800-1500)
    PLC Simulado MC5PG 2000 + PC SimuTarget legacy para exploits AWL en S5. Pruebas de shellcode básico y STUEB.Gratuito (abandonware)
    PLC Simulado MC7WinSPS-S7 V6Target principal para exploits AWL/MC7 en S7-300. Compilación y desensamblado de bytecode.Gratuito (demo funcional)
    PLC Real S5-95USiemens S5-95U + módulos E/S + cable AS511Validación en hardware real de exploits AWL. Pruebas de STUEB y corrupción de pila de módulos.~$200-500 (eBay, usado)
    PLC Real S7-300Siemens S7-300 (CPU 314/315) + MPI-USB adapterTarget para exploits MC7. Extracción de firmware vía S7comm. Análisis con JEB y rz-libmc7.~$300-800 (eBay, usado)
    PLC Real S7-1200Siemens S7-1200 (CPU 1214C o similar)Target para sandbox escape (CVE-2020-15782). Extracción de firmware .upd. Análisis de kernel ADONIS.~$400-900 (eBay, usado)
    Estación IngenieríaWindows 10 LTSC + TIA Portal V17 + STEP5Software de programación oficial de Siemens. Necesario para compilar y descargar código a PLCs reales.Licencia TIA Portal (consultar Siemens)
    Kali LinuxKali 2024.x + toolchains ARM/MIPSEstación de ataque ofensivo. Corre ROPgadget, AFL++, Wireshark, Metasploit, rz-libmc7.Gratuito
    REMnuxREMnux 7 + INetSim + fakednsSimulación de servidores C2 falsos. Redirección DNS para entornos de prueba.Gratuito
    QEMU ARM/MIPSQEMU system-arm / system-mipsEmulación del procesador del PLC para pruebas de shellcode nativo sin hardware real.Gratuito
    Diagrama de bloques organizacionales OB, FC, FB en sistemas SIMATIC S7
    Esquema de la jerarquía de bloques de memoria y su interacción con el sistema operativo

    7.3 Configuración de Red OT Segmentada

    La red OT debe estar completamente aislada de la red del host y de Internet. En VirtualBox, esto se logra con una red Host-Only dedicada:

    # Configuración de red OT en VirtualBox (host)
                VBoxManage hostonlyif create
                VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.100.1 --netmask 255.255.255.0
                # Asignar a cada VM la interfaz Host-Only
                # VM Kali:       192.168.100.10  (estación de ataque)
                # VM Windows 10: 192.168.100.20  (estación de ingeniería + TIA Portal)
                # VM QEMU ARM:   192.168.100.30  (emulador de PLC S7-1200)
                # VM REMnux:     192.168.100.40  (INetSim + fakedns)
                # VM PLC Sim:    192.168.100.50  (WinSPS-S7 V6)
                # PLC S5-95U:    192.168.100.60  (hardware real, si aplica)
                # PLC S7-300:    192.168.100.70  (hardware real, si aplica)
                # PLC S7-1200:   192.168.100.80  (hardware real, si aplica)

    Aislamiento Real: Crítico para Pruebas con Hardware Real

    La VM de Kali no debe tener acceso directo a Internet desde la red OT. Todo el tráfico de salida debe pasar por el túnel ofuscado hacia el Nodo A. Esto se configura con iptables en el Nodo B, redirigiendo el tráfico de Kali a través de redsocks + proxy residencial, exactamente como se documenta en la infraestructura de túnel ofuscado. Nunca se deben realizar pruebas ofensivas contra PLCs conectados a Internet sin autorización explícita y sin esta capa de ofuscación.

    34. Workshop 1: Shellcode AWL Básico (Encender/Apagar Salida Digital)

    Objetivo

    Escribir, compilar e inyectar shellcode AWL mínimo que fuerce el encendido de una salida digital, independientemente de la lógica del programa original. Este taller valida la primitiva fundamental de cualquier exploit en PLC: control del RLO y escritura en salidas.

    Entorno

    Procedimiento

    1. Escribir el shellcode: Crear un nuevo bloque de programa (PB 200 en S5, FC 200 en S7) con el shellcode de la Sección 3.1.
    2. Compilar: Compilar el programa con STEP5/WinSPS-S7. Verificar que no hay errores de sintaxis. Exportar el bloque compilado a formato binario (Formato 1 LE o Formato 2 BE según la documentación de JEB).
    3. Analizar el bytecode: Abrir el bloque compilado con rz-libmc7 y verificar la correspondencia entre instrucciones AWL y opcodes MC7. Documentar los opcodes para referencia futura.
    4. Cargar en el PLC: Transferir el programa al PLC simulado.
    5. Modificar el OB1: Insertar una llamada incondicional a PB/FC 200 al inicio del ciclo de scan:
      // OB1 modificado: shellcode se ejecuta en cada ciclo de scan
                          SPA PB 200     // S5: Salto incondicional al shellcode
                          // UC FC 200      // S7: Llamada incondicional a función
                          // ... lógica original del programa (nunca se ejecuta) ...
                          BE
    6. Verificar: Ejecutar el PLC en modo RUN. Las salidas A 3.0, A 3.1 y A 3.2 deben encenderse inmediatamente, sin necesidad de activar ninguna entrada física.

    Análisis de Resultados

    Este shellcode funciona porque SET fuerza el RLO a 1 sin evaluar ninguna entrada. Es el equivalente a inyectar mov eax, 1; mov [output], eax; ret en un exploit x86. La diferencia crucial es que en un PLC, "encender una salida" tiene consecuencias físicas reales: puede abrir una válvula, arrancar un motor o desactivar un sistema de seguridad.

    Extensión del taller: Usar rz-libmc7 para modificar directamente el bytecode del bloque compilado —sin pasar por el compilador— y verificar que el PLC ejecuta el bytecode modificado. Esto demuestra que la inyección directa de bytecode es viable.

    35. Workshop 2: ROP sobre MC7 (Bypass de DEP en PLC)

    Objetivo

    Construir una cadena ROP utilizando bloques de función existentes en el firmware del PLC para ejecutar una acción sin inyectar código nuevo. Este taller demuestra el bypass de las protecciones de memoria que impiden la ejecución de código en regiones de datos.

    Entorno

    Procedimiento

    1. Identificar gadgets: Usar JEB Pro para buscar en el firmware bloques de función (FB) existentes que realicen operaciones útiles y terminen en BE. Las bibliotecas IEC estándar (FC3, FC4, FC5, etc.) son una fuente rica de gadgets.
      // Gadget FB 50: Carga constante en AKKU1 y transfiere a salida
                          // (Este es un ejemplo conceptual; los gadgets reales dependen del firmware)
                          FB 50  (existente en el firmware del PLC, identificado con JEB)
                          L  KH 00FF   // Carga 0x00FF en AKKU1 (word hexadecimal)
                          T  AW 0     // Transfiere al word de salida AW 0 (A 0.0 - A 0.7)
                          BE            // "Ret": fin de bloque, vuelve al llamante
    2. Construir la cadena ROP: Encadenar múltiples gadgets en el OB1 modificado:
      // Cadena ROP: FB 50 → FB 51 → FB 52
                          // La ejecución fluye: gadget1 → gadget2 → gadget3 → programa original
                          UC  FB 50    // Gadget 1: fuerza A 0.0-0.7 a 0xFF
                          UC  FB 51    // Gadget 2: fuerza A 1.0-1.7 a 0xFF
                          UC  FB 52    // Gadget 3: escribe en marca de memoria M 100.0 (persistencia)
                          BE            // Fin del OB1 modificado
    3. Ejecutar y verificar: Las salidas deben activarse sin que el programa original contenga instrucciones que lo hagan explícitamente. Verificar con rz-libmc7 que la cadena de bytecode corresponde a la secuencia esperada de UC (llamadas incondicionales).

    Limitación de la Búsqueda de Gadgets en MC7

    Este taller es conceptual en la capa MC7. La búsqueda automatizada de gadgets en bytecode MC7 no tiene herramientas maduras como ROPgadget para ELF/PE. La identificación de gadgets es manual, revisando el código AWL de cada FB existente en el firmware con JEB Pro. Sin embargo, la estrategia híbrida —buscar gadgets en el binario ARM/MIPS del firmware con ROPgadget, como se describe en la Sección 4.2— es completamente viable y fue el enfoque utilizado por Claroty en CVE-2020-15782.

    36. Workshop 3: Fuzzing de Protocolos Modbus TCP y S7comm

    Objetivo

    Utilizar AFL++ o un fuzzer personalizado para encontrar crashes en la implementación de Modbus TCP (puerto 502) y S7comm (puerto TCP 102) de un PLC simulado, y analizar el crash para determinar su explotabilidad.

    Entorno

    Procedimiento

    1. Capturar tráfico legítimo: Usar Wireshark en Kali para capturar una sesión Modbus TCP y S7comm entre la estación de ingeniería (192.168.100.20) y el PLC simulado (192.168.100.50). Identificar los paquetes de lectura de coils, escritura de registros, y comandos STOP/RUN.
    2. Extraer semillas: Exportar los paquetes capturados como datos binarios para usarlos como semillas del fuzzer.
    3. Configurar AFL++ con harness en Python:
      // Harness de fuzzing para Modbus TCP (Python + sockets)
                          // Compatible con AFL++ mediante entrada stdin
                          import socket
                          import sys
                          # Leer input mutado de AFL++
                          data = sys.stdin.buffer.read()
                          # Conectar al PLC simulado (Modbus TCP)
                          sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                          sock.settimeout(2.0)
                          try:
                              sock.connect(('192.168.100.50', 502))
                              sock.send(data)
                              response = sock.recv(1024)
                              sock.close()
                          except Exception as e:
                              # Crash detectado: AFL++ registra este input como interesante
                              sys.exit(1)  # Señal de crash para AFL++
    4. Ejecutar AFL++: Lanzar el fuzzer con las semillas extraídas y esperar crashes. Monitorear el PLC simulado para detectar reinicios inesperados o cambios de estado.
    5. Triaje de crashes: Para cada crash detectado, reproducirlo manualmente con un script Python dedicado. Analizar con Wireshark la respuesta del PLC (o la falta de respuesta). Clasificar el crash por tipo: buffer overflow, null pointer dereference, use-after-free, etc.

    Resultados Esperados

    En un PLC simulado sin hardening, es esperable encontrar crashes por:

    37. Workshop 4: Explotación Completa con Sandbox Escape (CVE-2020-15782)

    Objetivo

    Simular una cadena de explotación completa inspirada en CVE-2020-15782 que: (1) comprometa una estación de ingeniería a través de un drive-by en Chrome (CVE-2020-6507), (2) desde allí acceda a la red OT y detecte un PLC S7-1200, (3) explote la vulnerabilidad de sandbox escape para escribir shellcode ARM en memoria protegida del kernel ADONIS, y (4) ejecute código nativo que modifique el comportamiento del proceso físico.

    Entorno

    Procedimiento

    1. Preparar el servidor de exploit CVE-2020-6507: En Kali, servir la página HTML que explota el out-of-bounds write en Chrome V8. El código JavaScript del exploit (documentado en el laboratorio de exploit development) ejecuta shellcode en el contexto del navegador.
    2. Redirección DNS con fakedns: En REMnux, configurar fakedns para que cualquier dominio solicitado por el Windows 10 redirija a la IP de Kali (192.168.100.10).
    3. Ejecutar el ataque drive-by: Desde el Windows 10 vulnerable, navegar a cualquier URL. fakedns redirige a Kali, que sirve el exploit CVE-2020-6507. El shellcode del navegador establece una reverse shell hacia Kali (192.168.100.10:4444).
    4. Reconocimiento post-explotación: Desde la reverse shell en Windows 10:
      • Enumerar la red OT (192.168.100.0/24) usando comandos nativos de Windows (ping sweep, netstat, arp).
      • Detectar el PLC S7-1200 en 192.168.100.30:102 (puerto S7comm abierto).
      • Identificar la versión de firmware del PLC mediante consultas S7comm.
    5. Explotar CVE-2020-15782: Desde la reverse shell, ejecutar un script Python que:
      • Se conecte al PLC por S7comm (puerto TCP 102).
      • Envíe la secuencia de paquetes que dispara el desbordamiento de búfer en la operación vulnerable de la VM.
      • Escriba el shellcode ARM en una región de memoria protegida del kernel ADONIS.
      • Parcha un opcode de la VM para que, al ser invocado, salte al shellcode.
    6. Verificar: El shellcode ARM ejecutado en el PLC debe modificar el comportamiento del proceso físico. En el laboratorio, esto se verifica con un LED conectado a la salida A 3.0 que cambia de estado, demostrando que el ataque desde el navegador ha llegado al procesador ARM del PLC y ha modificado su comportamiento.

    Notas sobre la Replicación de CVE-2020-15782

    Este taller asume que se dispone de un firmware S7-1200 vulnerable (anterior al parche de 2021). Siemens corrigió esta vulnerabilidad mediante actualización de firmware. Para propósitos de laboratorio, se puede utilizar un PLC S7-1200 con firmware antiguo adquirido de segunda mano, o un emulador QEMU configurado con una imagen de firmware vulnerable. No se debe intentar explotar esta vulnerabilidad en PLCs en producción sin autorización explícita del propietario.

    Además, CVE-2020-6507 requiere que el sandbox de Chrome esté deshabilitado para ser explotable remotamente. En el laboratorio, se puede ejecutar Chrome con --no-sandbox para validar la cadena completa, o utilizar un sandbox escape adicional si se dispone de uno.

    38. Integración con Infraestructura Ofuscada

    Todos los talleres anteriores asumen que el operador del laboratorio no quiere revelar su IP real al realizar pruebas contra PLCs conectados a Internet (por ejemplo, al descargar firmwares, consultar repositorios de vulnerabilidades, o comunicarse con PLCs remotos autorizados). La infraestructura documentada en WireGuard + udp2raw + Proxy Residencial proporciona exactamente eso:

    // Flujo de tráfico durante un exploit completo (Workshop 4)
                // ------------------------------------------------------------
                // [Kali] → (tráfico de exploit C2) → [iptables REDSOCKS_TCP] → redsocks → SOCKS5 → Internet (IP residencial)
                // [Kali] → (escaneo de red OT interna) → 192.168.100.0/24 (tráfico directo, sin proxy)
                // [Windows 10] ← (drive-by CVE-2020-6507) ← [Kali:80] (servido localmente en red OT)
                // [Windows 10] → (reverse shell) → [Kali:4444] (conexión directa en red OT)
                // [Windows 10] → (S7comm explotación) → [PLC S7-1200:102] (tráfico directo en red OT)
                // [PLC S7-1200] → (shellcode ARM modifica salidas) → [Proceso Físico]

    La clave del diseño es que la red OT interna (192.168.100.0/24) no pasa por el proxy. Solo el tráfico que sale del laboratorio hacia Internet se ofusca. Esto permite que los exploits que establecen conexiones dentro de la red OT funcionen con latencia mínima, mientras que cualquier comunicación con el exterior —como la descarga de herramientas, consultas a repositorios de CVE, o comunicación con C2— queda blindada por el túnel ofuscado y el proxy residencial.

    39. Automatización del Laboratorio

    Siguiendo la filosofía de "infraestructura como código" (IaC) del artículo de túnel ofuscado, el laboratorio ICS completo puede ser desplegado con un script de Bash que automatiza:

    1. Verificación de dependencias: VirtualBox 7.x, QEMU (system-arm, system-mips), Python 3.x con pwntools, AFL++, ROPgadget, rz-libmc7, JEB Pro (opcional).
    2. Creación de VMs: Importación de appliances preconfiguradas para Kali, Windows 10, REMnux, y el PLC simulado.
    3. Configuración de red OT: Creación de la interfaz Host-Only vboxnet0, asignación de IPs estáticas a cada VM.
    4. Instalación de herramientas de reversing: Clonación y compilación de rz-libmc7 desde GitHub. Descarga de JEB Pro (demo). Instalación de disectors de Wireshark para Modbus y S7comm.
    5. Configuración del túnel ofuscado: WireGuard + udp2raw en Nodo B, redsocks + dnscrypt-proxy + dnsmasq para salida blindada.
    6. Verificación de conectividad: Ping bidireccional entre todas las VMs, handshake Modbus TCP con el PLC simulado, handshake S7comm, resolución DNS sobre HTTPS.
    7. Generación de claves SSH y configuración de acceso: Para administración remota del laboratorio a través del túnel ofuscado.

    Este script es la evolución natural del script de despliegue de 90 segundos del túnel ofuscado, extendido para incluir el entorno ICS completo. La meta es que cualquier investigador pueda clonar el repositorio, ejecutar ./deploy_ics_lab.sh --mode full, y tener un laboratorio OT funcional en minutos, listo para ejecutar los cuatro talleres.

    40. Roadmap de Próximos Posts

    Este artículo es el punto de partida de una serie de posts prácticos que profundizarán en cada uno de los talleres propuestos. El roadmap planificado incluye:

    #PostContenidoDependenciasEstado
    1Shellcode AWL/MC7 en la PrácticaDesarrollo de 5 shellcodes con complejidad creciente: encender LED, puerta trasera con contador, bypass de verificación de seguridad, falso sensor, y denegación de servicio del ciclo de scan. Incluye análisis del bytecode generado con rz-libmc7 y JEB.PLC simulado (WinSPS-S7), rz-libmc7, JEB Pro demoEn progreso
    2Reversing de Firmware ARM/MIPS en PLCs SiemensExtracción de firmware .upd de un S7-1200, análisis con Ghidra + scripts de firmware, identificación de la capa de traducción MC7+→ARM, y documentación de la estructura del kernel ADONIS.PLC S7-1200 físico, Ghidra, scripts de extracción de firmwarePlanificado
    3ROP sobre ARM en Firmware de PLC: Replicando CVE-2020-15782Búsqueda automatizada de gadgets ARM en firmware S7-1200 con ROPgadget, construcción de cadena ROP funcional, y demostración de sandbox escape en entorno controlado.Firmware extraído, ROPgadget, QEMU ARM, PLC S7-1200 vulnerablePlanificado
    4Fuzzing de Protocolos Industriales: Resultados y CríticasResultados del fuzzing de Modbus TCP, S7comm y Profinet sobre PLCs simulados y reales. Documentación de crashes encontrados, análisis de explotabilidad, y recomendaciones de hardening.AFL++, PLC simulado/real, WiresharkPlanificado
    5Cadena de Explotación Completa OT: Del Drive-by al Proceso FísicoEjecución completa del Workshop 4 con hardware real. Documentación de cada etapa de la kill chain con tiempos, herramientas y obstáculos encontrados.Laboratorio ICS completo, CVE-2020-6507, CVE-2020-15782Planificado
    6Automatización del Laboratorio ICS: Infraestructura como CódigoScript completo de despliegue, playbook de Ansible, y guía de hardening del laboratorio. Integración con CI/CD para pruebas automatizadas de exploits.Todos los componentes del laboratorioPlanificado

    41. Conclusión: El Estado del Arte en Explotación de PLCs

    El exploit development en entornos OT ha madurado significativamente desde los días de Stuxnet. La publicación de CVE-2020-15782 por Claroty Team82 en 2021 marcó un punto de inflexión: demostró que incluso los PLCs modernos con sandbox y kernel propietario son vulnerables a ataques sofisticados que combinan desbordamiento de búfer en la VM, sandbox escape, y ejecución de código nativo ARM/MIPS.

    El ecosistema de herramientas también ha madurado. JEB Pro ofrece decompilación de MC7 a pseudo-C con soporte para los formatos de bloque binario de Siemens. rz-libmc7 proporciona desensamblado open-source de bytecode MC7. Ghidra permite analizar el firmware ARM/MIPS subyacente. Y herramientas clásicas como ROPgadget y AFL++ se adaptan perfectamente al entorno OT cuando se configuran correctamente.

    Sin embargo, la barrera de entrada sigue siendo alta. La adquisición de hardware real —PLCs S7-1200, S7-300, módulos de E/S, cables de programación— requiere inversión económica. La extracción de firmware puede requerir habilidades de hardware hacking. Y la validación de exploits en hardware real conlleva riesgos de dañar equipos costosos. Este artículo y la serie que inaugura buscan reducir esa barrera proporcionando una metodología que comienza con software gratuito y escala progresivamente.

    Los principios fundamentales son los mismos que en la explotación binaria tradicional: entender la arquitectura subyacente, identificar primitivas de control de flujo, construir cadenas ROP, y evadir mitigaciones. Lo que cambia es el contexto: en OT, un exploit exitoso no resulta en una shell remota, sino en la manipulación de un proceso físico con consecuencias potencialmente catastróficas. Esa responsabilidad —tanto para el atacante como para el defensor— es lo que hace de este campo uno de los más desafiantes y relevantes de la seguridad informática actual.

    Estado del Laboratorio (Junio 2026)

    Al momento de publicar este artículo, el laboratorio ICS está en fase de montaje. Los talleres 1 y 2 han sido validados con PLC simulado (WinSPS-S7 V6) y analizados con rz-libmc7. El taller 3 está en configuración de AFL++ con harness para Modbus TCP. El taller 4 depende de la adquisición de un PLC S7-1200 con firmware vulnerable a CVE-2020-15782 (parcheada en 2021) y de un sandbox escape para Chrome (CVE-2020-6507 requiere --no-sandbox). El script de automatización del laboratorio está en desarrollo. El progreso se documentará en los posts subsiguientes del roadmap.

    /¿Querés replicar este laboratorio o contribuir a la serie?

    Este artículo es el primero de una serie sobre exploit development en entornos OT. Todo el código, scripts de automatización y configuraciones estarán disponibles en GitHub. Si tenés hardware de PLCs que ya no uses y querés donarlo para investigación, o si querés colaborar en el desarrollo de herramientas de reversing de MC7/MC7+, ponete en contacto.

    Reversing PLC Siemens (Base Teórica) → Lab Exploit Development (Técnicas) → Infraestructura Ofuscada (Entorno) → Triage de Malware →

    42. Referencias