Skip to content

Commit a11ce93

Browse files
Fixing coderabbit suggestions
Flag.py had 2 slow imports, made them local imports that are imported when needed only, as well as changed sentence-transformer to only show logs when DEBUG is true Updated exception logging to discourage it, making only one script now using it, and updated parse_execution logging to include a internal error if the list given is not in the correct format, also added an "except" as replacement to "exception" in the string() function vulnscan.py, sensitive_data_miner.py, event_log.py : Changed code to follow Good Practises dump_memory.py: added a truncation system to not allow files to be too large SECURITY.md now includes the release date of the versions! Fixed HUGE bug in sensitive_data_miner.py where it didn't construct paths properly thus didn't search the correct paths. Signed-off-by: Shahm Najeeb <[email protected]>
1 parent a0902a5 commit a11ce93

File tree

12 files changed

+114
-55
lines changed

12 files changed

+114
-55
lines changed

CODE/config.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ files = "bluetooth_details.py, bluetooth_logger.py, browser_miner.ps1, cmd_comma
2727
# The default is 30.0, and is what we advise
2828
# If the accuracy is below this, the flag will move to the next suggestion process
2929
# The process is: difflib, then model, then history suggestions
30+
# Make sure to keep between 0.0 and 100.0
3031
accuracy_min = 30.0
3132

3233
# This is the model to use to suggest flags,
@@ -38,6 +39,7 @@ model_to_use = all-MiniLM-L6-v2
3839
# Finally, should debug mode be enabled for the flag module?
3940
# This will print out more information to the console,
4041
# This is for the model itself, and is based on tqdm, it shows extra info on batches
42+
# As well as more information on behind the scenes
4143
model_debug = false
4244

4345
###################################################

CODE/dump_memory.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
if __name__ == "__main__":
1010
log = Log({"log_level": DEBUG})
1111

12+
# TODO v3.3.1
13+
# psutil.virtual_memory(): used, free, percent, total
14+
# psutil.swap_memory(): used, free, percent, total
15+
16+
# If the file size exceeds this limit, the file will be truncated with a message
17+
# Put 0 to disable the limit
18+
LIMIT_FILE_SIZE = 20 # Always in MiB
19+
1220

1321
# Capture RAM Snapshot
1422
def capture_ram_snapshot():
@@ -23,6 +31,7 @@ def capture_ram_snapshot():
2331
file.write(f"Total Swap: {swap.total / (1024 ** 3):.2f} GB\n")
2432
file.write(f"Used Swap: {swap.used / (1024 ** 3):.2f} GB\n")
2533
file.write(f"Free Swap: {swap.free / (1024 ** 3):.2f} GB\n")
34+
file.write(f"Percent RAM Used: {memory.percent:.2f}%\n")
2635
except Exception as e:
2736
log.error(f"Error writing RAM snapshot: {e}")
2837
file.write("Error writing RAM snapshot.")
@@ -56,6 +65,7 @@ def memory_dump():
5665
try:
5766
process = psutil.Process(pid)
5867
with open("Ram_Dump.txt", "wb") as dump_file:
68+
total_size = 0
5969
for mem_region in process.memory_maps(grouped=False):
6070
# Check if the memory region is readable ('r' permission)
6171
if 'r' in mem_region.perms:
@@ -91,10 +101,15 @@ def memory_dump():
91101

92102
# Write the metadata to the dump file
93103
try:
94-
dump_file.write(f"Memory Region Metadata:\n".encode())
95-
for key, value in region_metadata.items():
96-
dump_file.write(f"{key}: {value}\n".encode())
97-
dump_file.write(b"\n")
104+
metadata_str = "Memory Region Metadata:\n" + "\n".join(
105+
f"{key}: {value}" for key, value in region_metadata.items()) + "\n\n"
106+
metadata_bytes = metadata_str.encode()
107+
if total_size + len(metadata_bytes) > LIMIT_FILE_SIZE * 1024 * 1024 and LIMIT_FILE_SIZE != 0:
108+
dump_file.write(f"Truncated due to file exceeding {LIMIT_FILE_SIZE}\n"
109+
"Additional memory regions not included.\n".encode())
110+
break
111+
dump_file.write(metadata_bytes)
112+
total_size += len(metadata_bytes)
98113
except Exception as e:
99114
log.error(f"Error writing memory region metadata: {str(e)}")
100115
except psutil.Error as e:

