pwndbg ksighand 命令详解:在内核调试会话中查看 Linux 用户任务的信号处理器
pwndbg ksighand 命令详解在内核调试会话中查看 Linux 用户任务的信号处理器【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg本指南系统讲解 pwndbg 的ksighand命令——用于在 QEMU 内核调试场景下展示指定用户任务user task的信号处理器signal handler信息。你将掌握该命令的完整用法、输出字段含义、底层内核结构sighand_struct/struct k_sigaction的解析原理以及它与ktask、kcurrent等内核命令的配合方式可直接用于内核漏洞利用与逆向分析中的进程信号状态审计。ksighand 是什么ksighand是 pwndbg 内核命令族KERNEL 分类的一员功能为Displays information about the signal handlers of a user task展示用户任务的信号处理器信息。它读取内核task_struct中的sighand指针所指向的struct sighand_struct把其中action[_NSIG]数组记录的每个信号的处理函数地址与标志位枚举出来并以人类可读的方式呈现。在内核调试尤其是通过 QEMU 加载内核镜像调试时你往往需要确认某个进程对SIGSEGV、SIGABRT等信号注册了什么样的处理逻辑是默认行为SIG_DFL、忽略SIG_IGN还是指向用户态/内核态某地址的自定义 handler。这正是ksighand的输出内容。命令用法与参数ksighand的完整用法如下摘自 docs/commands/kernel/ksighand.mdusage: ksighand [-h] [pid]位置参数位置参数说明pid目标任务线程的进程号省略时默认使用当前内核任务见下文kcurrent协作一节可选参数短选项长选项说明-h--help显示帮助信息并退出命令定义位于 pwndbg/commands/kcurrent.py其 argparse 解析器描述与帮助文本与上述文档自动生成部分完全一致该文档由scripts/generate-docs.sh自动维护。典型调用示例pwndbg ksighand 1234 # 查看 pid1234 任务的信号处理器 pwndbg ksighand # 查看当前内核任务 pwndbg ksighand -h # 查看帮助输出内容解读ksighand首先打印任务头部信息线程地址、pid、cpu、uid/gid、是否用户任务等随后以缩进方式逐行列出信号处理器表。每一行的格式为信号名 sa_flags sa_handler以源码逻辑pwndbg/commands/kcurrent.py为准信号名通过pwndbg.aglib.signal.PER_ARCH_SIGNAL_MAPPINGS[pwndbg.aglib.arch.name]将信号编号映射为SIGxxx名称以蓝色显示并左对齐填充{m[i]:10}sa_flags信号处理标志位以黄色 16 进制显示f0x{flags:016x}sa_handler处理函数地址按以下规则渲染值为0→ 红色SIG_DFL默认处理值为1→ 红色SIG_IGN忽略其他值 → 通过pwndbg.chain.format()格式化为地址即自定义 handler 或内核统一处理入口。这里0与1对应内核约定的SIG_DFL与SIG_IGN哨兵值。可以理解为一行输出即完整描述了该任务对某个信号发生时的处置策略。底层实现从 pid 到 signal 表的完整链路1. 任务选择select_kthread_from_pid命令的第一步是确定要分析的线程对象pwndbg/commands/kcurrent.py若未传pid优先返回此前通过kcurrent --set设定的内核任务get_kcurrent()若未设定则取当前 CPU 上的任务并校验其task_struct指针位于内核地址空间若传了pid则遍历pwndbg.commands.ktask.get_ktasks()返回的所有Ktask在其中所有线程里匹配pid找不到时打印警告ktask with pid {pid} not found。选中后若thread.user_task为假即task_struct-mm 0属于内核线程而非用户任务命令会打印not user task并提前返回——因为只有用户任务才持有完整的信号处理上下文。该判断来自 pwndbg/commands/ktask.pyproperty def user_task(self) - bool: return int(self.thread[mm]) ! 02. 读取信号表Kthread.sighand生成器任务线程对象由Kthread类封装pwndbg/commands/ktask.py。其sighand属性是一个生成器property def sighand(self) - Generator[tuple[int, int], None, None]: if not self.thread[sighand].dereference().type.has_field(action): return sighand self.thread[sighand][action] for i in range(sighand.type.array_len): action sighand[i][sa] yield (int(action[sa_handler]), int(action[sa_flags]))即遍历sighand-action[]数组长度_NSIG逐个取出struct k_sigaction中内嵌struct sigaction sa的sa_handler与sa_flags。3. 索引偏移signal - 1命令实现中有明确的注释与逻辑pwndbg/commands/kcurrent.py# sighand-action is indexed by signal - 1, so entry i describes signal i 1 for i, (handler, flags) in enumerate(thread.sighand, start1): if i not in m: continue由于内核中action[]数组以下标信号号 - 1存储因此第i个槽位描述的是信号i1。遍历时从 1 开始枚举并跳过当前架构不支持的信号编号if i not in m: continue。4. 信号编号映射表信号名映射定义于 pwndbg/aglib/signal.pyPER_ARCH_SIGNAL_MAPPINGS: dict[..., dict[int, SIGNALS]] { x86-64: COMMON_NUM_TO_SIGNAL_MAPPING, aarch64: COMMON_NUM_TO_SIGNAL_MAPPING, }COMMON_NUM_TO_SIGNAL_MAPPING覆盖 1–31 号常规信号如 1SIGHUP、2SIGINT、6SIGABRT、8SIGFPE、11SIGSEGV、15SIGTERM 等并额外内置 12 个共享编号映射作为兜底SHARED_NUM_TO_SIGNAL_MAPPING。也就是说当前ksighand的完整映射支持面向x86-64 与 aarch64两个架构其他架构在命令执行时因映射表缺失会被跳过。内核结构解析sighand_struct 与 k_sigactionksighand之所以能直接按字段名读取action数组依赖 pwndbg 的**类型信息恢复typeinfo recovery**机制在无调试符号的内核上pwndbg 会从内存中启发式重建内核结构体定义其中就包含信号相关结构pwndbg/aglib/kernel/ktask.py#define _NSIG 64 #define _NSIG_BPW (ptrsize 位数) #define _NSIG_WORDS (_NSIG / _NSIG_BPW) struct sigaction { __sighandler_t sa_handler; unsigned long sa_flags; #ifdef __ARCH_HAS_SA_RESTORER // x86-64 / aarch64 均定义 __sigrestore_t sa_restorer; #endif sigset_t sa_mask; /* mask last for extensibility */ }; struct k_sigaction { struct sigaction sa; }; struct sighand_struct { char _pad[off]; struct k_sigaction action[_NSIG]; };其中_pad偏移通过启发式扫描寻找sighand内存中的双向链表指针确定__ARCH_HAS_SA_RESTORER仅在 x86-64/aarch64 上定义与内核源码中__ARCH_HAS_SA_RESTORER的架构约定一致。同时恢复出的task_struct中信号相关字段布局也与内核一致pwndbg/aglib/kernel/ktask.py/* Signal handlers: */ struct signal_struct *signal; struct sighand_struct __rcu *sighand; sigset_t blocked; sigset_t real_blocked;整体恢复流程由recover_ktask_typeinfo()驱动pwndbg/aglib/kernel/ktask.py它依次推断mm、tasks、comm、pid、files、nsproxy等字段偏移后最终把sighand_struct并入生成的task_struct定义中。这也解释了为什么该命令要求内核符号与分页开启——恢复流程需要init_mm、init_task等符号作为锚点。运行前置条件ksighand被四组装饰器约束定义于 pwndbg/commands/init.py挂载于 pwndbg/commands/kcurrent.py装饰器校验内容不满足时的表现OnlyWhenQemuKernel当前目标必须是 QEMU 内核调试qemu.is_qemu_kernel()报错仅可在 QEMU 中调试 Linux 内核时运行OnlyWhenPagingEnabled内核分页已开启paging_enabled()报错仅可在分页开启时运行OnlyWithKernelSymbols内核具有调试符号has_debug_symbols()报错并提示使用 vmlinux-to-elf 提取符号或自行编译内核WarnOnKernelConfigRandstruct无调试信息且内核开启CONFIG_RANDSTRUCT打印警告输出可能不准确因此该命令面向带符号的 QEMU Linux 内核调试会话在普通用户态进程调试中无法使用。若目标内核启用了CONFIG_RANDSTRUCT结构体字段随机化且无调试信息命令仍会尝试运行但会提示结果可能不准确。与其他内核命令的协作ksighand属于 pwndbg 内核命令生态的一部分与之最常搭配的命令有ktask枚举所有内核任务及其线程pwndbg/commands/ktask.py输出中包含每个线程的 pid、cpu、uid/gid、[user task]标记——先用它定位目标 pid再交给ksighandkcurrent [--set pid]查看或设定当前内核任务。--set会把指定任务设定为多个命令kfile、kstack、knamespace、ksighand、kseccomp、pagewalk、vmmap的默认作用对象pwndbg/commands/kcurrent.py。设定后直接执行ksighand即可免去每次传 pidkseccomp展示用户任务的 seccomp 过滤器与信号表配合可完整刻画进程的系统调用与信号处置策略kstack/kfile/knamespace分别查看同一任务的栈、文件描述符与命名空间共同构成任务级的取证视图。它们共享同一套select_kthread_from_pid选择逻辑与Kthread封装因此任务定位行为完全一致。典型应用场景在内核漏洞利用与逆向中ksighand的典型价值包括确认目标进程是否安装自定义信号处理例如某服务进程对SIGSEGV设置了 handler输出为具体地址而非SIG_DFL则该地址指向的可能是其自身的崩溃恢复逻辑或沙箱兜底代码值得进一步在用户态内存中分析区分信号处置策略快速区分SIG_DFL/SIG_IGN/ 自定义 handler 三类处置辅助判断进程对异常如 0 地址解引用的敏感度沙箱/反调试审计结合sa_flags如是否设置SA_SIGINFO、SA_RESTORER相关标志位分析 handler 的调用约定与恢复机制为 ROP/信号驱动的攻击路径设计提供依据无符号内核取证在仅有符号甚至无调试信息、依赖类型恢复的内核上无需 VMLINUX DWARF 即可枚举任意用户任务的完整信号表。局限与注意事项仅对用户任务有效内核线程mm 0会得到not user task提示不会输出信号表信号名映射仅覆盖x86-64 与 aarch64其他架构下可能输出为空或仅显示部分信号输出依赖类型恢复的准确性若内核开启CONFIG_RANDSTRUCT且无调试信息字段偏移推断可能失真输出仅作参考sa_handler若为自定义地址pwndbg.chain.format只展示地址格式化结果命令本身不反汇编 handler 内容——如需进一步分析可结合nearpc或内存转储命令查看该地址处的指令。小结ksighand以极简的ksighand [pid]接口把内核sighand_struct中 64 槽位的信号处理表完整呈现给调试者。其实现贯通了 pwndbg 的类型恢复、内核任务枚举、按架构的信号名映射三条核心链路是 QEMU 内核调试场景下审计进程信号处置策略的实用工具。配合ktask定位线程、kcurrent --set固定目标即可在几秒内获得目标进程的完整信号处置画像。【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考