GDB/pwndbg/gef 动态调试

SkillDev tools

GDB/pwndbg/gef 调试:attach、断点、内存读写。 触发词:gdb、调试、pwndbg、attach

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the GDB/pwndbg/gef 动态调试 skill

What this skill tells your AI

The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-gdb/SKILL.md and read by ahel’s review.

何时使用 / 何时不用

  • 用:Linux 目标动态调试(attach/启动/断点/内存读写);core 文件分析;Wine 下调试 PE 进程
  • 不用:Windows 原生目标(走 [[re-x64dbg]],或 Wine 内 gdb 见 [[re-analyze/platform-tips]] Linux 分支);macOS 目标(走 [[re-lldb]])
  • 不用:只读内存不调试(默认转储优先,走 [[re-memdump]])

工具准备

参考 [[re-analyze/platform-tips]]:动态执行默认沙箱;Linux 分支的 Wine 进程 attach 经验;直读 vs 转储 决策——attach 失败即转 [[re-memdump]]。

gdb

  • Linux: apt install gdb / dnf install gdb / pacman -S gdb
  • macOS: brew install gdb(需自签证书,一般直接用 lldb 更顺)
  • WSL: Linux 包直接可用(跨 Windows 边界 attach 不可行,见 [[re-analyze/platform-tips]] WSL 分支)
  • 验证: gdb --version

pwndbg / gef(二选一,装到 ~/.gdbinit)

  • pwndbg:
    git clone https://github.com/pwndbg/pwndbg
    cd pwndbg && ./setup.sh        # 自动装依赖并写 ~/.gdbinit
    
  • gef:
    curl -L https://github.com/hugsy/gef/raw/master/gef.py -o ~/.gdbinit
    
  • 验证: 进入 gdb 出现 pwndbg/gef banner
  • 注意: 两者都写 ~/.gdbinit,不要同时装(后装的覆盖前装,残留脚本互相干扰);版本滚动较快,功能差异以各自官方 README 为准(详见 [[gotchas]])

checksec(二进制防护检查)

  • pwndbg 内置 checksec 命令(装好 pwndbg 即用)
  • pip install pwntoolspwn checksec --file ./target
  • 验证: gdb -q -ex 'checksec' -ex quit ./target 输出 NX/Canary/RELRO/PIE

操作步骤

  1. attach 前查 ptrace 权限

    cat /proc/sys/kernel/yama/ptrace_scope
    # 1 = 仅父进程可 attach(默认);0 = 任意同属主;容器内常被强制禁止
    sudo sysctl -w kernel.yama.ptrace_scope=0   # 临时放宽(重启还原)
    
    gdb -q -p <pid>          # 同属主或 root;失败(Operation not permitted)→ 见坑 1
    

    沙箱容器内 attach 常被 seccomp 拦 → 直接走 [[re-memdump]] 转储。

  2. 断点/单步/条件断点

    (gdb) file ./target
    (gdb) b *0x401000          # 地址断点
    (gdb) b sym.check if argc == 2    # 条件断点
    (gdb) r arg1 arg2          # 运行并传参
    (gdb) ni / si              # 单步(跳过/进入调用)
    (gdb) c                    # 继续
    (gdb) info b               # 列出断点
    

    带参数动态分析命令: gdb -q -ex 'b main' -ex 'r' -ex 'x/10i $rip' ./target

    • 数据断点: watch *(int*)0x601000(写触发)/ rwatch(读触发)——查密钥写入时刻/解密落点
    • 系统调用断点: catch syscall openat——理清文件/网络行为,配合 commands ... end 自动打印参数后继续
    • 断点命中自动化(不改执行流,批量验证参数):
      (gdb) b check
      (gdb) commands
        silent
        printf "arg=%s\n", $rdi
        continue
      end
      
  3. 查看/修改内存与寄存器

    (gdb) x/20wx $rsp          # 栈上 20 个 word
    (gdb) x/s 0x601000         # 字符串
    (gdb) p $rax               # 寄存器
    (gdb) set $rax = 0         # 改寄存器
    (gdb) set {int}0x601000 = 0x90909090   # 写内存(绕过校验)
    (gdb) find 0x400000, 0x410000, "flag{"  # 内存搜索字符串
    
  4. 反调试绕过

    • 改标志位(anti-debug 常见检查点):
      (gdb) p $eflags
      (gdb) set $eflags = $eflags | 0x100     # 置 TF 位
      
    • ptrace 自检: ptrace(PTRACE_TRACEME) 返回值被检查 → 断在调用点直接 set $eax = 0(x86)续跑
    • 时间差检测(rdtsc): 先 p $rax 记两次调用差值,超阈值即退出——断到比较点 patch 比较寄存器
    • 以上修改只影响本次运行,不改文件(需持久化 patch 再动二进制并重新哈希对照)
  5. gcore 转储(默认转储优先)

    (gdb) gcore out
    

    或外部命令: gcore -o out <pid>(gdb 包附带,含寄存器/线程 ELF notes) 按 [[re-analyze/platform-tips]]「直读 vs 转储」: 默认转储优先;脱壳须等 OEP 解密后再 dump;core 直接 gdb ./target core 复盘(bt 看崩溃栈、info proc mappings 看映射)。

  6. 脚本化批处理(-x / python)

    gdb -q -batch -x script.gdb ./target      # 非交互跑完整脚本
    

    script.gdb 里可含 commands ... enddefine 自定义命令、python 内嵌 Python(gdb 内置 Python 解释器,pwndbg/gef 即基于此)——重复性分析(批量打印调用参数、跑通一条路径)固化成脚本复用;交互式分析结论用 gdb -q -ex ... -ex quit 一行式落档。

