결국 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 |