2014.05.14 17:32

#ldd 명령어 분석 ( for dynamic symbol 저장 위치 찾기)  , ldd 동작 방식 ,shared library 호출 방식 

  1. #ldd 명령어 소스코드의 원형 분석
  • 파일 및 공유라이브러리들의 공유라이브러리 의존관계 출력 command 내부적으로LD_TRACE_LOADED_OBJECT=1 사용


        /* ld.so magic */

        setenv("LD_TRACE_LOADED_OBJECTS", "yes", 1);

        if (fmt1)

                setenv("LD_TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);

        if (fmt2)

                setenv("LD_TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);


  • 장점 : 실행 바이너리 실행되지 않은 공유 라이브러리 들간의 의존도도 있다. ( 2번에서 이어서 설명 )

 

 

  1. LD_TRACE_LOADED_OBJECT
  • root@k1rh4:~/libtest/1# LD_TRACE_LOADED_OBJECTS=1 ./main

        linux-gate.so.1 =>  (0xb774b000)

        libstrcpy2.so => /usr/lib/libstrcpy2.so (0xb7735000)

        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb758b000)

        /lib/ld-linux.so.2 (0xb774c000)

 

  • #ldd 커맨드와 LD_TRACE_LOADED_OBJECT 차이 
  • ( 실행 중이지 않은 라이브러리의 공유라이브러리 의존도 확인 가능 여부 )

root@k1rh4:~/libtest/1# ldd /usr/lib/libstrcpy2.so

        linux-gate.so.1 =>  (0xb7788000)

        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75c8000)

        /lib/ld-linux.so.2 (0xb7789000)

root@k1rh4:~/libtest/1# LD_TRACE_LOADED_OBJECTS=1 /usr/lib/libstrcpy2.so

세그멘테이션 오류 (core dumped)

실행파일만 .

 

 

  1. ELF 헤더 정보에 dynamic 심볼 정보를 참조.

 (테스트환경은 strcpy2 공유라이브러리를 링킹 테스트)

 

  • ELF section header 정보 ( 우측 )
    • [6].dynstr (STRTAB) 0x8048298 심볼 정보가 컴파일 저장됨.

(gdb) x/20s 0x08048298    //아래 섹션 헤더 부분을 참조 

0x8048298:       ""

0x8048299:       "libstrcpy2.so"   // 아래 섹션헤더 부분을 참조 

0x80482a7:       "__gmon_start__"

0x80482b6:       "_Jv_RegisterClasses"

0x80482ca:       "_init"

0x80482d0:       "_fini"

0x80482d6:       "strcpy2"

0x80482de:       "libc.so.6"

0x80482e8:       "_IO_stdin_used"

0x80482f7:       "__libc_start_main"

0x8048309:       "_edata"

0x8048310:       "__bss_start"

0x804831c:       "_end"

0x8048321:       "GLIBC_2.0"

0x804832b:       <Address 0x804832b out of bounds>

정보를 기준으로 libstrcpy2.so 탐색함.

 

  • 바이너리 실행 library 이름으로 탐색함

root@k1rh4:~/libtest/1# strace -i ./main

[b77b1424] execve("./main", ["./main"], [/* 20 vars */]) = 0

[b773bf94] brk(0)                       = 0x8228000

[b773dcb1] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)

[b773dd63] mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7723000

[b773dcb1] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

[b773db74] open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3

[b773dafd] fstat64(3, {st_mode=S_IFREG|0644, st_size=67880, ...}) = 0

[b773dd63] mmap2(NULL, 67880, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7712000

[b773dbad] close(3)                     = 0

[b773dcb1] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)

