xbase-util 0.0.8__tar.gz → 0.1.0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {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
|