好久没有更新博客了,因为作者太懒了,又懒又菜,今天来康康这道题,buuoj的babyfengshui_33c3_2016
分析elf文件
checksec一下发现canary保护和NX保护,got表没有保护,且随即地址没有开启。这就意味着got表可写,拖到IDA当中发现是一个经典的堆菜单题,以我现在的水平,那就是先分析它free后指针有无清零。本来一开始看它free了两个堆块,确指将一个指针清零了,以为是有uaf漏洞,但是后面发现不是这样的,它每一条目分一个name和对应的description,name且dscription是用指针指示,并且每个条目固定是80字节的大小,因此可以把一个条目看成一个结构体
1 | struct heap{ |
所以,我把整个结构体free了之后就相当于把这个description的指针清零了,因此本题不存在uaf漏洞。再观察添加一个项目的函数,发现name是固定长度输入,且用了fgets函数限定输入0x7c字节,整个name那就是不可能溢出了,就连off by null漏洞都不存在。那么这样的话只能看看edit函数了,edit函数它在之前if也会有一个长度输入,并且用了下面这一句if判断,如果为真就直接退出系统
1 | if((char *)(v3 + *(_DWORD *)*(&ptr + a1)) >= (char *)*(&ptr + a1) - 4 ) |
它这个是什么意思呢,翻译成c语言大概就是
1 | heap *item |
如果它们的地址之差小于输入的长度,那就退出,如果长度溢出到那个结构体堆块的metadata,那就退出。
看似这个也不能溢出,但是实际上这个能用一个方法绕过。因为如果我们直接分配堆块的话,它们物理地址是相邻的,但是如果它们不物理相邻,中间隔了一个堆块,那就可以任意溢出中间的堆块了。并且got表可写,我们是通过指针找到description的,如果把它溢出改成got表的地址,那么在edit的时候就可以修改got表的条目了。那么我们修改哪个?把free改成system,那么在free(item->description)的时候就会变成system(item->description),如果把item->description的内容改成”/bin/sh”,那么就可以愉快的getshell了。
这便是分析elf文件得到的信息。
编写脚本
先构造交互函数
1 | from pwn import * |
这里需要特别注意add函数,它有两个长度输入,一个是description的堆块大小,一个是description内容的长度大小。这个name其实没必要弄,因为利用不到,但是我还是弄了。
首先添加两个0x80大小description的堆块,这样得到了两个0x80和0x88的大堆块。free掉第一个堆块,因为都不属于fastbin范围的堆块,那么就会合并成0x108大小的堆块,那么接下来如果我再申请一个0x100大小的description就会得到这个free的堆块,那么就可以在这个堆块上溢出第二个堆块了。
下面是我的完整exp
exp
1 | from pwn import * |