ARTICLE DETAIL

资讯详情

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

哥斯拉Webshell流量分析实战:从Wireshark抓包到AES解密完整思路

哥斯拉Webshell流量分析实战:从Wireshark抓包到AES解密完整思路 今年的北京市职工职业技能大赛信息通信行业网络安全赛项复赛CTF里有一道哥斯拉GodzillaWebshell流量分析题做完之后我一直觉得这道题出得挺典型。它不像有些杂项题那样靠脑洞也不像Pwn题那样需要比较深的二进制功底更贴近安全运营里真实会遇到的场景攻击者用Webshell管理工具连上了你的服务器你拿到一份流量包需要把加密的通信内容还原出来看清楚攻击者到底做了什么。这道题就是把完整过程压缩到了比赛环境里既考流量分析基本功也考对Webshell管理工具加密机制的理解。这篇文章我把拿到流量包后的完整分析思路、Wireshark操作、解密脚本和踩坑记录都整理出来。无论你是准备CTF比赛的在校学生还是做护网、应急响应时想补流量分析短板的从业者这套思路应该都用得上。反正记住一句话流量加密并不可怕只要搞清楚了密钥生成规律和加解密流程流量里的任何行为都藏不住。1. 拿到流量包先别急着翻数据包1.1 从协议分布判断题目类型很多人拿到pcapng的第一反应是直接看包列表然后越看越迷茫。我的习惯是先看整体再抠细节打开Wireshark第一步永远是Statistics - Protocol Hierarchy看看流量包里到底什么协议占主导。这场比赛给的是一个大概2MB出头的流量包包数量在1800个左右。点开协议分级统计HTTP流量占了绝对大头TCP下面几乎全是HTTP这说明题目的核心就在Web层面不是DNS隧道也不是ICMP隧道。这时候基本可以判断这是一道和Web访问、Webshell连接相关的流量分析题。继续往下看发现HTTP请求数量不多大概十几个请求集中在同一台主机的同一个路径上。这个特征很重要正常用户访问网站的流量会带有各种资源请求图片、CSS、JS、接口乱七八糟的都有而这里所有请求都指向一个PHP文件几乎没有其他资源请求。这种“一个文件被反复POST”的模式不用想大概率就是Webshell通信。到这一步我基本已经把题目范围缩到了一个很小的圈子里这不可能是SQL注入不可能是XSS也不可能是正常的业务流量接下来的重点只有一个——分析这个PHP文件背后的通信内容。很多时候做题卡住不是因为技术不够而是因为一上来就往细节里钻没有先从宏观上判断题型。1.2 用过滤语法快速定位Webshell通信判断完协议分布之后下一步就是快速定位到具体会话。这里我有几个常用的操作习惯效率比一个个点开看快很多。在Wireshark的过滤栏里直接输入http.request把所有HTTP请求过滤出来。对比响应码和请求方法会非常直观正常请求基本是GET为主状态码200、301、404都有而Webshell通信几乎全是POST状态码稳定200。接下来在过滤条件后面再加一个 http.request.method POST基本上就能锁定攻击者的连接行为。定位到具体请求后右键任意一条POST请求选择Follow - HTTP Stream就能看到完整的请求和响应。在这道题里点开TCP流的瞬间就能看到很明显的特征请求体是一长串不可读的字符串响应体同样是一长串密文根本没有明文参数。用Wireshark的导出对象功能也可以File - Export Objects - HTTP能一次性把所有HTTP对象列出来按大小排序后那个反复出现的shell.php就非常显眼。这里补充一个小技巧如果流量包比较大、请求比较多可以先看TCP流的长度分布。Webshell通信的包通常呈现“小请求、大响应”或者“大请求、小响应”的规律和正常浏览行为差异很大。找到可疑流之后再回到包列表逐包看细节思路会清晰得多。2. 从加密流量特征反推Webshell工具2.1 菜刀、蚁剑、冰蝎、哥斯拉的流量差异定位到Webshell通信之后第二个关键问题是攻击者用的是哪款Webshell管理工具不同工具的流量特征差异很大识别错了工具后面解密就会走很多弯路。国内安全圈常用的Webshell管理工具从老的到新的主流就是中国菜刀Chopper、蚁剑AntSword、冰蝎Behinder、哥斯拉Godzilla这几款。它们的流量特征差别非常明显菜刀是最老的一款流量基本不加密POST请求里直接带着z0eval...这种明文字符串特征一眼就能认出来。由于危害太大现在正规流量分析题目里几乎不会考它太简单了。蚁剑默认也不做加密虽然可以自定义编码器但默认情况下请求体里能直接看到eval、assert、base64_decode这类函数名甚至能看到执行的命令路径。蚁剑还有一个细节是默认User-Agent会伪装成百度爬虫看到User-Agent: Mozilla/5.0 (compatible; Baiduspider/2.0; http://www.baidu.com/search/spider.html)这种基本可以优先考虑蚁剑。冰蝎就进入了加密时代。冰蝎3.0使用AES加密通信过程中请求体会携带一个aesKey参数而且每次请求都会重新协商密钥经典特征是请求头里的Content-Type: application/x-www-form-urlencoded和User-Agent中的一些固定字段组合。冰蝎的流量分析需要先获取密钥才能解密。哥斯拉和冰蝎类似同样是AES加密但流量结构和加密细节有区别。哥斯拉的请求参数通常叫pass后面跟一长串密文响应体也是密文。在CTF题目里如果题干直接提到“哥斯拉”或者流量包文件名里有“godzilla”字样那基本就是送分提示了我们就顺着哥斯拉的加密机制去解。我用一个表格来总结这几个工具的差异以后做题时对照着看会方便很多工具名称请求特征请求参数加密方式典型User-Agent菜刀明文z0evalz0、z1无加密自带UA蚁剑明文函数名可见动态参数名可选编码器伪装百度爬虫冰蝎存在固定特征aesKeyAES动态密钥固定UA特征哥斯拉密文passpass、keyAES-CBC固定密钥普通浏览器UA2.2 哥斯拉的加密链路与密钥生成规则识别出哥斯拉之后接下来要解决的就是“怎么解密”的问题。哥斯拉的PHP Payload加密机制简单说就是AES-CBC模式加密后再做Base64编码传输但密钥不是随便设置的它有非常明确的生成规则。哥斯拉连接时会设置一个连接密钥也就是配置界面里的Key。每次通信前客户端和服务端会基于这个Key生成AES的密钥和IV具体规则是先对连接密钥取MD5取MD5结果的前16位作为AES密钥后16位作为AES的IV。举个例子如果连接密钥是abc123那么md5(abc123)的结果是e99a18c428cb38d5f260853678922e03取前16位e99a18c428cb38d5作为AES Key取后16位f260853678922e03作为IV。这个规则在哥斯拉的多版本PHP Payload里基本保持一致也是整个解密流程中最核心的知识点。还要注意一个细节哥斯拉的请求体和响应体传输格式略有不同。有些情况下请求体里的密文是Base64编码有些情况下则是十六进制字符串甚至有的版本会在密文传输前先做一次URL编码。所以在写解密脚本时最好把Base64和Hex两种解码方式都考虑进去自动判断、自动尝试否则很容易被卡在一个小小的编码环节上。理解了密钥生成规则整个人就轻松了一大半。因为加密算法本身是公开的你只要有密钥就相当于拿到了打开所有通信内容的门钥匙剩下的全是体力活。3. 解密实操用Python把请求和响应全部还原3.1 从流量包里提取key和密文这道题比较“友好”的地方在于题干直接给了连接密钥是一条类似2025BICTE的字符串。CTF题目里出题人通常会通过题目描述、附件备注或者压缩包注释给出这种关键信息如果题干里没有也可以翻一下流量包里有没有明文传输的测试请求有时候客户端在连接初期会先发一个带Key参数的数据包。拿到密钥之后就要手动提取密文了。操作路径是定位到任意一条POST请求在Wireshark中间面板展开HTML Form URL Encoded能看到请求体被解析成了参数名和值。哥斯拉的请求体里通常就是pass密文密文就在等号后面。响应体密文则在响应的Body部分。我建议把所有请求和响应的密文都按顺序复制出来排好序编上号不要只盯着某一条看。因为哥斯拉的通信不只是执行一条命令它会有多条请求测试连接、执行命令、读取文件、写入文件等。只有把所有密文都还原出来才能看到攻击者的完整操作链条才能找到flag真正藏在哪一步。复制密文时注意一个坑密文中间可能被换行符打断尤其是从Wireshark的文本视图直接复制时。这时候需要把复制出来的字符串里的空白字符、换行符全部清理掉否则后续解码必定报错。3.2 写一个自动解密脚本把请求和响应都还原出来密钥有了、密文有了、算法规则也清楚了剩下就是写脚本。这里我用Python实现一个完整的解密函数直接复制运行即可里面已经做了编码格式自动判断和填充字节清理。#!/usr/bin/env python3 # -*- coding: utf-8 -*- import hashlib from base64 import b64decode from Crypto.Cipher import AES def trim_padding(data: bytes) - bytes: if not data: return data if data[-1] 16 and data[-data[-1]:] bytes([data[-1]]) * data[-1]: return data[:-data[-1]] return data.rstrip(b\x00) def godzilla_decrypt(key: str, payload: str) - bytes: key_md5 hashlib.md5(key.encode()).hexdigest() aes_key key_md5[:16].encode() aes_iv key_md5[16:].encode() try: raw b64decode(payload) except Exception: raw bytes.fromhex(payload) cipher AES.new(aes_key, AES.MODE_CBC, aes_iv) plaintext cipher.decrypt(raw) return trim_padding(plaintext) if __name__ __main__: key 2025BICTE req_cipher 粘贴第一条请求体密文 resp_cipher 粘贴第一条响应体密文 print([*] 请求明文:) print(godzilla_decrypt(key, req_cipher).decode(utf-8, errorsreplace)) print([*] 响应明文:) print(godzilla_decrypt(key, resp_cipher).decode(utf-8, errorsreplace))这段代码的核心逻辑就三步第一步对连接密钥做MD5第二步按规则切出AES Key和IV第三步对密文做Base64解码后执行AES-CBC解密。最后的trim_padding函数是处理解密后末尾多余的填充字节这一步非常关键不然打印出来的明文后面会挂着一堆\x00或者不可见字符。解密脚本跑起来后第一条请求解出来的是哥斯拉的初始化握手数据。响应体里能看到类似会话状态的字符串这些不用太关心重点是后续几条明显是命令执行的流量。3.3 沿着命令回显找到flag按顺序把一组请求和响应全部解密后攻击者的操作链条就很清楚了。前面几条是建立连接时的握手和参数初始化后面出现了命令执行类的Payload。解密后能看到页面返回的是一段包含命令结果的文本比如执行了whoami、ipconfig、dir这类基础命令再往后出现了cat flag或者type flag这种明显是冲着flag去的操作。flag的藏法各题不同有些直接躺在命令回显里有些则通过Base64编码后的文件名出现需要再翻转一层。这道题里比较直接在倒数第二条请求的响应明文中直接出现了一行flag{...}格式的字符串。看到这个格式基本上就可以提交收工了。如果解出来发现一段明文里有大量转义字符比如\x开头的内容说明后面还可能藏着一层编码不要急着放弃常见的做法是把这段字符串再交给CyberChef用From Hex或者From Base64再解一层。CTF里流量分析题最喜欢搞这种“套娃”式编码多尝试几层比重新看流量包更高效。整个解密过程其实并不复杂真正的难点在于搞明白“密钥从哪来、密文在哪、怎么组装”这三个问题。4. 踩坑记录与这类题目的延伸思考4.1 实际解密中容易翻车的几个点做这道题的时候我在几个细节上浪费了一些时间复盘后整理成一份避坑清单这些坑在同类题目里基本都会遇到。第一个坑是解码格式判断。哥斯拉的密文有时是Base64有时是Hex。如果脚本里默认走Base64遇到Hex格式的密文就会直接报错或者解出乱码。解决办法就是我脚本里写的先用Base64解报错就换Hex再试。不要抱侥幸心理两道题之间差一层编码是常有的事。第二个坑是AES Key和IV的顺序。哥斯拉的规则是MD5结果前16位做Key、后16位做IV顺序反了也能解但结果是完全乱码。我一开始图省事想当然地拿整个MD5值当Key结果解密出来全是乱码。这个顺序是哥斯拉固定的做过一次之后最好形成条件反射别再绕弯子。第三个坑是解密后的明文末尾填充数据。解密结果看着像明文但末尾总有异常字符打印出来会干扰判断。其实是PKCS7或零填充残留没清理掉。上面脚本里的trim_padding函数就是为了解决这个问题正式分析时这步不能省。第四个坑存在于Wireshark操作层面从请求包里复制密文时中间可能混入URL解码后的换行符、多余的空格。我建议复制后先做一次正则清理把\r、\n、空格全部去掉再送去解密。我把这些问题整理成速查表分析时对照着看常见问题表现解决方式编码格式判断错误Base64解出来是乱码自动回退到Hex解码Key与IV顺序颠倒解出完全乱码前16位Key后16位IV填充字节残留明文末尾有异常字符去掉PKCS7或零填充密文含换行空格解码报错先清理所有空白字符再解密匹配错了请求解出握手初始化数据按流顺序完整解密所有密文4.2 哥斯拉流量的变种与后续扩展方向解完这道题我一直在想这类题目还能怎么变着花出。哥斯拉本身支持PHP、JSP、ASP.NET等多种语言的服务端不同语言的加密细节和请求格式有差异但底层的AES-CBC加密规则基本一致。只要掌握了核心规则换到JSP环境无非就是请求参数、密文格式有一些变化分析思路完全可以复用。另外哥斯拉的请求中可以自定义Cookie、自定义User-Agent、自定义加密器。出题人如果稍微魔改一下比如把默认参数名pass改成data或者把密钥藏在某个响应头里题目难度就立刻上来了。这种时候单纯靠特征识别就不够用了需要静下心分析流量结构看哪些字段是可变的、哪些是程序固定生成的找到规律再下手。现实中的流量分析场景比CTF题目复杂得多流量规模大、协议混杂通常要结合Zeek这类全流量分析框架做自动化的协议解析和威胁检测而不是只用Wireshark一个个点开看。但底层逻辑是一样的先发现异常会话再还原通信内容最后定位恶意行为。CTF里的流量分析题本质上就是把这个流程浓缩成了可控的小规模练习题。4.3 流量分析方向的学习建议如果你刚接触CTF想从流量分析这块入手我的建议是先把Wireshark用熟尤其是过滤语法、TCP流追踪、HTTP导出对象这几个功能高频操作做到不用想就能写出来。接着花时间把HTTP协议搞透看会请求行、请求头、请求体的结构差异这对判断WebShell流量至关重要。然后多找现成的Webshell流量样本练手。GitHub上有不少公开的样本包可以拿哥斯拉、蚁剑、冰蝎各跑一遍亲手操作一次”抓包-识别-解密-还原“的全流程。第一次可能比较慢但跑通一次之后你再遇到同类题目就有肌肉记忆了。这里也推荐多看看CTF社区里其他人的WriteUp往往能学到很多自己完全想不到的角度比如某个工具的参数名特征、某种加密算法的边界情况这些都是实战中积累出来的经验。说实话流量分析是一个越做越有手感的方向而且它在实战里利用率极高应急响应、护网、溯源处处用得上。投入时间学这块不管打比赛还是做安全工作都不会亏。最后再分享一个我在比赛中实际养成的小习惯做流量分析题时我会把流量包里的所有可疑密文统一提取到一个txt文件里编好序号再写脚本批量解密。这样比一条一条复制粘贴高效很多而且不容易漏掉关键请求。很多时候flag就藏在某一组不起眼的响应里完整梳理一遍才是最稳妥的做法。
返回列表