systemhacking/background

linux background 1 (binary hacks)

qkqhxla1 2015. 2. 6. 18:31

결국 binary hacks라는 책을 구입했습니다 (-_-;)


file - 파일 종류 확인 (page 12)

i옵션은 mime 미디어 타입 문자열로 표시된다고 함.

[root@localhost fedora]# file /usr/bin/file

/usr/bin/file: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped


[root@localhost fedora]# file -i /usr/bin/file

/usr/bin/file: application/x-executable; charset=binary



od - 바이너리 파일 덤프 (page 15)

기본적으로 8진수로 덤프됨. 행의 맨 첫번째 컬럼은 오프셋을 8진수로 적은것. 한 행마다 2바이트씩 표현.

옵션에 따라 보기 편하게 16진수나 바이트, 크기 지정자 등으로 출력 가능.

[root@localhost fedora]# od test | head -5

0000000 042577 043114 000401 000001 000000 000000 000000 000000

0000020 000002 000003 000001 000000 156040 004005 000064 000000

0000040 143650 000014 000000 000000 000064 000040 000010 000050

0000060 000040 000037 000006 000000 000064 000000 070064 004004

0000100 070064 004004 000400 000000 000400 000000 000005 000000


[root@localhost fedora]# od -t x1z test | head -5

0000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  >.ELF............<

0000020 02 00 03 00 01 00 00 00 20 dc 05 08 34 00 00 00  >........ ...4...<

