NOTETips:
本教程于 2026.1 更新
由于教程是在 WSL 子系统教程之后编写的,只作为针对新手的补充,后续可以参照子系统的教程,相对来说没有子系统的教程细致,但是更适合新手
使用 VMWare:VMWare Linux 基础配置
使用 WSL:WSL Linux 基础配置
工具安装:基础 Pwn 环境安装
本教程默认你有了基本的计算机操作水平并且已经解决了任何网络问题
由于网页和图床代理到 Cloudflare,如果你浏览有些卡顿甚至加载失败,请自行加速并刷新
1. Pwn 基础环境安装
IMPORTANT
- 确保你使用了
pyenv,conda,venv等虚拟环境- 或确保你可以使用
pipx进行包管理- 或使用
apt安装
1-1 安装 Pwntools
apip install pwntools
pipx install pwntools
sudo apt install python3-pwntools
uv pip install pwntools
pythonfrom pwn import *
1-2 安装 GDB 以及 Pwndbg / GEF
首先需要安装 GDB
sudo apt install gdb gdbserver gdb-multiarch在此基础上我们会安装 Pwndbg / Pwngdb /peda / gef ,事实上 Pwndbg 是目前最常用的,gef 的非官方一个版本也很厉害,他们可以满足大部分需求,对于入门师傅来说,peda 不推荐使用了
1-2-1 安装 Pwndbg
TIP一键安装的 Pwndbg 的 gdb 默认支持异架构,无需使用 multiarch 版本
项目链接:
新版简化了安装流程,无需从源码安装,我们直接可以
apt install xz-utilscurl -qsL 'https://install.pwndbg.re' | sh -s -- -t pwndbg-gdb就安装好了,输入 pwndbg 即可使用
如果你想自定义安装位,你可以前往 Releases 下载压缩包解压到合适的位置
apt install xz-utilschmod 777 pwndbg_2025.05.30_x86_64-portable.tar.xztar -xvf pwndbg_2025.05.30_x86_64-portable.tar.xz解压之后会有四个文件夹出现,我们可以将当前文件夹的 bin 目录添加到环境变量,也可以将文件夹下的 bin 里的可执行文件链接到系统的任意环境变量目录下,这里采用了后者
sudo ln -s /path/to/pwndbg/bin/pwndbg /usr/bin/pwndbg测试一下

1-2-2 集成 Pwngdb 与去重
在任意目录下克隆库
git clone https://github.com/scwuaptx/Pwngdb.git克隆之后你可以看到 angelheap 和 pwngdb.py
修改 Pwndbg 启动文件
vim /path/to/pwndbg/bin/pwndbg其中最后一行为
exec "$dir/lib/ld-linux-x86-64.so.2" "$dir/exe/gdb" --quiet --early-init-eval-command="set auto-load safe-path /" --command=$dir/exe/gdbinit.py "$@"添加刚才两文件路径
exec "$dir/lib/ld-linux-x86-64.so.2" "$dir/exe/gdb" --quiet --early-init-eval-command="set auto-load safe-path /" --command=$dir/exe/gdbinit.py --command=/path/to/pwngdb.py --command=/path/to/angelheap/gdbinit.py "$@"可以使用一些特殊的命令验证是否安装成功

安装此插件会导致 Pwndbg 的 canary 以及 got 命令被替换,对于喜欢 pwndbg 的命令(或者是因为颜色)的人来说,你可以去搞一下这个
其实作者留下了一个兼容的脚本,就在 Pwngdb/pwndbg 中,不过由于更新问题兼容较为麻烦,这里我们有一种简单粗暴的方法


我们直接找到 /path/to/Pwngdb/pwngdb.py 使用直接注释法,把上图两个位置的函数注释掉就行
效果对比

和

1-2-3 GEF 安装(可以用于内核 / 异架构)
一键安装,但是安装到了并且只推荐以 root 身份安装
wget -q https://raw.githubusercontent.com/bata24/gef/dev/install-uv.sh -O- | sudo sh由于作者亲自说明是在 root 环境下测试,所以这里保持原位置
为了方便使用,可以:
sudo vim /usr/bin/gef#!/bin/shsudo /usr/bin/gdb "$@"然后赋予可执行权限
sudo chmod 777 /usr/bin/gef效果图