CODE/event_log.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import os
22
import shutil
33
import threading
4-
from os import mkdir
54

65
import wmi # Import the wmi library
76

@@ -51,6 +50,8 @@ def parse_event_logs(log_type: str, output_file: str):
5150
f.write(str(event_data) + '\n\n')
5251

5352
log.info(f"{log_type} events (Windows Events) have been written to {output_file}")
53+
except wmi.x_wmi as err:
54+
log.error(f"Error opening or reading the event log: {err}")
5455
except Exception as err:
5556
log.error(f"Fatal issue: {err}")
5657

@@ -59,7 +60,7 @@ def parse_event_logs(log_type: str, output_file: str):
5960
try:
6061
if os.path.exists('event_logs'):
6162
shutil.rmtree('event_logs')
62-
mkdir('event_logs')
63+
os.mkdir('event_logs')
6364
except Exception as e:
6465
log.error(f"Fatal issue: {e}")
6566
exit(1)

CODE/logicytics/Execute.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class Execute:
88
@classmethod
9-
def script(cls, script_path: str) -> list[list[str]] | None:
9+
def script(cls, script_path: str) -> list[list[str, str]] | None:
1010
"""
1111
Executes a script file and handles its output based on the file extension.
1212
Parameters:

CODE/logicytics/Flag.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
from collections import Counter
1010
from datetime import datetime
1111

12-
import matplotlib.pyplot as plt
13-
from sentence_transformers import SentenceTransformer, util
14-
1512
# Check if the script is being run directly, if not, set up the library
1613
if __name__ == '__main__':
1714
exit("This is a library, Please import rather than directly run.")
@@ -31,11 +28,11 @@
3128
DEBUG_MODE = config.getboolean("Flag Settings", "model_debug") # Debug mode for Sentence Transformer
3229
# File for storing user history data
3330
HISTORY_FILE = 'logicytics/User_History.json.gz' # User history file
34-
if DEBUG_MODE:
35-
print(f"Loading Sentence Transformer model...")
3631
# Minimum accuracy threshold for flag suggestions
3732
MIN_ACCURACY_THRESHOLD = float(
3833
config.get("Flag Settings", "accuracy_min")) # Minimum accuracy threshold for flag suggestions
34+
if not 0 <= MIN_ACCURACY_THRESHOLD <= 100:
35+
raise ValueError("accuracy_min must be between 0 and 100")
3936

4037

4138
class Match:
@@ -45,7 +42,23 @@ def __get_sim(user_input: str, all_descriptions: list[str]) -> list[float]:
4542
Get the similarity between the user input and the flag description.
4643
"""
4744
# Encode the current user input and historical inputs
48-
MODEL = SentenceTransformer(config.get("Flag Settings", "model_to_use"))
45+
from sentence_transformers import SentenceTransformer, util
46+
47+
import logging # Suppress logging messages from Sentence Transformer due to verbosity
48+
# Set the logging level based on the debug mode, either DEBUG or ERROR (aka only important messages)
49+
if DEBUG_MODE:
50+
logging.getLogger("sentence_transformers").setLevel(logging.DEBUG)
51+
else:
52+
logging.getLogger("sentence_transformers").setLevel(logging.ERROR)
53+
54+
try:
55+
MODEL = SentenceTransformer(config.get("Flag Settings", "model_to_use"))
56+
except Exception as e:
57+
print(f"Error: {e}")
58+
print("Please check the model name in the config file.")
59+
print(f"Model name {config.get('Flag Settings', 'model_to_use')} may not be valid.")
60+
exit(1)
61+
4962
user_embedding = MODEL.encode(user_input, convert_to_tensor=True, show_progress_bar=DEBUG_MODE)
5063
historical_embeddings = MODEL.encode(all_descriptions, convert_to_tensor=True, show_progress_bar=DEBUG_MODE)
5164

