jujuwon
시크릿주주
jujuwon
전체 방문자
오늘
어제
  • 분류 전체보기 (106)
    • 🔠 프로그래밍언어 (35)
      • ☕️ Java (19)
      • 🐠 Python (15)
      • 🍠 Kotlin (1)
    • 🔙 Backend (16)
      • 🌿 Springboot (12)
      • 🐳 Docker (1)
      • ☁️ AWS (3)
    • 💼 CS (12)
      • 📶 Network (12)
    • 🕹 알고리즘 (14)
      • 📑 스터디 (2)
      • 💁🏻‍♂️ 백준 (9)
      • 👨🏼‍🔬 프로그래머스 (3)
    • 📚 Book (8)
      • 🔎 오브젝트 (4)
      • 🧪 TDD (2)
      • 📜 논문 (2)
    • 🔐 보안 (7)
      • 👾 Pwnable (7)
    • 📝 회고 (4)
    • 🧩 etc. (10)
      • ⚠️ issue (2)
      • 💡 꿀팁 (7)
      • ✏️ 끄적 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

최근 글

hELLO · Designed By 정상우.
jujuwon

시크릿주주

Pwnable.kr :: Toddler's Bottle - bof write up
🔐 보안/👾 Pwnable

Pwnable.kr :: Toddler's Bottle - bof write up

2021. 5. 14. 14:18
반응형

Pwnable.kr 의 세번째 문제를 풀어보자.

이번 문제는 Buffer Overflow 에 대한 문제이다.

Buffer Overflow 란, 데이터를 버퍼에 저장할 때, 데이터가 지정된 범위 바깥에 저장되는 것을 의미하고,

벗어난 데이터는 인접 메모리를 덮어쓰게 된다.

 

nc 로 접속하면 bof 파일이 바로 실행되고,

그 전에 wget 으로 bof 파일과 bof.c 소스파일을 다운받아보았다.

 

 

bof.c 소스파일은 main 함수와 func 함수로 이루어져 있다.

main 함수에서는 func 함수를 호출하는 거 이외에 별다른 코드가 없고,

0xdeadbeef 라는 값을 인자로 넘기면서 func 함수를 호출하고 있다.

func 함수에서는 0xdeadbeef 라는 값을 int 형 변수 key 에다가 넣고,

overflowme 라는 32byte 크기의 char 배열을 선언한다.

그리고 gets 함수로 overflowme 배열에 값을 입력받은 후, key 변수의 값과 0xcafebabe 라는 값을 비교하여

같으면 system 함수를 호출해 shell 을 실행시키고 있다.

 

여기서 문제를 해결하기 위해서 주목해야 되는 부분은 gets 함수이다.

gets 함수는 입력 크기에 제한이 없기 때문에 취약하다.

위 코드에서 배열을 32byte 크기 만큼 선언하고 gets 함수를 이용해 배열에 값을 입력받는데,

만약 사용자가 32byte 가 넘는 값을 입력한다면, 메모리의 다른 부분에 덮어씌워지는

Buffer Overflow 가 발생할 수 있다.

 

그럼 이제 고민해야 할 부분은 문제를 해결하기 위해서는 if 문의 조건을 만족시키는 것이다.

key 변수의 값과 0xcafebabe 를 비교해서 같아야 하는데,

key 변수에는 main 함수에서 파라미터로 넘겨준 0xdeadbeef 라는 값이 들어가 있고,

이것을 변경할 수 있는 부분은 코드에 보이지 않는다.

그렇다면 우리는 Buffer Overflow 를 이용해 key 변수 부분의 값을 덮어씌워야 한다는 결론에 도달한다.

 

 

위 코드를 기반으로 메모리 구조를 간단하게 그려보면 이런 식으로 될 것이다.

이 그림이 이해되지 않는다면 메모리 구조, 스택 프레임, 레지스터에 대해 간단히 공부해보자.

우리는 gets 함수를 통해 overflowme 배열에 데이터를 삽입한다.

이때 우리가 바꾸고 싶은 부분은 key 변수이고, 데이터를 몇 byte 삽입해야 key 변수 부분을

덮어씌울 수 있는 지만 찾으면 된다.

단순히 스택 구조로 생각하면 byte 를 유추할 수 있지만 dummy byte 가 삽입되어 있을 수 있기 때문에,

gdb를 이용해 확실하게 주소값을 찾아보자.

 

 

func 함수 부분을 disassemble 해보았다.

소스 코드와 비교해서 확인해보면,

첫 번째 call 은 printf() 이고, 두 번째 call 은 gets() 이다.

두 번째 call 밑 라인에 있는 cmp 는 key 와 0xcafebabe 를 비교하는 구문이다.

 

 

우리가 눈여겨 봐야 할 부분은 여기이다.

해석해보자면, printf() 함수 호출 이후

gets() 함수가 호출되기 이전에 ebp 에서 0x2c 만큼 뺀 부분을 eax 에 저장하고 있다.

이는 곧 overflowme 배열의 주소가 ebp-0x2c 라는 것이다.

또한 cmp 하는 부분에서 ebp+0x8 부분의 값과 0xcafebabe 를 비교하고 있다.

이는 ebp 에서 0x8만큼 +한 부분에 key 변수가 위치하고 있음을 나타낸다. 

 

 

최종적인 구조는 이렇게 될 것이다.

overflowme 변수와 key 변수 사이의 크기는 ebp 를 기준으로 -0x2c, +0x8 만큼 차이가 나므로,

52byte 만큼 값을 입력하면 overflow 가 일어나 값이 덮어씌워지고 key 변수 부분에도 원하는 값을 덮어씌울 수 있다.

페이로드를 작성해보면

 

 

flag 를 획득할 수 있다 !

728x90
반응형
    '🔐 보안/👾 Pwnable' 카테고리의 다른 글
    • Pwnable.kr :: Toddler's Bottle - random write up
    • Pwnable.kr :: Toddler's Bottle - passcode write up
    • Pwnable.kr :: Toddler's Bottle - collision write up
    • Pwnable.kr :: Toddler's Bottle - fd write up
    jujuwon
    jujuwon

    티스토리툴바