※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)


아 요즘 참 공부 복잡하다. 슬럼프인가..? 무슨 공부를 해야하는지 너무 고민되고 하다가 Exploit을 공부하기로 했다. 얼마전에 Exploit 공부하면서 너무 재밌어서 Maybe에서 하자고 했다. 기존에 공부하던 커널은 어쩌고? 우선 잠시 미루자. 제 커널 포스팅을 기다리고 계셨던 독자님들 죄송합니다ㅠㅠ 그래도 공부하면서 조금씩 커널에 관한 이야기는 올라올 겁니다. 사실 올릴 이야기도 많이 있고요.


그래도 Maybe에서 Exploit을 공부하기로 했으니 Assembly를 다시 복습할 수 밖에 없었다. 기본적인 것은 이해하고 있으나 조금 더 구체적으로 공부를 다시 해보고 싶었다. 그래서 Procedure Call을 다시 복습했고 그 외의 명령어들에 대한 복습도 조금씩 했다.


Procedure Call에 대해서는 아래의 링크에서 아주 자세하게 설명해놨다.

http://operatingsystems.tistory.com/entry/SP-Procedure-Call


위의 내용과 관련하여 추가적으로 정리하고 싶은 것은 전체적인 스택의 구조이다. 위의 링크에서는 각각의 메모리가 어떤식으로 값이 저장되는지 어떤식으로 다시 이전의 프레임으로 돌아오는지에 대한 이야기는 구체적으로 잘 적혀있지만 전체적인 그림은 없다. 그 전체적인 그림이 아래의 그림과 같다.



친절하게 같은 그림을 두 개 그려서 실제로 어떤 식으로 값이 들어가 있는지 오른쪽 그림에서 볼 수 있다. sum함수의 stack frame과 main 함수의 stack frame 그 경계에 어떤 값이 있으며 그 양쪽으로 어떤 값이 늘어서는지 잘 보고 그 구조를 이해한 후 외워야 한다.


위의 그림을 보면 두 함수의 경계에서 caller함수인 main함수 쪽에는 eip값이 들어가 있고 callee함수인 sum함수 쪽에는 main함수 stack frame의 가장 bottom address인 main의 %ebp가 들어있다. 그리고 eip값 이전에는 sum함수를 호출하기 위해 쓰일 argument들이 쌓여있다. 마지막으로 main의 %ebp 다음에는 sum함수에서 쓰일 변수들이 쌓여있다.


저 구조를 머리 속에 외워두면 실제 어셈블리 코드를 작성할 수도 있다. 정말이냐고? 정말이다. 그래서 간단한 프로그램을 직접 어셈블리 언어로 작성해봤다. 간단하게 hello world를 10번 출력하는 프로그램이다.



첫번째 이렇게 코딩을 해서 실행을 시켜보니까 아래와 같은 에러가 발생했다.


위의 에러가 발새하는 이유를 읽어보면 main에 대한 reference가 정의되지 않았다고 하는데...

나는 사실 여기서 생각했다. 조금더 알기 위해서는 elf 파일 포멧에 대해서 공부를 해야되겠다고. 이것을 보자마자 예전에 시스템 프로그래밍 공부했을 때 봤던 책을 펴서 elf 파일 포멧에 대해서 공부했다.


여기서는 ELF 포멧이 어떤 것이며 어떠한 정보를 포함하고 있는지만 간략적으로 언급하고 넘어가겠다. (ELF 포멧에 대한 자세한 포스팅은 조만간 올라올 예정이다. 그러니까 조금만 기다려주라.)


컴퓨터를 전공하는 사람이라면 PE 파일 포멧이라는 말을 들어봤을 것이다. 이는 windows의 실행파일 포멧을 의미한다. windows의 실행파일 포멧 대표적으로 exe가 있고 dll이 있다. 그 외의 windows의 실행파일 포멧은 .cpl .ocx .sys .scr .drv .efi 등등이 있다. 이 파일들이 실제 reverse engineering 이나 다른 부분에서 얼마나 자주 쓰이는 지는 잘 모르겠다. 아무튼 PE파일 포멧은 이러한 확장자를 가진 파일에 대한 파일 구조이다.


