Exploit Development # 3 : Attacking PLCs with Analog Input Forcing – Vulnerability Analysis @ Hack-the-Box

Welcome to the thrilling debut of our “Exploit Development” series! Buckle up for “Attacking PLCs with Analog Input Forcing” – a title that’s as vibrant as the adventure we’re about to undertake!

Ever wondered how to take control of PLCs and manipulate those Analog inputs like a pro? You’re in for a treat! This guide will unlock the secrets of exploiting PLC systems, blending a dash of digital mischief with a solid dose of vulnerability analysis and proof-of-concept (PoC).

Get ready for an exciting journey where we turn theory into practice and make PLC security feel like an exhilarating game of digital dodgeball. Whether you’re a seasoned pro or just here for the tech thrills, prepare to dive deep into the world of PLC exploits—with some laughs and surprises along the way!

Analog vs. Digital: The Basics

Since you’re a tech wizard, I’ll skip the long-winded lecture on what analog and digital mean. But just in case you’ve been living under a rock, analog is all about smooth, continuous signals (like your favorite radio station volume adjustment).

while digital deals in discrete chunks of data (think of a digital clock stubbornly sticking to exact times).

Objective

In this blog post, Analog input Forcing we aim to provide a comprehensive guide on developing and implementing a Python exploit to force Analog inputs on PLCs. We will cover several key phases:.

In our PLC setup, we have two Variable Speed Drives (VSDs):

  • VSD1 is mapped to O:4.3 and controlled by N7.5.
  • VSD2 is mapped to O:5.0 and controlled by N7.11.

The frequency range for these VSDs spans from 6271 to 31207 in decimal, which corresponds to 0 to 50 Hz. VSD1 controls motor-1 (connected to O:0.0), and VSD2 controls motor-2 (connected to O:0.1).

For context, Digital Input & Digital Output forcing are thoroughly explored in Exploit Development # 1 : and Exploit Development # 2.

In this post, we will go though remotely control the frequency of VSD to control the speed of motor by forcing Analog input.

variable frequency drive VFD or VSD

Analog input Forcing of PLC
  1. Vulnerability Analysis: We start with an overview of the PLC systems and the specific vulnerability related to forcing. We analyze the PLC’s security weaknesses exposed by our exploit, highlighting potential risks and impacts.
  2. Exploit Development: We delve into crafting a Python script designed to exploit this vulnerability, including detailed explanations of the code and its functions.
  3. Real-World Application: Using real PLC hardware, we demonstrate the exploit in action and discuss its practical implications.
  4. Hack-the-Box PoC: Finally, we tie it all together with a Hack-the-Box approach, proof of concept (PoC), how this exploit fits into a broader cybersecurity framework.

By the end of this post, you’ll have a solid understanding of how to develop, test, and analyze a PLC exploit, enriched with practical insights and hands-on experience

MicroLogix 1400 PLC: Device under test (DUT)

The MicroLogix 1400 PLC by Rockwell Automation’s Allen-Bradley is vital in many industries. Disruptions to its operation or configuration can lead to severe consequences, including halting critical processes and causing significant equipment damage.

Identified Vulnerability: Remote Forcing PLCs

The PLC’s forcing feature is used to manually enable or disable inputs and outputs, which is valuable for troubleshooting. For example, if a pump isn’t working due to a faulty sensor, forcing the pump to stay on can temporarily resolve the issue.

However, this feature can also be exploited maliciously. Attackers can remotely manipulate these forces to disrupt operations or gain unauthorized control. This vulnerability.

Confused? 🤔 Check Out These Phases for a Step-by-Step Guide!

Feeling a bit lost in the technical jungle of hex code? No worries! If you’re getting stuck in this phase, take a step back and check out our earlier explorations:

  • Phase 1: Basic Network Discovery – – – – – – – – – –> [Explore Phase 1 ]
  • Phase 2: MITM Attack and Protocol Packet captuing – – – –> [Explore Phase 2 ]
  • Phase 3: Packet Communication Protocol Analysis – – – – – – – – –> [Explore Phase 3 ]
  • Phase 4: Deep Packet Inspection (DPI) – – – – – – – – – – – – –> [Explore Phase 4 ]
  • Phase 5: Exploit Development – – – – – – – – – – – – – – – – – – – – – – – –> [Explore Phase 5 ]

Exploit Development: Forcing Analog inputs of PLC

Here’s a closer look at the Python script that powers our exploit. We’ll walk through its key components, so you know exactly what’s happening under the hood.

1. hexadecimal padding – pad_hex(hex_str, size)

Purpose: Ensures that your hexadecimal string is the right size by padding it with leading zeros. Think of it as giving your hexadecimal string a well-fitted jacket!

Details: This function takes a hexadecimal string (hex_str) and ensures it matches the desired size (size) by padding it with zeros.

2. Generation of Transaction Number : get_tns()

Purpose: Generates a unique transaction number for each command. It’s like giving your commands a unique name tag at a party—no confusion, just pure, unadulterated identity!

Details: This function creates a 4-byte hexadecimal string from a random integer, which is crucial for tracking commands.

3. Create a Register session packet : Register_Session()