0000040 a8 c7 0c 00 00 00 00 00 34 00 20 00 08 00 28 00  >........4. ...(.<

0000060 20 00 1f 00 06 00 00 00 34 00 00 00 34 70 04 08  > .......4...4p..<

0000100 34 70 04 08 00 01 00 00 00 01 00 00 05 00 00 00  >4p..............<


[root@localhost fedora]# od -t x1c test | head -5

0000000  7f  45  4c  46  01  01  01  00  00  00  00  00  00  00  00  00

        177   E   L   F 001 001 001  \0  \0  \0  \0  \0  \0  \0  \0  \0

0000020  02  00  03  00  01  00  00  00  20  dc  05  08  34  00  00  00

        002  \0 003  \0 001  \0  \0  \0     334 005  \b   4  \0  \0  \0

0000040  a8  c7  0c  00  00  00  00  00  34  00  20  00  08  00  28  00



ELF파일. (page 21, 42)

ELF는 실행 가능한 바이너리 또는 오브젝트 파일등의 형식. elf.h에 구조가 있다함.

[root@localhost fedora]# readelf -h /bin/ls

ELF Header:

  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 

  Class:                             ELF32

  Data:                              2's complement, little endian

  Version:                           1 (current)

  OS/ABI:                            UNIX - System V

  ABI Version:                       0

  Type:                              EXEC (Executable file)

  Machine:                           Intel 80386

  Version:                           0x1

  Entry point address:               0x8049a90

  Start of program headers:          52 (bytes into file)

  Start of section headers:          118832 (bytes into file)

  Flags:                             0x0

  Size of this header:               52 (bytes)

  Size of program headers:           32 (bytes)

  Number of program headers:         8

  Size of section headers:           40 (bytes)

  Number of section headers:         32

  Section header string table index: 31

[root@localhost fedora]# readelf -S /bin/ls

There are 32 section headers, starting at offset 0x1d030:


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        08048134 000134 000013 00   A  0   0  1

  [ 2] .note.ABI-tag     NOTE            08048148 000148 000020 00   A  0   0  4

  [ 3] .note.gnu.build-i NOTE            08048168 000168 000024 00   A  0   0  4

  [ 4] .gnu.hash         GNU_HASH        0804818c 00018c 000068 04   A  5   0  4

  [ 5] .dynsym           DYNSYM          080481f4 0001f4 000770 10   A 19   1  4

  [ 6] .gnu.liblist      GNU_LIBLIST     08048964 000964 0000b4 14   A 19   0  4

  [ 7] .gnu.conflict     RELA            08048a18 000a18 000198 0c   A  5   0  4

  [ 8] .gnu.version      VERSYM          08048ed6 000ed6 0000ee 02   A  5   0  2

  [ 9] .gnu.version_r    VERNEED         08048fc4 000fc4 0000d0 00   A 19   3  4

  [10] .rel.dyn          REL             08049094 001094 000080 08   A  5   0  4

  [11] .rel.plt          REL             08049114 001114 000310 08   A  5  13  4

  [12] .init             PROGBITS        08049424 001424 000030 00  AX  0   0  4

  [13] .plt              PROGBITS        08049454 001454 000630 04  AX  0   0  4

  [14] .text             PROGBITS        08049a90 001a90 013a9c 00  AX  0   0 16

  [15] .fini             PROGBITS        0805d52c 01552c 00001c 00  AX  0   0  4

  [16] .rodata           PROGBITS        0805d560 015560 003d94 00   A  0   0 32

  [17] .eh_frame_hdr     PROGBITS        080612f4 0192f4 0006ac 00   A  0   0  4

  [18] .eh_frame         PROGBITS        080619a0 0199a0 001a78 00   A  0   0  4

  [19] .dynstr           STRTAB          08063418 01b418 0005ac 00   A  0   0  1

  [20] .ctors            PROGBITS        08064000 01c000 000008 00  WA  0   0  4

  [21] .dtors            PROGBITS        08064008 01c008 000008 00  WA  0   0  4

  [22] .jcr              PROGBITS        08064010 01c010 000004 00  WA  0   0  4

  [23] .data.rel.ro      PROGBITS        08064020 01c020 000544 00  WA  0   0 32

  [24] .dynamic          DYNAMIC         08064564 01c564 0000e8 08  WA 19   0  4

  [25] .got              PROGBITS        0806464c 01c64c 000044 04  WA  0   0  4

  [26] .got.plt          PROGBITS        08064690 01c690 000194 04  WA  0   0  4

  [27] .data             PROGBITS        08064840 01c840 000120 00  WA  0   0 32

  [28] .bss              NOBITS          08064960 01c960 000460 00  WA  0   0 32

  [29] .gnu_debuglink    PROGBITS        00000000 01c960 000010 00      0   0  4

  [30] .gnu.prelink_undo PROGBITS        00000000 01c970 000594 01      0   0  4

  [31] .shstrtab         STRTAB          00000000 01cf04 00012c 00      0   0  1

Key to Flags:

  W (write), A (alloc), X (execute), M (merge), S (strings)

  I (info), L (link order), G (group), x (unknown)

  O (extra OS processing required) o (OS specific), p (processor specific)



정적 라이브러리와 공유 라이브러리. (page 34)

정적 라이브러리의 생성과 확인.

[root@localhost fedora]# cc -c -o foo.o foo.c

[root@localhost fedora]# cc -c -o bar.o bar.c

[root@localhost fedora]# ar ruv libfoo.a foo.o bar.o

ar: creating libfoo.a

a - foo.o

a - bar.o

[root@localhost fedora]# ar tv libfoo.a

rw-rw-r-- 0/0    676 Feb  7 18:41 2015 foo.o

rw-rw-r-- 0/0    673 Feb  7 18:41 2015 bar.o

동적 라이브러리의 생성.

[root@localhost fedora]# cc -fPIC -c -o foo.o foo.c

[root@localhost fedora]# cc -fPIC -c -o bar.o bar.c

[root@localhost fedora]# cc -shared -Wl,-soname,libfoo.so.0 -o libfoo.so foo.o bar.o


정적 라이브러리는 실행시 정적 라이브러리의 코드를 복사해서 실행파일에 넣으므로 코드 크기가 커지지만 동적 라이브러리는 코드 자체를 목사하진 않고, 참조하므로 코드 크기가 커지지는 않는다. 어딘가에 글을 쓴 태국이의 LD_PRELOAD문서 참조하기.



공유 라이브러리 의존관계.

[root@localhost fedora]# readelf -d /bin/ls | head -10


Dynamic section at offset 0x1c564 contains 28 entries:

  Tag        Type                         Name/Value

 0x00000001 (NEEDED)                     Shared library: [librt.so.1]

 0x00000001 (NEEDED)                     Shared library: [libselinux.so.1]

 0x00000001 (NEEDED)                     Shared library: [libcap.so.2]

 0x00000001 (NEEDED)                     Shared library: [libacl.so.1]

 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

 0x0000000c (INIT)                       0x8049424

 0x0000000d (FINI)                       0x805d52c

[root@localhost fedora]# objdump -p /bin/ls


/bin/ls:     file format elf32-i386


Program Header:

    PHDR off    0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2

         filesz 0x00000100 memsz 0x00000100 flags r-x

  INTERP off    0x00000134 vaddr 0x08048134 paddr 0x08048134 align 2**0

         filesz 0x00000013 memsz 0x00000013 flags r--

    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12

         filesz 0x0001b9c4 memsz 0x0001b9c4 flags r-x

    LOAD off    0x0001c000 vaddr 0x08064000 paddr 0x08064000 align 2**12

         filesz 0x00000960 memsz 0x00000dc0 flags rw-

 DYNAMIC off    0x0001c564 vaddr 0x08064564 paddr 0x08064564 align 2**2

         filesz 0x000000e8 memsz 0x000000e8 flags rw-

    NOTE off    0x00000148 vaddr 0x08048148 paddr 0x08048148 align 2**2

         filesz 0x00000044 memsz 0x00000044 flags r--

EH_FRAME off    0x000192f4 vaddr 0x080612f4 paddr 0x080612f4 align 2**2

         filesz 0x000006ac memsz 0x000006ac flags r--

   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2

         filesz 0x00000000 memsz 0x00000000 flags rw-


Dynamic Section:

  NEEDED               librt.so.1

  NEEDED               libselinux.so.1

  NEEDED               libcap.so.2

  NEEDED               libacl.so.1

  NEEDED               libc.so.6

**중략


위에서 보듯이 librt.so.1등등의 라이브러리가 필요함을 알 수 있다. 하지만 자세하게 잘 알려면 ldd사용.

[root@localhost fedora]# ldd /bin/ls

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

librt.so.1 => /lib/librt.so.1 (0x00ce1000)

libselinux.so.1 => /lib/libselinux.so.1 (0x00cc1000)

libcap.so.2 => /lib/libcap.so.2 (0x003f1000)

libacl.so.1 => /lib/libacl.so.1 (0x00aae000)

libc.so.6 => /lib/libc.so.6 (0x00aea000)

libpthread.so.0 => /lib/libpthread.so.0 (0x00c8f000)

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

libdl.so.2 => /lib/libdl.so.2 (0x00c88000)

libattr.so.1 => /lib/libattr.so.1 (0x003c1000)

LD_TRACE_LOADED_OBJECT환경변수를 사용해서도 동일한 결과를 얻을 수 있음. ldd는 실행 파일뿐만이 아니라 공유 라이브러리에도 사용 가능한데, 환경변수를 사용해서는 공유 라이브러리의 결과를 얻을 수 없음. 일부는 가능.

[root@localhost fedora]# LD_TRACE_LOADED_OBJECTS=1 /bin/ls



오브젝트 파일 덤프 (page 45)

objdump를 이용해 덤프가 가능하다.

[root@localhost fedora]# objdump -s /bin/ls | head -50


/bin/ls:     file format elf32-i386


Contents of section .interp:

 8048134 2f6c6962 2f6c642d 6c696e75 782e736f  /lib/ld-linux.so

 8048144 2e3200                               .2.             

Contents of section .note.ABI-tag:

 8048148 04000000 10000000 01000000 474e5500  ............GNU.

 8048158 00000000 02000000 06000000 12000000  ................

Contents of section .note.gnu.build-id:

 8048168 04000000 14000000 03000000 474e5500  ............GNU.

 8048178 c45c3d67 ab19efc1 6c791159 fe6ad1bb  .\=g....ly.Y.j..

 8048188 1850b6c1                             .P..            

Contents of section .gnu.hash:

 804818c 03000000 68000000 04000000 07000000  ....h...........

 804819c 00001a24 80298049 4805000d 80040820  ...$.).IH...... 

 80481ac 68000000 6c000000 72000000 108a4d23  h...l...r.....M#

 80481bc c84d4223 bae3927c 4345d5ec c8418790  .MB#...|CE...A..

 80481cc ac4be3c0 9c0932d6 462de4de d871581c  .K....2.F-...qX.

 80481dc b98df10e ead3ef0e 3e044b86 fca9da79  ........>.K....y

 80481ec 1ced632a 2bd4b8d3                    ..c*+...        

