pwnable.kr之unlink

 

前言:

这道题目应该是pwnable.krToddler's Bottle最难的题目了,涉及到相对比较难的堆利用的问题,所以拿出来分析。

 

 

登录

 

 

 

看看源程序

 

 

 

程序中有几点要注意的地方:

1. 定义的OBJ结构体中一个指针4字节,buf[]数组8字节

2. Unlink()的过程其实就是双向链表中摘下中间那一块的过程

3. 主函数中malloc了三个结构体,并通过指针连成了双向链表A<->B<->C

4. 打印出A的栈地址,堆地址,这两个地址这里记做stack,hep,待会儿在分析中会用到

5. 漏洞在于gets函数会造成溢出,同时通过随后的unlink()进行利用

 

 

具体而言什么是unlink呢?

unlinked 是堆溢出中的一种常见形式,通过将双向列表中的空闲块拿出来与将要free的物理相邻的块进行合并。(将双向链表上的chunk卸载下来与物理chunk合并)Unlink漏洞的利用条件就是3个以上的空闲chunk链表,其中最前面的chunk存在有堆溢出。没错我们这次的题目就存在这个情况

 

解链的原理相信学过数据结构的师傅们都清楚了

 

 

 

对照着这次的程序,BK相当于A,P相当于BFD相当于C

 

这次需要用到的漏洞溢出漏洞技术称为Dword shoot在进行双向链表的操作过程中,有溢出等的情况下,删除的chunkfdbk两个指针被恶意的改写的话,就会在链表删除的时候发生的漏洞。

对应到本题的程序,将被删除的chunkB,而我们可以通过溢出A来修改Bfdbk,修改后会引发什么漏洞呢?我们接下来详细说明。

 

把二进制文件下到本地分析

 

 

 

要我们攻击的最终是目的是劫持返回地址,写入shellcode的地址,以及为了能够溢出A,修改B的指针等操作,我们都需要看看汇编中一些关键量的地址

 

 

 

 

 

 

关键的地方:

  1. A在栈上的地址是ebp-0x14,即ebp-0x14=stack=&A
  2. 最后的ret,作用是赋值给eip寄存器,而我们要做的就是修改esp寄存器的内容为shellcode的地址
  3. 通过lea esp,[ecx-0x4]可以知道esp的值来自[ecx-4]
  4. leave指令对esp没影响
  5. mov ecx,DWORD PTR[ebp-0x4],可知,ecx的值来自[ebp-4]
  6. 综上,我们只需要把shellcode的地址写到[ebp-8]地址(事实上这样很不方便,我们下面实际上是把shellcode地址+4写到[ebp-4]地址,这样的话,shellcode地址+4-4,传给esp的时候恰好就是shellcode的地址)

推论:

1)由1得,ebp-4等于stack+0x14-0x4

2heap_A在堆中的地址,加上在buf前有fdbk链各个指针共8个字节,所以shellcode的地址是写到了heap+0x8处,所以 (shellcode地址+4)=heap+0x8+0x4

 

只要实现了* (ebp-4)=&shellcode+4,则ecx就被覆盖成了&shellcode+4,然后执行了

   0x08048603 <+212>:   lea    esp,[ecx-0x4]

   0x08048606 <+215>:   ret    

我们就拿到shell

 

 

 

 

我们前面留下了一个问题:

被删除的chunkB,修改Bfdbk,修改后会引发什么漏洞

先举个简单的例子看看

设我们修改了B->fd=!!!!,B->bk=@@@@

在调用unlink(B)时,

    BK=P->bk;

FD=P->fd;

FD->bk=BK;

BK->fd=FD;

对应执行的流程是这样子的

BK=*(B+4)=@@@@   //B->bk前还有B->fd,4字节

FD=*(B)=!!!!

*(FD+4)=*(!!!!+4)=BK=@@@@

*(BK)=*(@@@@)=FD=!!!!

 

通过红色字体的关系,我们知道,修改了Bfd,bk之后,就可以在进行覆盖操作

这里我们设修改了B->bk=[ebp-4],B->fd=&shellcode+4

则进过unlink(B)之后会有

*(&shellcode+4+4)=[ebp-4]   //这个结果无影响

* (ebp-4)=&shellcode+4    //实现了* (ebp-4)=&shellcode+4,因为*(ebp-4)覆给ecx,则ecx就被覆盖成了&shellcode+4,然后就可以拿到shell

 

 

接下来具体看看怎么布局

我们知道

shellcode地址+4=heap+0x8+0x4=heap+12,来修改B->fd

ebp-4=stack+0x14-0x4=stack+16,来修改B->bk

Abuf大小是8字节,写了shellcode地址花了4字节,因为最小单位为16字节,所以还剩16-4=12字节需要填充,我们填充12A

综上,得到了如下的布局

 

 

 

shellcode的地址是什么呢

 

 

 

heapstack的地址每次运行时都会打印出来的

 

 

 

 

 

 

 

综上,写出exp

 

 

 

上传到服务器

 

 

 

 

 

执行得到shell

 

 

 

 

 

值得注意的是,本题的unlink利用是比较古老的方式了,现在的glibc已经加入了很多新的保护措施

包括:

Double Free检测

该机制不允许释放一个已经处于free状态的chunk。因此,当攻击者将second chunksize设置为-4的时候,就意味着该sizePREV_INUSE位为0,也就是说second chunk之前的first chunk(我们需要freechunk)已经处于free状态,那么这时候再free(first)的话,就会报出double free错误。相关代码如下:

#!c

 

 

 

next size非法检测

该机制检测next size是否在8到当前arena的整个系统内存大小之间。因此当检测到next size-4的时候,就会报出invalid next size错误。相关代码如下:

 

 

 

双链表冲突检测

该机制会在执行unlink操作的时候检测链表中前一个chunkfd与后一个chunkbk是否都指向当前需要unlinkchunk。这样攻击者就无法替换second chunkfdfd了。相关代码如下:

 

 

 

 

 

 

也出现很多新的技巧的关于unlinkCTF题目,如:

HITCON 2014 stkof

0CTF 2016 – Zerostorage

0CTF 2015 'freenote'

HITCON CTF 2016: Secret Holder

强网杯2018 silent2

这些题目有兴趣的师傅们可以自行去pwn

 

参考:

1.https://paper.seebug.org/papers/Archive/drops2/Linux%E5%A0%86%E6%BA%A2%E5%87%BA%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E4%B9%8Bunlink.html

2.https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit.html

3. https://paper.seebug.org/papers/Archive/refs/2015-1029-yangkun-Gold-Mining-CTF.pdf

4. https://cysecguide.blogspot.com/2017/10/pwnablekr-unlink-solution.html

5.cft wiki

posted @ 2020-06-16 09:14  SKLOISer  阅读(335)  评论(0编辑  收藏  举报