-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_hashing_ioc_match.py
More file actions
94 lines (77 loc) · 3.25 KB
/
Copy pathfile_hashing_ioc_match.py
File metadata and controls
94 lines (77 loc) · 3.25 KB
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
"""
File hashing for IOC matching — companion script for the post:
"Python Quick Guide: File Hashing for IOC Matching"
The hashing/scanning functions below are exactly as they appear in the post.
The demo at the bottom builds a small sample directory and a bad-hash list so
the scan prints a real [MATCH] with no external setup — that line is the
screenshot for the post.
Run:
python file_hashing_ioc_match.py
"""
import hashlib
import os
import shutil
# --- post code: Step 1 -------------------------------------------------------
def sha256_file(path, chunk_size=65536):
"""Return the SHA-256 hex digest of a file, read in chunks."""
h = hashlib.sha256()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(chunk_size), b""):
h.update(chunk)
return h.hexdigest()
# --- post code: Step 2 -------------------------------------------------------
def load_iocs(ioc_path):
"""Load known-bad hashes into a lowercase set for O(1) lookups."""
with open(ioc_path, "r", encoding="utf-8") as f:
return {line.strip().lower() for line in f if line.strip()}
# --- post code: Step 3 -------------------------------------------------------
def scan(root, iocs):
for dirpath, _dirs, files in os.walk(root):
for name in files:
full = os.path.join(dirpath, name)
try:
digest = sha256_file(full)
except (PermissionError, FileNotFoundError, OSError) as exc:
print(f"[skip] {full}: {exc}")
continue
if digest in iocs:
print(f"[MATCH] {full} {digest}")
# --- post code: Step 4 -------------------------------------------------------
def multi_hash(path, chunk_size=65536):
hashers = {
"md5": hashlib.md5(),
"sha1": hashlib.sha1(),
"sha256": hashlib.sha256(),
}
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(chunk_size), b""):
for h in hashers.values():
h.update(chunk)
return {name: h.hexdigest() for name, h in hashers.items()}
# --- demo harness (not in the post) -----------------------------------------
def _build_sample(folder):
"""Create a few files; return the SHA-256 of the one we'll mark bad."""
if os.path.exists(folder):
shutil.rmtree(folder)
os.makedirs(folder)
files = {
"report.txt": b"quarterly numbers, nothing to see here\n",
"notes.md": b"# meeting notes\n- patch the web server\n",
"totally_legit.exe": b"MZ\x90\x00fake-but-deterministic-payload-bytes",
}
for name, data in files.items():
with open(os.path.join(folder, name), "wb") as f:
f.write(data)
return sha256_file(os.path.join(folder, "totally_legit.exe"))
if __name__ == "__main__":
sample_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
"_demo_hashing")
ioc_file = os.path.join(sample_dir, "bad_hashes.txt")
bad_hash = _build_sample(sample_dir)
with open(ioc_file, "w", encoding="utf-8") as f:
f.write(bad_hash + "\n")
print(f"Scanning {sample_dir} against {os.path.basename(ioc_file)} "
f"({1} known-bad hash)\n")
iocs = load_iocs(ioc_file)
scan(sample_dir, iocs)
print("\nScan complete.")