bss section은 왜 4바이트를 가질까?
저의 친구 죽창이가 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의 주소를 받아 출력하는 프로그램이다.
며용? 0이라니,,, 이거슨,, 잘못되었을 것이다,,
혹시 전처리를 하는 과정에서 초기화되지 않은 전역변수를 집어넣은 것일까? 라는 생각을 가지고 gcc --save-temps 옵션을 이용해서 컴파일 해보았다. *.i 파일을 열어보았지만, 아무런 단서도 얻지 못했다. 그럼 대체 뭘까. 질문을 해보았다.
받은 답변은 .bss는 디스크 상에서 섹션의 존재를 나타내기 위해서 4바이트를 할당한다는 것이다. 그냥 .bss 가 나 여기있어요!! 하면서 그냥 4바이트를 갖고 있는 것이다.
삽질한 것에 비해서 너무 허무했던 결과였다.. ㅋㅋ 그래도 bss 에 대해서 더 자세히 알게 되어서 뿌듯하다.