Pretty easy challenge to get started with, but was asked to post a writeup for this, so here we go…
From the menu, one could assume this would be some heap challenge with UAF or something similar. But no heap involved at all for solving this.
Let’s check the function for showing a name:
It only checks the upper boundaries but fails on checking for negative indices.
So let’s take a look at the surrounding memory of the names array:
When a name is added, it would be created on the heap, and the address for the string would be stored in the names array.
The show_name function would dereference the address and show the string at the corresponding location on the heap.
So to be able to do some proper leaking, we need a pointer to an interesting address. We’d want to read one of the got entries to calculate the libc base address.
We could create one in our username and try to show its content, but since the username is stored behind the names array, we’d need a positive index, don’t we?
Nope, we can just abuse the fact, that in 32bit subtraction an address will wrap around from 0x0 to 0xffffffff. So we can just specify such a big negative index, that when subtracted from 0x804b0a0 goes below 0x0 wrapping to 0xffffffff arriving at 0x804b0e0 again (the address of our username).
If we now specify -1073741808 as the index for our buffer, the show_function will read the pointer from 0x804b0e0 and shows the content at this address, so let’s just point this to read got.
With libc address at hand, we can use the same bug in edit_name
We already prepared a pointer to atoi directly after the read pointer in username, and thus can use this one to overwrite the atoi got entry:
Since the menu handler always calls atoi on our input to convert it into a number, we now just have to select /bin/sh to trigger a shell (which will basically call system("/bin/sh")))