일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 앙버터마카롱
- 잠실새내 도그존
- promise처리
- 금별맥주
- 화이트해커를 위한 웹 해킹의 기술
- 지보싶 신촌점
- promise메서드
- 고르드
- graphql react native
- 홍대 예술
- 토라비
- 잠실새내
- 비동기배열
- useMutation error
- 신촌 소문난집
- 운정 소바동
- graphql with reactnative
- graphql
- 비동기배열처리방법
- apollo react native
- typescript
- graphql mutation error
- apolloclient
- graphql 400
- 홍대 카페 장쌤
- 화이트 해커를 위한 웹 해킹의 기술
- graphql with RN
- 홍대 토라비
- 도그존
- 예쁜술집 예술
- Today
- Total
yehey's 공부 노트 \n ο(=•ω<=)ρ⌒☆
FTZ level20 풀이 본문
id: level20
pw: we are just regular guys
이번에는 fgets에서 79바이트만 읽기 때문에 BOF를 사용할 수 없다.
printf(bleh)를 보면 일반적이지 않은 형식으로 bleh를 출력하고 있다.
C언어에서는 출력할 때 %d, %s, %c 등 과 같은 형식 지정자를 사용하는데 여기서는 이를 사용하지 않아 FSB(포맷 스트링 버그)가 발생한다.
FSB
위와 같이 문자열만 입력하는 것이 아니라 %x와 같은 형식 지정자가 일반 문자열에 포함되어 있으면 문자열을 출력할 뿐만 아니라 서식문자가 명령어처럼 실행되어 문자열로 입력하지 않은 부분이 출력되는 것을 볼 수 있다.
다음과 같이 스택이 구성되어 있을 때 print(bleh)가 실행되면 스택의 &bleh에서 바로 bleh의 내용을 가지고 오게 된다. 처음에는 AAAA, AAAA가 출력되지만 %x를 만나면 스택에서 &bleh 위의 값을 차례대로 읽어서 출력하게 된다. 이렇게 계속 출력하다보면 실제 blef 위치까지 이동해서 bleh 값까지 아스키 값으로 출력된다.
특히 형식 지정자 중 %n 은 현재 스택에 해당하는 변수 혹은 주소에 바로 이전에 출력한 값의 크기를 저장한다.
따라서 %n을 적절하게 사용하면 ret에 우리가 원하는 값을 덧씌울 수 있다.
우선 실행되어야 하는 쉘 코드를 환경변수에 저장해서 쉘 코드 주소를 얻어보자
쉘 코드의 주소는 0xbffffba9
이제 ret 주소를 알아내보자
ret 주소를 얻으려 gdb를 실행했지만 main함수가 없다는 메시지가 출력되었다.
해결방법을 찾아내기 위해 구글링한 결과 FSB 취약점 공격을 할 때는 보통 .dtors 영역을 사용한다고 한다.
.dtors 세그먼트는 gcc 컴파일 시에 자동으로 생성되며 main 함수 종료 후에 실행된다.
따라서 ret에 쉘 코드 주소를 넣는 대신 .dtors에 쉘 코드 주소를 덧 씌워보자.
위와 같이 .dtors의 주소는 0x08049594 이다.
우리는 여기에 +4 를 한 0x08049598 에 쉘 코드 주소 0xbffffba9 를 넣어줄 것이다.
(아직까지 의문인 부분은 왜 .dtors 세그먼트 주소에 4바이트를 더한 위치에 쉘 코드를 저장할까?)
이제 payload를 작성해보자
기본적인 흐름은 위와 같다
여기서 주의해야 하는 부분은 .dtors 주소에 쉘 코드 주소를 넣을 때 2바이트씩 나누어 입력해야하는 부분이다.
(x86에서는 일정 길이 이상의 숫자는 읽어들이지 못한다.)
왼쪽 그림처럼 .dtors에는 0xfba9가 .dtors+2에는 0xbfff가 들어가도록 %c를 구성해야 한다.
또한 %c 바이트 수를 계산해야하는데, 이 과정에서 %x에서 출력하는 바이트 수를 정확하게 지정해야 오류없이 전달할 수 있다.
따라서 %8x 로 8바이트가 항상 출력되도록 고정하자.
AAAA(4)+.dtors 주소(4)+AAAA(4)+.dtors+2 주소(4)+%8x *3 (24)
=40바이트
첫번째 %c에 도착하기 전에 40바이트가 출력된다.
.dtors에는 0xfba9=64,425 가 입력되어야 한다.
따라서 64425-40=64385 가 첫번째 c의 출력 바이트가 된다.
그 다음 %c는 앞서 64425가 이미 출력된 이후의 상태이다.
따라서 0xbfff=49151 에서 64425를 빼준 만큼 출력해야 하는데 값이 음수가 나오기 때문에 2의 보수를 이용해서 0x1bfff-0xfba9=50262 가 된다.
payload: (python -c 'print "AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64385c%n%50262c%n"';cat)|./attackme
위와 같이 쉘이 실행되었고
level20이 끝났다!!!
FTZ 마지막 문제 풀이 끝!
'wargame 풀이 > FTZ' 카테고리의 다른 글
FTZ level19 풀이 (0) | 2020.10.06 |
---|---|
FTZ level18 풀이 (0) | 2020.10.05 |
FTZ level17 풀이 (0) | 2020.09.30 |
FTZ level16 풀이 (0) | 2020.09.30 |
FTZ level15 풀이 (0) | 2020.09.29 |