[b773db74] open("/usr/lib/libstrcpy2.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

[b773db74] open("/lib/i386-linux-gnu/tls/i686/sse2/cmov/libstrcpy2.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

[b773dabd] stat64("/lib/i386-linux-gnu/tls/i686/sse2/cmov", 0xbff9d860) = -1 ENOENT (No such file or directory)

[b773db74] open("/lib/i386-linux-gnu/tls/i686/sse2/libstrcpy2.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

[b773dabd] stat64("/lib/i386-linux-gnu/tls/i686/sse2", 0xbff9d860) = -1 ENOENT (No such file or directory)

[b773db74] open("/lib/i386-linux-gnu/tls/i686/cmov/libstrcpy2.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

.

.( 탐색 중… )

.

[b773db74] open("/lib/libstrcpy2.so", O_RDONLY|O_CLOEXEC) = 3  

           //   [ /lib/ 에서  strcpy2 공유 라이브러리를 찾음 ]

[b773dbf4] read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\260\3\0\0004\0\0\0"..., 512) = 512

[b773dafd] fstat64(3, {st_mode=S_IFREG|0755, st_size=6760, ...}) = 0

[b773dd63] mmap2(NULL, 8216, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb770f000

             //   [ /lib/libstrcpy2.so ] 메모리에 적재 시킴

 

  • 바이너리를 실행하면 .init 보다 먼저 공유라이브러리가 올라오게 된다.

(gdb) x/10xi 0xb7fc746c  // 공유라이브러리의 strcpy2()

   0xb7fc746c <strcpy2>:        push   %ebp

   0xb7fc746d <strcpy2+1>:      mov    %esp,%ebp

   0xb7fc746f <strcpy2+3>:      push   %ebx

   0xb7fc7470 <strcpy2+4>:      sub    $0x14,%esp

   0xb7fc7473 <strcpy2+7>:      call   0xb7fc7467 <__i686.get_pc_thunk.bx>

   0xb7fc7478 <strcpy2+12>:     add    $0x1b7c,%ebx

   0xb7fc747e <strcpy2+18>:     lea    -0x1b02(%ebx),%eax

   0xb7fc7484 <strcpy2+24>:     mov    %eax,(%esp)

   0xb7fc7487 <strcpy2+27>:     call   0xb7fc7380 <printf@plt>

   0xb7fc748c <strcpy2+32>:     add    $0x14,%esp

 


  • Strcpy2@PLT -> strcpy2@GOT.PLT 가리키고 있음.

(gdb) x/10xi 0x80483f0

   0x80483f0 <strcpy2@plt>:     jmp    *0x804a008

   0x80483f6 <strcpy2@plt+6>:   push   $0x10

   0x80483fb <strcpy2@plt+11>:  jmp    0x80483c0

(gdb) x/10xi 0x804a008

   0x804a008 <strcpy2@got.plt>: testb  $0x0,0x804(%ebx)

 

        • Strcpy 한번 호출 뒤의 변화

(gdb) x/10xi 0x80483f0

   0x80483f0 <strcpy2@plt>:     jmp    *0x804a008

   0x80483f6 <strcpy2@plt+6>:   push   $0x10

   0x80483fb <strcpy2@plt+11>:  jmp    0x80483c0

(gdb) x/10xi *0x804a008

   0xb7fc746c <strcpy2>:        push   %ebp   // 공유라이브러리의 주소

   0xb7fc746d <strcpy2+1>:      mov    %esp,%ebp

   0xb7fc746f <strcpy2+3>:      push   %ebx

   0xb7fc7470 <strcpy2+4>:      sub    $0x14,%esp

   0xb7fc7473 <strcpy2+7>:      call   0xb7fc7467 <__i686.get_pc_thunk.bx>


[ Section Headers: ]

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                       NULL            00000000 000000 000000 00      0   0  0

  [ 1] .interp              PROGBITS        08048154 000154 000013 00   A  0   0  1

  [ 2] .note.ABI-tag     NOTE            08048168 000168 000020 00   A  0   0  4

  [ 3] .note.gnu.build-i NOTE            08048188 000188 000024 00   A  0   0  4

  [ 4] .gnu.hash         GNU_HASH        080481ac 0001ac 00003c 04   A  5   0  4

  [ 5] .dynsym           DYNSYM          080481e8 0001e8 0000b0 10   A  6   1  4

  [ 6] .dynstr            STRTAB          08048298 000298 000093 00   A  0   0  1   // 참조된 섹션 헤더

  [ 7] .gnu.version      VERSYM          0804832c 00032c 000016 02   A  5   0  2

  [ 8] .gnu.version_r    VERNEED         08048344 000344 000020 00   A  6   1  4

  [ 9] .rel.dyn            REL             08048364 000364 000008 08   A  5   0  4

  [10] .rel.plt             REL             0804836c 00036c 000018 08   A  5  12  4

  [11] .init                PROGBITS        08048384 000384 00002e 00  AX  0   0  4

  [12] .plt               PROGBITS        080483c0 0003c0 000040 04  AX  0   0 16

  [13] .text              PROGBITS        08048400 000400 00017c 00  AX  0   0 16

  [14] .fini               PROGBITS        0804857c 00057c 00001a 00  AX  0   0  4

  [15] .rodata           PROGBITS        08048598 000598 000008 00   A  0   0  4

  [16] .eh_frame_hdr  PROGBITS        080485a0 0005a0 000034 00   A  0   0  4

  [17] .eh_frame        PROGBITS        080485d4 0005d4 0000c4 00   A  0   0  4

  [18] .ctors             PROGBITS        08049f0c 000f0c 000008 00  WA  0   0  4

  [19] .dtors             PROGBITS        08049f14 000f14 000008 00  WA  0   0  4

  [20] .jcr                PROGBITS        08049f1c 000f1c 000004 00  WA  0   0  4

  [21] .dynamic         DYNAMIC         08049f20 000f20 0000d0 08  WA  6   0  4

  [22] .got              PROGBITS        08049ff0 000ff0 000004 04  WA  0   0  4

  [23] .got.plt          PROGBITS        08049ff4 000ff4 000018 04  WA  0   0  4

  [24] .data              PROGBITS        0804a00c 00100c 000008 00  WA  0   0  4

  [25] .bss               NOBITS          0804a014 001014 000008 00  WA  0   0  4

  [26] .comment       PROGBITS        00000000 001014 00002a 01  MS  0   0  1

  [27] .shstrtab         STRTAB          00000000 00103e 0000fc 00      0   0  1

  [28] .symtab          SYMTAB          00000000 0015ec 000410 10     29  45  4

  [29] .strtab           STRTAB          00000000 0019fc 0001f2 00      0   0  1


Posted by k1rha