Noleak
题目描述
题目来源:MiniL-2020
curd(增删改查)典型堆类题目、带后门函数
root@ubuntu:~/exp# checksec --file='/root/exp/time_management'
[*] '/root/exp/time_management'
Arch: amd64-64-little
RELRO: Partial RELRO(got可改)
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)(无aslr)
题目原理
简单来说unlink的题目原理
- 利用绕过unlink检查机制的固定套路后unlink
- 再根据实际情况进行系统堆管理数据进行篡改实现getshell
0x00 前置知识
堆结构
addr=堆块地址
用户原始修改区域是addr+0x10
addr(0~0x10)
储存了的系统管理数据(上一堆块长度、本堆块长度+上一堆块状态标志、fd、bk)
下一堆块的系统管理区域的size位,储存了上一堆块是否释放状态
ptr定义为全局堆地址管理存放的指针
共定义堆块0、1、2、3、4
整数溢出
调用者:
被调用函数:
条件:size=0 | i=0
为什么i <= (size-1)能通过呢?
原来是[[整数溢出]],(size-1)该变量的类型原先是无符号整数(unsigned int64)
↓
当size=0,size=size-1=-1(0xffff),汇编对于无符号负数转换:下界溢出
-1转换为无符号数是4294967295
所以i<=(size-1)
free、unlink的glibc代码
glibc的free
函数代码
glibc的unlink
代码
- 其实质是
往ptr里面写入了ptr-0x18的值
0x01 绕过unlink检测
手动修改堆块0的状态
标志位 | 解释 |
---|---|
0x00 | 释放Freed |
0x01 | 使用Used |
(这边涉及一个整数溢出的漏洞在edit,传入0可任意输入不限制长度的内容入堆,导致堆溢出)
详细:[[整数溢出]]
漏洞使用edit,利用堆溢出修改了系统控制区域 0x603030,将size的标志为改为0(Freed)(0xa1=>0xa0)
↓
随后系统将0x603000认定为释放块(下一堆块的系统(SIZE)区域记录了上一堆块的状态)
为下一步unlink做准备
同时将第一个堆块的fd、bk设置为(ptr-0x18)、(ptr-0x10)=>unlink内部会对bk、fd的地址检查
第二个堆块的bk设置为ptr,达到修改堆块0为ptr的效果
0x02 unlink
unlink
手动调用了程序的delete功能,delete(1)=>free
=>unlink
内存布局
相当于在堆块2(0x6030d0 )的系统控制(SIZE)的状态标志位为0x00(freed)
随后 0x603000、0x603030堆块被标记为freed
内存对比图(释放前、释放后):