Hey guys, welcome back on Exploitnetoworking! Today we will see the writeup of the binary exploitation challenge Jendy’s by UTCTF. This challenge is an hard pwn binary, that for exploit it, you must use two technics, the first step is manage the heap for obtain an arbitrary free and the second step is use a format string for obtain a write what where. In this github repository you can find the challenge and the exploit.py for test it.
In the binary there are 5 different options:
With the first option it’s possible insert in heap a chunk of dimension 48 byte with a name chosen by us. The second option permit us to add an item in heap, we can’t chose the content of this chunk. With the third option it’s possible obtain a free of a chunk. With four option it is possible see the content of some chunk in heap and with the last option the process end.
The first step is see how the chunks are positioned in memory, for this purpose we can add a name and add some items, below there is a layout after some add:
We have write a name with the first option and we can see it on address 0x603040, after that we have add 5 different items and we can see these from 0x603070 to 0x603130. How we can see the items are added in a linked list, because at the end of any chunks there is an address, this address is a pointer to the next chunk in the linked list, for example the first chunk 0x603070 point to 0x6030a0, that it point to 0x6030d0 and so on. The pointer of the linked list is saved on the first chunk at 0x603010, in this chunk is also saved the pointer to the last chunk 0x603130 and the pointer to our name 0x603040.
After more investigation I have see that there isn’t any overflow, but there is only an error, if we delete an item, the data of this item remain in memory included the address of the next element in the linked list, and the previous address unchanged if we delete the last item on the linked list! What happened if I insert a new name after delete the last item? For test it I have delete the chunk on address 0x603130 and add a new name, below there is the result:
how we can see our name at address 0x603130 is pointed by the item on address 0x603100, in other word our name is entered in linked list 🙂 . Now, the next step is obtain an arbitrary free (because the free is done on the address to the next element in the linked list, then we can insert a crafted address to our fake element).
For this purpose we must first get a leak of an heap address for bypass the asrl, and this can be obtained using the 4 option of the program “View order”. If we look the item at address 0x603100 we can see that the string end before the address of the next element in the linked list, if we print this item, the address will also be printed how can see below:
“01`” is the value of the address 0x603130! Ok now we can insert an address in our linked list using the “new name” feature and remove it!
My main idea was been insert the address of the data structure with the pointer to linked list 0x603000 and remove it, after that insert a new name with a crafted address that will replace the content at address 0x603000. We can see the result below (note that the next layout is different to previous memory layout, this is because I have modify the execution adding more name and some items for obtain a correct leak to heap):
Now the pointer to the linked list is 0x603160 and not at 0x6030a0! (Note that in this execution the linked list started to 0x6030a0). Now we have a new pointer to a new linked list, below there is the new linked list in memory:
Ok, now let’s look again the structure at 0x603010, where there are the pointer to linked list, and a pointer to name. The pointer to our name is 0x602030, but this is not an address of the heap but is an address of the GOT table, its purpose is the leak of the libc for bypass the asrl (in particular this address is a pointer to puts function). Now using the functionality “view order” we can get an address of the libc and calculate the libc base and the address of a one gadget.
Now, the next step is obtain the write what where. For obtain that, I have reversed the binary with Hopper (I love it <3) and I have see this:
in particular I have see this instruction: printf(var_38), in other words: format string! And is obtained using view order, then the next step is construct our format string. My idea was been write a one gadget in GOT table using the format string and obtain a RCE. For this purpose I have examined the stack for see how manipulate it for obtain a write what where. For examine it I have insert a break point to printf in gdb and print the content of the stack:
how we can see there aren’t any address to GOT :(, but there are some pointer to the stack such as at 0x7fffffffdd10 where there is 0x00007fffffffdd50, we can use this value for write an address of the GOT in 0x00007fffffffdd50, and then use it for overwrite an address in GOT (note that I have used two different write, because I wrote two byte at a time). After examine the GOT table I have chosen the address of scanf, and write on it the address of the one gadget :). Now I have insert all this concept in a script and exploit it:
And then get the flag: