第五届红明谷-异常行为溯源-WP

  |  

在刷题时,遇到了这个题,感觉适合写python脚本(AI打工雾)和练习bash命令的。所以记下。

题目说明

某企业网络安全部门人员正在对企业网络资产受到的攻击行为进行溯源分析,该工作人员发现攻击者删除了一段时间内的访问日志数据,但是攻击者曾传输过已被删除的访问日志数据并且被流量监控设备捕获,工作人员对流量数据进行了初步过滤并提取出了相应数据包。已知该攻击者在开始时曾尝试低密度的攻击,发现未被相关安全人员及时发现后进行了连续多日的攻击,请协助企业排查并定位攻击者IP,flag格式为:flag{md5(IP)}

分析题目压缩包发现,tcp流量里被base64编码。

1
eyJtc2ciOiJPVEF1T1RjdU1qUXlMakk0TFNBdElGc3dPQzlLWVc0dk1qQXlOVG95TWpvMU56b3pOeUFyTURBd01GMGdJbEJQVTFRZ0wyMWhhVzR2YzJWaGNtTm9MbkJvY0NCSVZGUlFMekV1TVNJZ01qQXdJREl6T0RBZ0lpMGlJQ0pOYjNwcGJHeGhMelV1TUNBb1kyOXRjR0YwYVdKc1pUc2dUVk5KUlNBNUxqQTdJRmRwYm1SdmQzTWdUbFFnTmk0eE95QlVjbWxrWlc1MEx6VXVNU2tpQ2c9PSIsInR5cGUiOiJMb2ctRGF0YSJ9

解密后,发现是一个json数据里面msg里有包含一个base64数据。

1
{"msg":"OTAuOTcuMjQyLjI4LSAtIFswOC9KYW4vMjAyNToyMjo1NzozNyArMDAwMF0gIlBPU1QgL21haW4vc2VhcmNoLnBocCBIVFRQLzEuMSIgMjAwIDIzODAgIi0iICJNb3ppbGxhLzUuMCAoY29tcGF0aWJsZTsgTVNJRSA5LjA7IFdpbmRvd3MgTlQgNi4xOyBUcmlkZW50LzUuMSkiCg==","type":"Log-Data"}

解密msg里的base64编码数据,发现是一个日志数据。

1
90.97.242.28- - [08/Jan/2025:22:57:37 +0000] "POST /main/search.php HTTP/1.1" 200 2380 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.1)"

发现这个规律后,我们可以先编写python将文件里的base64提起处理,再去分析base64数据。

python脚本编写

我们分析了tcp流量发现里面的base64有鲜明的特征,我们可以编写脚本来判断base64启始位置,再同时提取出来进行解码。于是得到以下脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import base64
import re
import argparse
from pathlib import Path

def is_valid_base64(s):
"""检查字符串是否是有效的Base64"""
try:
# Base64字符串长度必须是4的倍数,不足的补=
padding = len(s) % 4
if padding:
s += '=' * (4 - padding)
# 尝试解码
base64.b64decode(s)
return True
except:
return False

def extract_and_decode_base64(input_file, output_file=None, min_length=8):
"""
从文件中提取Base64字符串并解密

参数:
input_file: 输入文件路径
output_file: 输出文件路径(可选)
min_length: 最小Base64字符串长度(默认8)
"""
try:
# 读取文件内容
content = Path(input_file).read_text(encoding='utf-8', errors='ignore')

# 匹配Base64字符串的正则表达式
base64_pattern = r'(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?'

print(f"正在分析文件: {input_file}")
print(f"找到的Base64字符串:\n{'='*40}")

results = []
unique_strings = set() # 用于去重

for match in re.finditer(base64_pattern, content):
base64_str = match.group()

# 过滤短字符串和重复字符串
if (len(base64_str) >= min_length and
is_valid_base64(base64_str) and
base64_str not in unique_strings):

unique_strings.add(base64_str)

try:
# 解码Base64
decoded_bytes = base64.b64decode(base64_str)

# 尝试UTF-8解码
try:
decoded_str = decoded_bytes.decode('utf-8')
result = f"Base64: {base64_str}\n解码(UTF-8): {decoded_str}\n"
except UnicodeDecodeError:
# 如果不是UTF-8,显示16进制
hex_str = decoded_bytes.hex()
result = f"Base64: {base64_str}\n解码(HEX): {hex_str}\n"

print(result)
results.append(result)

except Exception as e:
error_msg = f"Base64: {base64_str}\n解码失败: {str(e)}\n"
print(error_msg)
results.append(error_msg)

# 如果没有找到任何Base64字符串
if not results:
print("没有找到有效的Base64字符串")
return

# 写入输出文件
if output_file:
with open(output_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(results))
print(f"\n结果已保存到: {output_file}")

except Exception as e:
print(f"处理文件时出错: {str(e)}")

if __name__ == "__main__":
parser = argparse.ArgumentParser(description='从文件中提取Base64字符串并解密')
parser.add_argument('-i', '--input', required=True, help='输入文件路径')
parser.add_argument('-o', '--output', help='输出文件路径(可选)')
parser.add_argument('-l', '--min-length', type=int, default=8,
help='最小Base64字符串长度(默认8)')

args = parser.parse_args()

extract_and_decode_base64(
input_file=args.input,
output_file=args.output,
min_length=args.min_length
)

bash命令配合

我们执行python脚本两次,第一次提取出json数据到1.txt。

1
python3 1.py -i ./network_traffic.pcap -o 1.txt

再从1.txt里提取出日志信息到2.txt

1
python3 1.py -i ./1.txt -o 2.txt

再利用bash命令行的grep命令,把日志信息里的POST信息分离

1
cat 2.txt | grep "POST" >3.txt

通过awk 把ip 匹配出,再通过sort和uniq 找出出现次数最多的IP。

1
cat  3.txt|  awk '{print $2}'|  sort | uniq -c | sort

找点一个次数异常的ip:

1
2
3
4
5
6
7
8
9
 4 220.90.115.241
4 222.124.84.168
4 30.74.60.8
4 33.218.233.40
4 69.144.190.184
4 73.96.151.224
4 89.195.144.147
5 153.148.53.46
67 35.127.46.111

将 35.127.46.111 md5后就是flag。

文章目录
  1. 题目说明
  2. python脚本编写
  3. bash命令配合
|