프로그래밍/C

파도파도 끝이 없는 bss에 대하여

2018. 2. 14. 23:17

예전에 bss 영역에 대해서 정리한 포스트와는 다르게, 오늘 bss에 대해서 새롭게 알게 된 사실이 있어서 여기에 적어보도록 하겠다.. 

( 해당 포스트에서는 bss 영역이 초기화되지 않은 전역변수를 갖고 있지 않아도 규칙적으로 4bytes 를 갖는 것에 의문이 들어 정리한 글이다. )



초기화되지 않은 전역변수가 없을 경우에도 bss section은 4 bytes의 크기를 갖게 되는데, 이 때 들어가는 값은 0x00000000 이다. gdb로 값을 보면, <completed.7200> 이렇게 표현되어 있는데 아무리 구글링을 해도 나오지가 않는다. 



(예제로 사용한 코드는 "Hello world"를 출력하는 단순한 프로그램이었다.) 그냥 bss 영역이 "나 여기 있어요!!"라고 소리치는 값으로 생각하면 될 것 같다. 


bss의 숨겨진 값... 

 사실 bss는 초기화되지 않은 전역변수를 넣는 공간이기 때문에, 프로그램에서 정확히 어떤 역할을 하는지 몰랐었다. 더군다나 초기화되지 않은 전역변수가 선언되지 않았더라도 4 bytes의 공간을 갖고 있었기 때문에 굳이 존재할 필요가 있을까라는 생각을 하고 있었다. 

 근데 개쩌는 것이 stdin과 bss 영역은 서로 관계가 있다는 것이다..! 
 여기 stdin을 이용해서 간단한 입력을 받는 프로그램이 있다. 

해당 코드를 컴파일한 ELF 파일을 헥스레이해보면, 

fgets(buffer, 64, stdin); 이 코드는 아래의 코드로 보이게 된다. 

fgets(buffer, 64, _bss_start);



wow,,, 사실 stdin은 _bss_start 였던 것이다.. 



여러 번의 삽질.. 

 여러 번의 삽질 끝에, stdin은 bss에 들어간다는 것을 알게 되었다. 


해당 프로그램은 bss 영역의 주소가 0x0804a020 이고 크기가 0xc(12)인 프로그램이다.  main 함수 안에 bp를 걸고 bss 영역을 보자. 



stdin이 들어있다!! 


bss 영역에는 이렇게 3가지가 있다. 

------------------------------------------------------------------------------

| stdin | <completed.7200>(?) | 내가 추가한 초기화되지않은 전역변수 | 

------------------------------------------------------------------------------


bss 영역에 stdin은 포인터 형식으로 저장된다. bss에 저장되어 있는 주소를 보면 



stdin도 fd이기 때문에 fd struct가 있다. 진짜 신기한 bss의 세계이다...



이렇게 알게된 bss의 exploit 상에서의 활용

나는 보통 rop 공격시, /bin/sh 을 &bss에 넣는다. 하지만, 그냥 쌩으로 bss에 넣으면 stdin이 있을 경우, 프로그램의 흐름이 망가질 수 있다. 따라서, 이런 경우를 미연에 방지하기 위해서 &bss + 16 에 /bin/sh 를 넣어야 할 듯하다. 




참고로..

 참고로, stdout을 써도 bss에 저장된다. 


stdin 뒤에 있는 주소가 stdout의 주소이다.