在kernelpwn(内核pwn)不打包内核,通过网络把 EXP 快速送入 QEMU 内测试
前言
在打kernelpwn(内核pwn)的时候,写好exp并本地编译后常常需要重新打包内核,再qume运行,十分麻烦,于是想能不能直接让其直接联网发送过去
一、原理
本质上就是新建一个虚拟网桥,给主机和虚拟机连上,然后分配双方ip和网关,之后用nc在端口上打开一个shell给python脚本连接发送二进制exp
二 宿主机设置
每次宿主机开机都要做一次,别嫌麻烦,到时候好改
# 1. 创建一个 TAP 虚拟网卡 tap0,当前用户可用
sudo ip tuntap add dev tap0 mode tap user $(whoami)
# 2. 启用 tap0 网卡
sudo ip link set tap0 up
# 3. 创建一个网桥 br0
sudo brctl addbr br0
# 4. 将 tap0 接口加入到 br0 网桥中(用于桥接虚拟机)
sudo brctl addif br0 tap0
# 5. 给 br0 分配静态 IP(虚拟机将通过这个网关通信)
sudo ip addr add 10.0.2.2/24 dev br0
# 6. 启用 br0 网桥接口
sudo ip link set br0 up
在主机上创建一个tap0虚拟网卡,并将其加入网桥br0,给br0设置一个静态 IP(如 10.0.2.2),用于与 QEMU 虚拟机(如10.0.2.15)进行桥接通信。
也可以使用这个脚本一键启动:
#!/bin/bash
# Author: 归海言诺
# Description: 初始化 QEMU 网络环境,创建 tap0 和 br0,并配置静态 IP
set -e
TAP="tap0"
BR="br0"
HOST_IP="10.0.2.2"
NETMASK="255.255.255.0"
CIDR="/24"
echo "[*] 创建 TAP 接口: $TAP"
ip tuntap add dev $TAP mode tap user $(whoami) || echo "[!] TAP 接口可能已存在"
ip link set $TAP up
echo "[*] 创建网桥: $BR"
brctl addbr $BR 2>/dev/null || echo "[!] 网桥 $BR 已存在"
echo "[*] 将 TAP 接口加入网桥"
brctl addif $BR $TAP 2>/dev/null || echo "[!] TAP 接口可能已加入网桥"
echo "[*] 配置主机桥 IP: $HOST_IP"
ip addr flush dev $BR
ip addr add ${HOST_IP}${CIDR} dev $BR
ip link set $BR up
echo "[✔] 主机桥接环境配置完成"
brctl show $BR
ip addr show $BR
三、修改qume启动命令(修改start.sh)
一般来说,是通过start.sh启动的,例如:
qemu-system-x86_64 \
-m 125M \
-kernel ./bzImage \
-initrd ./core.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nokaslr" \
-s \
-netdev user,id=t0 \
-device e1000,netdev=t0,id=nic0 \
-nographic
做如下改动:
# 修改后
# 将运行内存扩大,修改网络连接部分
qemu-system-x86_64 \
-m 512M \
-kernel ./bzImage \
-initrd ./core.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nokaslr" \
-s \
-netdev tap,id=t0,ifname=tap0,script=no,downscript=no \
-device e1000,netdev=t0,id=nic0 \
-nographic
四、修改虚拟机启动脚本(修改init)
修改解包后的init
# 初始
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
/sbin/mdev -s
mkdir -p /dev/pts
mount -vt devpts -o gid=4,mode=620 none /dev/pts
chmod 666 /dev/ptmx
cat /proc/kallsyms > /tmp/kallsyms
echo 1 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict
ifconfig eth0 up
udhcpc -i eth0
ifconfig eth0 10.0.2.15 netmask 255.255.255.0
route add default gw 10.0.2.2
insmod /core.ko
poweroff -d 120 -f &
setsid /bin/cttyhack setuidgid 1000 /bin/sh
echo 'sh end!\n'
umount /proc
umount /sys
poweroff -d 0 -f
修改网络部分:
#!/bin/sh
# 基础挂载
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
/sbin/mdev -s
mkdir -p /dev/pts
mount -vt devpts -o gid=4,mode=620 none /dev/pts
chmod 666 /dev/ptmx
# 导出 kallsyms,设置限制
cat /proc/kallsyms > /tmp/kallsyms
echo 1 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict
# 正确网络配置(静态 IP)
ifconfig eth0 up
ifconfig eth0 10.0.2.15 netmask 255.255.255.0
route add default gw 10.0.2.2
# 插入内核模块
insmod /core.ko
# 绑定 shell 到端口 1145(主机连接)
nc -ll -p 1145 -e /bin/sh &
# 启动交互 shell
# !去除了开机时长限制!!!!!!!!!!!!
setsid /bin/cttyhack setuidgid 1000 /bin/sh
# 清理
echo 'sh end!\n'
umount /proc
umount /sys
poweroff -d 0 -f
主要修改网络部分,并且去掉了开机时长限制,修改完成后打包!记得打包!
五、发送exp
理论上现在已经可以通过nc 10.0.2.15 1145连接一个shell了,再用这个脚本发送:
原作者:@author arttnba3 (arttnba@gmail.com),已获授权
from pwn import *
import base64
from tqdm import tqdm
import time
# context.log_level = 'info'
HOST, PORT = "10.0.2.15", 1146
CHUNK_SIZE = 0x200 # 每次上传的 base64 块大小
# 读取并编码可执行文件
with open("./A", "rb") as f:
b64_exp = base64.b64encode(f.read())
total_chunks = (len(b64_exp) + CHUNK_SIZE - 1) // CHUNK_SIZE
# 建立连接
log.info(f"连接 {HOST}:{PORT}")
p = remote(HOST, PORT)
# 清空目标文件
p.sendline(b"rm -f /tmp/b64_exp")
# tqdm 显示进度条
log.info("开始上传 exploit")
for i in tqdm(range(total_chunks), desc="Uploading", unit="chunk"):
chunk = b64_exp[i * CHUNK_SIZE: (i + 1) * CHUNK_SIZE].decode()
p.sendline(f'echo -n "{chunk}" >> /tmp/b64_exp'.encode())
# 解码 + 加权限 + 执行
log.info("解码并执行 exploit")
p.sendline(b"base64 -d /tmp/b64_exp > /tmp/exploit")
p.sendline(b"chmod +x /tmp/exploit")
p.sendline(b"/tmp/exploit")
# 保持交互
p.interactive()
一键编译+测试命令:
gcc -masm=intel -no-pie -static -O2 -Wall -o A 1.c && python remort.py
这样就可以快速测试了
六、总结
本篇教程适用于ctf,请勿在日常中这么干,会开一个不要密码的shell!

浙公网安备 33010602011771号