unsortedbin_attack
知识点glibc2.23
我们知道当一个chunk大于0x80时,再free掉的时候会进入unsorted_bin (先进先出),这时如果我们通过堆溢出等手段改变这个chunk的bk指针,这样再申请这样的堆块,就可以达到把bk指针的值造成改变
好好说话之Unsorted Bin Attack_unsortedbin attack-CSDN博客
这个师傅的图讲这里很清晰,这里借用一下
这是unsortedbin将一个堆块挂入时发生的变化
这是,我们改变chunk_400的bk指针后再申请堆快回来
可以看到我们可以再target处改写一个字节大小的值
例题:buu hitcontraining_magicheap
保护
这里其实有个后门,就是magic地址的>4869时,会进入后门
所以这题的思路很清晰了,就是要改变magic的值
怎么改变呢,这里要利用之这里堆溢出和unsorted bin 结构
经典编辑函数时字节溢出漏洞
我们进入动态调试
先创建3个堆快,再free掉第二个
12345CreateHeap(0x30,'aaaa')CreateH ...
ret2csu及例题
写到newstar的week2才发现一直没写过有关ret2csu的博客,刚好有例题,乘着这个机会写个相关的知识点介绍
知识点
一般在二进制文件中一般有这样的两个函数,大部分的文件都有,我们今天的的csu的汇编就是在这两函数的下面
这就是我们今天的主角
先来介绍一下这两函数
下面的部分函数(我们称之为csu2)(主要是改变寄存器的值)
123456789loc_4013A6: add rsp, 8 pop rbx pop rbp pop r12 pop r13 pop r14 pop r15 retn
这段代码应该都看的懂,就是先把rsp栈顶寄存器+8,再依次把参数弹入相应的寄存器中去
在这个漏洞利用之中一 ...
fastbin_attack
fastbin_attack这里的版本是2.23的glibc
double freedouble free就是在一个函数中重复free了一个chunk
假设有这样的函数
1234567*p1=malloc(0x10) ; //chunk1*p2=malloc(0x10);*p3=malloc(0x10);free(p1);free(p2);free(p3);
这个时候fastbin中的指针会是这个样子
fastbin[20]–>chunk3—>chunk2—->chunk1
这个时候如果我们这样
123456*p1=malloc(0x10) ; //chunk1*p2=malloc(0x10); //chunk2free(p1);free(p2);free(p1);
fastbin[20]–>chunk1—>chunk2<—-chunk1
这个时候molloc(0x10)
改写chunk1中的fd的地址使其指到bss段
这样
fastbin[20]–>chunk2—>chunk1—>bss
连续malloc三次就可以得到一个可 ...
buu刷题脚本
第二页[ZJCTF 2019]EasyHeap这里有几个点,首先要用ret把栈的地址叠高,这样防止exp覆盖函数原来的数据
第二个就是
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768from pwn import *#p=process('./pwn')context(log_level='debug')p=remote('node5.buuoj.cn',27294)elf=ELF('./pwn')libc=ELF('./libc-2.23.so')free_got = elf.got['free']puts_got = elf.got['puts']puts_plt = elf.plt['puts']+0x16system ...
pwn堆—unlink
知识点就我自己的理解,unlink就是大概就是在unsortedbin中这样的双向链表中,在第一个堆中写入伪造的一个堆结构,溢出到第二个堆的prve_size,和size位时,改size的最后一位为0,这样free第二个堆时,会触发堆的合并机制,在改写第一个堆的内容是可以造成一个任意位置的读写
保护检查下面是一个大佬总结的 大佬的文章
检查1:检查与被释放chunk相邻高地址的chunk的prevsize的值是否等于被释放chunk的size大小
可以看左图绿色框中的内容,上面绿色框中的内容是second_chunk的size大小,下面绿色框中的内容是hollk5的prev_size,这两个绿色框中的数值是需要相等的(忽略P标志位)。在wiki上我记得在基础部分有讲过,如果一个块属于空闲状态,那么相邻高地址块的prev_size为前一个块的大小
检查2:检查与被释放chunk相邻高地址的chunk的size的P标志位是否为0
可以看左图蓝色框中的内容,这里是hollk5的size,hollk5的size的P标志位为0,代表着它前一个chunk(second_chunk)为空闲状态
...
UAF漏洞(hitcontraining_uaf)
知识点学到这里感觉学的很乱,感觉什么都要去了解,但是什么都不是很了解,可能学到后面的点把这些知识点串起来就好了吧。
UAFuse after free顾名思义就是在这个chunk被free后面进行利用
当一个chunk被free后,这个函数内部的数据不会马上清除,这些数据会被保留在原来的位置,然后这个chunk会被标记为free后,并且会根据chunk的大小被分到不同的bin中去,有(fastbin,unsorted bin,large bin….)这些bin就是以链表的形势把这些free后chunk链在一起
例题下面以buu上面的hitcontraining_uaf进行说明
这个题目应该在glibc2.23环境中运行,但是这个题目大部分环境都可以打,就没改了
检查保护
ida打开
函数运行的时候会进行菜单选择
这里的delete函数中
这里可以看到free掉函数后面没有把函数的指针置零
因此这里存在漏洞
同时这个题目存在后门函数
先申请两个堆块
这个时候再free掉
free后面的bin
这个时候我们add(0x10,magic_addr)
因为在printf函数 ...
栈迁移(详解)
栈迁移我有罪,写错了好久才被发现(已更正)
原理
栈迁移主要利用了leave_ret这个指令
leave
返回上级函数时,恢复原本的栈空间
leave
mov esp,ebp pop ebp
ret
返回上级函数后,执行上级函数的命令
ret
等同于 pop eip (不存在这样的指令
ret是把栈顶的元素弹到rip中,之前这里没有理解,一直搞错了,抱歉
1234esp'''ebpret
在函数的先执行到leave指令时,会将ebp处填充的地址pop到ebp中去,这样栈基地址发生了变化,在下次的栈位置就会发生变化
有个图对这些指令变化阐 ...
羊城杯比赛pwn复现
首先推荐这个博客
本篇学习的思路来自这个大佬
实力有限,只复现出了pstack这一题
pstack
知识点这个题目是个很经典的栈迁移的题目,因为栈溢出的空间不够,但是常规的栈迁移一般有方法获得一个地址来进行leave_ret
这个题目有个很妙的点
这里call 完read后面有一个leave_ret(平时没注意过)
本题的核心就在于对这里进行反复利用
题解由于leave_ret这个指令
两次这样就可以控制rbp 和rsp
这里重点讲下调用vuln_read这个函数后面的过程
这里我们动态调试
123456789101112131415161718192021222324252627from pwn import *from LibcSearcher import *context(log_level='debug')p=process('./pwn')elf=ELF('./pwn')libc=ELF('./libc.so.6')bss=elf.bss()+0x500leave_ret=0x4006dbr ...
off-by-one
知识点通过堆块的错位来改变下个堆块的size位置,从可以改写指定的位置的函数
题目npuctf_2020_easyheap参考
64位 可以改写plt表
点开就是菜单
这个存在溢出漏洞
解法先创造两个chunk
通过改写chunk0(第一个)溢出通过溢出多一个字节(0x41)使得下面两个堆块整合到一起
接着free chunk1(第二个chunk)
再重新申请一个大小为0x38的块
可以看到之前的0x41申请回来了
这个发的是’a‘
利用上个改写41溢出导致下个堆块记录输入内容的地址发生变化
这里把那个地址改成了free函数
泄露libc通过题目里面的show函数泄露free处的libc
就是这个堆块的返回地址已经变成你指定的位置了,无论是输出还是改写就容易了
最后找到system 将free函数改成system加上前面写入的/bin/sh\x00EXP123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 ...
武功山杯pwn复现
穿云入雾这题nc连接后输入WuGongShan_i_Come
安源路矿
canary保护和NX保护
利用上面这个函数溢出一个泄露canary 还可以泄露在这里的rbp
这里泄露出来了
关键然后当我想正常走ret2libc的流程的时候发现在连接后会出现超时的情况
这个时候,在高人指点下(赛后)发现可以利用一种类似于栈迁移的方法,就是利用上面泄露的rbp将函数puts完后回到puts这里,puts出puts的got表,之后在进行one_gadget(ret2libc超时)
但是要注意这里的rbp有变化
read到puts rbp-0x50
最后exp如下
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465from pwn import *from LibcSearcher import *context(log_level='debug')libc=ELF('. ...