@@ -95,6 +108,8 @@ def _generate_summary_and_graph(cls):
95108
"""Generates a full summary and graph based on user history data."""
96109
# TODO Yet in beta
97110
# Load the decompressed history data using the load_history function
111+
import matplotlib.pyplot as plt
112+
98113
if not os.path.exists(HISTORY_FILE):
99114
exit("No history data found.")
100115

CODE/logicytics/Logger.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import inspect
44
import logging
55
import os
6+
import time
67
from datetime import datetime
78
from typing import Type
89

@@ -119,7 +120,7 @@ def __trunc_message(self, message: str) -> str:
119120

120121
def __internal(self, message):
121122
"""
122-
Logs an internal message.
123+
Logs an internal message. Internal messages are displayed in the console only.
123124
124125
:param message: The internal message to be logged.
125126
"""
@@ -138,6 +139,8 @@ def debug(self, message):
138139
def raw(self, message):
139140
"""
140141
Logs a raw message directly to the log file.
142+
This should only be called from within the Log class.
143+
So do not use this method in your code.
141144
142145
:param message: The raw message to be logged.
143146
"""
@@ -150,7 +153,7 @@ def raw(self, message):
150153
try:
151154
with open(self.filename, "a", encoding="utf-8") as f:
152155
f.write(f"{str(message)}\n")
153-
except UnicodeDecodeError or UnicodeEncodeError as UDE:
156+
except (UnicodeDecodeError, UnicodeEncodeError) as UDE:
154157
self.__internal(
155158
f"UnicodeDecodeError: {UDE} - Message: {str(message)}"
156159
)
@@ -221,7 +224,7 @@ def string(self, message, type: str):
221224
:param type: The type of the log message.
222225
"""
223226
if self.color and message != "None" and message is not None:
224-
type_map = {"err": "error", "warn": "warning", "crit": "critical"}
227+
type_map = {"err": "error", "warn": "warning", "crit": "critical", "except": "exception"}
225228
type = type_map.get(type.lower(), type)
226229
try:
227230
getattr(self, type.lower())(str(message))
@@ -245,20 +248,27 @@ def exception(self, message, exception_type: Type = Exception):
245248
)
246249
raise exception_type(message)
247250

248-
def parse_execution(self, message_log: list[list[str]]):
251+
def parse_execution(self, message_log: list[list[str, str]]):
249252
"""
250253
Parses and logs a list of messages with their corresponding log types.
254+
Only use this method if you have a list of lists where each inner list contains a message and its log type.
255+
Use case include "Execute.script()" function.
251256
252257
:param message_log: A list of lists, where each inner list contains a message and its log type.
253258
"""
254259
if message_log:
255260
for message_list in message_log:
256261
if len(message_list) == 2:
257262
self.string(message_list[0], message_list[1])
263+
else:
264+
self.__internal(
265+
f"Message List is not in the correct format: {message_list}"
266+
)
258267

259268
def function(self, func: callable):
260269
"""
261-
A decorator that logs the execution of a function, including its start time, end time, and elapsed time.
270+
A decorator that logs the execution of a function,
271+
including its start time, end time, and elapsed time.
262272
263273
:param func: The function to be decorated.
264274
:return: The wrapper function.
@@ -275,12 +285,12 @@ def wrapper(*args, **kwargs):
275285
"""
276286
if not callable(func):
277287
self.exception(f"Function {func.__name__} is not callable.", TypeError)
278-
start_time = datetime.now()
288+
start_time = time.perf_counter()
279289
self.debug(f"Running the function {func.__name__}().")
280290
result = func(*args, **kwargs)
281-
end_time = datetime.now()
291+
end_time = time.perf_counter()
282292
elapsed_time = end_time - start_time
283-
self.debug(f"Function {func.__name__}() executed in {elapsed_time}.")
293+
self.debug(f"Function {func.__name__}() executed in {elapsed_time:.6f} seconds.")
284294
return result
285295

286296
return wrapper

CODE/packet_sniffer.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,12 @@ def packet_sniffer():
248248
if packet_count <= 0 or timeout <= 0:
249249
try:
250250
log.error(
251-
f"Oops! Can't work with these values:\n"
251+
"Oops! Can't work with these values:\n"
252252
f"- Packet count: {packet_count} {'❌ (must be > 0)' if packet_count <= 0 else '✅'}\n"
253253
f"- Timeout: {timeout} {'❌ (must be > 0)' if timeout <= 0 else '✅'}"
254254
)
255255
except Exception:
256-
log.error(f"Error reading configuration: Improper values for packet count or timeout")
256+
log.error("Error reading configuration: Improper values for packet count or timeout")
257257
exit(1)
258258

259259
try:
@@ -263,8 +263,11 @@ def packet_sniffer():
263263
if interface == "WiFi" or interface == "Wi-Fi":
264264
log.warning("Attempting to correct the interface name...")
265265
interface = "Wi-Fi" if interface == "WiFi" else "WiFi"
266-
log.info(f"Interface name corrected to '{interface}'.")
267-
start_sniffing(interface, packet_count, timeout)
266+
log.info(f"Interface name auto-corrected to '{interface}', retrying packet sniffing...")
267+
try:
268+
start_sniffing(interface, packet_count, timeout)
269+
except Exception as err:
270+
log.error(f"Error sniffing packets on auto-corrected interface '{interface}': {err}")
268271

269272

270273
# Entry point of the script

CODE/sensitive_data_miner.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,24 @@ def __search_files_by_keyword(root: Path, keyword: str) -> list:
3434
list: List of files that match the search criteria.
3535
"""
3636
matching_files = []
37-
for filename in os.listdir(root):
37+
path_list = []
38+
try:
39+
path_list = os.listdir(root)
40+
except WindowsError as e:
41+
if DEBUG:
42+
# Log the error if in debug mode, as it is a common occurrence.
43+
log.warning(f"Permission Denied: {e}")
44+
45+
for filename in path_list:
3846
file_path = root / filename
3947
if (
4048
keyword.lower() in filename.lower()
4149
and file_path.is_file()
4250
and file_path.suffix in allowed_extensions
4351
):
4452
matching_files.append(file_path)
53+
else:
54+
log.debug(f"Skipped {file_path}, Unsupported due to {file_path.suffix} extension")
4555
return matching_files
4656