windows에서 PE파일 포멧을 사용한다면 linux에서는 어떤 파일 포멧을 사용할까? 그것이 ELF파일 포멧이다. ELF파일은 Executable and Linking Format의 약자로, wikipedia에서 아래와 같이 설명되어있다.

In computing, the Executable and Linkable Format (ELF, formerly called Extensible Linking Format) is a common standard file format for executablesobject codeshared libraries, and core dumps. First published in the System V Application Binary Interfacespecification,[1] and later in the Tool Interface Standard,[2] it was quickly accepted among different vendors of Unix systems. In 1999 it was chosen as the standard binary file format for Unix and Unix-like systems on x86 by the 86open project.

ELF is flexible and extensible by design, and it is not bound to any particular processor or architecture. This has allowed it to be adopted by many different operating systems on many different platforms.

Filename extensionnone, .o.so.elf.prx,.puff.bin
Magic number0x7F 'E' 'L' 'F'
Developed byUnix System Laboratories
Type of formatBinaryexecutableobject,shared librariescore dump
Container forMany executable binary formats

출처 : http://en.wikipedia.org/wiki/Executable_and_Linkable_Format


위의 표에서 보이다 시피 ELF 포멧은 .none .o .so .elf .prx .puff .bin 파일에 대한 포멧이다. 여기서 잠깐 자꾸 포멧 포멧 하는데 도데체 포멧이 무엇이냐 라고 질문하는 사람이 있을 것이다. 여기서 말하는 포멧이란 파일의 구조를 말하는 것이다. 가령 100byte짜리 프로그램이 있다면 처음 7byte까지는 header가 있고 그 다음부터 20byte까지는 section table이 있고 등등 이런 식이다.(단순 예를 들기 위한 예시일 뿐이다. 실제로는 header 다음에 section table이 오지 않는다.)


위의 그림을 다시 한번 보자.

여기에는 오로지 코드밖에 없다. assembly language는 코드만 가지고는 동작하지 않는다. 반드시 아래와 같이 추가적인 정보가 head와 tail에 붙여져야 한다.



사실 .c파일을 컴파일러로 컴파일을 하면 나오는 .s파일은 위의 정보보다 더욱 많은 정보를 포함하고 있다. 실제로 컴파일을 해보면 .cfi_startproc .cfi_endproc 등등과 같은 여러 가지 내용이 각 함수의 procedure마다 추가되어있다. 그 내용들에 대해서는 다음 포스팅에서 설명할 생각이다. 위의 그림에서 head에 나온 내용을 설명해보면 다음과 같다.



위의 정보들을 보면 대충 무엇에 대한 정보가 들어있는지 추측할 수 있다. Hello World\nHello World처럼 main 함수에서 print할 문자열도 있다. main이 global 하다는 것도 알려주며 그것이 함수라는 것도 알려준다. 대략 이런 정보들이 있다.


도대체 이게 뭘까 아직도 궁금한 사람이 있다면 다음 포스팅을 기다려라. 다음 포스팅을 보기 전에 아래의 그림을 봐주길 바란다. 봐도 뭔지 모르겠지만 그냥 봐서 익숙해지자. section은 뭐고 symbol은 뭐고 section table은 무엇이며 아놔 모르겠다. 라고 말하셔도 된다. 그럴 수 밖에 없다. 그렇지만 다음에 배울 내용에 대한 예습 맛보기 라고 생각하고 보자. 아래의 그림은 readelf 라는 명령어로 elf 파일 포멧을 읽은 것이다.


============================================================================

