INTRODUCCIÓN
Buenas!.
La forma tradicional de capturar las pulsaciones del teclado es mediante un hook del teclado, sin embargo, esta técnica está deprecada en .Net, ya que existe una forma alternativa o "moderna" que aporta bastantes mejoras (sobre todo mejoras de rendimiento), RawInput (el cual también sirve para sustituir a un LL-Hook del mouse):
➢ About Raw Input
Citar
The raw input model is different from the original Windows input model for the keyboard and mouse.
In the original input model, an application receives device-independent input in the form of messages that are sent or posted to its windows, such as WM_CHAR, WM_MOUSEMOVE, and WM_APPCOMMAND. In contrast, for raw input an application must register the devices it wants to get data from.
Also, the application gets the raw input through the WM_INPUT message.
There are several advantages to the raw input model:
An application does not have to detect or open the input device.
An application gets the data directly from the device, and processes the data for its needs.
An application can distinguish the source of the input even if it is from the same type of device. For example, two mouse devices.
An application manages the data traffic by specifying data from a collection of devices or only specific device types.
HID devices can be used as they become available in the marketplace, without waiting for new message types or an updated OS to have new commands in WM_APPCOMMAND.
In the original input model, an application receives device-independent input in the form of messages that are sent or posted to its windows, such as WM_CHAR, WM_MOUSEMOVE, and WM_APPCOMMAND. In contrast, for raw input an application must register the devices it wants to get data from.
Also, the application gets the raw input through the WM_INPUT message.
There are several advantages to the raw input model:
An application does not have to detect or open the input device.
An application gets the data directly from the device, and processes the data for its needs.
An application can distinguish the source of the input even if it is from the same type of device. For example, two mouse devices.
An application manages the data traffic by specifying data from a collection of devices or only specific device types.
HID devices can be used as they become available in the marketplace, without waiting for new message types or an updated OS to have new commands in WM_APPCOMMAND.
Siempre tuve curiosidad por RawInput pero nunca me animé a implementar este modelo ya que sabía que iba a ser una auténtica pesadilla de P/Invoking, pero al final la curiosidad pudo conmigo, y tras analizar decenas de ejemplos y semi-ejemplos en C#, acabé acumulando suficiente información para desarrollar el core de un keylogger para uso genérico en VB.Net.
DESCRIPCIÓN
Esto NO es un programa, es un algoritmo o código que encapsula los datos y las definiciones de la API de Windows de los miembros de RawInput, junto a todo lo demás adicional y necesario, exponiendo sus funcionalidades a través de una Class, con propiedades, y eventos.
Se puede decir que es la base o el core para poder desarrollar la UI de un KeyLogger, ya que usando esta Class solamente sería necesario diseñar la UI y/o adaptar este código si fuese necesario según las necesidades del programador por ejemplo para monitorizar las ventana que tiene el foco activado, o la interpretación textual de las teclas del sistema, etc...
Hay varias cosas que perfeccionar y refactorizar en el código, no comparto este código cómo si fuese el mejor y más completo algoritmo del mundo, me he tomado la molestia de decorar bastante este post por que creo que el código cómo ejemplo está muy bien ...ha sido bastante laborioso y por ese motivo se merece una mención especial de esta forma (por mi parte), pero simplemente comparto el código para mostrarles una manera curiosa, distina y mejor, una alternativa "moderna" a la deprecada técnica de SetWindowsHookEx + CallNextHookEx + UnhookWindowsHookEx para llevar a cabo la misma tarea.
CARACTERÍSTICAS
- Multi-Idioma
El keylogger soporta distintos layouts del teclado.
Gracias a esto, se puede cambiar el comportamiento de las pulsaciones en cualquier momento, por ejemplo del teclado Español (es-ES) al Inglés (en-US). - Multi-Dispositivo
El Keylogger soporta varios dispositivos de teclado al mismo tiempo.
NOTA: En teoría. Se intentan registrar todos los dispositivos conectados que sean de tipo "KEYBOARD", pero no lo puedo probar con certeza. - Soporte para caracteres especiales.
Gracias a la función 'ToUnicodeEx' de la API de Windows, el Keylogger es capaz de interpretar caracteres especiales cómo la Ñ o la Ç.
NOTA: En teoría. No lo he probado con el layout ruso por ejemplo. - Ignorar teclas, caracteres, o strings producidos por teclas muertas (dead keys).
Se puede especificar una serie de teclas, caracteres, o strings que serán ignorados por el keylogger. - Controlar las operaciones de pegado (pasting) de texto (Ctrl+v).
Se puede activar esta característica para que, mediante un evento, se nos notifique el texto que se ha pegado (si algún texto) al pulsar la combinación de teclas Ctrl+V.
DEMOSTRACIÓN
A la derecha está lo que escribo en un editor de texto, a la izquierda está lo que intercepta el keylogger y la interpretación de las teclas del sistema.
El código que he utilizado para desarrollar el ejemplo:
El código que he utilizado para desarrollar el ejemplo:
Código
Public NotInheritable Class Form1 : Inherits Form Private WithEvents keyLogger As InputDevice Public Sub New() Me.InitializeComponent() ' Instance an InputDevice object, which enumerates and registers the keyboards found. Me.keyLogger = New InputDevice(Me.Handle) ' Set keyboard layout to the default culture, in my case 'es-ES'. Me.keyLogger.Language = InputLanguage.DefaultInputLanguage.Culture.Name ' Handle text pasting operations (Ctrl+V). Me.keyLogger.HandlePastes = True ' Avoid raising KeyPressed event for non-relevant keys for this app example: ' Left/Right Shift, Alt, AltGr, CapsLock, NumLock, and Left/Right Win key. Me.keyLogger.IgnoredKeys = {Keys.ShiftKey, Keys.Menu, Keys.CapsLock, Keys.NumLock, Keys.LWin, Keys.RWin} ' Me.keyLogger.IgnoredChars = {"^"c} ' Me.keyLogger.IgnoredCharsComparer = EqualityComparer(Of Char).Default ' Me.keyLogger.IgnoredStrings = {"^^"} ' Me.keyLogger.IgnoredStringsComparer = StringComparer.OrdinalIgnoreCase End Sub Private Sub KeyLogger_KeyPressed(ByVal sender As Object, ByVal e As InputDevice.KeyPressedEventArgs) _ Handles keyLogger.KeyPressed Me.Label_Handle.Text = String.Format("Device Handle: {0}", e.DeviceInfo.DeviceHandle.ToString) Me.Label_Type.Text = String.Format("Device Type: {0}", e.DeviceInfo.DeviceType) Me.Label_Name.Text = String.Format("Device Name: {0}", e.DeviceInfo.DeviceName.Replace("&", "&&")) Me.Label_Descr.Text = String.Format("Device Description: {0}", e.DeviceInfo.DeviceDescription) Me.Label_Key.Text = String.Format("Device Key: System.Windows.Forms.Keys.{0}", e.DeviceInfo.Key.ToString) Me.Label_DevCount.Text = String.Format("Devices Count: {0}", Me.keyLogger.DeviceCount.ToString) Select Case e.DeviceInfo.Key Case Keys.Enter e.DeviceInfo.Chars = ControlChars.CrLf & "{ENTER}" Case Keys.Back e.DeviceInfo.Chars = "{BACKSPACE}" Case Keys.ControlKey e.DeviceInfo.Chars = "{CTRL}" Case Else ' ... End Select Me.TextBox1.Text = e.DeviceInfo.Chars Me.TextBox2.AppendText(e.DeviceInfo.Chars) End Sub Private Sub KeyLogger_HotkeyPastePressed(ByVal sender As Object, ByVal e As InputDevice.HotkeyPastePressedEventArgs) _ Handles keyLogger.HotkeyPastePressed Me.TextBox2.AppendText("{INIT_PASTE}" & e.ClipboardData & "{END_PASTE}") End Sub Private Sub Button_Clean_Click(sender As Object, e As EventArgs) _ Handles Button_Clean.Click Me.TextBox2.Clear() End Sub Private Sub Button_Dispose_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles Button_Dispose.Click If Me.keyLogger IsNot Nothing Then Me.keyLogger.Dispose() End If End Sub End Class
DIAGRAMA DE CLASS
v
http://pastebin.com/sMGREDTj
http://pastebin.com/u7uKf8ge
Espero que les haya gustado.
Si encuentran cualquier bug por favor coméntenlo aquí.
Saludos!
CÓDIGO FUENTE
http://pastebin.com/u7uKf8ge
Espero que les haya gustado.
Si encuentran cualquier bug por favor coméntenlo aquí.
Saludos!