xbase-util 0.0.8__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xbase_util-0.0.8 → xbase_util-0.1.0}/PKG-INFO +2 -1
- {xbase_util-0.0.8 → xbase_util-0.1.0}/setup.py +2 -1
- xbase_util-0.1.0/xbase_util/es_db_util.py +29 -0
- xbase_util-0.1.0/xbase_util/esreq.py +26 -0
- xbase_util-0.1.0/xbase_util/handle_features_util.py +161 -0
- xbase_util-0.1.0/xbase_util/pcap_util.py +247 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util.egg-info/PKG-INFO +2 -1
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util.egg-info/SOURCES.txt +4 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/README.md +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/setup.cfg +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util/__init__.py +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util/xbase_util.py +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util.egg-info/dependency_links.txt +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util.egg-info/not-zip-safe +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util.egg-info/top_level.txt +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util_assets/GeoLite2-City.mmdb +0 -0
- {xbase_util-0.0.8 → xbase_util-0.1.0}/xbase_util_assets/arkimeparse.js +0 -0
@@ -3,13 +3,14 @@ from distutils.core import setup
|
|
3
3
|
from setuptools import find_packages
|
4
4
|
|
5
5
|
setup(name="xbase_util",
|
6
|
-
version="0.0
|
6
|
+
version="0.1.0",
|
7
7
|
description="网络安全基础工具",
|
8
8
|
long_description="包含提取,预测,训练的基础工具",
|
9
9
|
author="xyt",
|
10
10
|
author_email="2506564278@qq.com",
|
11
11
|
license="<MIT License>",
|
12
12
|
packages=find_packages(),
|
13
|
+
url="https://gitee.com/jimonik/xbase_util.git",
|
13
14
|
install_requires=[
|
14
15
|
],
|
15
16
|
zip_safe=False,
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import os.path
|
2
|
+
|
3
|
+
|
4
|
+
class EsDb:
|
5
|
+
def __init__(self, req):
|
6
|
+
self.req = req
|
7
|
+
self.internals = {}
|
8
|
+
print("初始化:Elasticsearch DB")
|
9
|
+
|
10
|
+
def get_file_by_file_id(self, node, num, prefix=None):
|
11
|
+
key = f'{node}!{num}'
|
12
|
+
if key in self.internals:
|
13
|
+
return self.internals[key]
|
14
|
+
res = self.req.search_file(f"{node}-{num}")
|
15
|
+
hits = res['hits']['hits']
|
16
|
+
if len(hits) > 0:
|
17
|
+
self.internals[key] = hits[0]['_source']
|
18
|
+
file = hits[0]['_source']
|
19
|
+
if prefix is None:
|
20
|
+
return file
|
21
|
+
prefix_res = prefix
|
22
|
+
if not prefix.endswith('/'):
|
23
|
+
prefix_res = f"{prefix}/"
|
24
|
+
origin_path = file['name']
|
25
|
+
basename = os.path.basename(origin_path)
|
26
|
+
result_path = f"{prefix_res}{basename}"
|
27
|
+
file['name'] = result_path
|
28
|
+
return file
|
29
|
+
return None
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import requests
|
2
|
+
|
3
|
+
|
4
|
+
class EsReq:
|
5
|
+
def __init__(self, url,timeout=120):
|
6
|
+
self.es_url = url
|
7
|
+
self.timeout = timeout
|
8
|
+
print("初始化自定义es请求类")
|
9
|
+
|
10
|
+
def clear_all_scroll(self):
|
11
|
+
return requests.delete(self.es_url + "/_search/scroll", timeout=self.timeout, json={'scroll_id': '_all'})
|
12
|
+
|
13
|
+
def search(self, body, scroll):
|
14
|
+
requests.post(self.es_url + "/_search/scroll", data=body, timeout=self.timeout, json={'scroll_id': scroll})
|
15
|
+
|
16
|
+
def start_scroll(self, exp, scroll):
|
17
|
+
return requests.post(self.es_url + "/_search/scroll", timeout=self.timeout,
|
18
|
+
json=exp)
|
19
|
+
|
20
|
+
def scroll_by_id(self, scroll_id, scroll):
|
21
|
+
return requests.post(self.es_url + "/_search/scroll", timeout=self.timeout,
|
22
|
+
json={'scroll_id': scroll_id, 'scroll': scroll})
|
23
|
+
|
24
|
+
def search_file(self, id):
|
25
|
+
return requests.get(f"{self.es_url}/arkime_files_v30/_search", timeout=self.timeout,
|
26
|
+
json={"query": {"term": {"_id": id}}})
|
@@ -0,0 +1,161 @@
|
|
1
|
+
import json
|
2
|
+
import re
|
3
|
+
import traceback
|
4
|
+
from urllib.parse import unquote
|
5
|
+
|
6
|
+
import pandas as pd
|
7
|
+
|
8
|
+
|
9
|
+
def handle_uri(data):
|
10
|
+
print(f"处理URI:{len(data)}")
|
11
|
+
# 定义正则表达式,确保精确匹配各种攻击特征
|
12
|
+
regex_patterns = {
|
13
|
+
"sql": re.compile(
|
14
|
+
r"\b(select|union|insert|update|delete|drop|--|#| or |' or '|information_schema|database\(\)|version\(\))\b",
|
15
|
+
re.IGNORECASE),
|
16
|
+
"xss": re.compile(r"(<script\b|javascript:|onload=|onclick=|<iframe\b|src=)", re.IGNORECASE),
|
17
|
+
"cmd": re.compile(
|
18
|
+
r"(/etc/passwd\b|/etc/shadow\b|;|&&|\||\$\(.+\)|\bcurl\b|\bwget\b|\bexec\b|\bsystem\b|cmd=|proc/self/environ)",
|
19
|
+
re.IGNORECASE),
|
20
|
+
"path": re.compile(r"(\.\./|\.\.%2f|\.\.%5c|\.\.\\|\.\.;|%2f%2e%2e%2f)", re.IGNORECASE),
|
21
|
+
"redirect": re.compile(r"(redirect=|url=|next=|redirect_uri=|redirect:|RedirectTo=)", re.IGNORECASE),
|
22
|
+
"danger": re.compile(
|
23
|
+
r"(%3C|%3E|%27|%22|%00|%2F|%5C|%3B|%7C|%28|%29|%20|%3D|%3A|%3F|%26|%23|%2B|%25|file://|<foo|xmlns:|/etc/passwd|windows/win\.ini)",
|
24
|
+
re.IGNORECASE),
|
25
|
+
"suspicious_ext": re.compile(
|
26
|
+
r"\.(exe|sh|py|pl|bak|php5|jspx|bat|cmd|pif|js|vbs|vbe|sct|ini|inf|tmp|swp|jar|java|class|ps1)\b",
|
27
|
+
re.IGNORECASE)
|
28
|
+
}
|
29
|
+
|
30
|
+
# 定义多层解码函数,确保完全解码 URI
|
31
|
+
def fully_decode_uri(uri):
|
32
|
+
try:
|
33
|
+
decoded_uri = str(uri)
|
34
|
+
for _ in range(3): # 尝试多次解码嵌套的编码
|
35
|
+
decoded_uri = unquote(decoded_uri)
|
36
|
+
return decoded_uri
|
37
|
+
except Exception as e:
|
38
|
+
return uri
|
39
|
+
|
40
|
+
def process_row(row):
|
41
|
+
uris = row['http.uri']
|
42
|
+
if not isinstance(uris, list):
|
43
|
+
try:
|
44
|
+
uris = json.loads(uris)
|
45
|
+
if not isinstance(uris, list):
|
46
|
+
uris = [str(uris)]
|
47
|
+
except Exception:
|
48
|
+
uris = [str(uris)]
|
49
|
+
try:
|
50
|
+
decoded_uris = [fully_decode_uri(uri) for uri in uris]
|
51
|
+
except Exception as e:
|
52
|
+
traceback.print_exc()
|
53
|
+
exit(0)
|
54
|
+
|
55
|
+
|
56
|
+
# 初始化统计变量
|
57
|
+
param_count = 0
|
58
|
+
path_depth = 0
|
59
|
+
param_lengths = []
|
60
|
+
feature_flags = {key: False for key in regex_patterns.keys()}
|
61
|
+
|
62
|
+
# 遍历解码后的 URI
|
63
|
+
for uri in decoded_uris:
|
64
|
+
param_count += uri.count('&') + 1
|
65
|
+
path_depth += uri.count('/')
|
66
|
+
|
67
|
+
# 提取参数长度
|
68
|
+
if '?' in uri:
|
69
|
+
params = uri.split('?', 1)[-1].split('&')
|
70
|
+
for param in params:
|
71
|
+
if '=' in param:
|
72
|
+
_, value = param.split('=', 1)
|
73
|
+
param_lengths.append(len(value))
|
74
|
+
|
75
|
+
# 检查正则匹配特征
|
76
|
+
for key, pattern in regex_patterns.items():
|
77
|
+
if pattern.search(uri):
|
78
|
+
feature_flags[key] = True
|
79
|
+
|
80
|
+
# 计算参数长度的统计值
|
81
|
+
avg_length = sum(param_lengths) / len(param_lengths) if param_lengths else 0
|
82
|
+
max_length = max(param_lengths) if param_lengths else 0
|
83
|
+
|
84
|
+
# 创建返回结果字典
|
85
|
+
result = {
|
86
|
+
"URI_FEATURES_EXTRA_param_count": param_count,
|
87
|
+
"URI_FEATURES_EXTRA_path_depth": path_depth,
|
88
|
+
"URI_FEATURES_EXTRA_param_length_avg": avg_length,
|
89
|
+
"URI_FEATURES_EXTRA_param_length_max": max_length,
|
90
|
+
}
|
91
|
+
|
92
|
+
# 添加特征标志到结果
|
93
|
+
for key, value in feature_flags.items():
|
94
|
+
result[f"URI_FEATURES_EXTRA_contains_{key}"] = value
|
95
|
+
|
96
|
+
return result
|
97
|
+
feature_data = data.progress_apply(process_row, axis=1, result_type="expand")
|
98
|
+
data = pd.concat([data, feature_data], axis=1)
|
99
|
+
return data
|
100
|
+
|
101
|
+
|
102
|
+
def handle_ua(data):
|
103
|
+
print("处理UA")
|
104
|
+
data['http.useragent'] = data['http.useragent'].fillna('').astype(str)
|
105
|
+
# 处理换行符及多余空格
|
106
|
+
data['http.useragent'] = data['http.useragent'].str.replace(r'\s+', ' ', regex=True)
|
107
|
+
# 常见攻击的 User-Agent 字符串匹配模式,忽略大小写
|
108
|
+
attack_patterns = '|'.join([
|
109
|
+
r"\bselect\b", r"\bunion\b", r"\binsert\b", r"\bupdate\b", r"\bdelete\b", r"\bdrop\b", r"--", r"#", r" or ",
|
110
|
+
r"' or '",
|
111
|
+
r"information_schema", r"database\(\)", r"version\(\)", # SQL注入相关
|
112
|
+
r"<script>", r"javascript:", r"onload=", r"onclick=", r"<iframe>", r"src=", # XSS相关
|
113
|
+
r"/etc/passwd", r"/etc/shadow", r"\&\&", r"\|", r"\$\(\)", r"exec", r"system", # 命令执行相关
|
114
|
+
r"\.\./", r"\.\.%2f", r"\.\.%5c", r"%c0%af", r"%252e%252e%252f", # 路径遍历
|
115
|
+
r"\.php", r"\.asp", r"\.jsp", r"\.exe", r"\.sh", r"\.py", r"\.pl", # 文件扩展名
|
116
|
+
r"redirect=", r"url=", r"next=", # 重定向
|
117
|
+
r"%3C", r"%3E", r"%27", r"%22", r"%00", r"%2F", r"%5C", r"%3B", r"%7C", r"%2E", r"%28", r"%29", # 编码
|
118
|
+
r'Googlebot', r'Bingbot', r'Slurp', r'curl', r'wget', r'Nmap',
|
119
|
+
r'SQLMap', r'Nikto', r'Dirbuster', r'python-requests', r'Apache-HttpClient',
|
120
|
+
r'Postman', r'Burp Suite', r'Fuzzing', r'nessus'
|
121
|
+
])
|
122
|
+
# 企业客户端 User-Agent 模式
|
123
|
+
enterprise_patterns = '|'.join([
|
124
|
+
r'MicroMessenger', r'wxwork', r'QQ/', r'QQBrowser', r'Alipay', r'UCWEB'
|
125
|
+
])
|
126
|
+
# 批量检查是否为攻击的 User-Agent,忽略大小写
|
127
|
+
data['UserAgent_is_attack'] = data['http.useragent'].str.contains(attack_patterns, case=False, regex=True)
|
128
|
+
# 批量检查是否为企业客户端,忽略大小写
|
129
|
+
data['UserAgent_is_enterprise'] = data['http.useragent'].str.contains(enterprise_patterns, case=False)
|
130
|
+
# 提取浏览器和版本
|
131
|
+
data['UserAgent_browser'] = data['http.useragent'].str.extract(r'(Chrome|Firefox|Safari|MSIE|Edge|Opera|Trident)',
|
132
|
+
expand=False, flags=re.IGNORECASE).fillna("Unknown")
|
133
|
+
data['UserAgent_browser_version'] = data['http.useragent'].str.extract(
|
134
|
+
r'Chrome/([\d\.]+)|Firefox/([\d\.]+)|Version/([\d\.]+).*Safari|MSIE ([\d\.]+)|Edge/([\d\.]+)|Opera/([\d\.]+)|Trident/([\d\.]+)',
|
135
|
+
expand=False, flags=re.IGNORECASE).bfill(axis=1).fillna("Unknown").iloc[:, 0]
|
136
|
+
# 提取操作系统和版本
|
137
|
+
os_info = data['http.useragent'].str.extract(
|
138
|
+
r'(Windows NT [\d\.]+|Mac OS X [\d_\.]+|Linux|Android [\d\.]+|iOS [\d_\.]+|Ubuntu|Debian|CentOS|Red Hat)',
|
139
|
+
expand=False, flags=re.IGNORECASE)
|
140
|
+
data['UserAgent_os'] = os_info.str.extract(r'(Windows|Mac OS X|Linux|Android|iOS|Ubuntu|Debian|CentOS|Red Hat)',
|
141
|
+
expand=False, flags=re.IGNORECASE).fillna("Unknown")
|
142
|
+
data['UserAgent_os_version'] = os_info.str.extract(r'([\d\._]+)', expand=False).fillna("Unknown")
|
143
|
+
# 提取设备类型,忽略大小写
|
144
|
+
data['UserAgent_device_type'] = data['http.useragent'].str.contains('mobile|android|iphone', case=False).map(
|
145
|
+
{True: 'Mobile', False: 'Desktop'})
|
146
|
+
# 提取硬件平台,增加对 x64 的匹配
|
147
|
+
data['UserAgent_platform'] = data['http.useragent'].str.extract(r'(x86|x86_64|arm|arm64|x64)', expand=False,
|
148
|
+
flags=re.IGNORECASE).fillna('Unknown')
|
149
|
+
# 判断是否为爬虫,忽略大小写
|
150
|
+
data['UserAgent_is_bot'] = data['http.useragent'].str.contains('bot|crawler|spider|slurp|curl|wget|httpclient',
|
151
|
+
case=False)
|
152
|
+
# 提取语言偏好(如果存在),忽略大小写
|
153
|
+
data['UserAgent_language'] = data['http.useragent'].str.extract(r'\b([a-z]{2}-[A-Z]{2})\b', expand=False,
|
154
|
+
flags=re.IGNORECASE).fillna("Unknown")
|
155
|
+
# 统计 User-Agent 中的特殊字符个数
|
156
|
+
data['UserAgent_special_char_count'] = data['http.useragent'].progress_apply(
|
157
|
+
lambda x: len(re.findall(r'[!@#$%^&*\'=:|{}]', x, flags=re.IGNORECASE)))
|
158
|
+
# 更新 UserAgent_is_unknown 的计算逻辑
|
159
|
+
data['UserAgent_is_unknown'] = data[['UserAgent_browser', 'UserAgent_os', 'UserAgent_platform']].isna().any(
|
160
|
+
axis=1).fillna("Unknown")
|
161
|
+
return data
|
@@ -0,0 +1,247 @@
|
|
1
|
+
import math
|
2
|
+
import os
|
3
|
+
import struct
|
4
|
+
import time
|
5
|
+
import zlib
|
6
|
+
from datetime import datetime
|
7
|
+
|
8
|
+
from Crypto.Cipher import AES
|
9
|
+
from zstandard import ZstdDecompressor
|
10
|
+
|
11
|
+
|
12
|
+
def fix_pos(pos, packetPosEncoding):
|
13
|
+
if pos is None or len(pos) == 0:
|
14
|
+
return
|
15
|
+
if packetPosEncoding == "gap0":
|
16
|
+
last = 0
|
17
|
+
lastgap = 0
|
18
|
+
for i, pos_item in enumerate(pos):
|
19
|
+
if pos[i] < 0:
|
20
|
+
last = 0
|
21
|
+
else:
|
22
|
+
if pos[i] == 0:
|
23
|
+
pos[i] = last + lastgap
|
24
|
+
else:
|
25
|
+
lastgap = pos[i]
|
26
|
+
pos[i] += last
|
27
|
+
last = pos[i]
|
28
|
+
|
29
|
+
|
30
|
+
def group_numbers(nums):
|
31
|
+
result = []
|
32
|
+
for num in nums:
|
33
|
+
if num < 0:
|
34
|
+
result.append([num])
|
35
|
+
elif result:
|
36
|
+
result[-1].append(num)
|
37
|
+
return result
|
38
|
+
|
39
|
+
|
40
|
+
def decompress_streaming(compressed_data, id, fro):
|
41
|
+
try:
|
42
|
+
decompressor = ZstdDecompressor()
|
43
|
+
with decompressor.stream_reader(compressed_data) as reader:
|
44
|
+
decompressed_data = reader.read()
|
45
|
+
return decompressed_data
|
46
|
+
except Exception as e:
|
47
|
+
print(f"解码错误:{e} {id}")
|
48
|
+
return bytearray()
|
49
|
+
|
50
|
+
|
51
|
+
def read_header(param_map, id):
|
52
|
+
shortHeader = None
|
53
|
+
headBuffer = os.read(param_map['fd'], 64)
|
54
|
+
if param_map['encoding'] == 'aes-256-ctr':
|
55
|
+
if 'iv' in param_map:
|
56
|
+
param_map['iv'][12:16] = struct.pack('>I', 0)
|
57
|
+
headBuffer = bytearray(
|
58
|
+
AES.new(param_map['encKey'], AES.MODE_CTR, nonce=param_map['iv']).decrypt(bytes(headBuffer)))
|
59
|
+
else:
|
60
|
+
print("读取头部信息失败,iv向量为空")
|
61
|
+
elif param_map['encoding'] == 'xor-2048':
|
62
|
+
for i in range(len(headBuffer)):
|
63
|
+
headBuffer[i] ^= param_map['encKey'][i % 256]
|
64
|
+
if param_map['uncompressedBits']:
|
65
|
+
if param_map['compression'] == 'gzip':
|
66
|
+
headBuffer = zlib.decompress(bytes(headBuffer), zlib.MAX_WBITS | 16)
|
67
|
+
elif param_map['compression'] == 'zstd':
|
68
|
+
headBuffer = decompress_streaming(headBuffer, id, "header")
|
69
|
+
headBuffer = headBuffer[:24]
|
70
|
+
magic = struct.unpack('<I', headBuffer[:4])[0]
|
71
|
+
bigEndian = (magic == 0xd4c3b2a1 or magic == 0x4d3cb2a1)
|
72
|
+
# nanosecond = (magic == 0xa1b23c4d or magic == 0x4d3cb2a1)
|
73
|
+
if not bigEndian and magic not in {0xa1b2c3d4, 0xa1b23c4d, 0xa1b2c3d5}:
|
74
|
+
corrupt = True
|
75
|
+
# os.close(param_map['fd'])
|
76
|
+
raise ValueError("Corrupt PCAP header")
|
77
|
+
if magic == 0xa1b2c3d5:
|
78
|
+
shortHeader = struct.unpack('<I', headBuffer[8:12])[0]
|
79
|
+
headBuffer[0] = 0xd4 # Reset header to normal
|
80
|
+
linkType = struct.unpack('>I' if bigEndian else '<I', headBuffer[20:24])[0]
|
81
|
+
return headBuffer, shortHeader, bigEndian
|
82
|
+
|
83
|
+
|
84
|
+
def create_decipher(pos, param_map):
|
85
|
+
param_map['iv'][12:16] = struct.pack('>I', pos)
|
86
|
+
return AES.new(param_map['encKey'], AES.MODE_CTR, nonce=param_map['iv'])
|
87
|
+
|
88
|
+
|
89
|
+
def read_packet_internal(pos_arg, hp_len_arg, param_map, id):
|
90
|
+
pos = pos_arg
|
91
|
+
hp_len = hp_len_arg
|
92
|
+
if hp_len == -1:
|
93
|
+
if param_map['compression'] == "zstd":
|
94
|
+
hp_len = param_map['uncompressedBitsSize']
|
95
|
+
else:
|
96
|
+
hp_len = 2048
|
97
|
+
inside_offset = 0
|
98
|
+
if param_map['uncompressedBits']:
|
99
|
+
inside_offset = pos & param_map['uncompressedBitsSize'] - 1
|
100
|
+
pos = math.floor(pos / param_map['uncompressedBitsSize'])
|
101
|
+
pos_offset = 0
|
102
|
+
if param_map['encoding'] == 'aes-256-ctr':
|
103
|
+
pos_offset = pos % 16
|
104
|
+
pos = pos - pos_offset
|
105
|
+
elif param_map['encoding'] == 'xor-2048':
|
106
|
+
pos_offset = pos % 256
|
107
|
+
pos = pos - pos_offset
|
108
|
+
|
109
|
+
hp_len = 256 * math.ceil((hp_len + inside_offset + pos_offset) / 256)
|
110
|
+
buffer = bytearray(hp_len)
|
111
|
+
os.lseek(param_map['fd'], pos, os.SEEK_SET)
|
112
|
+
read_buffer = os.read(param_map['fd'], len(buffer))
|
113
|
+
if len(read_buffer) - pos_offset < 16:
|
114
|
+
return None
|
115
|
+
if param_map['encoding'] == 'aes-256-ctr':
|
116
|
+
decipher = create_decipher(pos // 16, param_map)
|
117
|
+
read_buffer = bytearray(decipher.decrypt(read_buffer))[pos_offset:]
|
118
|
+
elif param_map['encoding'] == 'xor-2048':
|
119
|
+
read_buffer = bytearray(b ^ param_map['encKey'][i % 256] for i, b in enumerate(read_buffer))[pos_offset:]
|
120
|
+
if param_map['uncompressedBits']:
|
121
|
+
try:
|
122
|
+
if param_map['compression'] == 'gzip':
|
123
|
+
read_buffer = zlib.decompress(read_buffer, zlib.MAX_WBITS | 16)
|
124
|
+
elif param_map['compression'] == 'zstd':
|
125
|
+
read_buffer = decompress_streaming(read_buffer, id, "packet")
|
126
|
+
except Exception as e:
|
127
|
+
print(f"PCAP uncompress issue: {pos} {len(buffer)} {read_buffer} {e}")
|
128
|
+
return None
|
129
|
+
if inside_offset:
|
130
|
+
read_buffer = read_buffer[inside_offset:]
|
131
|
+
header_len = 16 if param_map['shortHeader'] is None else 6
|
132
|
+
if len(read_buffer) < header_len:
|
133
|
+
if hp_len_arg == -1 and param_map['compression'] == 'zstd':
|
134
|
+
return read_packet_internal(pos_arg, param_map['uncompressedBitsSize'] * 2, param_map, id)
|
135
|
+
print(f"Not enough data {len(read_buffer)} for header {header_len}")
|
136
|
+
return None
|
137
|
+
packet_len = struct.unpack('>I' if param_map['bigEndian'] else '<I', read_buffer[8:12])[
|
138
|
+
0] if param_map['shortHeader'] is None else \
|
139
|
+
struct.unpack('>H' if param_map['bigEndian'] else '<H', read_buffer[:2])[0]
|
140
|
+
if packet_len < 0 or packet_len > 0xffff:
|
141
|
+
return None
|
142
|
+
if header_len + packet_len <= len(read_buffer):
|
143
|
+
if param_map['shortHeader'] is not None:
|
144
|
+
t = struct.unpack('<I', read_buffer[2:6])[0]
|
145
|
+
sec = (t >> 20) + param_map['shortHeader']
|
146
|
+
usec = t & 0xfffff
|
147
|
+
new_buffer = bytearray(16 + packet_len)
|
148
|
+
struct.pack_into('<I', new_buffer, 0, sec)
|
149
|
+
struct.pack_into('<I', new_buffer, 4, usec)
|
150
|
+
struct.pack_into('<I', new_buffer, 8, packet_len)
|
151
|
+
struct.pack_into('<I', new_buffer, 12, packet_len)
|
152
|
+
new_buffer[16:] = read_buffer[6:packet_len + 6]
|
153
|
+
return new_buffer
|
154
|
+
return read_buffer[:header_len + packet_len]
|
155
|
+
|
156
|
+
if hp_len_arg != -1:
|
157
|
+
return None
|
158
|
+
|
159
|
+
return read_packet_internal(pos_arg, 16 + packet_len, param_map, id)
|
160
|
+
|
161
|
+
|
162
|
+
def read_packet(pos, param_map, id):
|
163
|
+
if 'fd' not in param_map or not param_map['fd']:
|
164
|
+
time.sleep(0.01)
|
165
|
+
return read_packet(pos, param_map['fd'], id)
|
166
|
+
return read_packet_internal(pos, -1, param_map, id)
|
167
|
+
|
168
|
+
|
169
|
+
def get_file_and_read_pos(id, file, pos_list):
|
170
|
+
filename = file['name']
|
171
|
+
if not os.path.isfile(filename):
|
172
|
+
print(f"文件不存在:{filename}")
|
173
|
+
return None
|
174
|
+
encoding = file.get('encoding', 'normal')
|
175
|
+
encKey = None
|
176
|
+
iv = None
|
177
|
+
compression = None
|
178
|
+
if 'dek' in file:
|
179
|
+
dek = bytes.fromhex(file['dek'])
|
180
|
+
encKey = AES.new(file['kek'].encode(), AES.MODE_CBC).decrypt(dek)
|
181
|
+
|
182
|
+
if 'uncompressedBits' in file:
|
183
|
+
uncompressedBits = file['uncompressedBits']
|
184
|
+
uncompressedBitsSize = 2 ** uncompressedBits
|
185
|
+
compression = 'gzip'
|
186
|
+
else:
|
187
|
+
uncompressedBits = None
|
188
|
+
uncompressedBitsSize = 0
|
189
|
+
if 'compression' in file:
|
190
|
+
compression = file['compression']
|
191
|
+
|
192
|
+
if 'iv' in file:
|
193
|
+
iv_ = bytes.fromhex(file['iv'])
|
194
|
+
iv = bytearray(16)
|
195
|
+
iv[:len(iv_)] = iv_
|
196
|
+
fd = os.open(filename, os.O_RDONLY)
|
197
|
+
param_map = {
|
198
|
+
"fd": fd,
|
199
|
+
"encoding": encoding,
|
200
|
+
"iv": iv,
|
201
|
+
"encKey": encKey,
|
202
|
+
"uncompressedBits": uncompressedBits,
|
203
|
+
"compression": compression,
|
204
|
+
"uncompressedBitsSize": uncompressedBitsSize
|
205
|
+
}
|
206
|
+
res = bytearray()
|
207
|
+
headBuffer, shortHeader, bigEndian = read_header(param_map, id)
|
208
|
+
res.extend(headBuffer)
|
209
|
+
param_map['shortHeader'] = shortHeader
|
210
|
+
param_map['bigEndian'] = bigEndian
|
211
|
+
# _________________________________
|
212
|
+
byte_array = bytearray(0xfffe)
|
213
|
+
next_packet = 0
|
214
|
+
b_offset = 0
|
215
|
+
packets = {}
|
216
|
+
i = 0
|
217
|
+
for pos in pos_list:
|
218
|
+
packet_bytes = read_packet(pos, param_map, id)
|
219
|
+
if not packet_bytes:
|
220
|
+
continue
|
221
|
+
packets[i] = packet_bytes
|
222
|
+
while next_packet in packets:
|
223
|
+
buffer = packets[next_packet]
|
224
|
+
del packets[next_packet]
|
225
|
+
next_packet = next_packet + 1
|
226
|
+
if b_offset + len(buffer) > len(byte_array):
|
227
|
+
res.extend(byte_array[:b_offset])
|
228
|
+
b_offset = 0
|
229
|
+
byte_array = bytearray(0xfffe)
|
230
|
+
byte_array[b_offset:b_offset + len(buffer)] = buffer
|
231
|
+
b_offset += len(buffer)
|
232
|
+
i = i + 1
|
233
|
+
os.close(fd)
|
234
|
+
res.extend(byte_array[:b_offset])
|
235
|
+
return res
|
236
|
+
|
237
|
+
|
238
|
+
def process_session_id_disk_simple(id, node, packet_pos, esdb, pcap_path_prefix):
|
239
|
+
packetPos = packet_pos
|
240
|
+
file = esdb.get_file_by_file_id(node=node, num=abs(packetPos[0]),
|
241
|
+
prefix=None if pcap_path_prefix == "origin" else pcap_path_prefix)
|
242
|
+
if file is None:
|
243
|
+
return None
|
244
|
+
fix_pos(packetPos, file['packetPosEncoding'])
|
245
|
+
pos_list = group_numbers(packetPos)[0]
|
246
|
+
pos_list.pop(0)
|
247
|
+
return get_file_and_read_pos(id, file, pos_list)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|