root@xxxxx-MS-7592:/# readelf -a func

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:               0x80482f0

  Start of program headers:          52 (bytes into file)

  Start of section headers:          5284 (bytes into file)

  Flags:                             0x0

  Size of this header:               52 (bytes)

  Size of program headers:           32 (bytes)

  Number of program headers:         9

  Size of section headers:           40 (bytes)

  Number of section headers:         36

  Section header string table index: 33


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 000020 04   A  5   0  4

  [ 5] .dynsym           DYNSYM          080481cc 0001cc 000040 10   A  6   1  4

  [ 6] .dynstr           STRTAB          0804820c 00020c 000045 00   A  0   0  1

  [ 7] .gnu.version      VERSYM          08048252 000252 000008 02   A  5   0  2

  [ 8] .gnu.version_r    VERNEED         0804825c 00025c 000020 00   A  6   1  4

  [ 9] .rel.dyn          REL             0804827c 00027c 000008 08   A  5   0  4

  [10] .rel.plt          REL             08048284 000284 000010 08   A  5  12  4

  [11] .init             PROGBITS        08048294 000294 000023 00  AX  0   0  4

  [12] .plt              PROGBITS        080482c0 0002c0 000030 04  AX  0   0 16

  [13] .text             PROGBITS        080482f0 0002f0 0001c4 00  AX  0   0 16

  [14] .fini             PROGBITS        080484b4 0004b4 000014 00  AX  0   0  4

  [15] .rodata           PROGBITS        080484c8 0004c8 000008 00   A  0   0  4

  [16] .eh_frame_hdr     PROGBITS        080484d0 0004d0 000034 00   A  0   0  4

  [17] .eh_frame         PROGBITS        08048504 000504 0000d0 00   A  0   0  4

  [18] .init_array       INIT_ARRAY      08049f08 000f08 000004 00  WA  0   0  4

  [19] .fini_array       FINI_ARRAY      08049f0c 000f0c 000004 00  WA  0   0  4

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

  [21] .dynamic          DYNAMIC         08049f14 000f14 0000e8 08  WA  6   0  4

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

  [23] .got.plt          PROGBITS        0804a000 001000 000014 04  WA  0   0  4

  [24] .data             PROGBITS        0804a014 001014 000008 00  WA  0   0  4

  [25] .bss              NOBITS          0804a01c 00101c 000008 00  WA  0   0  4

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

  [27] .debug_aranges    PROGBITS        00000000 001046 000020 00      0   0  1

  [28] .debug_info       PROGBITS        00000000 001066 0000fb 00      0   0  1

  [29] .debug_abbrev     PROGBITS        00000000 001161 00009e 00      0   0  1

  [30] .debug_line       PROGBITS        00000000 0011ff 00004e 00      0   0  1

  [31] .debug_str        PROGBITS        00000000 00124d 000096 01  MS  0   0  1

  [32] .debug_loc        PROGBITS        00000000 0012e3 000070 00      0   0  1

  [33] .shstrtab         STRTAB          00000000 001353 000151 00      0   0  1

  [34] .symtab           SYMTAB          00000000 001a44 0004a0 10     35  51  4

  [35] .strtab           STRTAB          00000000 001ee4 000249 00      0   0  1

Key to Flags:

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

  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)

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


There are no section groups in this file.


Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align

  PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4

  INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1

      [Requesting program interpreter: /lib/ld-linux.so.2]

  LOAD           0x000000 0x08048000 0x08048000 0x005d4 0x005d4 R E 0x1000

  LOAD           0x000f08 0x08049f08 0x08049f08 0x00114 0x0011c RW  0x1000

  DYNAMIC        0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW  0x4

  NOTE           0x000168 0x08048168 0x08048168 0x00044 0x00044 R   0x4

  GNU_EH_FRAME   0x0004d0 0x080484d0 0x080484d0 0x00034 0x00034 R   0x4

  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

  GNU_RELRO      0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R   0x1


 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 .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 

   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 

   04     .dynamic 

   05     .note.ABI-tag .note.gnu.build-id 

   06     .eh_frame_hdr 

   07     

   08     .init_array .fini_array .jcr .dynamic .got 


Dynamic section at offset 0xf14 contains 24 entries:

  Tag        Type                         Name/Value

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

 0x0000000c (INIT)                       0x8048294

 0x0000000d (FINI)                       0x80484b4

 0x00000019 (INIT_ARRAY)                 0x8049f08

 0x0000001b (INIT_ARRAYSZ)               4 (bytes)

 0x0000001a (FINI_ARRAY)                 0x8049f0c

 0x0000001c (FINI_ARRAYSZ)               4 (bytes)

 0x6ffffef5 (GNU_HASH)                   0x80481ac

 0x00000005 (STRTAB)                     0x804820c

 0x00000006 (SYMTAB)                     0x80481cc

 0x0000000a (STRSZ)                      69 (bytes)

 0x0000000b (SYMENT)                     16 (bytes)

 0x00000015 (DEBUG)                      0x0

 0x00000003 (PLTGOT)                     0x804a000

 0x00000002 (PLTRELSZ)                   16 (bytes)

 0x00000014 (PLTREL)                     REL

 0x00000017 (JMPREL)                     0x8048284

 0x00000011 (REL)                        0x804827c

 0x00000012 (RELSZ)                      8 (bytes)

 0x00000013 (RELENT)                     8 (bytes)

 0x6ffffffe (VERNEED)                    0x804825c

 0x6fffffff (VERNEEDNUM)                 1

 0x6ffffff0 (VERSYM)                     0x8048252

 0x00000000 (NULL)                       0x0