Contents of section .dynsym:

 80481f4 00000000 00000000 00000000 00000000  ................

 8048204 9d010000 00000000 00000000 12000000  ................


요렇게 알아서 섹션별로 출력된다. 옵션을 줘서 특정 섹션만을 덤프하는게 가능하다.

[root@localhost fedora]# objdump -s -j .interp /bin/ls


/bin/ls:     file format elf32-i386


Contents of section .interp:

 8048134 2f6c6962 2f6c642d 6c696e75 782e736f  /lib/ld-linux.so

 8048144 2e3200                               .2.             


주소 범위를 지정해서 덤프도 가능하다.

[root@localhost fedora]# objdump -s --start-address=0x8048004 --stop-address=0x8048204 /bin/ls


/bin/ls:     file format elf32-i386


Contents of section .interp:

 8048134 2f6c6962 2f6c642d 6c696e75 782e736f  /lib/ld-linux.so

 8048144 2e3200                               .2.             

Contents of section .note.ABI-tag:

 8048148 04000000 10000000 01000000 474e5500  ............GNU.

 8048158 00000000 02000000 06000000 12000000  ................

Contents of section .note.gnu.build-id:

 8048168 04000000 14000000 03000000 474e5500  ............GNU.

 8048178 c45c3d67 ab19efc1 6c791159 fe6ad1bb  .\=g....ly.Y.j..

 8048188 1850b6c1                             .P..            

