在kernelpwn(内核pwn)不打包内核,通过网络把 EXP 快速送入 QEMU 内测试

前言

在打kernelpwn(内核pwn)的时候,写好exp并本地编译后常常需要重新打包内核,再qume运行,十分麻烦,于是想能不能直接让其直接联网发送过去

一、原理

本质上就是新建一个虚拟网桥,给主机和虚拟机连上,然后分配双方ip和网关,之后用nc在端口上打开一个shellpython脚本连接发送二进制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!

posted @ 2025-07-18 16:51  归海言诺  阅读(55)  评论(0)    收藏  举报