Relocation section '.rel.dyn' at offset 0x27c contains 1 entries:

 Offset     Info    Type            Sym.Value  Sym. Name

08049ffc  00000106 R_386_GLOB_DAT    00000000   __gmon_start__


Relocation section '.rel.plt' at offset 0x284 contains 2 entries:

 Offset     Info    Type            Sym.Value  Sym. Name

0804a00c  00000107 R_386_JUMP_SLOT   00000000   __gmon_start__

0804a010  00000207 R_386_JUMP_SLOT   00000000   __libc_start_main


The decoding of unwind sections for machine type Intel 80386 is not currently supported.


Symbol table '.dynsym' contains 4 entries:

   Num:    Value  Size Type    Bind   Vis      Ndx Name

     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 

     1: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

     2: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.0 (2)

     3: 080484cc     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used


Symbol table '.symtab' contains 74 entries:

   Num:    Value  Size Type    Bind   Vis      Ndx Name

     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 

     1: 08048154     0 SECTION LOCAL  DEFAULT    1 

     2: 08048168     0 SECTION LOCAL  DEFAULT    2 

     3: 08048188     0 SECTION LOCAL  DEFAULT    3 

     4: 080481ac     0 SECTION LOCAL  DEFAULT    4 

     5: 080481cc     0 SECTION LOCAL  DEFAULT    5 

     6: 0804820c     0 SECTION LOCAL  DEFAULT    6 

     7: 08048252     0 SECTION LOCAL  DEFAULT    7 

     8: 0804825c     0 SECTION LOCAL  DEFAULT    8 

     9: 0804827c     0 SECTION LOCAL  DEFAULT    9 

    10: 08048284     0 SECTION LOCAL  DEFAULT   10 

    11: 08048294     0 SECTION LOCAL  DEFAULT   11 

    12: 080482c0     0 SECTION LOCAL  DEFAULT   12 

    13: 080482f0     0 SECTION LOCAL  DEFAULT   13 

    14: 080484b4     0 SECTION LOCAL  DEFAULT   14 

    15: 080484c8     0 SECTION LOCAL  DEFAULT   15 

    16: 080484d0     0 SECTION LOCAL  DEFAULT   16 

    17: 08048504     0 SECTION LOCAL  DEFAULT   17 

    18: 08049f08     0 SECTION LOCAL  DEFAULT   18 

    19: 08049f0c     0 SECTION LOCAL  DEFAULT   19 

    20: 08049f10     0 SECTION LOCAL  DEFAULT   20 

    21: 08049f14     0 SECTION LOCAL  DEFAULT   21 

    22: 08049ffc     0 SECTION LOCAL  DEFAULT   22 

    23: 0804a000     0 SECTION LOCAL  DEFAULT   23 

    24: 0804a014     0 SECTION LOCAL  DEFAULT   24 

    25: 0804a01c     0 SECTION LOCAL  DEFAULT   25 

    26: 00000000     0 SECTION LOCAL  DEFAULT   26 

    27: 00000000     0 SECTION LOCAL  DEFAULT   27 

    28: 00000000     0 SECTION LOCAL  DEFAULT   28 

    29: 00000000     0 SECTION LOCAL  DEFAULT   29 

    30: 00000000     0 SECTION LOCAL  DEFAULT   30 

    31: 00000000     0 SECTION LOCAL  DEFAULT   31 

    32: 00000000     0 SECTION LOCAL  DEFAULT   32 


    34: 08049f10     0 OBJECT  LOCAL  DEFAULT   20 __JCR_LIST__

    38: 0804a01c     1 OBJECT  LOCAL  DEFAULT   25 completed.6339

    39: 08049f0c     0 OBJECT  LOCAL  DEFAULT   19 __do_global_dtors_aux_fin

    41: 08049f08     0 OBJECT  LOCAL  DEFAULT   18 __frame_dummy_init_array_

    44: 080485d0     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__

    45: 08049f10     0 OBJECT  LOCAL  DEFAULT   20 __JCR_END__

    48: 08049f14     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC

    50: 0804a000     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_

    59: 0804a018     0 OBJECT  GLOBAL HIDDEN    24 __dso_handle

    60: 080484cc     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used

    66: 080484c8     4 OBJECT  GLOBAL DEFAULT   15 _fp_hw

    70: 0804a020     4 OBJECT  GLOBAL DEFAULT   25 glov

    71: 0804a01c     0 OBJECT  GLOBAL HIDDEN    24 __TMC_END__


