[Pwn] TJCTF 2019 Sledshop

2019. 4. 25. 17:00CTF/TJCTF2019

안녕하세요! 

오늘은 TJCTF 2019에서 출제된

sledshop 문제를 풀어보도록 하겠습니다!

 

해킹에 입문하는 미국 중*고등학생들을 위해

만들어진 대회이기 때문에

source코드도 제공되었습니다!

 

소스코드를 살펴보면

main 함수에서 3가지 함수가 실행됩니다!

shop_setup, shop_list, shop_order

 

이 3 함수중에서 취약점이 존재하겠죠?

 

(1) shop_setup 함수

id를 설정하는 함수 같네요!

저희가 입력하는 것도 없고

취약점이 없어보입니다!

 

(2) shop_list 함수

그냥 printf 함수로

출력문만 있는 함수입니다!

여기도 취약점이 없어 보이죠!

 

(3) 마지막으로 shop_order 

변수도 canary 선언되어 있고!

char형의 product_name 배열도 선언되어 있네요!

 

자, 여기에 이제 취약점이 있네요!

which product would you like?를 출력한 후

사용자에게서 입력을 받는데, 

 

gets함수로 받아서, product name에 저장하는데

사용자가 원하는 만큼 입력 값을 넣을 수 있기에,

product_name보다 크게 넣으면

overflow가 생기죠!

 

그리고 저희가 계속 overflow를 하다가 canary까지 

덮어 버리면, 

Sorry we are closed가 출력되겠죠?

canary가 더 이상 0이 아니기 때문이죠!

 

gdb를 통해서

얼마나 shop_order 함수가

메모리를 할당했는지 확인해보니

0x58 = 88byte만큼 할당했네요!

 

 

그리고 shop_order 함수+89지점에

breakpoint를 걸었습니다!

shop_order에서 leave지점입니다!

 

그리고는

shop_order의 return 주소가

어딘지 파악하기위해

4byte씩 끊어서 아래와 같이 입력했습니다!

그리고 ebp를 확인하고!

ebp+4를 해서 ret_address를 확인해보니!

uuuu가 나왔습니다!

(32byte 파일입니다)

 

그래서 a부터 t까지 저렇게 하이라이트 친 부분의 갯수를 구하니 

" 80문자를 복사했습니다! "

가 뜨네요!

 

81~84번째 순서가

ret_address네요!

 

그래서 payload를 작성하기 전에

어떤 보호기법이 적용되어 있나

확인하기 위해서 

checksec 명령어를 통해 아래와 같이 확인했습니다!

 

근데 보호기법이 쥐뿔도 안걸려있네요!

심지어 NX도 안걸려있네요!

PIE가 안 걸려있으니!

bss영역에 write 할 수가 있겠네요! (고정이니까요!)

 

그래서 저희가 할 exploit 방법은 

(1) shellcode를 고정적인 주소에 적는다

(2) 그리고 그 위치로 return 한다!

 

(1)의 경우 bss의 위치에 shellcode를 적을 거에요!

어떻게? gets함수를 호출해서요

 

1-1. return address에 gets 함수의 plt 주소를 넣는다

1-2. gets 함수의 ret 주소를 bss영역 주소를 둔다

1-3. gets 함수의 인자에 bss영역 주소를 둔다

1-4. gets 함수가 실행된 다음에, 쉘코드를 입력해야겠죠?

그걸 shellcode라는 변수에 미리 입력해두고!

shellcode 변수를 보내면 되요!

 

위에 있는 변수들

e, d, p는 기본 설정으로 해놓은 거에요!

e는 sledshop binary 다운받아서 ELF함수로 읽은 거구요!

p는 local에서는 process(e.path)으로 했었는데,

이건 server와 연결해야 하기때문에,

remote(서버, 포트)로 연결했습니다!

 

A를 80개 적은 이유는

저희가 return address 알기 위해서 

위에서 breakpoint 걸고

AAAABBBBCCCCDDDDEEEE... 

쭈욱 넣어서 찾은거 있죠?

더미로, ret_address전까지 채운거에요! 

 

그리고 sleep을 건 이유는

저희가 payload를 보내고

gets 함수에 입력을 넣을때 까지 delay가 있는게 

나은거 같아서 넣었습니다!

 

그리고 이렇게 하면 shell이 떨어질 것 같아서

마지막에는 p.interactive()를 추가했습니다!

 

payload 작성을 완료한 후,

python sled.py를 실행시키니

아래와 같이 쉘이 따지고

ls 명령어를 통해서

flag의 내용을 읽을 수 있었습니다!

고생하셨습니다!