-
Notifications
You must be signed in to change notification settings - Fork 1
Shared Libraries
Most binaries use shared libraries rather than static libraries: what this means is that the library is linked-in at load-time rather than at compile-time. ("Dynamic-linking vs. static linking").
You can detect dynamic linking using the file
command:
[~]> file <binary>
<binary>: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=da6b1da4bbc22b3072aef80a990e75f9df778498, not stripped
This binary is statically linked.
[~]> file <binary>
<binary>: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=15638c51c0168f90b778e3ae1dee8e553bcf769b, not stripped
while this one is dynamically linked.
Use the ldd
command:
[~]> ldd binary
linux-gate.so.1 => (0xf7767000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7568000)
/lib/ld-linux.so.2 (0xf7740000)
In most cases we're interested in the one that is called libc
(libc.so.6
in this case).
The libc
on your computer is gonna be very different from the libc on my computer. So, if there's a CTF challenge where the binary is running on some remote machine, you need to craft your artisanal ROP-chain using the libc
on the remote machine, not your machine. In these cases, the organizers will provide libc
along with the vulnerable binary itself. (If they don't, that's a strong indication that the solution involves shellcode, and not ROP). To run the binary with this custom libc, you might need to patch your executable to use the correct dynamic linker (you can use change-ld.py to do this along with the corresponding ld file in glibc_versions). After patching, you can use LD_PRELOAD
to specify the libc file:
LD_PRELOAD=/path/to/my/malloc.so /bin/ls
To debug the binary in gdb with a specified library, you can do:
gdb> set exec-wrapper env 'LD_PRELOAD=/path/to/sobject/yourobject.so'
gdb> file /path/to/binary/yourbin
gdb> r
The exec-wrapper
ensures that the linked library is used only for the binary in question, and not bash or gdb itself.
Simply use ROPGadget as you'd do normally:
ROPGadget --binary /lib/i386-linux-gnu/libc.so.6 > rop_gadgets
If we leaked libc address of certain function successfully, we could use get libc base address by subtracting the offset of that function.
readelf -s $libc | grep ${function}@
E.g.
$ readelf -s libc-2.19.so | grep system@
620: 00040310 56 FUNC GLOBAL DEFAULT 12 __libc_system@@GLIBC_PRIVATE
1443: 00040310 56 FUNC WEAK DEFAULT 12 system@@GLIBC_2.0
- Use pwntools, then you can use it in your exploit script.
E.g.
from pwn import *
libc = ELF('libc.so')
system_off = libc.symbols['system']
Once you know libc's base address, you can set it in pwntools and then reference specific symbols:
elf = ELF('./my_binary')
libc = elf.libc
libc.address = printf_addr - libc.symbols.printf
system_addr = libc.symbols.system
Need libc base address first
-
objdump -s libc.so | less
then search 'sh' strings -tx libc.so | grep /bin/sh
- Use pwntools
E.g.
from pwn import *
libc = ELF('libc.so')
...
sh = base + next(libc.search('sh\x00'))
binsh = base + next(libc.search('/bin/sh\x00'))
Alternatives: libcdb.com, https://github.com/niklasb/libc-database