이름만 봐도 포맷 스트링 공격을 해야 할 것 같은 비주얼이다.
그럼 풀이 시작해볼까...!
checksec으로 확인하니 전혀 문제될 것이 없었다.
그럼 IDA로 까보도록 하겠다.
vuln함수를 호출하는 것을 볼 수 있다. 그럼 들어가 봐야지!
보니까 snprintf로 format에 s의 내용을 복사하는 것 같았다.
진짜는 return줄이다. printf의 인자에 format의 주소가 있고, 다른 인자는 없다.
이때 사용하는 공격 기법을 FSB(Format-String Bug)라고 한다.
F S B (Format-String Bug)
printf에는 다양한 출력 포맷이 있다. %d, %s, %c, %f, %n 등이 존재한다.
그런데 우리가 기본적으로 보는 printf 함수의 사용법은
" printf("%d",buf); "
와 같이 앞에 출력 포맷이 있고 그것을 가리키는 하나의 값 또는 변수가 들어가 두 개의 인자가 들어간다.
그런데, 개발자의 실수로 " printf(buf); " 라고 코드를 적은 경우가 있다.
그렇다면, 저 경우에 buf에 입력을 받을 때 "%d" 를 치면 어떤 일이 발생할까?
저기서 출력되는 것은 메모리 안의 값이다.
위에서와 같은 vuln() 함수에서는 printf 전에 함수가 호출되었을 때 인자의 정렬에 따라 출력 값이 달라진다.
그럼 그냥 출력 포맷만 적었을 경우 어떻게 되는지 확인해보자.
이런식으로 다음 4byte 뒤에 있는 메모리에 들어있는 값을 가져온다.
그럼 만약 임의의 문자열을 넣고 %x %x %x %x를 하면 어떻게 될까?
이렇게 2번째 %x에서 buffer에 넣었던 값이 나오게 된다.
'이걸 활용해서 "0x41414141"이라는 주소에 내가 원하는 값을 넣을 수 있지 않을까?'
이 생각으로 나오게 된 것이 FSB이다.
아까 %n이라는 처음 보는 출력 포맷이 있었다. 이것의 기능은 현재까지 출력된 바이트 수를 계산하고,
자신이 출력 포맷으로 출력했던 값(41414141)을 주소라고 생각하여 계산한 값을 그 주소에 집어넣는 것이다.
ex) 내가 AAAA %x %n을 하면, AAAA(4byte)+공백(1)+%x(4byte)+공백(1)=10이 %n의 위치에 해당하는 값(위에서는 0x41414141)에 들어가는 것이다.
현재 위에서 2번째 %x에서 입력한 첫 4byte가 나오므로 return에서 실행되는 printf의 got를 변조하여 flag함수를 실행하는 것으로 하겠다.
(tip! 만약 exit(0);이 존재한다면 그 함수의 got를 변조할 수도 있다.)
"AAAA"가 들어갈 자리에 printf_got를 적어주면, 41414141이라고 나왔던 것이 printf_got 주소로 바뀔 것이다.
또한, printf_got를 flag 함수의 주소인 0x80485b4=134514100으로 바꿔주기 위해 밑에와 같은 코드를 짤 것이다.
exploit code는 "printf_got(4byte)+%(134514100-4byte=134514096)x+%n"으로 하면 될 것이다.
실행시켜보면...!
flag를 획득할 수 있다.
'Hacking > HackCTF' 카테고리의 다른 글
HackCTF x64 Simple_size_BOF Write-up (0) | 2019.12.23 |
---|---|
HackCTF x64 Buffer Overflow Write-up (0) | 2019.12.23 |
HackCTF 내 버퍼가 흘러넘친다!!! Write-up (0) | 2019.12.23 |
HackCTF Basic_BOF #2 Write-up (0) | 2019.12.22 |
HackCTF Basic_BOF #1 Write-up (2) | 2019.12.22 |