oneshot was a rather small binary with a simple oob-bug when reading an array.
So, first there’s an obvious oob write possible, since the index is not checked for any upper or lower limits, so we could write after the allocated chunk on the heap, but since we have only one allocation and one write, that alone wouldn’t lead us anywhere.
More important, if we define a size of -1calloc will return a null pointer. Together with the unchecked index access, this gives us a write-anywhere primitive, since chunk[i] is pretty much *(chunk + (i*4)).
To do something useful, it would be nice, if we can have multiple writes. To get started, we can use this to overwrite puts.got to point back into main.
Now that we can do unlimited writes, it’s time to get some leaks. We don’t know the address of libc yet and with the size check
we’re only able to allocate chunks on the heap. But we can eliminate this check by overwriting exit.got with something less annoying.
Pointing exit.got to setup worked out pretty well. The binary will still check the size, but continue execution afterwards and happily allocate a chunk with arbitrary size for us.
Being able to allocate huge chunks now, let’s just do exactly that.
This chunk will be placed in a memory region directly before the first libc region
Now, we can abuse the oob-index-access to overwrite things in libc :)
Since we’re still in need of leaks, stdout is a good target, so we just have to calculate the relative position from our allocated chunk to stdouts _IO_write_ptr.
The memory region for the chunk was somewhat off remote, so I needed some correction for this, but
gave us all the libc leaks we needed to calculate libc base.
The only call in the binary, for which we control the first parameter is calloc, so we can now again use a NULL chunk to overwrite calloc.got with system and call system("/bin/sh").
Since size is an int, we cannot reference /bin/sh from libc, but we can get easily around this, by just writing /bin/sh into bss first and then use that instead.
Now, all there’s left to do is to allocate a chunk with size 0x601050 and grab another flag.