🚩
Practical CTF
BlogContact
  • 🚩Home - Practical CTF
  • 🌐Web
    • Enumeration
      • Finding Hosts & Domains
      • Masscan
      • Nmap
      • OSINT
    • Client-Side
      • Cross-Site Scripting (XSS)
        • HTML Injection
        • Content-Security-Policy (CSP)
      • CSS Injection
      • Cross-Site Request Forgery (CSRF)
      • XS-Leaks
      • Window Popup Tricks
      • Header / CRLF Injection
      • WebSockets
      • Caching
    • Server-Side
      • SQL Injection
      • NoSQL Injection
      • GraphQL
      • XML External Entities (XXE)
      • HTTP Request Smuggling
      • Local File Disclosure
      • Arbitrary File Write
      • Reverse Proxies
    • Frameworks
      • Flask
      • Ruby on Rails
      • NodeJS
      • Bun
      • WordPress
      • Angular
    • Chrome Remote DevTools
    • ImageMagick
  • 🔣Cryptography
    • Encodings
    • Ciphers
    • Custom Ciphers
      • Z3 Solver
    • XOR
    • Asymmetric Encryption
      • RSA
      • Diffie-Hellman
      • PGP / GPG
    • AES
    • Hashing
      • Cracking Hashes
      • Cracking Signatures
    • Pseudo-Random Number Generators (PRNG)
    • Timing Attacks
    • Blockchain
      • Smart Contracts
      • Bitcoin addresses
  • 🔎Forensics
    • Wireshark
    • File Formats
    • Archives
    • Memory Dumps (Volatility)
    • VBA Macros
    • Grep
    • Git
    • File Recovery
  • ⚙️Reverse Engineering
    • Ghidra
    • Angr Solver
    • Reversing C# - .NET / Unity
    • PowerShell
  • 📟Binary Exploitation
    • ir0nstone's Binary Exploitation Notes
    • Reverse Engineering for Pwn
    • PwnTools
    • ret2win
    • ret2libc
    • Shellcode
    • Stack Canaries
    • Return-Oriented Programming (ROP)
      • SigReturn-Oriented Programming (SROP)
      • ret2dlresolve
    • Sandboxes (chroot, seccomp & namespaces)
    • Race Conditions
  • 📲Mobile
    • Setup
    • Reversing APKs
    • Patching APKs
    • HTTP(S) Proxy for Android
    • Android Backup
    • Compiling C for Android
    • iOS
  • 🌎Languages
    • PHP
    • Python
    • JavaScript
      • Prototype Pollution
      • postMessage Exploitation
    • Java
    • C#
    • Assembly
    • Markdown
    • LaTeX
    • JSON
    • YAML
    • CodeQL
    • NASL (Nessus Plugins)
    • Regular Expressions (RegEx)
  • 🤖Networking
    • Modbus - TCP/502
    • Redis/Valkey - TCP/6379
  • 🐧Linux
    • Shells
    • Bash
    • Linux Privilege Escalation
      • Enumeration
      • Networking
      • Command Triggers
      • Command Exploitation
      • Outdated Versions
      • Network File Sharing (NFS)
      • Docker
      • Filesystem Permissions
    • Analyzing Processes
  • 🪟Windows
    • The Hacker Recipes - AD
    • Scanning/Spraying
    • Exploitation
    • Local Enumeration
    • Local Privilege Escalation
    • Windows Authentication
      • Kerberos
      • NTLM
    • Lateral Movement
    • Active Directory Privilege Escalation
    • Persistence
    • Antivirus Evasion
    • Metasploit
    • Alternate Data Streams (ADS)
  • ☁️Cloud
    • Kubernetes
    • Microsoft Azure
  • ❔Other
    • Business Logic Errors
    • Password Managers
    • ANSI Escape Codes
    • WSL Tips
Powered by GitBook
On this page
  • Description
  • Interaction
  1. Networking

Modbus - TCP/502

A protocol for PLCs to store values in coils, inputs, and registers at addresses

PreviousRegular Expressions (RegEx)NextRedis/Valkey - TCP/6379

Last updated 1 year ago

Description

Modbus is a communication protocol commonly used in Programmable Logic Controllers (PLCs). There are a few different versions, but the most common are Modbus RTU and TCP:

  • Modbus RTU (Remote Terminal Unit): Used in slow serial communication, and makes use of a compact, binary representation of the data for protocol communication

  • Modbus ASCII: Similar to RTU, but only using printable ASCII characters for protocol communication, meaning it is less efficient

  • Modbus RTU/IP: A variant of Modbus TCP that differs in that a checksum is included in the payload, as with Modbus RTU

You can see a Modbus server as a small piece of memory, being able to store values at addresses in different sizes. The client asks the server for values or tells it to write a value somewhere. The following table shows all the different types of values:

Type
Access
Size
Addresses

Coil

Read-write

1 bit (0-1)

00001 – 09999

Discrete input

Read-only

1 bit (0-1)

10001 – 19999

Input register

Read-only

16 bits (0-65535)

30001 – 39999

Holding register

Read-write

16 bits (0-65535)

40001 – 49999

These coils, inputs, and registers can all have arbitrary meanings, like configuration values, status outputs, or ASCII-encoded strings. The addresses are pretty limited, so it is generally useful to dump all the data and then guess what it means locally, and possibly by testing the effects of changing values.

Interaction

Using a tool like modbus-cli you can interact with a modbus server easily from the CLI:

$ modbus read 10.10.10.10 400001 5
1
1
1
1
1
...
111
119
95
101
110
97
98
108
101
100
58
102
97
108
115
101
17
17
17
...
$ modbus write 10.10.10.10 400020 116 114 117 101 17

This was the solution to the challenge, because when the server now reads the Modbus data it finds our altered "ow_enabled:true" string instead.

Using the tool above you can even write special data types like signed integers or floating point numbers by providing a --int or --float parameter:

Type
Size
Formatted Address
Address
Parameter

word (default, unsigned)

16 bits

%MW100

400101

--word

integer (signed)

16 bits

%MW100

400101

--int

floating point

32 bits

%MF100

400101

--float

double word

32 bits

%MD100

400101

--dword

boolean (coils)

1 bit

%M100

101

N/A

Modbus TCP: Used on a network, over TCP port 502. When hacking remotely this is by far the most common. See for analyzing Wireshark captures of this data

is a good reference as an example of reading data, understanding it, and then changing it using the tool above. First, we try reading from the different registers, which we can even do in bulk for large ranges at a time. Be careful with this however because if your requested range falls out of the range the server holds it will give an InvalidAddress error message. Here we try reading the first 5 values from the Holding registers:

Do dump the entire space, simply keep increasing this amount until you get an error. From here it is a matter of understanding what the data means. The NahamConCTF 2023 - challenge for example contained the following values:

These values are all in the 50-60 and 90-110 range which is likely an ASCII string padded with 17s. We can decode it using to "ow_enabled:false". We could try to change this false to true to see what happens, and then write it back to the Modbus server at the correct offset ():

🤖
This writeup
Where's my Water
CyberChef
CyberChef
ModbusWikipedia
Detailed description of the modbus protocol
GitHub - tallakt/modbus-cli: Modbus command line utilityGitHub
Modbus command line utility for reading, writing, and dumping
Logo
Logo
Modbus