1-2-4 设置默认 GDB(可选)
这个基于个人习惯,如果习惯默认使用 Pwndbg 而只想输入 的话可以改一下名字
sudo mv /usr/bin/gdb /usr/bin/gdb-orisudo mv /usr/bin/pwndbg /usr/bin/gdb如果更改的话记得上面的 GEF 脚本要更改对应 GDB 二进制文件为对应名称
sudo vim /usr/bin/gef#!/bin/shsudo /usr/bin/gdb-ori "$@"如果是脚本里用可以指定
context.gdb_binary = '/path/to/gdb'1-3 安装其他小部件
如果你使用了 venv 或者是 anconda / miniconda 记得一定要激活环境,若未指定,请根据当前的环境管理方式自行决定工具的安装方式
conda activate <name>1-3-1 ROPgadget 与 ropper
用于搜寻在 ROP 攻击时使用的 gadget
apip install ROPgadget
sudo apt install ropper

1-3-2 one_gadget
用于在 libc 库中找到一个直接执行可以 getshell 的地址
sudo apt install ruby ruby-dev gcc makesudo gem install one_gadget
1-3-3 seccomp-tools
用于检测程序启用的沙箱保护
sudo gem install seccomp-tools
1-3-4 patchelf 与 glibc-all-in-one
由于题目在远程部署的环境和本地一定不相同,在某些对 libc 版本要求高的题目中需要更换指定的 libc
pip install patchelfgit clone https://github.com/matrix1001/glibc-all-in-one.gitglibc-all-in-one 官方页面在:
可以参考进行进一步下载不同版本 libc 的方式
cd ./glibc-all-in-one
./update_list # 更新列表cat list # 查看列表
./download <name> # 开始下载在之后使用 patchelf 即可
patchelf --set-interpreter <ld 位置> <文件位置>patchelf --replace-needed <需替换的 libc 类型,例如 "libc.so.6"> <libc 位置> <文件位置>或者patchelf --set-rpath <'动态库文件夹位置1(必选):动态库文件夹位置1(可选):......'> <文件位置>2. Pwn 特殊环境 - C++
并非完全体,还在更新
当我们目光看向一道 C++ 的题目,正常的 C++ 题目都会提供下面这几样库文件,使用 patchelf 更改就行

如果有些只给出了 libc.so.6 的话,你就需要手动下载其他的文件
2-1 下载对应发行版本的 libstdc++.so.6
2-1-1 从 Docker / 对应 Linux 里扒
很简单,如果题目给 Dockerfile 了,可以尝试部署题目的 Docker 环境,把用的库拷贝出来,使用 patchelf 或其他方式更改,如果没有就找 libc 或者是程序字符串寻找版本特征并从对应 Docker 或者 Linux 系统把缺的库扒出来
2-1-2 手动下载
如果你发现 patch 完之后会说你的 libstdc++.so.6 需要更高版本,那么你可能需要更换一下这个库,一般来说这个东西不吃小版本,也没必要对应 Ubuntu 的版本下载了,直接前往 Debian 官网下载对应版就行
访问官网:
点击下面有搜索,直接搜索

你要找的就是下面这样的,叫做 libstdc++6-xx-dbg 的包

如何确定你需要哪个?点进去看一眼版本

确认版本后就可以下载,如果程序需要的话,你可能还需要下载一个 libgcc_s.so.1

同时下面还有 dev 包供你选择,内含源码(可选,一般用不到)

2-2 替换程序使用的库
经测试,libm.so.6 有一定概率无法使用 patchelf 的 --set-interpreter 进行修改,我们可以通过指定环境变量 LD_PRELOAD 来强制替换该库,它的位置和 libc 与 ld 坐一桌,正常运行只需要
LD_PRELOAD=/path/to/target.so ./pwn# 示例 LD_PRELOAD=./libm.so.6 ./pwn如果你要引入多个,使用 : 隔开
LD_PRELOAD=./libc.so.6:./libstdc++.so.6:./libm.so.6:./libgcc_s.so.1 ./pwn