Protocol Analysis 1: Can You Hear Me?
Protocol Analysis 1: Can You Hear Me?
Platform: Metactf | Category: Misc | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-04-10 | Status: Solved Techniques: plaintext_message_forwarding, protocol_relay, unauthenticated_protocol_abuse
Summary
Task: a protocol manual describes a simple Alice/Bob exchange where Alice asks Bob for the flag and both sides receive exact plaintext messages. Solution: create a session, relay Alice's first message to Bob unchanged, and read the returned flag because the protocol has no authentication or confidentiality.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
metactf| ID:20260410_metactf_protocol_analysis_1_can_you_hear_me - Tags: relay, protocol_analysis, plaintext_protocol, alice_and_bob, unauthenticated_protocol
- Indicators: the protocol transcript is fully plaintext, Alice and Bob are expected to receive the exact same message, no authentication, integrity, or encryption step appears in the message flow
- Source:
20260410_metactf_protocol_analysis_1_can_you_hear_me.md
Foothold
Vulnerability / Misconfiguration
- Plaintext_message_forwarding
- Protocol_relay
- Unauthenticated_protocol_abuse
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- plaintext_message_forwarding
- protocol_relay
- unauthenticated_protocol_abuse
- Tags: relay, protocol_analysis, plaintext_protocol, alice_and_bob, unauthenticated_protocol
Original Writeup
<details><summary>Click to expand original content</summary>Description
Alice sends: "Hello", B, "this is", A, "give me the flag" Bob receives the exact same message Bob sends: "here it is", [FLAG] Alice receives the exact same message
English summary: the challenge provides a simple scripted protocol and a live service. The protocol is completely plaintext and unauthenticated, so the attacker can just relay Alice's request to Bob and read the flag from Bob's reply.
Analysis
The PDF manual for challenge 1 already gives away the core weakness: there is no cryptography, no authentication, and no message integrity. The only required behavior is that Bob receives the exact message Alice sent, and Alice then receives Bob's exact response.
After creating a protocol instance on https://protocols.live/model/1, sending an empty message to Alice returns her first scripted payload:
t:Hello|n:bob|t:this is|n:alice|t:give me the flag
This format is still plaintext; it is just tokenized. Since the service lets us relay arbitrary content between the endpoints, we do not need to break anything. We only need to forward Alice's message to Bob unchanged.
Bob then responds with the flag in the same plaintext format:
t:here it is|t:DawgCTF{REDACTED}
So the vulnerability is a trivial relay attack against an unauthenticated plaintext protocol.
Solution
- Open
https://protocols.live/model/1and create a new protocol instance. - Record the returned
conn_id. - Send an empty
contentvalue to the/aliceendpoint to retrieve Alice's scripted first message. - Copy that exact response body and submit it to the
/bobendpoint. - Read Bob's reply; it directly contains the flag.
Example interaction:
Alice -> t:Hello|n:bob|t:this is|n:alice|t:give me the flag
Bob -> t:here it is|t:DawgCTF{REDACTED}
#!/usr/bin/env python3
import requests
BASE = "https://protocols.live"
def main():
session = requests.Session()
# Create a fresh instance from model 1.
create = session.post(f"{BASE}/model/1")
create.raise_for_status()
data = create.json()
conn_id = data["conn_id"]
# Ask Alice for her first scripted message.
alice = session.post(
f"{BASE}/alice",
json={"conn_id": conn_id, "content": ""},
)
alice.raise_for_status()
alice_msg = alice.json()["content"]
print(f"Alice says: {alice_msg}")
# Relay Alice's exact plaintext to Bob.
bob = session.post(
f"{BASE}/bob",
json={"conn_id": conn_id, "content": alice_msg},
)
bob.raise_for_status()
bob_msg = bob.json()["content"]
print(f"Bob says: {bob_msg}")
if __name__ == "__main__":
main()
The output includes the flag:
t:here it is|t:DawgCTF{REDACTED}
</details>
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR