카테고리 없음

bss section은 왜 4바이트를 가질까?

2018. 1. 12. 23:26

저의 친구 죽창이가 ROP Chaining을 할 때 dynamic section에 /bin/sh 를 넣지 않고, bss section에 /bin/sh 를 넣어 항상 bss section에 대한 의문이 많았었는데 이제서야 bss section에 대해서 알아보게 되었다. 


일단 bss section은 정의되지 않은 전역변수와 정적변수가 0으로 초기화되어 저장되는 section이다. 그래서 초기화되지 않은 전역/정적 변수를 많이 선언해놓고 readelf -S 로 해당 바이너리를 읽게되면, (초기화한 바이트 수) + 4 bytes 만큼 들어가 있다. 



 ch4n3@trust  ~/tmp/c/bss  readelf -S ./b                                                                                              ?  8315  23:09:24 

There are 31 section headers, starting at offset 0x17ec:


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 000050 10   A  6   1  4

  [ 6] .dynstr           STRTAB          0804821c 00021c 00004a 00   A  0   0  1

  [ 7] .gnu.version      VERSYM          08048266 000266 00000a 02   A  5   0  2

  [ 8] .gnu.version_r    VERNEED         08048270 000270 000020 00   A  6   1  4

  [ 9] .rel.dyn          REL             08048290 000290 000008 08   A  5   0  4

  [10] .rel.plt          REL             08048298 000298 000010 08  AI  5  24  4

  [11] .init             PROGBITS        080482a8 0002a8 000023 00  AX  0   0  4

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

  [13] .plt.got          PROGBITS        08048300 000300 000008 00  AX  0   0  8

  [14] .text             PROGBITS        08048310 000310 000192 00  AX  0   0 16

  [15] .fini             PROGBITS        080484a4 0004a4 000014 00  AX  0   0  4

  [16] .rodata           PROGBITS        080484b8 0004b8 000014 00   A  0   0  4

  [17] .eh_frame_hdr     PROGBITS        080484cc 0004cc 00002c 00   A  0   0  4

  [18] .eh_frame         PROGBITS        080484f8 0004f8 0000cc 00   A  0   0  4

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

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

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

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

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

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

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

  [26] .bss              NOBITS          0804a01c 00101c 000014 00  WA  0   0  4

  [27] .comment          PROGBITS        00000000 00101c 000034 01  MS  0   0  1

  [28] .shstrtab         STRTAB          00000000 0016e0 00010a 00      0   0  1

  [29] .symtab           SYMTAB          00000000 001050 000460 10     30  47  4

  [30] .strtab           STRTAB          00000000 0014b0 000230 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)


bss 의 size가 0x14 만큼 있다고 보여주고 있지만, 우리는 0x10 만큼만 초기화되지 않은 전역변수를 선언했다. 과연 추가된 4바이트는 무엇일까? 


bss 영역에 있는 값을 확인해보기 위해서 아래와 같은 C 프로그램을 만들어보았다. 간단히 bss section의 주소를 받아 출력하는 프로그램이다. 



readelf -S로 확인한 결과 bss의 주소는 0x0804a024 이었다. 그럼 int로 값을 입력해서 확인해보자. 


며용? 0이라니,,, 이거슨,, 잘못되었을 것이다,,


혹시 전처리를 하는 과정에서 초기화되지 않은 전역변수를 집어넣은 것일까? 라는 생각을 가지고 gcc --save-temps 옵션을 이용해서 컴파일 해보았다. *.i 파일을 열어보았지만, 아무런 단서도 얻지 못했다. 그럼 대체 뭘까. 질문을 해보았다. 


받은 답변은 .bss는 디스크 상에서 섹션의 존재를 나타내기 위해서 4바이트를 할당한다는 것이다. 그냥 .bss 가 나 여기있어요!! 하면서 그냥 4바이트를 갖고 있는 것이다. 


삽질한 것에 비해서 너무 허무했던 결과였다.. ㅋㅋ 그래도 bss 에 대해서 더 자세히 알게 되어서 뿌듯하다.