From d935befcb2abee2f00aa10aabebeea241391c9c7 Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 09:46:31 +0400 Subject: [PATCH 1/9] Documentation Update --- Plans.md => PLANS.md | 0 README.md | 31 ++++++++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) rename Plans.md => PLANS.md (100%) diff --git a/Plans.md b/PLANS.md similarity index 100% rename from Plans.md rename to PLANS.md diff --git a/README.md b/README.md index 1fb38d1..1a730ab 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,10 @@ This opens a help menu. Once you have run the program, you can run the program with the following command: `python Logicytics.py -h` Replace the flags with the ones you want to use. -you must have admin privelages while running! +you must have admin privileges while running! > [!TIP] -> Although its really recommended to use admin, by setting debug in the config.json to true, you can bypass this requirement +> Although it's really recommended to use admin, by setting debug in the config.json to true, you can bypass this requirement 6) Wait for magic to happen 🧙‍♀️ Logicytics will now run and gather data according to the flags you used. @@ -102,7 +102,8 @@ If you have an idea or want to contribute to the project, you can submit an issu After running and successfully collecting data, you may traverse the ACCESS directory as much as you like, Remove add and delete files, it's the safest directory where your backups, hashes, data zips and logs are found. -Also watch this [video](https://www.youtube.com/watch?v=XVTBmdTQqOs) for a better understanding of Logicytics +> [!TIP] +> Watch this [video](https://www.youtube.com/watch?v=XVTBmdTQqOs) for a better understanding of Logicytics ## 🔧 Configuration 🔧 @@ -155,7 +156,7 @@ The `--modded` flag can also be used to run custom scripts. If you want to run a custom script with the `--modded` flag, you can add the script to the `MODS` directory, and it will be run with the `--modded` flag. -To check all the mods and how to make your own, you can check the `Logicytics.py` file and the WIKI. +To check all the mods and how to make your own, you can check the `Logicytics.py` file and the Wiki. Also refer to the contributing.md for more info ## 🛑 Troubleshooting 🛑 @@ -180,7 +181,7 @@ If those don't work attempt: ### Support Resources -Check out the [GitHub wiki](https://github.com/DefinetlyNotAI/Logicytics/wiki) for help +Check out the [GitHub wiki](https://github.com/DefinetlyNotAI/Logicytics/wiki) for help. ## 📊 Data Analysis 📊 @@ -190,7 +191,8 @@ Logicytics extracts a wide range of data points on a Windows system. Here are some of the data points that Logicytics extracts: -Don't recreate these: +> [!IMPORTANT] +> Don't recreate these as then it's a waste of time for you @@ -283,7 +285,8 @@ Don't recreate these: This is not an exhaustive list, but it should give you a good idea of what data Logicytics is capable of extracting. -**Any file with `_` is not counted here, do note they may range from custom libraries to special files/wrappers** +> [!NOTE] +> **Any file with `_` is not counted here, do note they may range from custom libraries to special files/wrappers** ### Want to create your own mod? @@ -301,7 +304,10 @@ special tools ### Want to create your own mod? -Check out the [contributing guidlines](CONTRIBUTING.md) file for more info +Check out the [contributing guidlines](CONTRIBUTING.md) file for more info, as well as the [wiki guidelines](https://github.com/DefinetlyNotAI/Logicytics/wiki/5-Contribution-Guidelines) for more info + +> [!IMPORTANT] +> Always adhere to the [coding standards](https://github.com/DefinetlyNotAI/Logicytics/wiki/6-Coding-Standards) of Logicytics! ## 🌟 Conclusion 🌟 @@ -311,15 +317,14 @@ from forensics to system information gathering. Its ability to extract data from various sources makes it a valuable tool for any Windows system administrator or forensic investigator. -### 📣 Note - -Please remember that extracting data from a system without proper authorization is illegal and unethical. -Always obtain proper authorization before extracting any data from a system. +> [!CAUTION] +> Please remember that extracting data from a system without proper authorization is illegal and unethical. +> Always obtain proper authorization before extracting any data from a system. ### 🔗 Links - [Project's Wiki](https://github.com/DefinetlyNotAI/Logicytics/wiki) -- [Project's Future](https://definetlynotai.github.io/Logicytics/WEB/roadmap.html) +- [Project's Future](PLANS.md) - [Project's License](LICENSE) ### License From 2fab024b35c08bc58ba09108946f1a871df0cb2b Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 11:40:30 +0400 Subject: [PATCH 2/9] Fixed HUGE bug The __lib_class.py was failing to actually execute code due to a faulty shell code. Code affected are .bat, .exe and .ps1 that are purely executed from the Execute.script method, and Execute.__run_other_script method specifically - This does break how logging in the __lib_class.py works, so documents in wiki will be changed accordingly --- CODE/Logicytics.py | 17 ++++++----- CODE/__lib_class.py | 67 +++++++++++++++--------------------------- CODE/__lib_log.py | 6 ++++ CODE/browser_miner.ps1 | 6 ++-- 4 files changed, 41 insertions(+), 55 deletions(-) diff --git a/CODE/Logicytics.py b/CODE/Logicytics.py index 34f9fd7..500daa5 100644 --- a/CODE/Logicytics.py +++ b/CODE/Logicytics.py @@ -176,23 +176,24 @@ def special_run(file_path: str): log.debug(f"The following will be executed: {execution_list}") + # Check weather to use threading or not, as well as execute code if action == "threaded": def threaded_execution(execution_list_thread, index_thread): + log.debug(f"Thread {index_thread} started") try: - thread_log = Execute.file(execution_list_thread, index_thread) - if thread_log[0]: - log.info(thread_log[0]) - log.info(thread_log[1]) + log.execute_log_parse(Execute.script(execution_list_thread[index_thread])) + log.info(f"{execution_list[index_thread]} executed") except UnicodeDecodeError as err: log.error(f"Error in thread: {err}") except Exception as err: log.error(f"Error in thread: {err}") + log.debug("Using threading") threads = [] for index, file in enumerate(execution_list): thread = threading.Thread( - target=Execute.file, + target=Execute.script, args=( execution_list, index, @@ -206,12 +207,12 @@ def threaded_execution(execution_list_thread, index_thread): else: try: for file in range(len(execution_list)): # Loop through List - log.info(Execute.script(execution_list[file])) + log.execute_log_parse(Execute.script(execution_list[file])) log.info(f"{execution_list[file]} executed") except UnicodeDecodeError as e: - log.error(f"Error in thread: {e}") + log.error(f"Error in code: {e}") except Exception as e: - log.error(f"Error in thread: {e}") + log.error(f"Error in code: {e}") # Zip generated files if action == "modded": diff --git a/CODE/__lib_class.py b/CODE/__lib_class.py index 27f49ba..9a0e5a8 100644 --- a/CODE/__lib_class.py +++ b/CODE/__lib_class.py @@ -1,13 +1,15 @@ from __future__ import annotations + import argparse +import ctypes import json import os -import subprocess -import ctypes import os.path +import subprocess import zipfile -from subprocess import CompletedProcess from pathlib import Path +from subprocess import CompletedProcess + from __lib_log import Log @@ -310,7 +312,7 @@ def uac() -> bool: return int(value.strip("\n")) == 1 @staticmethod - def sys_internal_zip(): + def sys_internal_zip() -> str: """ Extracts the SysInternal_Suite zip file if it exists and is not ignored. @@ -331,14 +333,10 @@ def sys_internal_zip(): "SysInternal_Suite/SysInternal_Suite.zip" ) as zip_ref: zip_ref.extractall("SysInternal_Suite") - if __name__ == "__main__": - Log({"log_level": DEBUG}).debug("SysInternal_Suite zip extracted") + return "SysInternal_Suite zip extracted" elif ignore_file: - if __name__ == "__main__": - Log({"log_level": DEBUG}).debug( - "Found .sys.ignore file, skipping SysInternal_Suite zip extraction" - ) + return "Found .sys.ignore file, skipping SysInternal_Suite zip extraction" except Exception as err: exit(f"Failed to unzip SysInternal_Suite: {err}") @@ -346,34 +344,19 @@ def sys_internal_zip(): class Execute: @classmethod - def file(cls, execution_list: list, Index: int): - # IT IS USED, DO NOT REMOVE - """ - Executes a file from the execution list at the specified index. - Parameters: - Index (int): The index of the file to be executed in the execution list. - execution_list (list): List to use when indexing - Returns: - None - """ - cls.script(execution_list[Index]) - if __name__ == "__main__": - Log().info(f"{execution_list[Index]} executed") - - @classmethod - def script(cls, script_path: str): + def script(cls, script_path: str) -> list[list[str]] | None: """ Executes a script file and handles its output based on the file extension. Parameters: script_path (str): The path of the script file to be executed. """ - if script_path.endswith(".ps1"): - cls.__unblock_ps1_script(script_path) - cls.__run_other_script(script_path) - elif script_path.endswith(".py"): + if script_path.endswith(".py"): cls.__run_python_script(script_path) + return None else: - cls.__run_other_script(script_path) + if script_path.endswith(".ps1"): + cls.__unblock_ps1_script(script_path) + return cls.__run_other_script(script_path) @staticmethod def command(command: str) -> str: @@ -401,8 +384,6 @@ def __unblock_ps1_script(script: str): try: unblock_command = f'powershell.exe -Command "Unblock-File -Path {script}"' subprocess.run(unblock_command, shell=False, check=True) - if __name__ == "__main__": - Log().info("PS1 Script unblocked.") except Exception as err: exit(f"Failed to unblock script: {err}") @@ -421,8 +402,8 @@ def __run_python_script(script: str): # LEAVE AS PRINT print(result.decode()) - @staticmethod - def __run_other_script(script: str): + @classmethod + def __run_other_script(cls, script: str) -> list[list[str]]: """ Runs a script with other extensions and logs output based on its content. Parameters: @@ -430,14 +411,14 @@ def __run_other_script(script: str): Returns: None """ - - result = subprocess.run( - ["powershell.exe", ".\\" + script], capture_output=True, text=True - ) - lines = result.stdout.splitlines() - ID = next((line.split(":")[0].strip() for line in lines if ":" in line), None) - if ID and __name__ == "__main__": - Log().string(str(lines), ID) + result = cls.command(f"powershell.exe -File {script}") + lines = result.splitlines() + messages = [] + for line in lines: + if ":" in line: + id_part, message_part = line.split(":", 1) + messages.append([message_part.strip(), id_part.strip()]) + return messages class Get: diff --git a/CODE/__lib_log.py b/CODE/__lib_log.py index 8b33471..26fd6b2 100644 --- a/CODE/__lib_log.py +++ b/CODE/__lib_log.py @@ -221,6 +221,12 @@ def __internal(self, message): if self.color and message != "None" and message is not None: colorlog.log(self.INTERNAL_LOG_LEVEL, str(message)) + def execute_log_parse(self, message_log): + if message_log: + for message_list in message_log: + if len(message_list) == 2: + self.string(message_list[0], message_list[1]) + if __name__ == "__main__": Log().exception( diff --git a/CODE/browser_miner.ps1 b/CODE/browser_miner.ps1 index 3417179..9acd6ef 100644 --- a/CODE/browser_miner.ps1 +++ b/CODE/browser_miner.ps1 @@ -47,7 +47,7 @@ $fullSourcePath = $sourcePath -replace '\{\}', $currentUser # Enhanced error checking for source path existence and accessibility if (-not (Test-PathAndAccess $fullSourcePath)) { - Write-Host "ERROR: Source path $fullSourcePath does not exist or cannot be accessed." + Write-Host "WARNING: Source path $fullSourcePath does not exist or cannot be accessed." continue } @@ -84,9 +84,7 @@ Write-Host "INFO: Successfully copied $fullSourcePath to $destinationPath" catch { # Detailed error handling - Write-Host "ERROR: An error occurred while copying $fullSourcePath to $destinationPath. Error: $_" + Write-Host "ERROR: An error occurred while copying $fullSourcePath to $destinationPath : $_" exit } } - -# TODO Test me From 5c324f1edb03065f97cf550ca8e86be439029b6e Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 11:44:41 +0400 Subject: [PATCH 3/9] Fixed the threading bug Due to rehaul of __lib_class.py, threading has a failure bug `TypeError`, its fixed now --- CODE/Logicytics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CODE/Logicytics.py b/CODE/Logicytics.py index 500daa5..103a748 100644 --- a/CODE/Logicytics.py +++ b/CODE/Logicytics.py @@ -183,17 +183,17 @@ def threaded_execution(execution_list_thread, index_thread): log.debug(f"Thread {index_thread} started") try: log.execute_log_parse(Execute.script(execution_list_thread[index_thread])) - log.info(f"{execution_list[index_thread]} executed") + log.info(f"{execution_list_thread[index_thread]} executed") except UnicodeDecodeError as err: log.error(f"Error in thread: {err}") except Exception as err: log.error(f"Error in thread: {err}") - + log.debug(f"Thread {index_thread} finished") log.debug("Using threading") threads = [] for index, file in enumerate(execution_list): thread = threading.Thread( - target=Execute.script, + target=threaded_execution, args=( execution_list, index, From d71a85c4f0515330312174879d1947ee749cab99 Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 12:04:19 +0400 Subject: [PATCH 4/9] Made bat to ps1 To increase performance --- CODE/Logicytics.py | 6 +++--- CODE/tree.bat | 13 ------------- CODE/tree.ps1 | 9 +++++++++ PLANS.md | 1 + 4 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 CODE/tree.bat create mode 100644 CODE/tree.ps1 diff --git a/CODE/Logicytics.py b/CODE/Logicytics.py index 103a748..2919385 100644 --- a/CODE/Logicytics.py +++ b/CODE/Logicytics.py @@ -133,7 +133,7 @@ def special_run(file_path: str): "ssh_miner.py", "sys_internal.py", "tasklist.py", - "tree.bat", + "tree.ps1", "wmic.py", "browser_miner.ps1", "netadapter.ps1", @@ -147,7 +147,7 @@ def special_run(file_path: str): "cmd_commands.py", "registry.py", "tasklist.py", - "tree.bat", + "tree.ps1", "wmic.py", "netadapter.ps1", "property_scraper.ps1", @@ -160,7 +160,7 @@ def special_run(file_path: str): "netadapter.ps1", "property_scraper.ps1", "window_feature_miner.ps1", - "tree.bat" + "tree.ps1" ] if action == "modded": diff --git a/CODE/tree.bat b/CODE/tree.bat deleted file mode 100644 index 45dc8af..0000000 --- a/CODE/tree.bat +++ /dev/null @@ -1,13 +0,0 @@ -@echo off - -echo INFO: Starting Tree Command - -setlocal enabledelayedexpansion -:: Define the output file name as Tree.txt -set "outputFile=Tree.txt" -:: Run the tree command and redirect the output to the file -powershell.exe -Command "& {tree /f C:\ | Out-File -FilePath '!outputFile!' -Force}" - -echo INFO: Saved !outputFile! - -endlocal diff --git a/CODE/tree.ps1 b/CODE/tree.ps1 new file mode 100644 index 0000000..d19fde8 --- /dev/null +++ b/CODE/tree.ps1 @@ -0,0 +1,9 @@ +Write-Host "INFO: Starting Tree Command" + +# Define the output file name as Tree.txt +$outputFile = "Tree.txt" + +# Run the tree command and redirect the output to the file +tree /f C:\ | Out-File -FilePath $outputFile -Force + +Write-Host "INFO: Saved $outputFile" \ No newline at end of file diff --git a/PLANS.md b/PLANS.md index 5a19297..9e6f4fb 100644 --- a/PLANS.md +++ b/PLANS.md @@ -4,6 +4,7 @@ |----------------------------------------------------------------------------------------------------------------------|---------| | Check todos | v2.4.1 | | Refactor logicytics | v2.4.1 | +| Docstring everything again | v2.4.2 | | Implement a parser for Windows Event Logs to extract and analyze security-related events. | v2.4.2 | | Enable integration with popular SIEM (Security Information and Event Management) systems. | v2.5.0 | | Add a tool to capture and analyse network traffic, which can help in forensic investigations. | v2.5.0 | From 1fc2ae7e25035d0a2da3601a70c3f4e178afb7a8 Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 13:13:06 +0400 Subject: [PATCH 5/9] Fixed zipping bug For some reason the _zipper.py didn't properly zip directories, and so half of the data that was grouped in folders, were deleted --- CODE/_zipper.py | 13 ++++++++++--- CODE/media_backup.py | 1 - CODE/ssh_miner.py | 1 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CODE/_zipper.py b/CODE/_zipper.py index 7149c43..cc44d54 100644 --- a/CODE/_zipper.py +++ b/CODE/_zipper.py @@ -6,6 +6,8 @@ import zipfile +# TODO - Fix bug where directories aren't zipped and remove their contents + class Zip: """ A class to handle zipping files, generating SHA256 hashes, and moving files. @@ -36,13 +38,13 @@ class Zip: @staticmethod def __get_files_to_zip(path: str) -> list: """ - Returns a list of files to be zipped, excluding certain file types and names. + Returns a list of files and directories to be zipped, excluding certain file types and names. Args: path (str): The directory path to search for files. Returns: - list: A list of file names to be zipped. + list: A list of file and directory names to be zipped. """ return [ f @@ -66,7 +68,12 @@ def __create_zip_file(path: str, files: list, filename: str): """ with zipfile.ZipFile(f"{filename}.zip", "w") as zip_file: for file in files: - zip_file.write(os.path.join(path, file)) + if os.path.isdir(os.path.join(path, file)): + for root, _, files in os.walk(os.path.join(path, file)): + for f in files: + zip_file.write(os.path.join(root, f), os.path.relpath(os.path.join(root, f), path)) + else: + zip_file.write(os.path.join(path, file)) @staticmethod def __remove_files(path: str, files: list): diff --git a/CODE/media_backup.py b/CODE/media_backup.py index bdea425..748be38 100644 --- a/CODE/media_backup.py +++ b/CODE/media_backup.py @@ -60,4 +60,3 @@ def backup(self): Media().backup() -# TODO Test me diff --git a/CODE/ssh_miner.py b/CODE/ssh_miner.py index 866751f..36b571b 100644 --- a/CODE/ssh_miner.py +++ b/CODE/ssh_miner.py @@ -44,4 +44,3 @@ def ssh_miner(): ssh_miner() -# TODO Test me From 324b868917b49a7fba3ad9527347be19eb7f6d57 Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 13:24:45 +0400 Subject: [PATCH 6/9] Fixed zipping bug For some reason the _zipper.py didn't properly zip directories, and so half of the data that was grouped in folders, were deleted --- CODE/_zipper.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/CODE/_zipper.py b/CODE/_zipper.py index cc44d54..4df8762 100644 --- a/CODE/_zipper.py +++ b/CODE/_zipper.py @@ -6,8 +6,6 @@ import zipfile -# TODO - Fix bug where directories aren't zipped and remove their contents - class Zip: """ A class to handle zipping files, generating SHA256 hashes, and moving files. From 954ecb7830623e02b4d3d4c37f9dac6146769f7d Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 13:29:49 +0400 Subject: [PATCH 7/9] Fixed minor printing bug Fixed the issue of random operation completion message not adhering colorlog --- CODE/registry.py | 7 ++++--- PLANS.md | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CODE/registry.py b/CODE/registry.py index 96813a8..8edbf8c 100644 --- a/CODE/registry.py +++ b/CODE/registry.py @@ -16,11 +16,12 @@ def backup_registry(): cmd = [reg_path, "export", "HKLM", export_path] try: - subprocess.run(cmd, check=True) - log.info(f"Registry backed up successfully to {export_path}") + result = subprocess.run(cmd, check=True, capture_output=True, text=True) + log.info(f"Registry backed up successfully to {export_path}. Output: {result.stdout}") except subprocess.CalledProcessError as e: + log.error(f"Failed to back up the registry: {e}. More details: {result.stderr}") + except Exception as e: log.error(f"Failed to back up the registry: {e}") backup_registry() -# TODO Fix the issue of random operation completion message not adhering colorlog diff --git a/PLANS.md b/PLANS.md index 9e6f4fb..6d37df3 100644 --- a/PLANS.md +++ b/PLANS.md @@ -2,7 +2,6 @@ | Task | Version | |----------------------------------------------------------------------------------------------------------------------|---------| -| Check todos | v2.4.1 | | Refactor logicytics | v2.4.1 | | Docstring everything again | v2.4.2 | | Implement a parser for Windows Event Logs to extract and analyze security-related events. | v2.4.2 | From 53f5ecec033273bbd619ac0f95191db8ca273a9b Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 13:52:09 +0400 Subject: [PATCH 8/9] Refactored Logicytics.py Made it easier to maintain and in functions, fixed minor bugs, etc --- CODE/Logicytics.py | 420 +++++++++++++++++++++++++-------------------- PLANS.md | 2 +- 2 files changed, 232 insertions(+), 190 deletions(-) diff --git a/CODE/Logicytics.py b/CODE/Logicytics.py index 2919385..bfbd4a8 100644 --- a/CODE/Logicytics.py +++ b/CODE/Logicytics.py @@ -1,15 +1,13 @@ +from __future__ import annotations + import threading +from typing import Any from __lib_class import * from _health import backup, update from _hide_my_tracks import attempt_hide from _zipper import Zip -# Initialization -FileManagement.mkdir() - -if __name__ == "__main__": - log = Log({"log_level": DEBUG}) """ This python script is the main entry point for the tool called Logicytics. @@ -30,22 +28,30 @@ """ -if isinstance(Flag.data(), tuple): - try: - # Get flags - action, sub_action = Flag.data() - except Exception: - action = Flag.data() - action = action[0] - sub_action = None -else: - parser = Flag.data() - parser.print_help() - input("Press Enter to exit...") - exit(1) +def get_flags(): + if isinstance(Flag.data(), tuple): + try: + # Get flags + actions, sub_actions = Flag.data() + except Exception: + actions = Flag.data() + actions = actions[0] + sub_actions = None + else: + parser = Flag.data() + parser.print_help() + input("Press Enter to exit...") + exit(1) + return actions, sub_actions -def special_run(file_path: str): +def special_execute(file_path: str): + """ + Executes a Python script in a new command prompt window. + + Args: + file_path (str): The relative path to the Python script to be executed. + """ sr_current_dir = os.path.dirname(os.path.abspath(__file__)) sr_script_path = os.path.join(sr_current_dir, file_path) sr_process = subprocess.Popen(["cmd.exe", "/c", "start", "python", sr_script_path]) @@ -53,203 +59,239 @@ def special_run(file_path: str): exit(0) -# Special actions -> Quit -if action == "debug": - log.info("Opening debug menu...") - special_run("_debug.py") - -messages = Check.sys_internal_zip() -if messages: - # If there are messages, log them with debug - log.debug(messages) +def handle_special_actions(): + # Special actions -> Quit + if action == "debug": + log.info("Opening debug menu...") + special_execute("_debug.py") -if action == "dev": - log.info("Opening developer menu...") - special_run("_dev.py") + messages = Check.sys_internal_zip() + if messages: + # If there are messages, log them with debug + log.debug(messages) -if action == "extra": - log.info("Opening extra tools menu...") - special_run("_extra.py") + if action == "dev": + log.info("Opening developer menu...") + special_execute("_dev.py") -if action == "update": - log.info("Updating...") - message, log_type = update() - log.string(message, log_type) - log.info("Update complete!") - input("Press Enter to exit...") - exit(0) + if action == "extra": + log.info("Opening extra tools menu...") + special_execute("_extra.py") -if action == "restore": - log.warning( - "Sorry, this feature is yet to be implemented. You can manually Restore your backups, We will open " - "the location for you" - ) - FileManagement.open_file("../ACCESS/BACKUP/") - input("Press Enter to exit...") - exit(1) - -if action == "backup": - log.info("Backing up...") - backup(".", "Default_Backup") - log.debug("Backup complete -> CODE dir") - backup("../MODS", "Mods_Backup") - log.debug("Backup complete -> MODS dir") - log.info("Backup complete!") - input("Press Enter to exit...") - exit(0) + if action == "update": + log.info("Updating...") + message, log_type = update() + log.string(message, log_type) + log.info("Update complete!") + input("Press Enter to exit...") + exit(0) -if action == "unzip_extra": - log.warning( - "The contents of this directory can be flagged as malicious and enter quarantine, please use with " - "caution" - ) - log.info("Unzipping...") - FileManagement.unzip(Path("..\\EXTRA\\EXTRA.zip")) - log.info("Unzip complete!") - input("Press Enter to exit...") - exit(0) + if action == "restore": + log.warning( + "Sorry, this feature is yet to be implemented. You can manually Restore your backups, We will open " + "the location for you" + ) + FileManagement.open_file("../ACCESS/BACKUP/") + input("Press Enter to exit...") + exit(1) -log.info("Starting Logicytics...") + if action == "backup": + log.info("Backing up...") + backup(".", "Default_Backup") + log.debug("Backup complete -> CODE dir") + backup("../MODS", "Mods_Backup") + log.debug("Backup complete -> MODS dir") + log.info("Backup complete!") + input("Press Enter to exit...") + exit(0) -# Check for privileges and errors -if not Check.admin(): - if DEBUG == "DEBUG": - log.warning("Running in debug mode, continuing without admin privileges - This may cause issues") - else: - log.critical("Please run this script with admin privileges - To ignore this message, run with DEBUG in config") + if action == "unzip_extra": + log.warning( + "The contents of this directory can be flagged as malicious and enter quarantine, please use with " + "caution" + ) + log.info("Unzipping...") + FileManagement.unzip(Path("..\\EXTRA\\EXTRA.zip")) + log.info("Unzip complete!") input("Press Enter to exit...") - exit(1) + exit(0) -if Check.uac(): - log.warning("UAC is enabled, this may cause issues") - log.warning("Please disable UAC if possible") - -# Create execution list [default] -execution_list = [ - "cmd_commands.py", - "log_miner.py", - "media_backup.py", - "registry.py", - "ssh_miner.py", - "sys_internal.py", - "tasklist.py", - "tree.ps1", - "wmic.py", - "browser_miner.ps1", - "netadapter.ps1", - "property_scraper.ps1", - "window_feature_miner.ps1", - "wifi_stealer.py", -] - -if action == "minimal": + +def check_privileges(): + if not Check.admin(): + if DEBUG == "DEBUG": + log.warning("Running in debug mode, continuing without admin privileges - This may cause issues") + else: + log.critical( + "Please run this script with admin privileges - To ignore this message, run with DEBUG in config") + input("Press Enter to exit...") + exit(1) + + if Check.uac(): + log.warning("UAC is enabled, this may cause issues") + log.warning("Please disable UAC if possible") + + +def generate_execution_list(actions: str) -> list | list[str] | list[str | Any]: + """ + Creates an execution list based on the provided action. + + Args: + actions (str): The action to determine the execution list. + + Returns: + list: The execution list of scripts to be executed. + """ execution_list = [ "cmd_commands.py", + "log_miner.py", + "media_backup.py", "registry.py", + "ssh_miner.py", + "sys_internal.py", "tasklist.py", "tree.ps1", "wmic.py", - "netadapter.ps1", - "property_scraper.ps1", - "window_feature_miner.ps1", - ] - -if action == "nopy": - execution_list = [ "browser_miner.ps1", "netadapter.ps1", "property_scraper.ps1", "window_feature_miner.ps1", - "tree.ps1" + "wifi_stealer.py", ] -if action == "modded": - # Add all files in MODS to execution list - execution_list = Get.list_of_files(Path("../MODS"), execution_list) - -if action == "depth": - log.warning("This flag will use clunky and huge scripts, and so may take a long time, but reap great rewards.") - execution_list.append("sensitive_data_miner.py") - execution_list.append("dir_list.py") - log.warning("This flag will use threading!") - action = "threaded" - -log.debug(f"The following will be executed: {execution_list}") - - -# Check weather to use threading or not, as well as execute code -if action == "threaded": - def threaded_execution(execution_list_thread, index_thread): - log.debug(f"Thread {index_thread} started") + if actions == "minimal": + execution_list = [ + "cmd_commands.py", + "registry.py", + "tasklist.py", + "tree.ps1", + "wmic.py", + "netadapter.ps1", + "property_scraper.ps1", + "window_feature_miner.ps1", + ] + + if actions == "nopy": + execution_list = [ + "browser_miner.ps1", + "netadapter.ps1", + "property_scraper.ps1", + "window_feature_miner.ps1", + "tree.ps1" + ] + + if actions == "modded": + # Add all files in MODS to execution list + execution_list = Get.list_of_files(Path("../MODS"), execution_list) + + if actions == "depth": + log.warning("This flag will use clunky and huge scripts, and so may take a long time, but reap great rewards.") + execution_list.append("sensitive_data_miner.py") + execution_list.append("dir_list.py") + log.warning("This flag will use threading!") + + log.debug(f"The following will be executed: {execution_list}") + return execution_list + + +def execute_scripts(): + """Executes the scripts in the execution list based on the action.""" + # Check weather to use threading or not, as well as execute code + if action == "threaded" or action == "depth": + def threaded_execution(execution_list_thread, index_thread): + log.debug(f"Thread {index_thread} started") + try: + log.execute_log_parse(Execute.script(execution_list_thread[index_thread])) + log.info(f"{execution_list_thread[index_thread]} executed") + except UnicodeDecodeError as err: + log.error(f"Error in thread: {err}") + except Exception as err: + log.error(f"Error in thread: {err}") + log.debug(f"Thread {index_thread} finished") + + log.debug("Using threading") + threads = [] + execution_list = generate_execution_list(action) + for index, file in enumerate(execution_list): + thread = threading.Thread( + target=threaded_execution, + args=( + execution_list, + index, + ), + ) + threads.append(thread) + thread.start() + + for thread in threads: + thread.join() + else: try: - log.execute_log_parse(Execute.script(execution_list_thread[index_thread])) - log.info(f"{execution_list_thread[index_thread]} executed") - except UnicodeDecodeError as err: - log.error(f"Error in thread: {err}") - except Exception as err: - log.error(f"Error in thread: {err}") - log.debug(f"Thread {index_thread} finished") - log.debug("Using threading") - threads = [] - for index, file in enumerate(execution_list): - thread = threading.Thread( - target=threaded_execution, - args=( - execution_list, - index, - ), - ) - threads.append(thread) - thread.start() - - for thread in threads: - thread.join() -else: - try: - for file in range(len(execution_list)): # Loop through List - log.execute_log_parse(Execute.script(execution_list[file])) - log.info(f"{execution_list[file]} executed") - except UnicodeDecodeError as e: - log.error(f"Error in code: {e}") - except Exception as e: - log.error(f"Error in code: {e}") - -# Zip generated files -if action == "modded": - zip_loc_mod, hash_loc = Zip().and_hash("..\\MODS", "MODS", action) - log.info(zip_loc_mod) - zip_values = Zip().and_hash("..\\MODS", "MODS", action) + execution_list = generate_execution_list(action) + for file in range(len(execution_list)): # Loop through List + log.execute_log_parse(Execute.script(execution_list[file])) + log.info(f"{execution_list[file]} executed") + except UnicodeDecodeError as e: + log.error(f"Error in code: {e}") + except Exception as e: + log.error(f"Error in code: {e}") + + +def zip_generated_files(): + """Zips generated files based on the action.""" + if action == "modded": + zip_loc_mod, hash_loc = Zip().and_hash("..\\MODS", "MODS", action) + log.info(zip_loc_mod) + zip_values = Zip().and_hash("..\\MODS", "MODS", action) + if isinstance(zip_values, str): + log.error(zip_values) + else: + zip_loc_mod, hash_loc = zip_values + log.info(zip_loc_mod) + log.debug(hash_loc) + + zip_values = Zip().and_hash(".", "CODE", action) if isinstance(zip_values, str): + # If error, log it log.error(zip_values) else: - zip_loc_mod, hash_loc = zip_values - log.info(zip_loc_mod) + zip_loc, hash_loc = zip_values + log.info(zip_loc) log.debug(hash_loc) -zip_values = Zip().and_hash(".", "CODE", action) -if isinstance(zip_values, str): - # If error, log it - log.error(zip_values) -else: - zip_loc, hash_loc = zip_values - log.info(zip_loc) - log.debug(hash_loc) - -# Attempt event log deletion -attempt_hide() - -# Finish with sub actions -log.info("Completed successfully") -if sub_action == "shutdown": - log.info("Shutting down in 3 seconds...") - subprocess.call("shutdown /s /t 3", shell=False) -if sub_action == "reboot": - log.info("Rebooting in 3 seconds...") - subprocess.call("shutdown /r /t 3", shell=False) -# if sub_action == "webhook": + +def handle_sub_action(): + if sub_action == "shutdown": + subprocess.call("shutdown /s /t 3", shell=False) + elif sub_action == "reboot": + subprocess.call("shutdown /r /t 3", shell=False) + # elif sub_action == "webhook": # Implement this in future # log.warning("This feature is not implemented yet! Sorry") -log.info("Exiting...") -input("Press Enter to exit...") -log.newline() + +# Initialization +FileManagement.mkdir() + +if __name__ == "__main__": + log = Log({"log_level": DEBUG}) + # Get flags and configs + action, sub_action = get_flags() + # Check for special actions + handle_special_actions() + # Check for privileges and errors + check_privileges() + # Execute scripts + log.info("Starting Logicytics...") + execute_scripts() + # Zip generated files + zip_generated_files() + # Attempt event log deletion + attempt_hide() + # Finish with sub actions + log.info("Completed successfully!") + # Finish with sub actions + log.newline() + handle_sub_action() + # Finish + input("Press Enter to exit...") diff --git a/PLANS.md b/PLANS.md index 6d37df3..640c8e5 100644 --- a/PLANS.md +++ b/PLANS.md @@ -2,9 +2,9 @@ | Task | Version | |----------------------------------------------------------------------------------------------------------------------|---------| -| Refactor logicytics | v2.4.1 | | Docstring everything again | v2.4.2 | | Implement a parser for Windows Event Logs to extract and analyze security-related events. | v2.4.2 | | Enable integration with popular SIEM (Security Information and Event Management) systems. | v2.5.0 | | Add a tool to capture and analyse network traffic, which can help in forensic investigations. | v2.5.0 | +| Change config.json to config.ini | v2.5.0 | | Integrate machine learning algorithms to detect anomalies and potential security threats automatically and log them. | v3.0.0 | \ No newline at end of file From 28df7e928ccf488d4ab000b9b27cbf0b44ddfb30 Mon Sep 17 00:00:00 2001 From: DefinetlyNotAI Date: Wed, 13 Nov 2024 13:55:02 +0400 Subject: [PATCH 9/9] Ran _dev.py --- CODE/_dev.py | 3 +-- CODE/config.json | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CODE/_dev.py b/CODE/_dev.py index d3505d1..5105c7d 100644 --- a/CODE/_dev.py +++ b/CODE/_dev.py @@ -65,8 +65,7 @@ def dev_checks(self) -> str | None: ("Have you made files you don't want to be run start with '_'?", "."), ("Have you added the file to CODE dir?", "."), ("Have you added docstrings and comments?", "../CONTRIBUTING.md"), - ("Is each file containing no more than 1 feature?", "../CONTRIBUTING.md"), - ("Have you NOT modified __wrapper__.py without authorization?", "Logicytics.py"), + ("Is each file containing around 1 main feature?", "../CONTRIBUTING.md"), ] try: for question, file_to_open in checks: diff --git a/CODE/config.json b/CODE/config.json index 4831e28..b13c60d 100644 --- a/CODE/config.json +++ b/CODE/config.json @@ -1,6 +1,6 @@ { "Log Level Debug?": false, - "VERSION": "2.4.0", + "VERSION": "2.4.1", "CURRENT_FILES": [ "browser_miner.ps1", "cmd_commands.py", @@ -15,7 +15,7 @@ "ssh_miner.py", "sys_internal.py", "tasklist.py", - "tree.bat", + "tree.ps1", "wifi_stealer.py", "window_feature_miner.ps1", "wmic.py",