This was an off-by-one vulnerability within the if comparison:
If strlen returns a result greater than 512, the script exits with ‘Nice Try.’, else text is copied into buff with no further checks.
In most cases this is fine- input upto 512 bytes and beyond will return the expected results- but supplying a total of 512 bytes exactly results in both an EBP and EIP overwrite.
So, why is this? Well, strlen doesn’t include the terminating null character when counting the amount of bytes in a given variable, meaning input of 513 bytes is counted as holding only 512 bytes by strlen.
Thus, input of 512 bytes will both return false in the above statement and overflow the variable buff with one byte (the terminating null character.)
Like 0x00, I approached the challenge very differently to the given hint (but maybe not incorrectly this time.)
Below is the hint compared to my exploit (I never look at hints prior to the challenge as I feel you learn more from discovering it yourself.)
I started off by triggering the segfault with 512 bytes- sure enough, the segfault was triggered and EIP was already overwritten with our input...But this isn’t a simple buffer overflow- any input beyond 512 bytes will simply cause the statement to return true and exit, discarding our input rather than copying it into strcpy.
But as I said- I’d already triggered an EIP overwrite. With this in mind, I fuzzed the application a little further, going back 4 bytes until I’d identified the offsets of EBP and EIP.
Once I’d identified these offsets, I opted with a method similar to the one I used in 0x00- store your shellcode in the buffer itself and jump to it on the stack.
The above method worked well for me- a payload consisting of my shellcode (a 100 byte NOP sled followed by a 28 byte execve /bin/sh system call and a further 400 bytes consisting of an address within the NOP sled off my shellcode), followed by ebp (the address of exit- when our payload has finished execution the leave instruction will execute, popping EBP to the top of the stack; this is not neccessary and EBP can be anything), EIP (an address within our NOP sled) and a further 4 bytes of whatever (in my case, exit out of laziness!)
However, the exploit is not successful without the 100 addresses at the end of the shellcode- this suggests that the EIP overwrite was not where my calculations had shown or perhaps the address I was jumping to was simply a little further down the stack than I thought, though I’m unsure when testing in GDB showed otherwise...
I’ve since looked at other solutions to the challenge, and the EIP overwrite actually occurred at offset 440, thus why my exploit worked.
All in all, I’m content with my exploit: while I didn’t calculate the correct offset of EIP correctly, I did think to resolve an issue with an incorrect address by simply putting references to an address in my NOP sled within the buffer.
The reason I never doubted my EIP offset is 1) due to the GDB results when testing initially and 2) my initial idea worked perfectly within GDB within the first hour or two of looking at it (though not out of it-it just segfaulted out of it, thus why I had to change it around.)
I also learned the importance of keeping the environment the same inside and outside of the debugger: doing this would have saved me a good few hours.
But yeah, I got a shell so yay? :’)