바이너리 수준 조사를 위한 Linux 명령 주석

13580 단어 LinuxCentOSELFBinary
바이너리 파일 분석 및 조사를 위한 명령 주석
다음 명령 실행례의 환경은 여기에 있습니다
[rso@localhost log]$ cat /etc/issue
CentOS release 6.3 (Final)
Kernel \r on an \m

바이너리 파일 읽기 및 쓰기


파일 형식을 찾고 싶습니다.

file 명령으로 간단하게 조사하다.
[rso@localhost log]$ file /bin/ls /bin/sh /var/log/messages  /dev/sda /dev/tty11 /tmp /tmp/test.pl /tmp/hoge
/bin/ls:           ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
/bin/sh:           symbolic link to `bash'
/var/log/messages: ASCII English text
/dev/sda:          block special
/dev/tty11:        character special
/tmp:              sticky directory
/tmp/test.pl:      ASCII text
/tmp/hoge:         data

바이너리 파일에 포함된 문자열을 추출하고 싶습니다.

strings.바이너리 파일을 추출하는 문자열이 가장 빠릅니다.
[rso@localhost log]$ strings /var/log/wtmp | head
reboot
2.6.32-279.el6.x86_64
runlevel
2.6.32-279.el6.x86_64
tty1
LOGIN
tty2
LOGIN
tty3
LOGIN
참고로 객체 바이너리가 객체 파일(ELF 파일)인 경우
초기화 및 로드 섹션의 문자열만 추출합니다.자세한 내용을 확인한 후
사용strings -a.

16진수로 바이너리 파일을 저장하려면

od.
[rso@localhost log]$ od -Ax -tx1z /var/log/wtmp |head
000000 02 00 00 00 00 00 00 00 7e 00 00 00 00 00 00 00  >........~.......<
000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
000020 00 00 00 00 00 00 00 00 7e 7e 00 00 72 65 62 6f  >........~~..rebo<
000030 6f 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >ot..............<
000040 00 00 00 00 00 00 00 00 00 00 00 00 32 2e 36 2e  >............2.6.<
000050 33 32 2d 35 37 33 2e 33 2e 31 2e 65 6c 36 2e 78  >32-573.3.1.el6.x<
000060 38 36 5f 36 34 00 00 00 00 00 00 00 00 00 00 00  >86_64...........<
000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
000150 00 00 00 00 ba 75 ff 55 84 37 09 00 00 00 00 00  >.....u.U.7......<```
hexdump도 가능합니다.나는 어떤 것을 즐겨 쓰느냐.
개인적으로 회고적인 환경hexdump에서도 사용할 수 없는 곳이 있고od 어디서든 사용할 수 있을 것 같다.
[rso@localhost log]$ hexdump -C /var/log/wtmp | head
00000000  02 00 00 00 00 00 00 00  7e 00 00 00 00 00 00 00  |........~.......|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  7e 7e 00 00 72 65 62 6f  |........~~..rebo|
00000030  6f 74 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |ot..............|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 32 2e 36 2e  |............2.6.|
00000050  33 32 2d 32 37 39 2e 65  6c 36 2e 78 38 36 5f 36  |32-279.el6.x86_6|
00000060  34 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |4...............|
00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000150  00 00 00 00 33 8d fc 4f  34 e5 01 00 00 00 00 00  |....3..O4.......|
또한objdump도 가능합니다.
이것은 뒤에 설명된 ELF 파일을 처리할 때 사용됩니다.
[rso@localhost log]$ objdump -s -b binary /var/log/wtmp | head

/var/log/wtmp:     file format binary

Contents of section .data:
 00000 02000000 00000000 7e000000 00000000  ........~.......
 00010 00000000 00000000 00000000 00000000  ................
 00020 00000000 00000000 7e7e0000 7265626f  ........~~..rebo
 00030 6f740000 00000000 00000000 00000000  ot..............
 00040 00000000 00000000 00000000 322e362e  ............2.6.
 00050 33322d32 37392e65 6c362e78 38365f36  32-279.el6.x86_6

바이너리 파일 편집하기

vim에서 바이너리 모드로 열면 명령%!xxd으로 바이너리를 표시할 수 있습니다.
편집이 끝나면 :%!xxd -r 로 돌아갑니다.
[rso@localhost log]$ vim -b binfile
 (省略)
:%!xxd
 (16進表示になる。編集する)
:%!xxd -r
 (元に戻る)
:wq
또한vim(xxd) 들어가지 않은전시대적인기계에서작업하거나vim열지 않고열면너무무거운경우dd 아래와 같이편집할 수 있다.
[rso@localhost log]$ hexdump binfile2 -C
00000000  62 62 62 62 62 62 62 62  62 62 62 62 62 62 62 62  |bbbbbbbbbbbbbbbb|
00000010  62 62 62 62 62 62 62 62  62 62 0a                 |bbbbbbbbbb.|
[rso@localhost log]$ echo  -en '\x5A\x5A' | dd of=binfile2 bs=1 se
ek=16 conv=notrunc
2+0 records in
2+0 records out
2 bytes (2 B) copied, 6.0608e-05 s, 33.0 kB/s
[rso@localhost log]$ hexdump binfile2 -C
00000000  62 62 62 62 62 62 62 62  62 62 62 62 62 62 62 62  |bbbbbbbbbbbbbbbb|
00000010  5a 5a 62 62 62 62 62 62  62 62 0a                 |ZZbbbbbbbb.|

