根据先知社区的一位大佬复现,地址:https://xz.aliyun.com/t/6087
这位大佬还有unlink的操作,我之后了解unlink的时候,会用这道题再来研究一下。
最近对heap稍有一点感觉,准备复现一下题目,一下上手offbyone,感觉现在自己还是太菜了,还有很多疑问,准备留下这篇博客记录一下。
到最后还是找到了大佬,最后自己也差不多了解了漏洞知识,他的博客地址就在我书签那,ID:ERROR404
offbyone的漏洞位置:
书本结构体:
1 | struct book{ |
解题思路:(此题开了pie,我是多次调试的,地址可能些不同,请以本人具体调试的为准)
1.构造两个结构体之后,堆的情况:
1 | create(48,"1a",240,"1b") #0 |
这边认识一下结构体,直接去看0x20020那边的参数,我这边输入0x1f个’a’先看看,打印结构体就不会泄露地址先。
因为有标白的\x00存在,所以地址就打印不出来:
将Author的地址直接填满(大小为32,具体在ida里有),就能泄露我们上上图像泄露的地址了:
2.伪造结构体
1 | payload = "a"*0xa0 + p64(1) + p64(first_heap_addr+0x38) + p64(first_heap_addr + 0x40) + p64(0xffff) |
目的是为了伪造一个结构体,让结构体的指针指向libc的残留地址,现在看一下堆的情况:
具体看一下堆的情况,看一下源结构体后面那俩地址到底指向哪了:
3.用offbyone的漏洞:
1 | author_name("author".rjust(0x20,"a")) |
将地址最低位覆盖成\x00,这样我们我们的那个堆块1的指针就指向了我们自己伪造的结构体了,这个结构体description和name我们指向了book2结构体,这样我们通过编辑堆块1的description就能改掉book2的结构体的description指针和name指针,我们能编辑book2的description,相当于任意写了。(引用地址:https://xz.aliyun.com/t/6087)
这样,打印堆块1,我们就可以泄露三号堆块里面的libc残留地址,用来计算libc_base,
4.打印一下堆块1的内容:
如果没有用offbyone那个漏洞,我们再来打印一下堆块1的内容:
我现在就是疑惑offbyone那个漏洞,多出来的0到底去哪了,文章写的内容(引用地址:https://xz.aliyun.com/t/6087)
将地址最低位覆盖成\x00,这样我们我们的那个堆块1的指针就指向了我们自己伪造的结构体了,这个结构体description和name我们指向了book2结构体,这样我们通过编辑堆块1的description就能改掉book2的结构体的description指针和name指针,我们能编辑book2的description,相当于任意写了。
后来发现是去修改book1结构体里面的*name的最后两位地址,变成00之后直接指向我们伪造的结构体里面,去泄露我们需要的libc偏移地址。
5.获取shell
任意地址写堆块一,让堆块一指向freehook的地址,然后用往堆块二(相当于往freehook)写入onegadget去获取shell
1 | one_offset = [0x45216,0x4526a,0xf02a4,0xf1147] |
这里贴几张图,大家理解一下,(有不明白的可以留言):
题目地址:https://github.com/Jaytain/ctf-challenges/tree/master/pwn/heap/off_by_one/Asis_2016_b00ks
最后exp:
1 | from pwn import * |