FlowAnalyzer 0.3.7__tar.gz → 0.3.8__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.
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer/FlowAnalyzer.py +54 -47
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer.egg-info/PKG-INFO +1 -1
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/PKG-INFO +1 -1
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/setup.py +1 -1
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer/Path.py +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer/__init__.py +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer/logging_config.py +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer.egg-info/SOURCES.txt +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer.egg-info/dependency_links.txt +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/FlowAnalyzer.egg-info/top_level.txt +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/LICENSE +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/README.md +0 -0
- {flowanalyzer-0.3.7 → FlowAnalyzer-0.3.8}/setup.cfg +0 -0
|
@@ -36,15 +36,15 @@ class HttpPair(NamedTuple):
|
|
|
36
36
|
class FlowAnalyzer:
|
|
37
37
|
"""FlowAnalyzer是一个流量分析器,用于解析和处理tshark导出的JSON数据文件"""
|
|
38
38
|
|
|
39
|
-
def __init__(self,
|
|
39
|
+
def __init__(self, json_path: str):
|
|
40
40
|
"""初始化FlowAnalyzer对象
|
|
41
41
|
|
|
42
42
|
Parameters
|
|
43
43
|
----------
|
|
44
|
-
|
|
44
|
+
json_path : str
|
|
45
45
|
tshark导出的JSON文件路径
|
|
46
46
|
"""
|
|
47
|
-
self.
|
|
47
|
+
self.json_path = json_path
|
|
48
48
|
self.check_json_file()
|
|
49
49
|
|
|
50
50
|
def check_json_file(self):
|
|
@@ -58,11 +58,11 @@ class FlowAnalyzer:
|
|
|
58
58
|
ValueError
|
|
59
59
|
当JSON文件内容为空时抛出异常
|
|
60
60
|
"""
|
|
61
|
-
if not os.path.exists(self.
|
|
62
|
-
raise FileNotFoundError("您的tshark导出的JSON文件没有找到!JSON路径:%s" % self.
|
|
61
|
+
if not os.path.exists(self.json_path):
|
|
62
|
+
raise FileNotFoundError("您的tshark导出的JSON文件没有找到!JSON路径:%s" % self.json_path)
|
|
63
63
|
|
|
64
|
-
if os.path.getsize(self.
|
|
65
|
-
raise ValueError("您的tshark导出的JSON文件内容为空!JSON路径:%s" % self.
|
|
64
|
+
if os.path.getsize(self.json_path) == 0:
|
|
65
|
+
raise ValueError("您的tshark导出的JSON文件内容为空!JSON路径:%s" % self.json_path)
|
|
66
66
|
|
|
67
67
|
def parse_packet(self, packet: dict) -> Tuple[int, int, float, str, str]:
|
|
68
68
|
"""解析Json中的关键信息字段
|
|
@@ -92,7 +92,6 @@ class FlowAnalyzer:
|
|
|
92
92
|
return frame_num, request_in, time_epoch, full_uri, full_request
|
|
93
93
|
|
|
94
94
|
def parse_http_json(self) -> Tuple[Dict[int, Request], Dict[int, Response]]:
|
|
95
|
-
# sourcery skip: use-named-expression
|
|
96
95
|
"""解析JSON数据文件中的HTTP请求和响应信息
|
|
97
96
|
|
|
98
97
|
Returns
|
|
@@ -100,7 +99,7 @@ class FlowAnalyzer:
|
|
|
100
99
|
tuple
|
|
101
100
|
包含请求字典和响应列表的元组
|
|
102
101
|
"""
|
|
103
|
-
with open(self.
|
|
102
|
+
with open(self.json_path, "r", encoding="utf-8") as f:
|
|
104
103
|
data = json.load(f)
|
|
105
104
|
|
|
106
105
|
requests, responses = {}, {}
|
|
@@ -149,17 +148,16 @@ class FlowAnalyzer:
|
|
|
149
148
|
yield HttpPair(request=None, response=resp)
|
|
150
149
|
|
|
151
150
|
@staticmethod
|
|
152
|
-
def get_hash(
|
|
153
|
-
with open(
|
|
151
|
+
def get_hash(file_path: str, display_filter: str) -> str:
|
|
152
|
+
with open(file_path, "rb") as f:
|
|
154
153
|
return hashlib.md5(f.read() + display_filter.encode()).hexdigest()
|
|
155
154
|
|
|
156
155
|
@staticmethod
|
|
157
|
-
def extract_json_file(
|
|
158
|
-
# sourcery skip: replace-interpolation-with-fstring, use-fstring-for-formatting
|
|
156
|
+
def extract_json_file(file_name: str, display_filter: str, tshark_work_dir: str, tshark_path: str) -> None:
|
|
159
157
|
command = [
|
|
160
158
|
tshark_path,
|
|
161
|
-
"-r",
|
|
162
|
-
"-Y", f"(
|
|
159
|
+
"-r", file_name,
|
|
160
|
+
"-Y", f"({display_filter})",
|
|
163
161
|
"-T", "json",
|
|
164
162
|
"-e", "http.response.code",
|
|
165
163
|
"-e", "http.request_in",
|
|
@@ -169,33 +167,43 @@ class FlowAnalyzer:
|
|
|
169
167
|
"-e", "frame.time_epoch",
|
|
170
168
|
"-e", "exported_pdu.exported_pdu",
|
|
171
169
|
"-e", "http.request.full_uri",
|
|
172
|
-
">", "output.json",
|
|
173
170
|
]
|
|
174
171
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
172
|
+
with open(f"{tshark_work_dir}/output.json", "wb") as output_file:
|
|
173
|
+
process = subprocess.Popen(
|
|
174
|
+
command,
|
|
175
|
+
stdout=output_file,
|
|
176
|
+
stderr=subprocess.PIPE,
|
|
177
|
+
cwd=tshark_work_dir
|
|
178
|
+
)
|
|
179
|
+
_, stderr = process.communicate()
|
|
180
|
+
|
|
181
|
+
if stderr and b"WARNING" not in stderr:
|
|
182
|
+
try:
|
|
183
|
+
print(f"[Warning/Error]: {stderr.decode('utf-8')}")
|
|
184
|
+
except Exception:
|
|
185
|
+
print(f"[Warning/Error]: {stderr.decode('gbk')}")
|
|
178
186
|
|
|
179
187
|
@staticmethod
|
|
180
|
-
def
|
|
181
|
-
if
|
|
182
|
-
shutil.move(
|
|
188
|
+
def move_and_add_md5sum(tshark_json_path: str, json_work_path: str, md5_sum: str) -> None:
|
|
189
|
+
if tshark_json_path != json_work_path:
|
|
190
|
+
shutil.move(tshark_json_path, json_work_path)
|
|
183
191
|
|
|
184
|
-
with open(
|
|
192
|
+
with open(json_work_path, "r", encoding="utf-8") as f:
|
|
185
193
|
data = json.load(f)
|
|
186
|
-
data[0]["MD5Sum"] =
|
|
194
|
+
data[0]["MD5Sum"] = md5_sum
|
|
187
195
|
|
|
188
|
-
with open(
|
|
196
|
+
with open(json_work_path, "w", encoding="utf-8") as f:
|
|
189
197
|
json.dump(data, f, indent=2)
|
|
190
198
|
|
|
191
199
|
@staticmethod
|
|
192
|
-
def get_json_data(
|
|
200
|
+
def get_json_data(file_path: str, display_filter: str, tshark_path: Optional[str] = None) -> str:
|
|
193
201
|
# sourcery skip: replace-interpolation-with-fstring
|
|
194
202
|
"""获取JSON数据并保存至文件,保存目录是当前工作目录,也就是您运行脚本所在目录
|
|
195
203
|
|
|
196
204
|
Parameters
|
|
197
205
|
----------
|
|
198
|
-
|
|
206
|
+
file_path : str
|
|
199
207
|
待处理的数据文件路径
|
|
200
208
|
display_filter : str
|
|
201
209
|
WireShark的显示过滤器
|
|
@@ -205,30 +213,30 @@ class FlowAnalyzer:
|
|
|
205
213
|
str
|
|
206
214
|
保存JSON数据的文件路径
|
|
207
215
|
"""
|
|
208
|
-
if not os.path.exists(
|
|
209
|
-
raise FileNotFoundError("您的填写的流量包没有找到!流量包路径:%s" %
|
|
216
|
+
if not os.path.exists(file_path):
|
|
217
|
+
raise FileNotFoundError("您的填写的流量包没有找到!流量包路径:%s" % file_path)
|
|
210
218
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
md5_sum = FlowAnalyzer.get_hash(file_path, display_filter)
|
|
220
|
+
work_dir = os.getcwd()
|
|
221
|
+
tshark_work_dir = os.path.dirname(os.path.abspath(file_path))
|
|
222
|
+
tshark_json_path = os.path.join(tshark_work_dir, "output.json")
|
|
223
|
+
json_work_path = os.path.join(work_dir, "output.json")
|
|
224
|
+
file_name = os.path.basename(file_path)
|
|
217
225
|
|
|
218
|
-
if os.path.exists(
|
|
226
|
+
if os.path.exists(json_work_path):
|
|
219
227
|
try:
|
|
220
|
-
with open(
|
|
228
|
+
with open(json_work_path, "r", encoding="utf-8") as f:
|
|
221
229
|
data = json.load(f)
|
|
222
|
-
if data[0].get("MD5Sum") ==
|
|
230
|
+
if data[0].get("MD5Sum") == md5_sum:
|
|
223
231
|
logger.debug("匹配HASH校验无误,自动返回Json文件路径!")
|
|
224
|
-
return
|
|
232
|
+
return json_work_path
|
|
225
233
|
except Exception:
|
|
226
234
|
logger.debug("默认的Json文件无法被正常解析, 正在重新生成Json文件中")
|
|
227
235
|
|
|
228
236
|
tshark_path = FlowAnalyzer.get_tshark_path(tshark_path)
|
|
229
|
-
FlowAnalyzer.extract_json_file(
|
|
230
|
-
FlowAnalyzer.
|
|
231
|
-
return
|
|
237
|
+
FlowAnalyzer.extract_json_file(file_name, display_filter, tshark_work_dir, tshark_path)
|
|
238
|
+
FlowAnalyzer.move_and_add_md5sum(tshark_json_path, json_work_path, md5_sum)
|
|
239
|
+
return json_work_path
|
|
232
240
|
|
|
233
241
|
@staticmethod
|
|
234
242
|
def get_tshark_path(tshark_path: Optional[str]) -> str:
|
|
@@ -253,8 +261,7 @@ class FlowAnalyzer:
|
|
|
253
261
|
exit(-1)
|
|
254
262
|
return use_tshark_path
|
|
255
263
|
|
|
256
|
-
def
|
|
257
|
-
# sourcery skip: use-named-expression
|
|
264
|
+
def split_http_headers(self, file_data: bytes) -> Tuple[bytes, bytes]:
|
|
258
265
|
headerEnd = file_data.find(b"\r\n\r\n")
|
|
259
266
|
if headerEnd != -1:
|
|
260
267
|
headerEnd += 4
|
|
@@ -266,7 +273,7 @@ class FlowAnalyzer:
|
|
|
266
273
|
print("[Warning] 没有找到headers和response的划分位置!")
|
|
267
274
|
return b"", file_data
|
|
268
275
|
|
|
269
|
-
def
|
|
276
|
+
def dechunck_http_response(self, file_data: bytes) -> bytes:
|
|
270
277
|
"""解码分块TCP数据
|
|
271
278
|
|
|
272
279
|
Parameters
|
|
@@ -306,10 +313,10 @@ class FlowAnalyzer:
|
|
|
306
313
|
tuple
|
|
307
314
|
包含header和file_data的元组
|
|
308
315
|
"""
|
|
309
|
-
header, file_data = self.
|
|
316
|
+
header, file_data = self.split_http_headers(bytes.fromhex(full_request))
|
|
310
317
|
|
|
311
318
|
with contextlib.suppress(Exception):
|
|
312
|
-
file_data = self.
|
|
319
|
+
file_data = self.dechunck_http_response(file_data)
|
|
313
320
|
|
|
314
321
|
with contextlib.suppress(Exception):
|
|
315
322
|
if file_data.startswith(b"\x1F\x8B"):
|
|
@@ -7,7 +7,7 @@ with open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8"
|
|
|
7
7
|
|
|
8
8
|
setup(
|
|
9
9
|
name="FlowAnalyzer",
|
|
10
|
-
version="0.3.
|
|
10
|
+
version="0.3.8",
|
|
11
11
|
description="FlowAnalyzer是一个流量分析器,用于解析和处理tshark导出的JSON数据文件",
|
|
12
12
|
author="Byxs20",
|
|
13
13
|
author_email="97766819@qq.com",
|
|
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
|