ELF 파일 시작


ELF(Exectable and Linking Format)는 Linux에서 실행할 수 있는 프로그램이나 링크된 공유 라이브러리 등 바이너리 파일의 파일 형식을 가리킨다.

ELF 헤더 표시


다음 간단한 Hello world 2진법을 대상으로 합니다.
[rso@localhost log]$ cat main.c
#include <stdio.h>

int main(){
        printf("hello, world\n");
}
[rso@localhost log]$ gcc main.c
readelf 명령을 사용합니다.
[rso@localhost log]$ readelf  -h a.out
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4003e0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          2472 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 27
64bit 2진법, 서열 등을 기록했다.

프로그램 제목 표시

[rso@localhost log]$ readelf  -l a.out
  (省略)
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001c0 0x00000000000001c0  R E    8
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000068c 0x000000000000068c  R E    200000
  LOAD           0x0000000000000690 0x0000000000600690 0x0000000000600690
                 0x00000000000001ec 0x0000000000000200  RW     200000
  (省略)

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
  (省略)
각 세그먼트의 오프셋을 시작하는 스토리지 읽기와 쓰기 권한, 세그먼트에 포함된 세그먼트에 대한 정보를 표시합니다.
예를 들어, 섹션입니다.rodata는 권한 RE(읽기, 실행)의 LOAD 세그먼트에 있습니다.

섹션 제목 표시

[rso@localhost log]$ cat main.c
#include <stdio.h>

int main(){
        printf("hello, world\n");
}
[rso@localhost log]$ gcc main.c
[rso@localhost log]$ readelf -S a.out
There are 30 section headers, starting at offset 0x9a8:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400200  00000200
       000000000000001c  0000000000000000   A       0     0     1
  (省略)
  [13] .text             PROGBITS         00000000004003e0  000003e0
       00000000000001d8  0000000000000000  AX       0     0     16
  (省略)
  [15] .rodata           PROGBITS         00000000004005c8  000005c8
       000000000000001d  0000000000000000   A       0     0     8
  (省略)
  [24] .data             PROGBITS         0000000000600878  00000878
       0000000000000004  0000000000000000  WA       0     0     4
  (省略)
각 절의 제목 종류와 위치를 표시합니다.Offset은 프로그램이 시작하는 거리의 일부를 표시하고 몇 개의 항목 제목 종류를 기록합니다.
  • .text 텍스트 세그먼트.실행 프로그램 구성 영역
  • .rodata...읽기 전용 정수 등이 있는 영역 구성
  • .data...초기화된 데이터로 구성된 변경 가능 영역
  • 해봐.rodata 단락의 내용을 저장해 보십시오.
    [rso@localhost log]$ hexdump a.out -s 0x5c8 -n $((0x01d)) -C
    000005c8  01 00 02 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    000005d8  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 00           |hello, world.|
    
    상기 프로그램을 포함하는 문자열 상수를 알 수 있습니다.
    절명을 알고 뽑고 싶다면objdump도 된다.
    [rso@localhost log]$ objdump -s -j .rodata a.out
    
    a.out:     file format elf64-x86-64
    
    Contents of section .rodata:
     4005c8 01000200 00000000 00000000 00000000  ................
     4005d8 68656c6c 6f2c2077 6f726c64 00        hello, world.
    
    그나저나 strings 명령도 다음과 같다.
    [rso@localhost log]$ strings -tx a.out
        200 /lib64/ld-linux-x86-64.so.2
      (省略)
        5d8 hello, world
    

    ELF 파일에서 기호를 표시합니다.


    기호는 함수, 변수, 주소와 관련된 식별자를 가리킨다.
    프로그램이나 링크를 실행할 때 사용합니다.nm 명령은 기호를 표시할 수 있습니다.
    [rso@localhost ~]$ gcc -o main -c main.o
    [rso@localhost ~]$ nm main.o
    0000000000000000 T main
                     U puts
    
    기호의 종류는 여기에 상세하게 쓰여 있지 않지만 U는 정의되지 않은 기호입니다.
    실행 가능한 파일에도 사용할 수 있습니다.
    [rso@localhost ~]$ nm a.out
    00000000006006b8 d _DYNAMIC
     (省略) 
    00000000004004c4 T main
                     U puts@@GLIBC_2.2.5
    

    실행 파일에서 사용하는 공유 라이브러리 보이기


    사용ldd이 편리합니다.
    실행할 때 읽은 라이브러리 일람표를 표시합니다.
    [rso@localhost log]$ ldd a.out
            linux-vdso.so.1 =>  (0x00007ffe39db9000)
            libc.so.6 => /lib64/libc.so.6 (0x0000003bc3e00000)
            /lib64/ld-linux-x86-64.so.2 (0x0000003bc3600000)
    

    참고 문헌


    주로 아래 자료에서 자신이 이해한 내용을 기재하였다.
  • ELF 시작...IBM의 기계용 해설 자료, Linux도 매우 통용된다.
  • Binary Hacks-해커 비전기술 100선... 2진 장인을 목표로 하는 사람을 위해...
  • // 기재 내용에 오류가 있으면 지적해 주십시오.

    좋은 웹페이지 즐겨찾기