문제파일을 ida로 열어보면 main함수가 있다. main함수에는 특별한점이 없으니 vuln함수로 넘어가자
var_808 에 입력을 받고, snprintf로 var_408 에 400만큼 출력하고 printf 로 var_408 을 출력한다.
하지만 코드에는 이상한 점이 있다. 바로 (%s 나 %d 같은)서식문자를 사용하지않는점인데,
이점은 포멧스트링 버그(Format String Bug) 로 이어질 수 있다.
포멧 스트링 버그는 문자열을 입력받을때 사용자가 서식문자를 입력하면 그 서식문자에 따라 출력이 된다.
한번 문제서버에 서식문자를 입력해보자.
AAAA %x %x %x %x 를 입력하면 그대로 출력되지않고 서식문자에 따라 16진수값들이 나오게된다.
이 16진수값들은 왼쪽부터 차례대로 스택에서 esp+4, +8, +12, +16 의 값을 가르키게되어
우리는 스택의 상태를 확인할 수 있다. 그렇다면 FSB 를 이용해 공격을 해보자.
[%n]
%n도 서식문자중에 하나인데, %n앞에 입력된 문자의개수만큼 변수값에 저장한다.
ex ) : printf("AA%n",&n); -> AA4
(주소) %c %n 이런식으로 사용해
%n으로 원하는주소에 원하는값을 쓸 수 있다. 이때 문자의 개수값은 %100c 처럼 원하는값을 넣을수있다.
그렇다면 쓸 주소를 정해보자.
위의 코드를 다시보면, printf에서 취약점이 터지는게아니라, snprintf함수에서 터지게된다. ( 둘다 서식문자를 사용하고있지않다 )
그렇다면 printf 함수는 사용자가입력한 서식문자를 적용한 문자열을 출력하게되므로 쓸모가 없게된다.
그렇기에 printf 의 GOT주소에 값을 쓰자
printf의 PLT주소에서 GOT주소로 점프하므로, printf의 GOT주소는 0x0804A00C
이 주소에 어떤값을 쓸까 함수목록을 찾아보면 flag함수가있다.
함수의 주소는 0x08085B4 이다.
[payload]
먼저 문자의 개수값을 정해보자. %(숫자)c 에서 숫자의 크기값을 원하는 주소에 쓸 수 있으므로
숫자를 flag 주소의 10진수값 - %n앞의 문자의 개수 로 넣으면된다.
80485B4h -> 134514100
AAAA %x %x %x %x 의 결과가 AAAA 0 41414141 XXXXXXXX XXXXXXXX
이렇게 출력되는걸 보면
- 1~4 : printf의 GOT주소
- 5 ~ 13: %(flag의 10진수값-문자개수)c
- 14 : %n
이렇게 payload를 작성하면 될 것 같다.
이제 %n앞의 문자의 개수를 구하면 134514100 - (주소4바이트) = 134514096
[최종 payload]
(python -c "print '\x0c\xa0\x04\x08'+'%134514096c%n'";cat) | nc ctf.j0n9hyun.xyz 3002