Junior Hacking Talent - Kid Protocol Writeup
Looking at the source code, we can see the basic processing of each packet
class KidPacket:
def __init__(self, rawPacket):
self.parse(rawPacket)
def parse(self, rawPacket):
self.contentLength = struct.unpack("<H", rawPacket[0:2])[0]
data = rawPacket[2:]
if self.contentLength != len(data):
raise Exception("Bad content-length")
try:
self.body = json.loads(data)
except:
raise Exception("Bad format")
def getValue(object, key):
try:
return object[key]
except KeyError:
raise Exception("Missing '%s' param" % key)
kidPacket = KidPacket(rawPacket)
action = getValue(kidPacket.body, "action")
inputFile = getValue(kidPacket.body, "file")
From this, we can figure out the format for each packet: they all starts with 2
bytes containing the length of the data packed as an unsigned short in
little-endian format (<H
). The rest of the packet is just JSON data which is
decoded and it’s action
and file
key is read.
The function below decides whether we get to read the flag or not according to the JSON data inside the packet body.
fileList = ["intro.txt", "flag.txt"]
def handle(self, rawPacket):
try:
kidPacket = KidPacket(rawPacket)
action = getValue(kidPacket.body, "action")
inputFile = getValue(kidPacket.body, "file")
if action == "read":
if inputFile in fileList:
file = inputFile
else:
file = "intro.txt"
with open(file, "r") as f:
return f.read()
return "Wrong action"
except Exception as e:
return str(e)
Therefore, what we should have inside the body in JSON is:
{"action":"read", "file":"flag.txt"}
Once we have both the data and the format of the packet, creating and sending one should be trivial.
import socket
import struct
import json
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
s.connect(("167.71.204.85", 3108))
def parse(body):
data = json.dumps(body).encode()
length = len(data)
content_length = struct.pack("<H", length)
return content_length + data
body = {"action": "read", "file": "flag.txt"}
packet = parse(body)
s.send(packet)
print(s.recvfrom(4096))
This script should, in theory, send an UDP packet to the server that will give us the flag.
❯ python solve.py
(b' _______ __ __ .__ \n \\
\\ _____/ |___ _ _____________| | _|__| ____ ____ \n / | \\_/ __ \
\ __\\ \\/ \\/ / _ \\_ __ \\ |/ / |/ \\ / ___\\ \n/ | \\ ___/|
| \\ ( <_> ) | \\/ <| | | \\/ /_/ >\n\\____|__ /\\___ >__| \\
/\\_/ \\____/|__| |__|_ \\__|___| /\\___ / \n \\/ \\/
\\/ \\//_____/ \n ___________.__
\n \\_ _____/| | _____ ____ \n
| __) | | \\__ \\ / ___\\ \n | \\
| |__/ __ \\_/ /_/ > \n \\___ / |____(___
_ /\\___ / \n \\/ \\//____
_/ \n
\n\nCTF{master_networking_fcbfce971dae5a7271deb6ffbc972b16}\n', ('167.71.204.85'
, 3108))