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
- Estructura modular: dividido en módulos que realizan funciones específicas. La sujeción se hace sobre carril DIN, placa perforadora o RACK donde va alojado el bus externo de unión de los distintos módulos.
- Estructura compacta: presenta en un solo bloque todos sus elementos: CPU, memorias, entradas, salidas, etc. Ejemplos comunes son los LOGO! de Siemens o los ОВЕН de fabricación rusa, populares en países de la órbita postsoviética por su relación costo-beneficio.
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.

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:
- Programa del sistema: instrucciones complejas y arreglos necesarios para el funcionamiento interno del controlador, almacenadas en memoria EPROM. No son afectadas por alteraciones del voltaje principal.
- Programa del usuario: instrucciones para el procesamiento de las señales que ejercen influencia sobre el proceso controlador, almacenadas en memoria RAM.
Lenguajes contenidos en STEP5:
- Listado de instrucciones (AWL): lenguaje de bajo nivel que utiliza nemónicos para representar las instrucciones del PLC. Ofrece control preciso y es muy compacto en uso de memoria. Su sintaxis recuerda enormemente al Assembly de arquitecturas como x86: se trabaja con un operador, un operando y un registro acumulador (RLO) que almacena el resultado de la última evaluación lógica.
- Diagrama de funciones (FUP): lenguaje gráfico que utiliza bloques de funciones. Adecuado para control continuo y procesamiento de señales.
- Diagrama de contacto (KOP): lenguaje gráfico que simula circuitos de relés tradicionales. Adecuado para control discreto y secuencial.
2. Bloques del Programa de Usuario
| Bloque | Nombre | Función |
|---|---|---|
| OB | Bloque de Organización | Controla la secuencia de ejecución del programa. Define puntos de entrada e interrupciones. Esencial para la estructura del programa. |
| PB | Bloque de Programa | Contiene el programa principal de control. Puede llamar a otros bloques de funciones y datos. |
| FB | Bloque de Funciones | Contiene funciones reutilizables que se pueden llamar desde otros bloques. Permite modularizar el programa. |
| SB | Bloque Secuencial | Utilizado para programar secuencias de pasos. Define transiciones entre pasos y acciones asociadas. |
| DB | Bloque de Datos | Almacena datos variables utilizados en el programa. Facilita el intercambio de datos entre diferentes bloques. |
Operandos en STEP5
- Entradas (E) — Interfaces del proceso al autómata.
- Salidas (A) — Interfaces del autómata al proceso.
- Marcas (M) — Memorias para resultados binarios intermedios.
- Datos (D) — Memorias para resultados digitales intermedios.
- Temporizadores (T) — Memorias para la realización de temporizadores.
- Contadores (Z) — Memorias para la realización de contadores.
- Periferia (P) — Interfaces del proceso al autómata.
- Constantes (K) — Valores numéricos fijos.
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.

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
- BE — Última instrucción obligatoria en todos los OB, PB, SB y FB.
- BEB — Fin de bloque si al momento de su ejecución RLO = 1.
- BEA — Fin de bloque con independencia del RLO.
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)
- Refleja contactos en serie.
- Multiplicación bit a bit entre RLO y el operando especificado.
- Negación: UN.
- Operandos posibles: E, A, M, DBX, DIX, L, T, Z.
- Registros afectados: RLO, STA.
OR (AWL = O)
- Refleja contactos en paralelo.
- Suma bit a bit entre RLO y el operando especificado.
- Negación: ON.
- Operandos posibles: E, A, M, DBX, DIX, L, T, Z.
- Registros afectados: RLO, STA.
XOR (AWL = X)
- Equivalente a una evaluación de "es distinto de". Su negación equivale a "es igual a".
- Negación: XN.
- Registros afectados: RLO, STA.
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
| Bit | Registro | Función |
|---|---|---|
| 0 | ER | Indica si la instrucción es la primera de una cadena lógica (inhibida). En este estado, la consulta se almacena directamente en RLO. |
| 1 | RLO | Registro donde se realizan las operaciones a nivel de bit. Almacena el resultado lógico (acumulador). |
| 2 | STA | Gestión de errores. |
| 3 | OR | Requerido para el proceso AND delante de OR. Indica si la operación AND ha dado valor 1. |
| 4 | OV | Se 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. |
| 5 | OS | Se 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-7 | A0, A1 | Códigos de condición: resultados de operaciones aritméticas, comparaciones, operaciones digitales, bits desplazados. |
| 8 | RB | Resultado 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.


