fr33f0r4ll

自分用雑記

リンクされる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で問題なくベースアドレスが取得できた。