跨域联合

  • [[re-address-space]]:基址换算(info proc mappings 与链接地址对齐)

  • [[re-binary-core]]:工作流第 6 步(Linux 调试器)

  • [[re-anti-analysis]]:脱壳验证(断 OEP)与反调试绕过

  • [[re-ctf]]:pwn 调试

  • [[re-malware]]:Linux 恶意样本动态观察

  • 与 [[re-memdump]] 互补(attach 失败→转储)

常见坑与陷阱

  • ptrace 被禁 → 转储兜底:yama ptrace_scope=1 时非父进程 attach 被拒;容器 seccomp 直接杀 attach——不要死磕,按 [[re-analyze/platform-tips]] 转 [[re-memdump]]
  • 反调试(ptrace 自检、时间差):样本用 ptrace(PTRACE_TRACEME) 自检或 rdtsc 时间差检测调试器——先静态定位检查点再断点 patch
  • Wine 进程 attach:Wine 下 PE 进程是 Linux 进程,gdb 可 attach,但地址空间混 PE 映射与 Wine 结构——按 [[re-analyze/platform-tips]] Linux 分支经验处理(查 /proc/<pid>/maps 定位 PE 镜像段)
  • 调试器注入痕迹(LD_PRELOAD/环境变量)会被检测——用 unset env LD_PRELOAD 类方式清理后 attach
  • 时钟对抗分三类:现象——样本检测到时间异常(计时倍率不对、单步耗时异常、时钟源非预期)后退出或改变行为;原因——时钟对抗分三类:时间倍率检测/单步延迟检测/VM 时间源检测;对策——先判定类别再分别应对:时间倍率类恢复真实时钟或 patch 比较点,单步延迟类用硬件断点减少被测量步数,VM 时间源类按 [[re-analyze/platform-tips]] 沙箱分支的环境指纹思路处理
  • 断点失效 ≠ 代码没执行:现象——在目标地址下断从不触发,误判该路径没跑、直接跳过关键逻辑;原因——四种机制使"断点没断"≠"代码没执行":自修改代码(int3 字节被运行时覆盖或校验)、内存重映射(代码换到新映射、旧地址失效)、异常机制(流程经异常处理路径跳转,不走断点指令)、反调试绕过(样本扫描 0xCC/校验代码段字节后改道);对策——先分四类排查:x/i 看断点处是否仍为 int3(自修改)、查 /proc/<pid>/maps 比对映射变化(重映射)、在异常上下文里找真实跳转目标(异常机制)、静态先找 0xCC 扫描与段校验点(反调试),再决定换断点位置 / 下内存断点 / patch 检查点(见 [[re-binary-core]] 分析方法论 R17)
  • 单步异常 → 查反调试(陷阱旗 / 异常处理):现象——si 单步时触发未预期的 SIGTRAP/#DB,或单步后样本行为跳变(时间差类见"时钟对抗分三类"坑);原因——陷阱旗检测(样本读 TF 位 / 利用单步异常自身做文章)与异常处理机制反调试(int3 由样本自身 handler 接管、SEH 链承担流程跳转、异常即控制流);对策——先排除时间检测,再静态定位 pushf/lahf 后查 TF 的检查点与 int3 写入点,断 handler 入口看真实流向,patch 检查点或改用硬件断点(见 [[re-binary-core]] 分析方法论 R18)
  • 命令速查(断点/内存/脚本/pwndbg-gef 命令族)见 [[commands]];工具特有坑与版本差异见 [[gotchas]]

Signals

GitHub stars
57
Forks
8
Last commit
Sep 2026

ahel review

  • K1binfo
    installs-packages

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Catalog kind
skill
Gateway key
re-gdb
Source
github.com/dslsdzc/rev-skills