Contents of section .gnu.hash:

 804818c 03000000 68000000 04000000 07000000  ....h...........

 804819c 00001a24 80298049 4805000d 80040820  ...$.).IH...... 

 80481ac 68000000 6c000000 72000000 108a4d23  h...l...r.....M#

 80481bc c84d4223 bae3927c 4345d5ec c8418790  .MB#...|CE...A..

 80481cc ac4be3c0 9c0932d6 462de4de d871581c  .K....2.F-...qX.

 80481dc b98df10e ead3ef0e 3e044b86 fca9da79  ........>.K....y

 80481ec 1ced632a 2bd4b8d3                    ..c*+...        

Contents of section .dynsym:

 80481f4 00000000 00000000 00000000 00000000  ................



objcopy - 실행 파일에 데이터 삽입하기. (page 55)

objcopy를 사용하면 임의의 파일을 링크 가능한 오브젝트 파일로 변경이 가능하다. 

예를 들어 wicd-1.7.0.tar.bz2라는 bz파일을 x86 elf32형식의 foo.o라는 오브젝트 파일로 변환하려면

[root@localhost fedora]# objcopy -I binary -O elf32-i386 -B i386 wicd-1.7.0.tar.bz2 foo.o

처럼 하면 된다. foo.o를 링크한 c프로그램에서 원래의 데이터는 extern변수들을 이용해 참조한다.

확실하지 않으므로 책을 다시 보거나 인터넷의 관련 자료 찾아보기.



nm - 오브젝트 파일에 포함된 심볼 확인. (page 57)

nm을 오브젝트 파일에 사용하면 심볼의 리스트를 볼 수 있다. 바로 위에서 생성된 foo.o를 대상으로 실험해보면.

[root@localhost fedora]# nm foo.o

0006461e D _binary_wicd_1_7_0_tar_bz2_end

0006461e A _binary_wicd_1_7_0_tar_bz2_size

00000000 D _binary_wicd_1_7_0_tar_bz2_start


실행 파일에도 사용 가능하다. (예전에 만들었던 backdoor파일을 대상으로 실험)

[root@localhost fedora]# nm backdoor

080495b8 d _DYNAMIC

08049684 d _GLOBAL_OFFSET_TABLE_

0804851c R _IO_stdin_used

         w _Jv_RegisterClasses

080495a8 d __CTOR_END__

080495a4 d __CTOR_LIST__

080495b0 D __DTOR_END__

080495ac d __DTOR_LIST__

080485a0 r __FRAME_END__