Purpose: Registers a session with the PLC, much like signing up for a new club. This function sends a registration command and retrieves a session handle.

Details: Constructs and sends a registration request to the PLC, then processes the response to get the session handle. This handle is essential for subsequent communication.

Reference:[Explore Phase 4 🔍]

4. Build an ENIP packet : Build_Ethernet_instruction()

Purpose: Crafts the Ethernet instruction payload for the PLC. Think of this as assembling the perfect care package for your PLC—everything it needs in one neat little box.

Details: Builds a complete payload for sending instructions to the PLC, including encapsulation headers and PCCC command data. This function ensures the message is formatted correctly and includes all necessary information.

Reference: build enip packet [Explore Phase 4 🔍].

5. Create a Function to send Packets: send_instruction()

Purpose: Sends an instruction to the PLC and waits for a response. This is your direct line to the PLC, like making a call and eagerly waiting for the answer.

Details: Uses the Build_Ethernet_instruction function to construct the payload, sends it to the PLC, and then waits for and processes the response.

Referece : [Explore Phase 4 🔍]

6. Function to send Program routine packet : program_register()

Purpose: Programs the PLC by sending a series of instructions to change CPU modes, execute commands, and more. It’s like performing a detailed operation—one step at a time—to ensure everything is set up correctly.

Details: Sends a sequence of commands to the PLC to prepare it for accepting forced writes. This includes changing CPU modes, executing commands, and applying port configurations.

After Sending above 7 CIP-PCCC packet to PLC, Our PLC is ready to accept Force Write to ANy register address.

Reference: program routine section [Explore Phase 4 🔍] .

7. Setting Up the Connection

  • PLC: Stores the IP address 192.168.0.102.
  • PORT: Typically Port 44818 for EtherNet/IP ML1400 PLC communication.
  • socket.socket: Creates an IPv4 socket object for connecting to the PLC.
  • sock.connect(): Establishes a connection to the PLC using the specified IP address and port.

8. Crafting a Malicious Payload: Forcing Analog inputs

Alright, folks, buckle up! We’re about to take a detour from the official playbook.

The standard protocol says, “Stick to the approved function codes and file types, or face the wrath of unpredictable results.” But where’s the fun in that?

We’re about to break the rules a bit. While the official guide would have us use safe, predictable codes, we’re throwing caution to the wind with some unconventional choices:

Function Code 0xAB for a three-field write

File Type 0xA1 for output operations

File Type 0xA2 for input operations

File Type 0x07 for Integer Operation

[Explore Phase 4 🔍] : Important Findings: section

Why stick to the mundane when we can spice things up? Following the official guidelines might get us a nice, neat, predictable operation—but that’s not what we’re here for.

We’re diving headfirst into exploit development, and that means shaking things up and seeing what magic (or black magic) we can create. Get ready for a wild ride!

If you’re scratching your head wondering why we’re using these codes, just take a peek at Phase 4 for the backstory. Trust me, it’ll all make sense!

Element Number: This is also known as the Register Number. It specifies the register’s position and is represented as a (1 bytes). The value of this element indicates the specific register:

  • x00 corresponds to I:0.0 or O:0.0 or N7:0
  • x01 corresponds to I:0.1 or O:0.1 or N7:1 and so on.

Sub-Element: Determines the offset from the base address in the register. It specifies how many bytes to skip before selecting the specific bit or part of the register.

  • 1st Address Field: Selects the bit number within the register. For example, [ff ff] selects the entire register for the Element Number (e.g., I:0.0).
  • 2nd Address Field: Makes the bit position editable. For example, [ff ff] make entire reg. editable.
  • 3rd Address Field: Specifies the data to be written at the selected bit position. For example, [ff ff] edit the entire register with (1111 1111 1111 1111) // Force ON
write with 3 address field

This is the reason it called a “logical write” with a 3-address field, ensuring data is written precisely to the desired bit location.

That’s Why we are using same data 3-time

We have changed PLC CPU mode REM PROG -> REM RUN before closing existing Register session by sock.close(). [Explore Phase 5 🔍]

Finally, we construct and send a malicious payload to force a Analog input. This is the moment of truth where our exploit comes to life!

Python POC for Malicious Payloads: Analog input Forcing on PLCs

POC Demo: Hacking PLCs with Python

Ever wondered what happens when you mix Python with a PLC? No, it’s not a new programming language, but rather a gateway to some serious digital mischief! In this demo, we’ll show you how to use Python to craft a malicious payload that forces a PLC’s Analog input. Think of it as a hacker’s version of a magician’s trick – except instead of pulling rabbits out of hats

PLC Analog Input force

As shown in video, we are able to change the motor speed by forcing frequency of VSD.

Conclusion

And there you have it! Our Python script has successfully forced an Analog input on the PLC. This phase not only showcases the effectiveness of scripting in cybersecurity but also provides a hands-on example of exploiting PLC vulnerabilities.

Stay tuned for more adventures in PLC hacking. Next, we’ll delve into additional features and fine-tune our exploits. Until then, happy hacking!

<—Prev

Exploit # 2: Digital output Forcing

Next —->

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top