8. Temporizadores en Siemens S5
| Tipo | Nemónico | Comportamiento |
|---|---|---|
| S_EVERZ | SE | Retardo 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_SEVERZ | SS | Retardo 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_IMPULS | SI | Genera 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_VIMP | SV | Pulso prolongado. Solo genera el pulso si la señal de entrada se mantiene activa durante un tiempo mínimo. |
| S_PULS | SP | Genera un pulso de duración definida (TV). La duración es independiente de cuánto tiempo se mantenga activa la entrada. |
| S_AVERZ | SA | Retardo 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:
- Z0 ... Zmax — Número de contador (CPU-90: 128).
- ZV — Incrementar (no supera 999).
- ZR — Decrementar (no decrementa por debajo de 0).
- S — Carga el valor inicial en el contador.
- KZ xxx — Valor inicial.
- R — Resetea el valor del contador.
10. Operaciones de Comparación y Saltos
Comparaciones
Un comparador relaciona dos datos del mismo formato (BYTE o WORD). Tipos disponibles:
- != F — Desigualdad
- > F — Mayor que
- < F — Menor que
- >= F — Mayor o igual que
- <= F — Menor o igual que
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ón | Condición |
|---|---|
| SPA | Salto Incondicional |
| SPB | Salta si RLO = 1 (True) |
| SPN | Salta si RLO = 0 (False) |
| SPZ | Salta si AKKU1 = 0 |
| SPP | Salta si AKKU1> 0 |
| SPM | Salta si AKKU1 < 0 |
| SPO | Salta si OV = 1 (desbordamiento) |
| SPS | Salta si OS = 1 (error persistente) |
| SPR | Salta 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ística | S5-95 | S7-300 |
|---|---|---|
| RAM | 16 KB (STEP5) + 64 KB (ejecución) | Mayor capacidad, dependiente del modelo |
| Puerto de programación | AS511 | Interfaces MPI |
| Memoria de trabajo | RAM | RAM |
| Memoria de carga | RAM o EPROM | RAM, Flash o tarjeta de memoria |
| Datos locales | No existen | Sí (datos temporales dentro de un bloque) |
| Datos remanentes | Menor capacidad | Mayor 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 S5 | Ejemplo S5 | Formato S7 | Ejemplo S7 | Tipo de dato |
|---|---|---|---|---|
| KB | L KB 10 | B#16# | L B#16# A | BYTE (8 bits) |
| KF | L KF 10 | — | L 10 | INT (16 bits) |
| KH | L KH FFF | W#16# | L W#16# FFFF | WORD (16 bits) |
| KM | L KM 1111111111111111 | 2# | L 11111111_11111111 | WORD (16 bits) |
| KY | L KY 10,12 | B# | L B#(10,12) | 2xBYTE (8+8 bits) |
| KT | L KT 10.0 | S5TIME# | L S5TIME# 100ms | TIME (S5TIME) |
| KZ | L KZ 30 | C# | L C#30 | COUNTER (BCD) |
| DH | L DH FFFF FFFF | DW#16# | L DW#16#FFFF_FFFF | DWORD (32 bits) |
| KC | L KC WW | ' xx ' | L ' WW ' | CHAR (8 bits por carácter) |
| KG | L KG +234 +09 | REAL | L +2.34 E+08 | REAL (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.



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:
- Profibus: estándar industrial para datos discretos y analógicos.
- Profinet: basado en Ethernet, ideal para aplicaciones en tiempo real.
- DeviceNet: utilizado en automatización de fábricas.
- CANopen: popular en aplicaciones de control de movimiento.
- AS-Interface: diseñado para conectar sensores y actuadores binarios.
Protocolos de comunicación
- Modbus RTU / ASCII / TCP/IP: protocolo serial ampliamente utilizado para comunicación entre PLCs, sensores y actuadores. Es importante señalar que Modbus carece de autenticación por diseño, lo que lo convierte en un vector de ataque significativo en entornos no segmentados.
- DNP3 (Distributed Network Protocol 3): comunicación entre equipos en sistemas de automatización de redes eléctricas y agua. Común en subestaciones eléctricas.
- ICCP (Inter-Control Center Communications Protocol): diseñado para comunicación entre centros de control en sistemas de energía eléctrica. Permite intercambio de datos en tiempo real.
- OPC (Open Platform Communication): estándar de interoperabilidad para el intercambio de datos entre dispositivos industriales de diferentes fabricantes. Utiliza DCOM para conectarse a servidores OPC dentro de una red ICS.
- WORLDFIP: bus de campo industrial para comunicación entre dispositivos en sistemas de automatización.
Sistemas SCADA, DCS y HMI
- ALSPA P320: Sistema de Control Distribuido presente en plantas de generación de energía e instalaciones industriales de gran escala.
- ABB 800xA: Sistema de Control Distribuido con alta capacidad de procesamiento. Se programa mediante Control Builder M.
- Wonderware SCADA: plataforma de supervisión y control con librerías de comunicación para PLCs S7, programables sobre C# o Java.
- PascalSCADA: alternativa open-source para sistemas SCADA que permite comunicación con PLCs Siemens vía Ethernet, Modbus TCP/RTU, y extensibilidad mediante clases personalizadas en Lazarus/Free Pascal.
- HMI Magelis (ahora Harmony): interfaces hombre-máquina con pantallas táctiles, configurables con EcoStruxure™ Operator Terminal Expert.
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.

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:
- La instrucción de carga L es representada por el opcode 0xFB.
- La instrucción de transferencia T es representada por el opcode 0x7E.
- La mayoría de las instrucciones, incluyendo sus operandos, tienen una longitud máxima de 4 bytes, lo que sugiere un formato de instrucción de longitud fija o semi-fija.
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.

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:
- Comprender cómo el compilador prepara el firmware para el MC7 y cómo se codifican las instrucciones.
- Estudiar la estructura del binario internamente, análogo a lo que sería el formato PE en Windows.
- Desarrollar shellcode para PLC Siemens S7, entendiendo qué tanto cambia la codificación entre versiones y marcas.
- Realizar prácticas de binary exploitation sobre el entorno MC7.
Puntos de entrada para fuzzing
Los vectores potenciales para realizar fuzzing en un entorno PLC incluyen:
- Sensores: los datos provenientes de sensores conectados a los módulos de entrada representan un flujo de datos que podría ser manipulado.
- Protocolos de comunicación: Modbus TCP/RTU, Profinet, OPC y otros protocolos constituyen interfaces expuestas a la red que procesan datos potencialmente maleables.
- Software de programación: las herramientas como TIA Portal, WinSPS S7 o PG2000 son vectores adicionales si un atacante logra comprometer la estación de ingeniería.
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.

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 Grado | Tecnologí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:
- Definir una política de registros mínimos: comandos del operador, cambios en la lógica del PLC, conexiones de red al puerto 502 (Modbus) o 102 (S7), y eventos de arranque/parada del controlador.
- Implementar sincronización horaria confiable: sin NTP, los registros de distintos dispositivos no pueden correlacionarse temporalmente.
- Proteger los logs contra manipulación: si el registro de eventos reside en el mismo PLC que puede ser reprogramado, un atacante puede borrar sus huellas.
- Incluir la verificación de logging en las pruebas FAT y SAT: si no se prueba en fábrica, no existirá en producción.
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:
- Un desensamblador de MC7 funcional, con soporte para exportar versiones compiladas desde entornos como WinSPS S7 o TIA Portal.
- Comprensión profunda de la estructura de los formatos compilados de MC7, mapeando la relación entre bytecodes y su representación en memoria.
- Estudio de la pasarela entre bytecodes MC7 e instrucciones reales del procesador (ARM/MIPS), incluyendo el proceso de equivalencia y traducción.
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:
- Adquirir equipo físico (PLCs, módulos de E/S, switches industriales) para validar las investigaciones más allá de los simuladores.
- Configurar una red OT segmentada con los protocolos más utilizados (Modbus TCP, Profinet, OPC).
- Estudiar los protocolos de red a nivel de formato de paquetes, reglas de negociación y vectores de ataque.
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:
- Desbordamiento de pila de módulos (STUEB): el límite de 16 niveles de anidamiento puede ser explotado si un atacante logra inyectar llamadas recursivas no controladas.
- Falta de detección de flancos en S5: obliga a implementar lógica de muestreo manual con marcas de memoria, lo que introduce complejidad y posible error humano.
- Protocolos sin autenticación: Modbus, Profibus y otros protocolos industriales carecen de mecanismos de autenticación, permitiendo inyección de comandos desde cualquier nodo con acceso a la red OT.
- Vulnerabilidades documentadas en Modicon Quantum: la posibilidad de paralizar CPUs sin autenticación vía Modbus TCP, junto con el desbordamiento de búfer en el Serial Modbus Driver de Schneider Electric, representan riesgos concretos para infraestructuras que no hayan aplicado los parches correspondientes.
- Direccionamiento indirecto: la capacidad de modificar operandos dinámicamente durante la ejecución introduce riesgos si un atacante logra manipular los punteros.
- Transición S5 → S7: sistemas legacy S5-95 siguen operando en infraestructuras críticas sin las mejoras de seguridad del S7-300/400, creando una brecha generacional explotable. La documentación pública de trabajos de grado confirma que estas migraciones han sido recientes o están aún en proceso.
- Exposición de información por documentación académica: los trabajos de grado y tesis universitarias constituyen una fuente de inteligencia de acceso público que detalla las tecnologías, arquitecturas y configuraciones de infraestructuras críticas.
- Malware con conocimiento del dominio OT: casos como Havex demuestran que los atacantes han desarrollado capacidades para enumerar y comprometer dispositivos ICS utilizando protocolos estándar como OPC.
- Ausencia de registros forenses (logging): la omisión sistemática de sistemas de registro de eventos en los proyectos documentados convierte cualquier incidente en una caja negra. Sin logs, la diferencia entre error técnico y acción maliciosa es imposible de establecer, como demostraron los casos de Oldsmar y TRITON.
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
- CISA — ICS Alert: Schneider Electric Modicon Quantum PLC Vulnerabilities
- Malpedia — Havex RAT
- PNF Software — JEB: Simatic S7 STL Opcodes
- PNF Software — JEB: PLC Decompiler
- Habr — Ingeniería inversa en PLC Siemens S7-300
- Habr — Mitsubishi PLC: desmontar el protocolo de red
- RUB-SysSec — Siemens S7 Bootloader (ejecución no invasiva de código)
- Matloff & Franklin — Introducción a la Microprogramación
- UTN — Arquitectura de Computadoras: Unidad 6 — Microprogramación
- TIB AV-Portal — Estructura en memoria de MC7
- Indi.An — Librería de comunicación para Siemens S7
- PascalSCADA — SCADA open-source con soporte para PLCs Siemens
- Explicación extensa sobre VM MC7 y ARM/MIPS (YouTube)
- Siemens — Manual de transición STEP5 a STEP7
- Yau, Chow & Yiu (2018). "A Forensic Logging System for Siemens Programmable Logic Controllers". IEEE Transactions on Industrial Informatics.
- Shahbi, F. (2026). "Forensic Readiness in Industrial Control Systems". Tesis doctoral, University of Bristol.
/¿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:
- 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).
- 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.
- 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.
- 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 AWL | Bit | Función | Equivalente en Explotación |
|---|---|---|---|
| FC (First Check) | 0 | Indica 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) | 1 | Resultado 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. |
| STA | 2 | Estado del bit direccionado. Refleja el valor del operando consultado. | Similar al flag CF (Carry Flag) — indica el estado de la última operación |
| OR | 3 | Indica si una operación AND previa dio 1, necesario para combinar AND con OR en cadenas lógicas. | Flag auxiliar para operaciones compuestas |
| OV | 4 | Desbordamiento aritmético: se activa en operaciones de coma flotante o enteros con overflow. | OF (Overflow Flag) en x86 |
| OS | 5 | Overflow 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, CC1 | 6-7 | Códigos de condición: actualizados por operaciones aritméticas, comparaciones y desplazamientos. | Similares a SF (Sign Flag) y PF (Parity Flag) |
| BR | 8 | Binary 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, AKKU2 | 32 bits c/u | Acumuladores 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, AR2 | 32 bits c/u | Registros 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, DB2 | 16 bits c/u | Registros 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.

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 S5 | AWL S7 | Condición | Equivalente x86 | Uso en Exploit |
|---|---|---|---|---|
| SPA | SPA | Incondicional | JMP | Redirigir ejecución a shellcode |
| SPB | SPB | RLO = 1 | JNE / JNZ | Salto condicional tras evaluación |
| SPN | SPN | RLO = 0 | JE / JZ | Bypass de verificaciones de seguridad |
| SPZ | SPZ | AKKU1 = 0 | JZ (tras CMP) | Control post-aritmética |
| SPP | SPP | AKKU1> 0 | JG | Validación de contadores |
| SPM | SPM | AKKU1 < 0 | JL | Detección de underflow |
| SPO | SPO | OV = 1 | JO | Captura de desbordamiento aritmético |
| SPS | SPS | OS = 1 | — | Detección de error persistente (latch) |
| SPR | SPR | BR = 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:
- Si es una VM: el exploit debe operar dentro de los límites del bytecode. Las instrucciones disponibles son las que la VM expone. Escapar de la VM requeriría una vulnerabilidad en el intérprete mismo —exactamente lo que Claroty logró con CVE-2020-15782—.
- Si es microprogramación: siguiendo el modelo de Matloff y Franklin, donde una Máquina A (CPU ARM/MIPS real) ejecuta un microprograma (firmware) que la hace comportarse como una Máquina B (la que entiende MC7), el procesador subyacente está expuesto a través del firmware. Un exploit que logre ejecutar instrucciones ARM/MIPS nativas puede tomar control total del hardware.
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.

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:
- Escapar del sandbox de la VM: escribir datos arbitrarios en regiones de memoria protegidas que normalmente están fuera del alcance del bytecode MC7+.
- 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.
- 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.
- 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.

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:

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:
- JEB Decompiler (PNF Software): El artículo de Nicolas Falliere detalla que la instrucción L (carga) es representada por opcodes que varían según el tipo de dato inmediato (0x30 para dec16, 0x38 para dec32, 0x28 para hex8, etc.), y que la instrucción T (transferencia) corresponde al opcode 0x7E. La mayoría de las instrucciones MC7, incluyendo sus operandos, tienen una longitud máxima de 4 bytes.
- rz-libmc7 (rizinorg): Plugin open-source para rizin que implementa un desensamblador de MC7 bytecode. Soporta la decodificación de instrucciones aritméticas (+D, -D, *D, /D, MOD), operaciones lógicas, y acceso a memoria.


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ística | x86/AMD64 | ARM | Impacto en Explotación |
|---|---|---|---|
| Conjunto de instrucciones | CISC (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 llamada | Argumentos en pila (x86) o RCX,RDX,R8,R9 (AMD64 Windows) | Argumentos en R0-R3, retorno en R0. Stack para argumentos adicionales | Los gadgets ROP deben manipular registros diferentes. Pop {r0, pc} es el gadget universal de ARM |
| Ejecución condicional | Solo 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 registro | RIP/EIP no es directamente accesible como registro de propósito general | R15 (PC) es de propósito general. Se puede leer y escribir como cualquier registro | Lectura/escritura directa del contador de programa facilita el control de flujo |
| Endianness | Little-endian | Bi-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ón | Ring 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:
| Herramienta | Desarrollador | Funcionalidad | Licencia | Target |
|---|---|---|---|---|
| JEB Pro | PNF Software | Desensamblador 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-libmc7 | rizinorg (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 |
| Ghidra | NSA | Framework 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 Source | Firmware 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.

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:
- 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.
- Analizar el binario ARM/MIPS con herramientas estándar: ROPgadget, ropper, o Ghidra con scripting en Python.
- 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.
| Componente | Protocolo/Puerto | Vector de Ataque | Impacto | Caso Documentado |
|---|---|---|---|---|
| PLC Siemens S7-300/400 | S7comm (TCP 102) | Inyección de comandos STOP/RUN, descarga/inyección de firmware | Parada de planta, modificación de lógica de control | Stuxnet (2010) |
| PLC Siemens S7-1200/1500 | S7comm+ (TCP 102) | Sandbox escape, escritura en memoria protegida, ejecución de código nativo ARM/MIPS | Control total del PLC a nivel de kernel | CVE-2020-15782 (Claroty, 2021) |
| Modbus TCP | TCP 502 | Escritura en coils/registers sin autenticación por diseño | Manipulación de E/S, falseo de sensores, activación/desactivación de actuadores | Múltiples incidentes no atribuidos |
| Profinet | Ethernet industrial (capa 2) | Inyección de tramas, denegación de servicio en tiempo real | Interrupción de comunicación determinista entre PLCs | Investigaciones académicas |
| OPC UA/DA | TCP 4840, DCOM (135, 445) | Enumeración de tags, lectura/escritura remota de variables de proceso | Fuga de información del proceso industrial, modificación de setpoints | Havex RAT (2013-2014) |
| HMI Magelis/Harmony | HTTP/HTTPS, VNC (5900) | Contraseñas por defecto, vulnerabilidades web, exposición de pantalla de operador | Control visual del operador comprometido, comandos no autorizados | Auditorí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 planta | Acceso total a toda la red OT, modificación de lógica en todos los PLCs | Patrón de ataque recurrente |
| Schneider Modicon Quantum | Modbus TCP (502), Serial Modbus Driver | Paralización de CPU sin autenticación, buffer overflow en driver serial | Denegación de servicio, potencial ejecución de código | ICS-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:
- La VM no es una barrera infranqueable: un desbordamiento de búfer en una operación específica de la VM permitió escribir fuera de los límites del sandbox.
- El firmware es accesible: mediante ingeniería inversa del protocolo S7comm+ y del formato de actualización .upd, se puede extraer y analizar el firmware completo.
- La ejecución de código nativo es posible: al parchar un opcode de la VM en memoria, el shellcode ARM/MIPS inyectado se ejecuta cuando el sistema operativo invoca esa instrucción.
- La detección es extremadamente difícil: el código a nivel de kernel es invisible para las herramientas de diagnóstico del PLC y para el TIA Portal.
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
| Componente | Software/Hardware | Propósito en el Laboratorio | Costo Aprox. (USD) |
|---|---|---|---|
| Nodo A (VPS) | Ubuntu 22.04 LTS + WireGuard + udp2raw | Puerta 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.x | Host de todas las VMs del laboratorio. Corre redsocks + dnscrypt-proxy + dnsmasq. | Hardware propio (~$800-1500) |
| PLC Simulado MC5 | PG 2000 + PC Simu | Target legacy para exploits AWL en S5. Pruebas de shellcode básico y STUEB. | Gratuito (abandonware) |
| PLC Simulado MC7 | WinSPS-S7 V6 | Target principal para exploits AWL/MC7 en S7-300. Compilación y desensamblado de bytecode. | Gratuito (demo funcional) |
| PLC Real S5-95U | Siemens S5-95U + módulos E/S + cable AS511 | Validació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-300 | Siemens S7-300 (CPU 314/315) + MPI-USB adapter | Target para exploits MC7. Extracción de firmware vía S7comm. Análisis con JEB y rz-libmc7. | ~$300-800 (eBay, usado) |
| PLC Real S7-1200 | Siemens 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ía | Windows 10 LTSC + TIA Portal V17 + STEP5 | Software de programación oficial de Siemens. Necesario para compilar y descargar código a PLCs reales. | Licencia TIA Portal (consultar Siemens) |
| Kali Linux | Kali 2024.x + toolchains ARM/MIPS | Estación de ataque ofensivo. Corre ROPgadget, AFL++, Wireshark, Metasploit, rz-libmc7. | Gratuito |
| REMnux | REMnux 7 + INetSim + fakedns | Simulación de servidores C2 falsos. Redirección DNS para entornos de prueba. | Gratuito |
| QEMU ARM/MIPS | QEMU system-arm / system-mips | Emulación del procesador del PLC para pruebas de shellcode nativo sin hardware real. | Gratuito |


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
- PLC simulado: WinSPS-S7 V6 (MC7) o PG 2000 + PC Simu (MC5).
- Editor AWL: cualquier editor de texto. Compilación con STEP5, STEP7 o el propio WinSPS-S7.
- Herramientas de análisis: rz-libmc7 para verificar el bytecode generado. JEB Pro (demo) para decompilar a pseudo-C.
- Target: programa original con lógica simple (ej: U E 2.0 ; = A 3.0) que será modificado para incluir el shellcode.
Procedimiento
- 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.
- 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).
- 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.
- Cargar en el PLC: Transferir el programa al PLC simulado.
- 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 - 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
- PLC simulado: WinSPS-S7 V6 con firmware que contenga funciones reutilizables (bibliotecas IEC estándar).
- Herramientas: JEB Pro para identificar gadgets en los bloques del firmware. rz-libmc7 para verificar la secuencia de bytecode. Calculadora de offsets para construir la cadena.
Procedimiento
- 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 - 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 - 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
- PLC simulado: WinSPS-S7 V6 con puerto Modbus TCP expuesto en 192.168.100.50:502 y puerto S7comm en 192.168.100.50:102.
- Kali Linux: 192.168.100.10 con AFL++, Wireshark (dissectors Modbus y S7comm), y herramientas de red.
- Wireshark: Para capturar tráfico legítimo que servirá como semillas del fuzzer.
Procedimiento
- 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.
- Extraer semillas: Exportar los paquetes capturados como datos binarios para usarlos como semillas del fuzzer.
- 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++ - 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.
- 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:
- Longitud de paquete excesiva: buffer overflow en el parser Modbus o S7comm.
- Function codes inválidos: manejo incorrecto de códigos de función no implementados en Modbus.
- Direcciones de registro fuera de rango: lectura/escritura fuera de los límites del mapa de memoria Modbus, potencialmente accediendo a regiones de memoria protegidas (similar a CVE-2020-15782 pero en la capa de protocolo).
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
- Windows 10: 192.168.100.20 con Chrome <83 (vulnerable a CVE-2020-6507) y TIA Portal instalado.
- Kali Linux: 192.168.100.10 como servidor de exploit CVE-2020-6507 y centro de comando post-explotación.
- REMnux: 192.168.100.40 con INetSim + fakedns para redirección DNS y simulación de Internet falsa.
- PLC S7-1200 simulado: 192.168.100.30 corriendo en QEMU ARM con firmware vulnerable a CVE-2020-15782 (versión anterior al parche de 2021).
- PLC S7-1200 físico: 192.168.100.80 (opcional, para validación en hardware real).
Procedimiento
- 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.
- 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).
- 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).
- 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.
- 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.
- 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:
- Nodo A (VPS público): Único punto de entrada desde Internet. Ejecuta WireGuard + udp2raw en modo servidor (faketcp:443, ofuscación XOR).
- Nodo B (Laboratorio local): Conecta al Nodo A vía udp2raw. Todo el tráfico de salida del laboratorio hacia Internet pasa por redsocks → SOCKS5 residencial, enmascarando la IP real.
- Kali Linux (VM en Nodo B): Su tráfico hacia Internet es capturado por iptables y redirigido a través del proxy residencial. Cualquier escaneo, exploit o conexión reversa hacia objetivos externos tendrá la IP del proxy, no la IP real del laboratorio.
- Red OT interna (192.168.100.0/24): Tráfico directo sin proxy para mínima latencia en las comunicaciones con PLCs simulados y reales.
// 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:
- Verificación de dependencias: VirtualBox 7.x, QEMU (system-arm, system-mips), Python 3.x con pwntools, AFL++, ROPgadget, rz-libmc7, JEB Pro (opcional).
- Creación de VMs: Importación de appliances preconfiguradas para Kali, Windows 10, REMnux, y el PLC simulado.
- Configuración de red OT: Creación de la interfaz Host-Only vboxnet0, asignación de IPs estáticas a cada VM.
- 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.
- Configuración del túnel ofuscado: WireGuard + udp2raw en Nodo B, redsocks + dnscrypt-proxy + dnsmasq para salida blindada.
- Verificación de conectividad: Ping bidireccional entre todas las VMs, handshake Modbus TCP con el PLC simulado, handshake S7comm, resolución DNS sobre HTTPS.
- 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:
| # | Post | Contenido | Dependencias | Estado |
|---|---|---|---|---|
| 1 | Shellcode AWL/MC7 en la Práctica | Desarrollo 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 demo | En progreso |
| 2 | Reversing de Firmware ARM/MIPS en PLCs Siemens | Extracció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 firmware | Planificado |
| 3 | ROP sobre ARM en Firmware de PLC: Replicando CVE-2020-15782 | Bú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 vulnerable | Planificado |
| 4 | Fuzzing de Protocolos Industriales: Resultados y Críticas | Resultados 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, Wireshark | Planificado |
| 5 | Cadena de Explotación Completa OT: Del Drive-by al Proceso Físico | Ejecució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-15782 | Planificado |
| 6 | Automatización del Laboratorio ICS: Infraestructura como Código | Script 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 laboratorio | Planificado |
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
- PLC Siemens S5/S7: Arquitectura MC7, AWL y la Deficiencia Estructural de Logs (tty503.com)
- Laboratorio de Exploit Development: Windows Internals, ROP y Shellcode (tty503.com)
- Infraestructura Ofuscada: WireGuard + udp2raw + Proxy Residencial (tty503.com)
- analystty: Automatizando el Triage de Malware PE (tty503.com)
- Pentesting a una Web API Financiera: IDOR y Fuga de Datos (tty503.com)
- PNF Software — JEB: PLC Decompiler (Soporte para Simatic S7)
- JEB Decompiler Blog — Reversing Simatic S7 PLC Programs (Nicolas Falliere, 2022)
- PNF Software — Simatic S7 STL Opcodes (Referencia rápida de instrucciones MC7)
- rizinorg/rz-libmc7 — Library to disassemble MC7 bytecode for Siemens PLC SIMATIC S7-300 and S7-400
- Claroty Team82 — The Race to Native Code Execution in PLCs (CVE-2020-15782, Tal Keren, 2021)
- SEC Consult — Reverse Engineering Architecture & Pinout PLC
- Matloff & Franklin — Introducción a la Microprogramación
- UTN — Arquitectura de Computadoras: Unidad 6 — Microprogramación
- Habr — Ingeniería inversa en PLC Siemens S7-300
- RUB-SysSec — Siemens S7 Bootloader (ejecución no invasiva de código en PLCs)
- TIB AV-Portal — Estructura en memoria de MC7
- ROP Emporium — Learn Return-Oriented Programming
- pwn.college — Cybersecurity Education Platform
- Felix Cloutier — x86 and AMD64 Instruction Reference
- x64.syscall.sh — Linux System Call Table
- ARM Instruction Set Reference Guide
- CISA — ICS Alert: Schneider Electric Modicon Quantum PLC Vulnerabilities
- Malpedia — Havex RAT
- DEVCORE — Streaming Vulnerabilities from Windows Kernel (Angelboy, 2024)
- MITRE ATT&CK — Enterprise Matrix (Tácticas y Técnicas)
- ired.team — Finding all RWX Protected Memory Regions
- Siemens — Manual de transición STEP5 a STEP7
- Siemens — Simatic Statement List (STL) for S7-300 and S7-400 Programming — Function Manual
- Siemens — SSA-434534: Vulnerabilidad de bypass de protección de memoria en SIMATIC S7-1200 y S7-1500 (CVE-2020-15782)