080495b4 d __JCR_END__

080495b4 d __JCR_LIST__

080496a8 A __bss_start

080496a4 D __data_start

080484d0 t __do_global_ctors_aux

080483a0 t __do_global_dtors_aux

08048520 R __dso_handle

         w __gmon_start__

080484ca T __i686.get_pc_thunk.bx

080495a4 d __init_array_end

080495a4 d __init_array_start

08048460 T __libc_csu_fini

08048470 T __libc_csu_init

         U __libc_start_main@@GLIBC_2.0

080496a8 A _edata

080496b0 A _end

080484fc T _fini

08048518 R _fp_hw

080482d4 T _init

08048370 T _start

080496a8 b completed.5918

080496a4 W data_start

080496ac b dtor_idx.5920

08048400 t frame_dummy

08048424 T main

         U setgid@@GLIBC_2.0

         U setuid@@GLIBC_2.0

         U system@@GLIBC_2.0


정적 바이너리가 아닌 공유 라이브러리의 경우의 심볼은 동적 심볼로서 이를 확인하려면 -D옵션을 사용해야 한다.



strings - 바이너리 파일에서 문자열 추출(page 63)

바이너리 파일에서 문자열 추출이 가능하다. .jpg, .mp3등의 확장자에서도 가능하다.

strings는 아스키로 구성된 4바이트 이상의 표현 가능한 문자열이라는 규칙으로 문자열을 판별한다.

[root@localhost fedora]# strings /bin/ls | head -5

/lib/ld-linux.so.2

PTRh0

HX9JX

HP9JP

HH9JH

grep와 같이 사용하면 편하다.

[root@localhost fedora]# cat /bin/ls | strings | grep ignoring

ignoring invalid value of environment variable QUOTING_STYLE: %s

ignoring invalid width in environment variable COLUMNS: %s

ignoring invalid tab size in environment variable TABSIZE: %s

[root@localhost fedora]# strings -tx /bin/ls | head -5

    134 /lib/ld-linux.so.2

   1a98 PTRh0

   1c94 HX9JX

   1d44 HP9JP

   1df4 HH9JH



c++filt - C++ 심볼 demangle(page 65)

nm으로 읽어온 복잡한 심볼명을 보기 편하게 해 준다.

nm foo.o | c++filt



addr2line (page 67)

gcc에서 -g옵션을 포함해서 디버그 정보를 포함하도록 컴파일되어있으면 addr2line을 사용해서

파일명과 행 정보를 얻을 수 있다.



strip - 오브젝트 파일에서 심볼 삭제(page 68)

strip 오브젝트파일.

-d옵션을 사용하면 디버그용 정보만 제거하고 함수명 등의 일반 심볼은 남게 된다.



gnu/리눅스 시스템에서 공유 라이브러리에 PIC을 사용하는이유.(page 85)

PIC을 이용한 함수는 PLT(Procedure Linkage Table)을 경유해서 함수를 호출한다.

PIC이 없는 버전의 단점은 실행시 재배치의 시간과, 재배치가 필요한 부분의 코드를 재작성하기 위해 재배치가 필요한 페이지 로드->copy on write발생->다른 프로세스와 텍스트 공유 불가 라는 사태가 발생하므로 다른 프로세스와 텍스트를 공유가 불가능한 공유 라이브러리의 중요한 장점이 사라지게 된다. 거기다 용량도 많다. (재배치에 필요한 정보 때문에.)



statifier - 동적 실행 파일에서 정적 실행 파일 생성(page 89)

statifier는 동적 링크된 실행 파일과 공유 라이브러리에를 하나의 파일로 합치기 위한 툴.

예로 /usr/bin/php와 공유 라이브러리를모아서 php2를 만들려면

ex) statifier /usr/bin/php php2 처럼 하면 된다.


'systemhacking > background' 카테고리의 다른 글

mprotect (메모리 권한 변경)  (0) 2015.02.10
linux background 2 (binary hacks)  (0) 2015.02.08
system 기본 용어들  (0) 2015.02.04
리버스 커넥션 쉘코드 제작  (0) 2015.01.31
쉘코드 제작, dumpcode  (0) 2014.12.29