Exploit/System2012. 11. 14. 13:59

Format String Bug



printf("Hello World!");

다들 익숙하다 못해 반가우실겁니다.

printf는 c 언어를 배울때 가장 먼저 사용하게 되는 함수일거라 믿어 의심치 않습니다.


printf를 사용하는 모습을 먼저 살펴보도록 하겠습니다.


위의 실행 코드에서 "print int : %d"가 format string 입니다.

Format string은 이름 그대로 출력하려는 string의 format을 지정해줍니다.


위와 같은 코드도 사용하시는 분이 더러 있습니다.

짧고 좋습니다.

당연히 정상적으로 실행이 됩니다.

하지만 악의적인 목적을 가진 사용자에게는 허점을 제공해 준 셈이 됩니다.


printf 함수는 printf(a)에서 a를 format string으로 인식하게 됩니다.

a에 %d같은 형식 지시자가 들어있으면 형식 지시자 수만큼 stack에서 값들이 출력됩니다.


어차피 출력만 되는거면 별 문제없는게 아니냐 생각하시겠지만

%n이라는 다소 생소한 형식 지시자가 있습니다.

%n은 자신이 사용되기 전까지 출력된 문자 개수가 %n이 가리키고 있는 주소에 저장이 됩니다.

원하는 주소에 저장이 가능하다는건

프로그램의 흐름을 바꿀 수 있다는 뜻입니다.


기본적인 Format String Bug 공격을 시도해 보겠습니다.

공격 대상이 되는 데몬의 코드는 다음과 같습니다.

입력받은 string을 출력하고 종료합니다.

BOF 취약점도 보입니다.


해당 데몬은 bugbear라는 유저의 setuid가 걸려있습니다.


gdb로 attackme를 열어봅니다.

권한 문제로 debugging이 불가능하니 코드를 이용해 새로 컴파일한 후 debugging 합니다.


a에 접근하는 printf 주변을 찾아봅니다.

0xbffffa64부터 a가 시작됩니다.


이제 ret의 주소를 찾아보겠습니다.

함수가 끝날 때의 esp를 보면됩니다.


ret의 주소는 0xbffffaec입니다.


이제 format string과 stack에서 추출할 영역의 거리가 어느정도인지 알아봐야합니다.

바로 붙어있는 것을 확인할 수 있습니다.


마지막으로 한가지가 남아있습니다.

%n으로 ret의 값을 바꾸기엔 ret의 값이 너무 큽니다.

그러므로 반씩 잘라서 저장을 해줘야됩니다.


shell code의 시작 주소는 대충 nop slide 중간인 0xbffffa78쯤이 되겠습니다.


이제 공격 코드를 만들도록 하겠습니다.


먼저 형식 지시자가 나오기 전까지의 크기를 정하겠습니다.

%c를 통해 출력할 AAAA

%n을 통해 저장할 ret 주소 1

%c를 통해 출력할 BBBB

%n을 통해 저장할 ret 주소 2

Shell code와 nop slide까지 해서 총 50-byte로 만들겠습니다.


ret 주소 1에 저장할 값은 0xfa78입니다.

0xfa78은 64120입니다.

앞서 출력될 크기인 50을 빼면 64070이 됩니다.


ret 주소 2에 저장할 값은 0xbfff입니다.

0xbfff에서 앞서 출력된 수를 빼면 overflow가 발생합니다.

앞에 1을 붙여주고 계산하도록 합니다.

0x1bfff는 114687입니다.

앞서 출력될 크기를 빼면 50567입니다.


공격 코드

AAAA

0xbffffaec

(ret 1)

BBBB

0xbffffaee

(ret 2)

Nop slide + Shell code

(34-byte)

%64070c

(0xfa78 - 50)

%n

(ret 1)

%50567c

(0x1bfff - 0xfa78)

%n

(ret 2)


공격해봅니다.



공격에 성공했습니다.


'Exploit > System' 카테고리의 다른 글

Return To Library  (0) 2012.11.24
Race condition  (0) 2012.09.14
Posted by slimV