I recently wrote a post about 32 bit ret2dlresolve in one of my interesting ROP technique articles. However, I left out some significant details... after making a challenge about it, here is more information about this insanely cool technique. Make sure to read that post beforehand for a basic understanding of this leakless technique.
First of all, you will need to find a space to write these fake structures so you can pass malicious indices to __dl_runtime_resolve. You can choose to write it anywhere (since the binary probably has an overflow, you can easily construct a rop chain to write stuff anywhere): BSS, stack, heap, etc.
Then, you will need to find a few important addresses (if your binary has PIE, then you will need to find a way to leak PIE base first). Link map is pushed and then dl resolve is called, which is usually right under the .plt section as displayed in objdump, with a pushl and then a jmp instruction. JMPREL is .rel.plt, SYMTAB is .dynsym, STRTAB is .dynstr.
I usually like to create one big area with all the fake structures, but separating them is also fine.
Here's what the set up should look like:
For the fake Elf32_Rel structure, you should first provide an address of where the retrieved function should be written (same location is fine). You must be very careful about the next four bytes. I usually use the following formula:
0x7 | ((locationOfFakeSymtab - symtab) / 16) << 8Why this formula? For our attack to work, the lower 8 bits must be 0x7 (R_386_JMP_SLOT). The high 24 bits helps the binary find the location of the fake symtab. Then, I do an extra 4 bytes for alighment afterwards.
Now, for our fake Elf32_Sym structure. First four bytes should contain offset between the string you want the binary to resolve and STRTAB. Then, it's just padding for the next 12 bytes because of how SYMTAB accesses it.
Also remember to keep a handy system and /bin/sh string around.
After placing these items in memory, now it's time for the actual pwning!
Construct another rop chain, but this time make it call the pushl and jmp instruction part first (to start the resolver). Place the offset between the fake Elf32_Rel structure and the JMPREL address afterwards. Then, pad with 4 bytes for a return address (really doesn't matter at this point) and then point it to the location of the bin sh string because of 32 bit calling conventions. A shell should be popped and the binary will be pwned!