リンクされるlibcのメモ
pwnしてるときに知ったので簡単にメモ。
プログラムにlibc.so.6がリンクされるとき、ASLRによってランダム化されるのは7バイト分で、下3バイトは000で固定、上6バイトは0x00007fで固定になる。
リンクされたときのlibcのベースアドレスはldd
コマンドで知ることができる。
何回か実行するとベースアドレスがランダム化されているのが分かる。
追記
lddはどうも正しい値を返さないらしい。
この記事によると環境変数LD_TRACE_LOADED_OBJECTS
によって結果が変わる。
ASLRをオフにして実験してみた、実際はfish shellでやったけどbash記法で書く。
$ LD_TRACE_LOADED_OBJECTS=1 ldd some_program linux-vdso.so.1 => (0x00007ffff7ffa000) libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007ffff7bae000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffff79aa000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e0000) /lib64/ld-linux-x86-64.so.2 (0x00007ffff7dd7000) $ ldd some_program linux-vdso.so.1 => (0x00007ffff7ffa000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff780a000) /lib64/ld-linux-x86-64.so.2 (0x00007ffff7dd7000)
結果はこんな感じになった。出力されるものが1つ増えているけど、実際にはどの値も間違っていた。 間違っているというか、pwnでret2libcできなかった。
解決策
gdb-pedaを使えば正しい方の値が手に入る。
一度プログラムを実行させてメモリにロードしてからvmmap libc
するとロードされたlibcの位置が分かる、一番最初のアドレスがベースアドレスになる。
例えば、以下の例の場合だとベースアドレスは0x7ffff7a0d000になる。少なくともret2libcはできるベースアドレスだった。
$ vmmap libc Start End Perm Name 0x00007ffff7a0d000 0x00007ffff7bcd000 r-xp /lib/x86_64-linux-gnu/libc-2.23.so 0x00007ffff7bcd000 0x00007ffff7dcd000 ---p /lib/x86_64-linux-gnu/libc-2.23.so 0x00007ffff7dcd000 0x00007ffff7dd1000 r--p /lib/x86_64-linux-gnu/libc-2.23.so 0x00007ffff7dd1000 0x00007ffff7dd3000 rw-p /lib/x86_64-linux-gnu/libc-2.23.so
ちなみにASLRが有効でもgdb環境下ではオフにされるので注意。
今度もっと詳しく調べてみよう。
追記その2
32bitのバイナリとlibcならlddで問題なくベースアドレスが取得できた。