## no procedure has lower address than _start besides _init

    61: 00000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_

    73: 08048294     0 FUNC    GLOBAL DEFAULT   11 _init

    65: 080482f0     0 FUNC    GLOBAL DEFAULT   13 _start

    53: 08048320     4 FUNC    GLOBAL HIDDEN    13 __x86.get_pc_thunk.bx

    35: 08048330     0 FUNC    LOCAL  DEFAULT   13 deregister_tm_clones

    36: 08048360     0 FUNC    LOCAL  DEFAULT   13 register_tm_clones

    37: 080483a0     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux

    40: 080483c0     0 FUNC    LOCAL  DEFAULT   13 frame_dummy

    62: 080483ec    49 FUNC    GLOBAL DEFAULT   13 func

    68: 0804841d    35 FUNC    GLOBAL DEFAULT   13 main

    63: 08048440    97 FUNC    GLOBAL DEFAULT   13 __libc_csu_init

    51: 080484b0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini

    56: 080484b4     0 FUNC    GLOBAL DEFAULT   14 _fini


## ABS is the file that should not be relocated

    33: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

    42: 00000000     0 FILE    LOCAL  DEFAULT  ABS test.c

    43: 00000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

    46: 00000000     0 FILE    LOCAL  DEFAULT  ABS 


    47: 08049f0c     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end

    49: 08049f08     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_start

    52: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab

    54: 0804a014     0 NOTYPE  WEAK   DEFAULT   24 data_start

    55: 0804a01c     0 NOTYPE  GLOBAL DEFAULT   24 _edata

    57: 0804a014     0 NOTYPE  GLOBAL DEFAULT   24 __data_start

    58: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

    64: 0804a024     0 NOTYPE  GLOBAL DEFAULT   25 _end

    67: 0804a01c     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start

    69: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses

    72: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable


Histogram for `.gnu.hash' bucket list length (total of 2 buckets):

 Length  Number     % of total  Coverage

      0  1          ( 50.0%)

      1  1          ( 50.0%)    100.0%


Version symbols section '.gnu.version' contains 4 entries:

 Addr: 0000000008048252  Offset: 0x000252  Link: 5 (.dynsym)

  000:   0 (*local*)       0 (*local*)       2 (GLIBC_2.0)     1 (*global*)   


Version needs section '.gnu.version_r' contains 1 entries:

 Addr: 0x000000000804825c  Offset: 0x00025c  Link: 6 (.dynstr)

  000000: Version: 1  File: libc.so.6  Cnt: 1

  0x0010:   Name: GLIBC_2.0  Flags: none  Version: 2


Notes at offset 0x00000168 with length 0x00000020:

  Owner                 Data size Description

  GNU                  0x00000010 NT_GNU_ABI_TAG (ABI version tag)

    OS: Linux, ABI: 2.6.24


Notes at offset 0x00000188 with length 0x00000024:

  Owner                 Data size Description

  GNU                  0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)

    Build ID: 15ba02e08f2be0aa3352d7cca6e07c77773b2c2f

============================================================================


위의 내용에 대해서 차근 차근 설명할 것이니 조금만 기다려라. section이 뭔지 symbol은 또 뭔지 전부 다 설명할거다. 나도 공부를 해야 블로깅을 할 수 있다.ㅠㅠ

Posted by 빛나유
,