parse_ioc 0.2.0__py3-none-any.whl

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.
@@ -0,0 +1,453 @@
1
+ Metadata-Version: 2.4
2
+ Name: parse_ioc
3
+ Version: 0.2.0
4
+ Summary: Parse a list of indicators into a dictionary or JSON structure for programmatic use.
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Dynamic: license-file
9
+
10
+ # ParseIOC
11
+
12
+ Parse a list of indicators into a dictionary or JSON structure for programmatic use.
13
+
14
+ Converts a plain list of indicators into a dictionary of:
15
+ - emails and their domains
16
+ - URL domains, and username+password and ports if present
17
+ - ipv4 and ipv6 addresses and networks
18
+ - md5, sha256, and sha512 hashes
19
+
20
+ ...with the goal of **mapping this dictionary to fields in a SIEM** or similar database.
21
+
22
+ This enables programatic use of an IOC file to quickly query specific values in a SIEM, such as `source.ip` or `file.hash.sha256`.
23
+
24
+ This tool will support more formats (imphash, ssdeep, ja3+) "eventually".
25
+
26
+ **Otherwise-unidentifiable strings are categorized as domains.**
27
+
28
+ ## Setup
29
+
30
+ ```
31
+ uv add parse_ioc
32
+ # or
33
+ pip3 install parse_ioc
34
+ ```
35
+
36
+ ## Usage
37
+ `from parse_ioc import ParseIOC, map_fields, parse_multi`
38
+
39
+
40
+ ### Categorize a single indicator
41
+ ```
42
+ i = ParseIOC("https://192.168.20.20/bad.txt")
43
+ i.to_dict
44
+ i.to_json
45
+ ```
46
+
47
+ ### Categorize a **list** or **file** of indicators
48
+ setting `mode="single"` will produce the same results as calling `ParseIOC(ioc)` by itself
49
+ ```
50
+ p = parse_multi(ioc_list, mode="combined")
51
+ # or
52
+ p = parse_multi("ioc_examples.txt", mode="combined")
53
+
54
+ print(json.dumps(p, indent=4))
55
+ ```
56
+
57
+ ### Map a **list** or **file** of indicators to a TOML of SIEM fields
58
+ ```
59
+ m = map_fields("ioc_examples.txt", "map_ecs.toml")
60
+ print(json.dumps(m, indent=4))
61
+ ```
62
+
63
+ ## Output from running `parse_ioc.py` directly
64
+ ```
65
+ ======================== categorize a single indicator =========================
66
+ .to_dict: <class 'dict'> {'ioc': '192.168.20.20', 'ioc_type': 'ipv4'}
67
+ .to_json: <class 'str'> {"ioc": "192.168.20.20", "ioc_type": "ipv4"}
68
+ ============ parse a list or file of IOCs into a combined structure ============
69
+ {
70
+ "email": [
71
+ "bob@email.local"
72
+ ],
73
+ "domain": [
74
+ "securewebsite.local",
75
+ "email.local",
76
+ "anotherwebsite.local",
77
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
78
+ "website.local"
79
+ ],
80
+ "port": [
81
+ 9443,
82
+ 8443
83
+ ],
84
+ "credentials": [
85
+ "username:password"
86
+ ],
87
+ "ipv4": [
88
+ "192.168.1.1",
89
+ "192.168.20.20"
90
+ ],
91
+ "ipv4_network": [
92
+ "192.168.1.0/24"
93
+ ]
94
+ }
95
+ {
96
+ "email": [
97
+ "bad.username@subdomain.bad.local",
98
+ "bob@email.local"
99
+ ],
100
+ "domain": [
101
+ "securewebsite.local",
102
+ "email.local",
103
+ "bob documents.pdf",
104
+ "file.txt",
105
+ "bad.local",
106
+ "not-an-ioc",
107
+ "anotherwebsite.local",
108
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
109
+ "subdomain.bad.local",
110
+ "website.local",
111
+ "aaaaaaaaaaaaaaaa"
112
+ ],
113
+ "ipv4": [
114
+ "8.8.8.8",
115
+ "192.168.1.1",
116
+ "192.168.20.20",
117
+ "1.2.3.4"
118
+ ],
119
+ "port": [
120
+ 9443,
121
+ 8443
122
+ ],
123
+ "credentials": [
124
+ "username:password"
125
+ ],
126
+ "ipv4_network": [
127
+ "8.8.8.0/24",
128
+ "192.168.1.0/24"
129
+ ],
130
+ "ipv6": [
131
+ "fe80::"
132
+ ],
133
+ "file_path_linux": [
134
+ "/home/bob/file.txt"
135
+ ],
136
+ "unknown": [
137
+ "rc:\\users\\bob smith\\desktop\\file.txt:alt.exe"
138
+ ],
139
+ "file_path_windows": [
140
+ "c:\\users\\bob\\desktop\\test.txt",
141
+ "c:/users/bob smith/desktop/file.txt:alt.exe",
142
+ "c:\\users\\bob smith\\desktop\\file.txt:alt.exe",
143
+ "file.txt:alt.exe",
144
+ "c:\\users\\bob smith\\desktop\\file.txt",
145
+ "c:\\users\\bob smith\\desktop\\file2.txt:alt.exe"
146
+ ],
147
+ "md5": [
148
+ "6cd3556deb0da54bca060b4c39479839"
149
+ ],
150
+ "sha256": [
151
+ "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"
152
+ ],
153
+ "sha512": [
154
+ "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421"
155
+ ]
156
+ }
157
+ === yield dictionaries from a list or file, instead of a combined structure ====
158
+ {'ioc': 'bob@email.local', 'ioc_type': 'email', 'extra': [{'ioc': 'email.local', 'ioc_type': 'domain'}]}
159
+ {'ioc': 'bad.username@subdomain.bad.local', 'ioc_type': 'email', 'extra': [{'ioc': 'subdomain.bad.local', 'ioc_type': 'domain'}]}
160
+ {'ioc': '8.8.8.8', 'ioc_type': 'ipv4'}
161
+ {'ioc': '1.2.3.4', 'ioc_type': 'ipv4'}
162
+ {'ioc': 'website.local', 'ioc_type': 'domain'}
163
+ {'ioc': 'anotherwebsite.local', 'ioc_type': 'domain', 'extra': [{'ioc': 9443, 'ioc_type': 'port'}]}
164
+ {'ioc': 'securewebsite.local', 'ioc_type': 'domain', 'extra': [{'ioc': 'username:password', 'ioc_type': 'credentials'}, {'ioc': 8443, 'ioc_type': 'port'}]}
165
+ {'ioc': '192.168.1.1', 'ioc_type': 'ipv4'}
166
+ {'ioc': '192.168.1.0/24', 'ioc_type': 'ipv4_network'}
167
+ {'ioc': '8.8.8.0/24', 'ioc_type': 'ipv4_network'}
168
+ {'ioc': '192.168.20.20', 'ioc_type': 'ipv4'}
169
+ {'ioc': 'fe80::', 'ioc_type': 'ipv6'}
170
+ {'ioc': 'n--nhk-u63b1cko2lyc6jrwxgom6k.com', 'ioc_type': 'domain'}
171
+ {'ioc': 'bad.local', 'ioc_type': 'domain'}
172
+ {'ioc': '/home/bob/file.txt', 'ioc_type': 'file_path_linux'}
173
+ {'ioc': 'rc:\\users\\bob smith\\desktop\\file.txt:alt.exe', 'ioc_type': 'unknown'}
174
+ {'ioc': 'file.txt', 'ioc_type': 'domain'}
175
+ {'ioc': 'file.txt:alt.exe', 'ioc_type': 'file_path_windows'}
176
+ {'ioc': 'bob documents.pdf', 'ioc_type': 'domain'}
177
+ {'ioc': '/home/bob/file.txt', 'ioc_type': 'file_path_linux'}
178
+ {'ioc': 'c:\\users\\bob\\desktop\\test.txt', 'ioc_type': 'file_path_windows'}
179
+ {'ioc': 'c:\\users\\bob smith\\desktop\\file.txt', 'ioc_type': 'file_path_windows'}
180
+ {'ioc': 'c:\\users\\bob smith\\desktop\\file.txt', 'ioc_type': 'file_path_windows'}
181
+ {'ioc': 'c:\\users\\bob smith\\desktop\\file.txt:alt.exe', 'ioc_type': 'file_path_windows'}
182
+ {'ioc': 'c:\\users\\bob smith\\desktop\\file.txt:alt.exe', 'ioc_type': 'file_path_windows'}
183
+ {'ioc': 'c:\\users\\bob smith\\desktop\\file.txt:alt.exe', 'ioc_type': 'file_path_windows'}
184
+ {'ioc': 'c:\\users\\bob smith\\desktop\\file2.txt:alt.exe', 'ioc_type': 'file_path_windows'}
185
+ {'ioc': 'c:/users/bob smith/desktop/file.txt:alt.exe', 'ioc_type': 'file_path_windows'}
186
+ {'ioc': 'not-an-ioc', 'ioc_type': 'domain'}
187
+ {'ioc': 'aaaaaaaaaaaaaaaa', 'ioc_type': 'domain'}
188
+ {'ioc': '6cd3556deb0da54bca060b4c39479839', 'ioc_type': 'md5'}
189
+ {'ioc': '315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3', 'ioc_type': 'sha256'}
190
+ {'ioc': 'c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421', 'ioc_type': 'sha512'}
191
+ ======== provide IOC (file or list) and TOML config (path) map_fields() ========
192
+ {
193
+ "email.from.address": [
194
+ "bad.username@subdomain.bad.local",
195
+ "bob@email.local"
196
+ ],
197
+ "email.sender.address": [
198
+ "bad.username@subdomain.bad.local",
199
+ "bob@email.local"
200
+ ],
201
+ "email.to.address": [
202
+ "bad.username@subdomain.bad.local",
203
+ "bob@email.local"
204
+ ],
205
+ "email.reply_to.address": [
206
+ "bad.username@subdomain.bad.local",
207
+ "bob@email.local"
208
+ ],
209
+ "email.cc.address": [
210
+ "bad.username@subdomain.bad.local",
211
+ "bob@email.local"
212
+ ],
213
+ "email.bcc.address": [
214
+ "bad.username@subdomain.bad.local",
215
+ "bob@email.local"
216
+ ],
217
+ "destination.domain": [
218
+ "securewebsite.local",
219
+ "email.local",
220
+ "bob documents.pdf",
221
+ "file.txt",
222
+ "bad.local",
223
+ "not-an-ioc",
224
+ "anotherwebsite.local",
225
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
226
+ "subdomain.bad.local",
227
+ "website.local",
228
+ "aaaaaaaaaaaaaaaa"
229
+ ],
230
+ "url.domain": [
231
+ "securewebsite.local",
232
+ "email.local",
233
+ "bob documents.pdf",
234
+ "file.txt",
235
+ "bad.local",
236
+ "not-an-ioc",
237
+ "anotherwebsite.local",
238
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
239
+ "subdomain.bad.local",
240
+ "website.local",
241
+ "aaaaaaaaaaaaaaaa"
242
+ ],
243
+ "tls.client.server_name": [
244
+ "securewebsite.local",
245
+ "email.local",
246
+ "bob documents.pdf",
247
+ "file.txt",
248
+ "bad.local",
249
+ "not-an-ioc",
250
+ "anotherwebsite.local",
251
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
252
+ "subdomain.bad.local",
253
+ "website.local",
254
+ "aaaaaaaaaaaaaaaa"
255
+ ],
256
+ "dns.question.registered_domain": [
257
+ "securewebsite.local",
258
+ "email.local",
259
+ "bob documents.pdf",
260
+ "file.txt",
261
+ "bad.local",
262
+ "not-an-ioc",
263
+ "anotherwebsite.local",
264
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
265
+ "subdomain.bad.local",
266
+ "website.local",
267
+ "aaaaaaaaaaaaaaaa"
268
+ ],
269
+ "file.origin_referrer_url": [
270
+ "securewebsite.local",
271
+ "email.local",
272
+ "bob documents.pdf",
273
+ "file.txt",
274
+ "bad.local",
275
+ "not-an-ioc",
276
+ "anotherwebsite.local",
277
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
278
+ "subdomain.bad.local",
279
+ "website.local",
280
+ "aaaaaaaaaaaaaaaa"
281
+ ],
282
+ "file.origin_url": [
283
+ "securewebsite.local",
284
+ "email.local",
285
+ "bob documents.pdf",
286
+ "file.txt",
287
+ "bad.local",
288
+ "not-an-ioc",
289
+ "anotherwebsite.local",
290
+ "n--nhk-u63b1cko2lyc6jrwxgom6k.com",
291
+ "subdomain.bad.local",
292
+ "website.local",
293
+ "aaaaaaaaaaaaaaaa"
294
+ ],
295
+ "source.ip": [
296
+ "8.8.8.8",
297
+ "192.168.1.1",
298
+ "192.168.20.20",
299
+ "1.2.3.4",
300
+ "8.8.8.0/24",
301
+ "192.168.1.0/24",
302
+ "fe80::"
303
+ ],
304
+ "destination.ip": [
305
+ "8.8.8.8",
306
+ "192.168.1.1",
307
+ "192.168.20.20",
308
+ "1.2.3.4",
309
+ "8.8.8.0/24",
310
+ "192.168.1.0/24",
311
+ "fe80::"
312
+ ],
313
+ "dns.resolved_ip": [
314
+ "8.8.8.8",
315
+ "192.168.1.1",
316
+ "192.168.20.20",
317
+ "1.2.3.4",
318
+ "8.8.8.0/24",
319
+ "192.168.1.0/24",
320
+ "fe80::"
321
+ ],
322
+ "host.ip": [
323
+ "8.8.8.8",
324
+ "192.168.1.1",
325
+ "192.168.20.20",
326
+ "1.2.3.4",
327
+ "8.8.8.0/24",
328
+ "192.168.1.0/24",
329
+ "fe80::"
330
+ ],
331
+ "network.forwarded_ip": [
332
+ "8.8.8.8",
333
+ "192.168.1.1",
334
+ "192.168.20.20",
335
+ "1.2.3.4",
336
+ "8.8.8.0/24",
337
+ "192.168.1.0/24",
338
+ "fe80::"
339
+ ],
340
+ "related.ip": [
341
+ "8.8.8.8",
342
+ "192.168.1.1",
343
+ "192.168.20.20",
344
+ "1.2.3.4",
345
+ "8.8.8.0/24",
346
+ "192.168.1.0/24",
347
+ "fe80::"
348
+ ],
349
+ "client.ip": [
350
+ "8.8.8.8",
351
+ "192.168.1.1",
352
+ "192.168.20.20",
353
+ "1.2.3.4",
354
+ "8.8.8.0/24",
355
+ "192.168.1.0/24",
356
+ "fe80::"
357
+ ],
358
+ "server.ip": [
359
+ "8.8.8.8",
360
+ "192.168.1.1",
361
+ "192.168.20.20",
362
+ "1.2.3.4",
363
+ "8.8.8.0/24",
364
+ "192.168.1.0/24",
365
+ "fe80::"
366
+ ],
367
+ "server.nat.ip": [
368
+ "8.8.8.8",
369
+ "192.168.1.1",
370
+ "192.168.20.20",
371
+ "1.2.3.4",
372
+ "8.8.8.0/24",
373
+ "192.168.1.0/24",
374
+ "fe80::"
375
+ ],
376
+ "threat.enrichments.indicator.ip": [
377
+ "8.8.8.8",
378
+ "192.168.1.1",
379
+ "192.168.20.20",
380
+ "1.2.3.4",
381
+ "8.8.8.0/24",
382
+ "192.168.1.0/24",
383
+ "fe80::"
384
+ ],
385
+ "file.path": [
386
+ "/home/bob/file.txt",
387
+ "c:\\users\\bob\\desktop\\test.txt",
388
+ "c:/users/bob smith/desktop/file.txt:alt.exe",
389
+ "c:\\users\\bob smith\\desktop\\file.txt:alt.exe",
390
+ "file.txt:alt.exe",
391
+ "c:\\users\\bob smith\\desktop\\file.txt",
392
+ "c:\\users\\bob smith\\desktop\\file2.txt:alt.exe"
393
+ ],
394
+ "file.name": [
395
+ "/home/bob/file.txt",
396
+ "c:\\users\\bob\\desktop\\test.txt",
397
+ "c:/users/bob smith/desktop/file.txt:alt.exe",
398
+ "c:\\users\\bob smith\\desktop\\file.txt:alt.exe",
399
+ "file.txt:alt.exe",
400
+ "c:\\users\\bob smith\\desktop\\file.txt",
401
+ "c:\\users\\bob smith\\desktop\\file2.txt:alt.exe"
402
+ ],
403
+ "dll.hash.md5": [
404
+ "6cd3556deb0da54bca060b4c39479839"
405
+ ],
406
+ "email.attachments.file.hash.md5": [
407
+ "6cd3556deb0da54bca060b4c39479839"
408
+ ],
409
+ "file.hash.md5": [
410
+ "6cd3556deb0da54bca060b4c39479839"
411
+ ],
412
+ "process.hash.md5": [
413
+ "6cd3556deb0da54bca060b4c39479839"
414
+ ],
415
+ "dll.hash.sha256": [
416
+ "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"
417
+ ],
418
+ "email.attachments.file.hash.sha256": [
419
+ "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"
420
+ ],
421
+ "file.hash.sha256": [
422
+ "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"
423
+ ],
424
+ "process.hash.sha256": [
425
+ "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3"
426
+ ],
427
+ "dll.hash.sha512": [
428
+ "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421"
429
+ ],
430
+ "email.attachments.file.hash.sha512": [
431
+ "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421"
432
+ ],
433
+ "file.hash.sha512": [
434
+ "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421"
435
+ ],
436
+ "process.hash.sha512": [
437
+ "c1527cd893c124773d811911970c8fe6e857d6df5dc9226bd8a160614c0cd963a4ddea2b94bb7d36021ef9d865d5cea294a82dd49a0bb269f51f6e7a57f79421"
438
+ ],
439
+ "source.port": [
440
+ 9443,
441
+ 8443
442
+ ],
443
+ "destination.port": [
444
+ 9443,
445
+ 8443
446
+ ]
447
+ }
448
+ ```
449
+
450
+ ## Known Issues
451
+
452
+ - need to streamline and optimize code
453
+ - remove both regex statements created by AI
@@ -0,0 +1,6 @@
1
+ parse_ioc.py,sha256=led9yY9zWPMQFUSrhdsWbdbeiP_MgL94C2U7sSsaS2c,12559
2
+ parse_ioc-0.2.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
3
+ parse_ioc-0.2.0.dist-info/METADATA,sha256=o35GC_-Ry1zUkz0ssoKFeSfbv6hM4OzzoZ2M4tLu5Rg,13478
4
+ parse_ioc-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ parse_ioc-0.2.0.dist-info/top_level.txt,sha256=-Dv5Zg9sS5ogsCrWw31wiwsbPWYKwbx3WbwU1arFlx0,10
6
+ parse_ioc-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+