Skip to content
Rahul Sridhar edited this page Oct 21, 2017 · 7 revisions

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").

Detecting dynamic 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.

Identifying shared library paths

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).

Running a binary with a custom shared library (aka the LD_PRELOAD trick)

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, use the LD_PRELOAD trick:

LD_PRELOAD=/path/to/my/malloc.so /bin/ls

Finding ROP gadgets in shared libraries

Simply use ROPGadget as you'd do normally:

ROPGadget --binary /lib/i386-linux-gnu/libc.so.6 > rop_gadgets

Find specific function offset in libc

If we leaked libc address of certain function successfully, we could use get libc base address by subtracting the offset of that function.

Manually

  • 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

Automatically

  • 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']

Find '/bin/sh' or 'sh' in library

Need libc base address first

Manually

  • objdump -s libc.so | less then search 'sh'
  • strings -tx libc.so | grep /bin/sh

Automatically

E.g.

from pwn import *

libc = ELF('libc.so')
...
sh = base + next(libc.search('sh\x00'))
binsh = base + next(libc.search('/bin/sh\x00'))
Clone this wiki locally