티스토리 뷰

 

카테고리

PWNABLE

 

문제

32bit elf 바이너리인 easy_fsb_ 파일이 주어졌다.

IDA로 열어봤다.


지역변수인 buf에 100 바이트만큼의 입력을 받고 이 변수를 printf로 바로 출력하는 간단한 프로그램이다.

버퍼 오버플로우는 존재하지 않으며, printf가 변수를 포맷 없이 출력하고 있으므로,

변수에 "%x"등을 입력할 경우 이것을 문자열이 아닌 포맷 스트링으로 인식하는 Format String Bug가 발생한다.

 

"AAAA%x%x%x%x%x%x%x"를 입력할 경우, 스택의 값들이 출력되는데 이때 일곱 번째 %x에서 "AAAA"에 해당하는 값인 "41414141"이 출력된 것을 확인할 수 있다.

이 위치가 입력 데이터가 들어가는 변수인 buf의 시작 지점이다.

 

printf에 사용되는 포맷 스트링 중 "%n"이라는 특별한 포맷 스트링이 있는데, 지금까지 출력된 문자열들의 자릿수를 다음 스택에 기록된 주소 위치에 기록하는 기능을 한다.

즉, printf 함수로 입력이 가능해진다.

 

A라는 주소에 B라는 값을 쓰고 싶다면,

스택(buf)에 A를 쓰고, printf로 B만큼의 문자열을 출력한 후 "%n"을 이용하여 A에 B를 쓸 수 있다.

이 문제에서 입력 데이터는 일곱 번째 스택에 들어가므로 "%n"의 대상은 일곱 번째 스택이 되어야 한다.

 

 

 

이제 원하는 주소에 원하는 값을 기록할 수 있게 되었다.

어떤 주소에 어떤 값을 쓸까?

shell을 띄우거나 flag를 읽기 위해서는 system 함수를 사용하고 싶다.

printf 함수의 got를 system 함수로 overwrite한 후, for문을 통해 read와 printf 함수가 다시 실행된다면

printf 함수는 system 함수로 바뀌고 내가 입력한 값은 system 함수의 인자로 들어갈 것이다.

 

 

system 함수의 주소는 어떻게 알아낼까?

이 대회에서는 친절하게도 문제 서버의 라이브러리를 공개했다.

해당 라이브러리를 사용하여 printf 함수의 실제 주소와 system 함수의 실제 주소의 offset 차이를 알아내면

문제에서 사용하는 printf 함수의 실제 주소로부터 system 함수의 주소를 계산할 수 있다.

 

 

문제에서 사용하는 printf 함수의 실제 주소는 어떻게 알아낼까?

이때는 다시 printf 함수의 포맷 스트링을 이용한다.

%x, %d 등의 숫자를 출력하는 포맷 스트링들은 스택의 값을 그대로 출력하지만

%s, %c 와 같이 문자열을 출력하는 포맷 스트링들은 스택의 값을 주소로 인식하여 그 주소에 기록된 값을 출력한다.

 

그렇다면 스택에 printf함수의 got를 기록하고 %s로 읽어오면 printf함수의 got에 기록된 printf함수의 실제 주소가 나타난다.

이때, printf함수가 한 번이라도 호출되지 않으면 got는 plt+6을 가리키고 있으므로 printf함수가 한 번이라도 호출된 상태에서 got의 값을 읽어와야 한다.

for문이 10번 반복되니 기회는 충분하다.

 

exploit

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함