echo
コマンドのオブジェクトファイルと戯れてみる第二弾
第一弾はこちら
unless.hatenablog.jp
共有ライブラリの依存関係
objdump で依存関係を見てみる
ja.wikipedia.org
共有ライブラリが何かという情報はELFの[Dynamic Section]のNEEDEDに記載されている
# objdump -p /bin/echo
/bin/echo: file format elf64-x86-64
Program Header:
PHDR off 0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3
filesz 0x00000000000001f8 memsz 0x00000000000001f8 flags r-x
INTERP off 0x0000000000000238 vaddr 0x0000000000400238 paddr 0x0000000000400238 align 2**0
filesz 0x000000000000001c memsz 0x000000000000001c flags r--
LOAD off 0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
filesz 0x0000000000005ecc memsz 0x0000000000005ecc flags r-x
LOAD off 0x0000000000006da8 vaddr 0x0000000000606da8 paddr 0x0000000000606da8 align 2**21
filesz 0x0000000000000478 memsz 0x00000000000005d8 flags rw-
DYNAMIC off 0x0000000000006e08 vaddr 0x0000000000606e08 paddr 0x0000000000606e08 align 2**3
filesz 0x00000000000001d0 memsz 0x00000000000001d0 flags rw-
NOTE off 0x0000000000000254 vaddr 0x0000000000400254 paddr 0x0000000000400254 align 2**2
filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
EH_FRAME off 0x00000000000051cc vaddr 0x00000000004051cc paddr 0x00000000004051cc align 2**2
filesz 0x000000000000023c memsz 0x000000000000023c flags r--
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
RELRO off 0x0000000000006da8 vaddr 0x0000000000606da8 paddr 0x0000000000606da8 align 2**0
filesz 0x0000000000000258 memsz 0x0000000000000258 flags r--
Dynamic Section:
NEEDED libc.so.6
INIT 0x0000000000401050
FINI 0x000000000040442c
INIT_ARRAY 0x0000000000606da8
INIT_ARRAYSZ 0x0000000000000008
FINI_ARRAY 0x0000000000606db0
FINI_ARRAYSZ 0x0000000000000008
GNU_HASH 0x0000000000400298
STRTAB 0x0000000000400810
SYMTAB 0x00000000004002b8
STRSZ 0x000000000000025d
SYMENT 0x0000000000000018
DEBUG 0x0000000000000000
PLTGOT 0x0000000000607000
PLTRELSZ 0x0000000000000498
PLTREL 0x0000000000000007
JMPREL 0x0000000000400bb8
RELA 0x0000000000400b40
RELASZ 0x0000000000000078
RELAENT 0x0000000000000018
VERNEED 0x0000000000400ae0
VERNEEDNUM 0x0000000000000001
VERSYM 0x0000000000400a6e
Version References:
required from libc.so.6:
0x0d696913 0x00 06 GLIBC_2.3
0x09691974 0x00 05 GLIBC_2.3.4
0x06969194 0x00 04 GLIBC_2.14
0x0d696914 0x00 03 GLIBC_2.4
0x09691a75 0x00 02 GLIBC_2.2.5
readelfコマンドの場合は下記
# readelf -d /bin/echo
Dynamic section at offset 0x6e08 contains 24 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000c (INIT) 0x401050
0x000000000000000d (FINI) 0x40442c
0x0000000000000019 (INIT_ARRAY) 0x606da8
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x606db0
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x400298
0x0000000000000005 (STRTAB) 0x400810
0x0000000000000006 (SYMTAB) 0x4002b8
0x000000000000000a (STRSZ) 605 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x607000
0x0000000000000002 (PLTRELSZ) 1176 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x400bb8
0x0000000000000007 (RELA) 0x400b40
0x0000000000000008 (RELASZ) 120 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x400ae0
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x400a6e
0x0000000000000000 (NULL) 0x0
/bin/echo
にはlibc.so.6
という共有ライブラリが必要だということがわかる
が、実際に必要なのはこの一つのみではなくその共有ライブラリが必要としている別の共有ライブラリも必要
NEEDEDに記載されているのはSONAME
なのでSONAME
から実際のファイルを探す必要がある
特になにも設定されてない場合は/usr/lib
及び/lib
にSONAME
に対応するファイルが存在すればそれが対象の共有ライブラリとなる
環境変数LD_LIBRARY_PATH
があればそこを参照し、/etc/ld.so.cache
に情報があればそれを参照する
lddコマンドで依存関係を見てみる
lddコマンドを使うと共有ライブラリのSONAME
とパス名の一覧が表示される
# ldd /bin/echo
linux-vdso.so.1 => (0x00007ffca93e5000)
libc.so.6 => /lib64/libc.so.6 (0x00007f88dde02000)
/lib64/ld-linux-x86-64.so.2 (0x00007f88de1cf000)
# ldd /lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2 (0x00007f7508b2c000)
linux-vdso.so.1 => (0x00007fff0fd0d000)
ちなみにlddコマンド自体はshellで出来てる
# file /bin/ldd
/bin/ldd: Bourne-Again shell script, ASCII text executable
objdumpでオブジェクトファイルをダンプしてみる
前回はodコマンドでみたがobjdumpコマンドで特定のセクションだけdumpすることもできる
セクションの確認
# objdump -h /bin/echo
/bin/echo: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000400238 0000000000400238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 0000000000400254 0000000000400254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 0000000000400274 0000000000400274 00000274 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 0000001c 0000000000400298 0000000000400298 00000298 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 00000558 00000000004002b8 00000000004002b8 000002b8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 0000025d 0000000000400810 0000000000400810 00000810 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
~~~(ry~~~
.dynstr
をdump
# objdump -s -j .dynstr /bin/echo
/bin/echo: file format elf64-x86-64
Contents of section .dynstr:
400810 006c6962 632e736f 2e360066 666c7573 .libc.so.6.fflus
400820 68007374 72637079 005f5f70 72696e74 h.strcpy.__print
400830 665f6368 6b007365 746c6f63 616c6500 f_chk.setlocale.
400840 6d627274 6f776300 7374726e 636d7000 mbrtowc.strncmp.
400850 73747272 63687200 64636765 74746578 strrchr.dcgettex
400860 74006572 726f7200 5f5f7374 61636b5f t.error.__stack_
400870 63686b5f 6661696c 00697377 7072696e chk_fail.iswprin
400880 74007265 616c6c6f 63006162 6f727400 t.realloc.abort.
400890 5f657869 74007072 6f677261 6d5f696e _exit.program_in
4008a0 766f6361 74696f6e 5f6e616d 65005f5f vocation_name.__
4008b0 63747970 655f6765 745f6d62 5f637572 ctype_get_mb_cur
4008c0 5f6d6178 0063616c 6c6f6300 7374726c _max.calloc.strl
4008d0 656e0075 6e676574 63006d65 6d736574 en.ungetc.memset
4008e0 005f5f65 72726e6f 5f6c6f63 6174696f .__errno_locatio
4008f0 6e006d65 6d636d70 005f5f66 7072696e n.memcmp.__fprin
400900 74665f63 686b0073 74646f75 74006c73 tf_chk.stdout.ls
400910 65656b00 6d656d63 70790066 636c6f73 eek.memcpy.fclos
400920 65006d61 6c6c6f63 006d6273 696e6974 e.malloc.mbsinit
400930 005f5f75 666c6f77 006e6c5f 6c616e67 .__uflow.nl_lang
400940 696e666f 005f5f63 74797065 5f625f6c info.__ctype_b_l
400950 6f630067 6574656e 76005f5f 66726561 oc.getenv.__frea
400960 64696e67 00737464 65727200 66736361 ding.stderr.fsca
400970 6e660066 696c656e 6f006677 72697465 nf.fileno.fwrite
400980 005f5f66 70656e64 696e6700 70726f67 .__fpending.prog
400990 72616d5f 696e766f 63617469 6f6e5f73 ram_invocation_s
4009a0 686f7274 5f6e616d 65006664 6f70656e hort_name.fdopen
4009b0 0062696e 64746578 74646f6d 61696e00 .bindtextdomain.
4009c0 73747263 6d70005f 5f6c6962 635f7374 strcmp.__libc_st
4009d0 6172745f 6d61696e 00667365 656b6f00 art_main.fseeko.
4009e0 5f5f6f76 6572666c 6f770066 70757473 __overflow.fputs
4009f0 5f756e6c 6f636b65 64006672 6565005f _unlocked.free._
400a00 5f70726f 676e616d 65005f5f 70726f67 _progname.__prog
400a10 6e616d65 5f66756c 6c005f5f 6378615f name_full.__cxa_
400a20 61746578 6974005f 5f676d6f 6e5f7374 atexit.__gmon_st
400a30 6172745f 5f00474c 4942435f 322e3300 art__.GLIBC_2.3.
400a40 474c4942 435f322e 332e3400 474c4942 GLIBC_2.3.4.GLIB
400a50 435f322e 31340047 4c494243 5f322e34 C_2.14.GLIBC_2.4
400a60 00474c49 42435f32 2e322e35 00 .GLIBC_2.2.5.
objdumpでオブジェクトファイルを逆アセンブルしてみる
objdumpでオブジェクトファイルを逆アセンブル
-dオプションで逆アセンブルができるので下記のように実行
# objdump -d /bin/echo
/bin/echo: file format elf64-x86-64
Disassembly of section .init:
0000000000401050 <.init>:
401050: 48 83 ec 08 sub $0x8,%rsp
401054: 48 8b 05 85 5f 20 00 mov 0x205f85(%rip),%rax # 606fe0 <__ctype_b_loc@plt+0x205c60>
40105b: 48 85 c0 test %rax,%rax
40105e: 74 05 je 401065 <__uflow@plt-0x1b>
401060: e8 2b 03 00 00 callq 401390 <__ctype_b_loc@plt+0x10>
401065: 48 83 c4 08 add $0x8,%rsp
401069: c3 retq
Disassembly of section .plt:
0000000000401070 <__uflow@plt-0x10>:
401070: ff 35 92 5f 20 00 pushq 0x205f92(%rip) # 607008 <__ctype_b_loc@plt+0x205c88>
401076: ff 25 94 5f 20 00 jmpq *0x205f94(%rip) # 607010 <__ctype_b_loc@plt+0x205c90>
40107c: 0f 1f 40 00 nopl 0x0(%rax)
~~~(ry~~~
アドレスとバイト列もみたい場合は下記のようにオプションを指定すれば見れるようになる
# objdump -d --prefix-address --show-raw-insn /bin/echo
/bin/echo: file format elf64-x86-64
Disassembly of section .init:
0000000000401050 <.init> 48 83 ec 08 sub $0x8,%rsp
0000000000401054 <.init+0x4> 48 8b 05 85 5f 20 00 mov 0x205f85(%rip),%rax # 0000000000606fe0 <__ctype_b_loc@plt+0x205c60>
000000000040105b <.init+0xb> 48 85 c0 test %rax,%rax
000000000040105e <.init+0xe> 74 05 je 0000000000401065 <__uflow@plt-0x1b>
0000000000401060 <.init+0x10> e8 2b 03 00 00 callq 0000000000401390 <__ctype_b_loc@plt+0x10>
0000000000401065 <.init+0x15> 48 83 c4 08 add $0x8,%rsp
0000000000401069 <.init+0x19> c3 retq
Disassembly of section .plt:
0000000000401070 <__uflow@plt-0x10> ff 35 92 5f 20 00 pushq 0x205f92(%rip) # 0000000000607008 <__ctype_b_loc@plt+0x205c88>
0000000000401076 <__uflow@plt-0xa> ff 25 94 5f 20 00 jmpq *0x205f94(%rip) # 0000000000607010 <__ctype_b_loc@plt+0x205c90>
000000000040107c <__uflow@plt-0x4> 0f 1f 40 00 nopl 0x0(%rax)
~~~(ry~~~
特定のセクションのみ逆アセンブルすることもできる
# objdump -d -j .dynstr /bin/echo
/bin/echo: file format elf64-x86-64
Disassembly of section .dynstr:
0000000000400810 <.dynstr>:
400810: 00 6c 69 62 add %ch,0x62(%rcx,%rbp,2)
400814: 63 2e movslq (%rsi),%ebp
400816: 73 6f jae 400887 <__uflow@plt-0x7f9>
400818: 2e 36 00 66 66 cs add %ah,%ss:0x66(%rsi)
40081d: 6c insb (%dx),%es:(%rdi)
40081e: 75 73 jne 400893 <__uflow@plt-0x7ed>
400820: 68 00 73 74 72 pushq $0x72747300
400825: 63 70 79 movslq 0x79(%rax),%esi
~~~(ry~~~
ソースファイルとの対応を表示
デバッグ情報が含まれてるオブジェクトファイルの場合は-Sオプションでそのソースファイルがあれば
ソースコードをその場に挿入してくれる
# cat hello.c
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
# gcc -g -o hello hello.c
# ll
total 16
-rwxr-xr-x 1 root root 9432 Mar 21 03:15 hello
-rw-r--r-- 1 root root 82 Mar 21 03:08 hello.c
# objdump -d -S hello
~~~~(ry~~~
000000000040051d <main>:
#include <stdio.h>
int main(void)
{
40051d: 55 push %rbp
40051e: 48 89 e5 mov %rsp,%rbp
printf("Hello World\n");
400521: bf d0 05 40 00 mov $0x4005d0,%edi
400526: e8 d5 fe ff ff callq 400400 <puts@plt>
return 0;
40052b: b8 00 00 00 00 mov $0x0,%eax
}
400530: 5d pop %rbp
400531: c3 retq
400532: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
400539: 00 00 00
40053c: 0f 1f 40 00 nopl 0x0(%rax)
~~~(ry~~~
とりあえず今回は逆アセンブルまでしてみた
たぶん次回もあると思うが今回はここまで
参考
www.oreilly.co.jp