프로그램의 스택 시작 주소를 출력하는 간단한 코드이다.






위 코드를 컴파일 후 실행하면 0xbffff0c8 주소가 출력 된다.






하지만 같은 프로그램을 gdb에서 실행시키면?? 그림에서 보이는 것 처럼 0xbffff0c8이 아닌, 0xbffff0b8이 출력 된다.


/proc/sys/kernel/randomize_va_space의 값을 0으로 설정해서 ASLR(Address Space Layout Randomization)이


일어나지 않게 설정을 했는데도, 셸에서 실행했을 때와 gdb에서 실행했을 때 스택 주소가 미묘하게 차이가 난다.


(ASLR 관련 글 : http://huammmm1.tistory.com/498 )



문제의 원인은 바로 환경변수에 있었다. 프로그램이 메모리에 올라갈 때 스택에는 가장 높은 주소에서부터 차례 대로


환경변수들, 프로그램에 전달하는 인수들, 프로그램이 사용하는 지역변수들이 자리잡게 되는데, gdb가 자체적으로


사용하는 환경변수들이 있기 때문에 gdb로 실행했을 때는 스택의 주소가 미묘하게 달라지는 것이었다.






gdb로 실행했을 때 show env 명령어를 입력하면 현재 gdb에서 사용하는 환경 변수들의 목록을 볼 수 있다.


보통 프로그램을 실행하면 시스템에 설정된 환경변수들을 상속받아 사용하기 때문에 그림에서 보이는 것 처럼


시스템에 설정된 환경변수들(TERM, HOME, PATH 등)을 볼 수 있다.







위의 그림에서는 env에다가 i옵션을 주고(--ignore-environment) gdb를 실행하도록 하고 있는데,


env -i gdb sp


이는 gdb를 실행할 때 기존의 환경변수들을 상속받지 않도록 하라는 의미가 된다.


그리고 show env를 입력했더니 이번에는 LINES 환경변수와 COLUMNS 환경변수만 출력 된다.


이 두 환경변수는 gdb 내에서 사용되는 환경변수인데, gdb가 이 두 환경변수를 내부적으로 사용하기 때문에 셸에서


출력한 esp의 값과 gdb에서 출력한 esp의 값이 달라지는 것이었다. 


(두 환경변수가 추가적으로 스택에 들어가야 하므로 gdb에서 출력한 esp의 주소가 더 낮아지게됨)






원인을 알았으므로 셸로 돌아온다음에 gdb를 다시 실행시킨다.


그리고 나서 unset env 명령어를 이용해서 gdb에서 LINES 환경변수와 COLUMNS 환경변수를 사용하지 않도록 설정


한 다음에 실행을 하면 이번에는 셸에서 실행시켰을 때와 동일한 0xbffff0c8 주소가 출력된다.






참고로 c프로그램의 argv[0]로는 프로그램을 실행시킨 경로가 전달이 되고, 이 문자열도 환경변수들과 같이 스택에


저장되기 때문에 ./sp 처럼 상대경로로 sp를 실행했을 때와 /home/huammmm1/sp 처럼 절대경로로 sp를 실행했을


때 esp의 값이 서로 다르다. 따라서 이것 또한 셸에서 실행했을 때와 gdb에서 실행했을 때의 스택 주소가 달라지는


원인이 되기도 한다.



참고 자료 : http://stackoverflow.com/questions/17775186/buffer-overflow-works-in-gdb-but-not-without-it/17775966#17775966






Posted by huammmm1
,