Bypassing ASLR: overwriting the .dynamic section

I was recently confronted with a software exploit challenge on a CTF website that took me much more time to flag that I would have expected at first. The solution was closed to another one I knew but which was not working. I will provide a quick write-up of this method because I still cannot find any mention of it in any paper online, despite its simplicity. I hope it will help someone save some precious brain cycles.

Source code

I do not want to spoil that website’s challenge so I will present a different source code:

We are obviously facing a format string vulnerability and what we want to do is calling the flag function.
We could overwrite the saved return value in the main function’s stack frame. As ASLR is on, we are only allowed a single write with something like (N being the relevant offset to reach saved EIP):

I mean that we cannot use the well-known method of %hhn (or %hn) to write the 4-bytes-long address of flag one after another. And the address is as always a way too high hexadecimal value so we cannot write it in one go. But anyway, that is not an issue here since we only need to overwrite the two least significant bytes due to address proximity between code segment’s objects. This is too easy but it works.

Another classic way of dealing with this kind of challenge is rewriting the .dtors ELF section (see here if you don’t know about it). But for a reason I still ignore, that was not working on that platform.

Solution: the .dynamic ELF section

When I asked about that on IRC, someone told me that whatever the problem was with .dtors, there was another ELF section that was working for him. So I kept looking for writable ELF sections in that binary and tried to overwrite them.

Overwriting the GOT is another classic trick but this is not useful in our case since no library function is called after the vulnerable call to printf. The only interesting section remaining is .dynamic. This section holds dynamic linking information.

If you open GDB and try to find out where all those little endian addresses are pointing to, you will find interesting things like the GOT address or, most importantly, the address of the .fini section (0x0804862c) at 0x080496a4. The address of that section is registered in the .dynamic section so that the linker can make the program run code from that section when it exits. That’s all we were asking for. Replace this address by the flag function address using classic %hn format string trick, and you will see a nice You win! on your screen.

As I said at the beginning, this is not much. But that makes an alternative to the .dtors overwriting method when needed.

Leave a Reply

Your email address will not be published. Required fields are marked *