4757
@staticmethod
@@ -79,8 +89,10 @@ def __search_and_copy_files(cls, keyword: str):
7989

8090
with ThreadPoolExecutor() as executor:
8191
for root, dirs, files in os.walk(drives_root):
82-
future_to_file = {executor.submit(cls.__search_files_by_keyword, Path(root), keyword): root_path for
83-
root_path in dirs}
92+
future_to_file = {
93+
executor.submit(cls.__search_files_by_keyword, Path(root) / sub_dir, keyword): sub_dir
94+
for sub_dir in dirs
95+
}
8496
for future in future_to_file:
8597
for file_path in future.result():
8698
dst_file_path = destination / file_path.name
@@ -110,5 +122,6 @@ def passwords(cls):
110122

111123

112124
if __name__ == "__main__":
113-
log.warning("Sensitive Data Miner Started, This may take a while... (aka touch some grass and drink coffee)")
125+
log.warning(
126+
"Sensitive Data Miner Initialized. Processing may take a while... (Consider a break: coffee or fresh air recommended!)")
114127
Mine.passwords()

CODE/vulnscan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def vulnscan(model, SCAN_PATH, vectorizer):
170170
]
171171

172172
for base_path in base_paths:
173-
for root, dirs, files_main in os.walk(base_path):
173+
for root, _, files_main in os.walk(base_path):
174174
for file_main in files_main:
175175
paths.append(os.path.join(root, file_main))
176176

PLANS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
| Task | Version | Might or Will be done? |
99
|----------------------------------------------------------------------------------------------|---------|------------------------|
1010
| Remove deprecated feature: `_generate_data.py` | v3.4.0 ||
11+
| New feature: Psutil Network functions, most likely `net_info.py` | v3.4.0 ||
1112
| Implement the 2 missing flags | v3.5.0 ||
1213
| Move VulnScan tools and v3 module to separate repository, keep only the model and vectorizer | v3.5.0 ||
1314
| Encrypted Volume Detection and Analysis, Advanced USB Device History Tracker | v3.6.0 ||

0 commit comments

Comments
 (0)