Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

No Leak, No Problem - Bypassing ASLR with a ROP Chain to Gain RCE- 1798

Michael Imfeld - Mod ZeroPosted 3 Months Ago
  • The author of this post found a really straight forward buffer overflow in the authentication API of an IP camera that could overwrite the return address on the stack. The application had NX enabled and ASLR but had no canaries, no PIE and partial RELRO. Given that they couldn't find a libc leak for a simple RET2Win attack, they needed to do this without an information disclosure. They did have the ability to call arbitrary code in the binary via ROP chains though!
  • The technique they end up using is interesting: use the Global Offset Table (GOT) and Procedure Linkage Table (PLT) to bypass ASLR. The idea is to use the code in the PLT to jump to incorrect functions using relative offsets. At a high level, this can work by reading a GOT entry into a register, increment/decrement the register until it's at the proper value and then jump to the register. An additional path is incrementing the GOT pointer itself.
  • After some effort, they found the function isalnum from libc that could take in user controlled input and was already loaded in the GOT. The difference between this function and system() is only 0x13230. So, the goal was to add this much to the address in the GOT entry to trigger code execution. While hunting for quick/easy gadgets, they didn't find any. All of them had side effects that made it infeasible.
  • After searching for gadgets for a while, they found a string of gadgets that could perform what they needed to do. Notably, the gadgets sometimes needed to call other gadgets, which made this even harder to do. The list of gadgets was as follows:
    1. Dereference isalnum@got and store the results in r6. The gadget wasn't perfect but did the job before jumping into the value in r3 for the next gadget.
    2. Use the next gadget to add the offset to system back into the GOT entry stored in r6. This jumps to the value stored in r3 for the next gadget in the chain.
    3. The final gadget writes r6 back to the GOT entry that we originally read. This is because they couldn't find a way to jump to r6.
    4. Prepare function arguments for system(). Then, trigger the overwritten GOT entry for code execution.
  • At the end of the post, they point out that this was a 32-bit binary and the offsets could have just been brute forced. In fact, their original exploit did exactly this. The creation of the exact chain required some difficult maneuvering of values in order to not have bad side effects. Overall, a great post on the end to end of exploiting the device!