Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: nico56 en 29 Enero 2010, 02:14 am



Título: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 02:14 am
Hola que tal, tengo una consulta supongamos que tengo un formulario con un texbox solamente,y el cursor que titila esta en el textbox listo para escribir, aunque la aplicacion este minimizada o desatendida, como puedo hacer para seguir capturando las teclas pulsadas?

Desde ya gracias y saludos. P.D. C# en lo posible. :xD


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: seba123neo en 29 Enero 2010, 02:30 am
Hook


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 02:38 am
Hook

???


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: raul338 en 29 Enero 2010, 02:43 am
Busca Hookear teclado, hay millones de resultados en google :P

http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 02:46 am
Ah ok, entonces buscare por ahi porque cai en muchas paginas pero no andaban lo que decian, el poder de sintesis de sebas es muy alto :D


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: DragonFire en 29 Enero 2010, 02:47 am
Hola que tal, tengo una consulta supongamos que tengo un formulario con un texbox solamente,y el cursor que titila esta en el textbox listo para escribir, aunque la aplicacion este minimizada o desatendida, como puedo hacer para seguir capturando las teclas pulsadas?

Desde ya gracias y saludos. P.D. C# en lo posible. :xD


un hook a la api y en lugar de un programa comun te convendria un servicio de windows, si es que piensas hacerlo en windows.


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 02:50 am
Si pienso hacerlo como un servicio pero por ahora estoy intentando hacerlo como un programa simple.

Lo que no entendi del link que me dejo raul es esta instruccion:

Código:
private static LowLevelKeyboardProc _proc = HookCallback;[code]

Tampoco el visual studio la deja pasar, me da error ahi.
[/code]


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: DragonFire en 29 Enero 2010, 03:19 am
Si pienso hacerlo como un servicio pero por ahora estoy intentando hacerlo como un programa simple.

Lo que no entendi del link que me dejo raul es esta instruccion:

Código:
private static LowLevelKeyboardProc _proc = HookCallback;[code]

Tampoco el visual studio la deja pasar, me da error ahi.
[/code]

bajate el codigo fuente de algun keyloggers, revisa el codigo y como hacen el hook, a la api que necesitas, un hook es "enganche" caulquier api, no necesariaente las del teclado, peude ser cualquier otra y de cualquier cosa.

en tu caso un programa comun en el mundo del hacking que hace el hook para lo que quieres es un keylogger, solo leete su codigo, si esta escrito en VB6 o anterior se te facilitaria mucho entenderlo....


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 05:15 am
Miren esto es bastante simple:

http://www.c-sharpcorner.com/UploadFile/grusso/KeyLoggerAplicationinCSharp11252005000941AM/KeyLoggerAplicationinCSharp.aspx

Solo me queda una duda porque no funciona cuando el formulario esta fuera de foco, para que sirve exactamente la propiedad "KeyPreview" ?


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: seba123neo en 29 Enero 2010, 05:20 am
no eso no te va a servir, porque usa solo los eventos del formulario y tiene que estar activo, por eso te digo que con un Hook...no veas que porque es facil te va a servir...haber si veo algo y lo posteo, pero mientras ponete en la cabeza la palabra HOOK... :P



Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 05:22 am
no eso no te va a servir, porque usa solo los eventos del formulario y tiene que estar activo, por eso te digo que con un Hook...no veas que porque es facil te va a servir...haber si veo algo y lo posteo, pero mientras ponete en la cabeza la palabra HOOK... :P



Ok  ;D


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: seba123neo en 29 Enero 2010, 07:08 am
haber proba algo asi, empeza un proyecto nuevo y pega todo este codigo en el Form1, y pone un textbox...es solo un ejemplo despues vos ya veras...

Código
  1. using System;
  2. using System.Diagnostics;
  3. using System.Windows.Forms;
  4. using System.Collections.Generic;
  5. using System.Runtime.InteropServices;
  6.  
  7. namespace WindowsApplication1
  8. {
  9.    public partial class Form1 : Form
  10.    {
  11.        public Form1()
  12.        {
  13.            InitializeComponent();
  14.            this.textBox1.Multiline = true;
  15.            this.textBox1.SetBounds(0, 0, 1000, 1000);
  16.        }
  17.  
  18.        private void Form1_Load(object sender, EventArgs e)
  19.        {
  20.            Hook.CreateHook(KeyHandler); // Instala el Hook
  21.        }
  22.  
  23.        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  24.        {
  25.            Hook.DestroyHook(); //Descarga el Hook
  26.        }
  27.  
  28.        public void KeyHandler(IntPtr wParam, IntPtr lParam)
  29.        {
  30.            int key = Marshal.ReadInt32(lParam);
  31.  
  32.            Hook.VK vk = (Hook.VK)key;
  33.  
  34.            switch (vk)
  35.            {
  36.                case Hook.VK.VK_F1: ActualizarTextbox(this.textBox1, "F1");
  37.                    break;
  38.  
  39.                default: break;
  40.            }
  41.        }
  42.  
  43.        public static void ActualizarTextbox(TextBox txt, string Texto)
  44.        {
  45.            txt.Text += Texto + "\r\n";
  46.        }
  47.    }
  48. }
  49.  
  50. public class Hook
  51. {
  52.    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  53.    public static extern IntPtr SetWindowsHookEx(int idHook, HookDel lpfn, IntPtr hMod, uint dwThreadId);
  54.  
  55.    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  56.    [return: MarshalAs(UnmanagedType.Bool)]
  57.    public static extern bool UnhookWindowsHookEx(IntPtr hhk);
  58.  
  59.    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  60.    public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
  61.  
  62.    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  63.    public static extern IntPtr GetModuleHandle(string lpModuleName);
  64.  
  65.    public enum VK
  66.    {
  67.        VK_LBUTTON = 0X01,
  68.        VK_RBUTTON = 0X02,
  69.        VK_MBUTTON = 0X04,
  70.        VK_BACK = 0X08,
  71.        VK_TAB = 0X09,
  72.        VK_RETURN = 0X0D,
  73.        VK_SHIFT = 0X10,
  74.        VK_CONTROL = 0X11,
  75.        VK_PAUSE = 0X13,
  76.        VK_CAPITAL = 0X14,
  77.        VK_ESCAPE = 0X1B,
  78.        VK_SPACE = 0X20,
  79.        VK_PRIOR = 0X21,
  80.        VK_NEXT = 0X22,
  81.        VK_END = 0X23,
  82.        VK_HOME = 0X24,
  83.        VK_LEFT = 0X25,
  84.        VK_UP = 0X26,
  85.        VK_RIGHT = 0X27,
  86.        VK_DOWN = 0X28,
  87.        VK_SNAPSHOT = 0X2C,
  88.        VK_INSERT = 0X2D,
  89.        VK_DELETE = 0X2E,
  90.  
  91.        VK_0 = 0X30,
  92.        VK_1 = 0X31,
  93.        VK_2 = 0X32,
  94.        VK_3 = 0X33,
  95.        VK_4 = 0X34,
  96.        VK_5 = 0X35,
  97.        VK_6 = 0X36,
  98.        VK_7 = 0X37,
  99.        VK_8 = 0X38,
  100.        VK_9 = 0X39,
  101.  
  102.        VK_A = 0X41,
  103.        VK_B = 0X42,
  104.        VK_C = 0X43,
  105.        VK_D = 0X44,
  106.        VK_E = 0X45,
  107.        VK_F = 0X46,
  108.        VK_G = 0X47,
  109.        VK_H = 0X48,
  110.        VK_I = 0X49,
  111.        VK_J = 0X4A,
  112.        VK_K = 0X4B,
  113.        VK_L = 0X4C,
  114.        VK_M = 0X4D,
  115.        VK_N = 0X4E,
  116.        VK_O = 0X4F,
  117.        VK_P = 0X50,
  118.        VK_Q = 0X51,
  119.        VK_R = 0X52,
  120.        VK_S = 0X53,
  121.        VK_T = 0X54,
  122.        VK_U = 0X55,
  123.        VK_V = 0X56,
  124.        VK_W = 0X57,
  125.        VK_X = 0X58,
  126.        VK_Y = 0X59,
  127.        VK_Z = 0X5A,
  128.  
  129.        VK_NUMPAD0 = 0X60,
  130.        VK_NUMPAD1 = 0X61,
  131.        VK_NUMPAD2 = 0X62,
  132.        VK_NUMPAD3 = 0X63,
  133.        VK_NUMPAD4 = 0X64,
  134.        VK_NUMPAD5 = 0X65,
  135.        VK_NUMPAD6 = 0X66,
  136.        VK_NUMPAD7 = 0X67,
  137.        VK_NUMPAD8 = 0X68,
  138.        VK_NUMPAD9 = 0X69,
  139.  
  140.        VK_SEPERATOR = 0X6C,
  141.        VK_SUBTRACT = 0X6D,
  142.        VK_DECIMAL = 0X6E,
  143.        VK_DIVIDE = 0X6F,
  144.  
  145.        VK_F1 = 0X70,
  146.        VK_F2 = 0X71,
  147.        VK_F3 = 0X72,
  148.        VK_F4 = 0X73,
  149.        VK_F5 = 0X74,
  150.        VK_F6 = 0X75,
  151.        VK_F7 = 0X76,
  152.        VK_F8 = 0X77,
  153.        VK_F9 = 0X78,
  154.        VK_F10 = 0X79,
  155.        VK_F11 = 0X7A,
  156.        VK_F12 = 0X7B,
  157.  
  158.        VK_NUMLOCK = 0X90,
  159.        VK_SCROLL = 0X91,
  160.        VK_LSHIFT = 0XA0,
  161.        VK_RSHIFT = 0XA1,
  162.        VK_LCONTROL = 0XA2,
  163.        VK_RCONTROL = 0XA3,
  164.    }
  165.  
  166.    public delegate IntPtr HookDel(int nCode, IntPtr wParam, IntPtr lParam);
  167.    public delegate void KeyHandler(IntPtr wParam, IntPtr lParam);
  168.  
  169.    private static IntPtr hhk = IntPtr.Zero;
  170.    private static HookDel hd;
  171.    private static KeyHandler kh;
  172.  
  173.    public static void CreateHook(KeyHandler _kh)
  174.    {
  175.        Process _this = Process.GetCurrentProcess();
  176.        ProcessModule mod = _this.MainModule;
  177.        hd = HookFunc;
  178.        kh = _kh;
  179.  
  180.        hhk = SetWindowsHookEx(13, hd, GetModuleHandle(mod.ModuleName), 0);
  181.    }
  182.  
  183.    public static bool DestroyHook()
  184.    {
  185.        return UnhookWindowsHookEx(hhk);
  186.    }
  187.  
  188.    private static IntPtr HookFunc(int nCode, IntPtr wParam, IntPtr lParam)
  189.    {
  190.        int iwParam = wParam.ToInt32();
  191.  
  192.        if (nCode >= 0 && (iwParam == 0x100 || iwParam == 0x104)) kh(wParam, lParam);
  193.  
  194.        return CallNextHookEx(hhk, nCode, wParam, lParam);
  195.    }
  196.  
  197. }

el tema de estar declarando todas las teclas se puede hacer con un For Each a System.Windows.Forms.Keys...

saludos.


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 14:11 pm
Hola seba te agradezco el codigo pero tengo problemas con estas 4 instrucciones:

Código:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr SetWindowsHookEx(int idHook, HookDel lpfn, IntPtr hMod, uint dwThreadId);
 
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool UnhookWindowsHookEx(IntPtr hhk);
 
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);

Es el mismo problema que tuve cono otros códigos de otras paginas, el compilador me dice que no encuentra el espacio de nombres "DLLImport", posiblemente me falte alguna referencia ?


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 14:16 pm
Yo solo me contesto problema de mi compilador, lo que no entiendo del código es que la teclas que pulso no van a parar a un archivo ?


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: raul338 en 29 Enero 2010, 14:23 pm
Para usar DllImport debes importar (using arriba de todo) los namespace System.Runtime.InteropServices


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 29 Enero 2010, 18:13 pm
Para usar DllImport debes importar (using arriba de todo) los namespace System.Runtime.InteropServices

Si justamente me comi un "using" , pero no logro hallar en el codigo donde va la informacion acerca de las teclas pulsadas :S


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: seba123neo en 29 Enero 2010, 19:38 pm
pues hay que leer 2 minutos el codigo y va sa ver que en KeyHandler es dodne van a parar las teclas, ponele un punto de interrupcion ahi, y apreta una tecla y fijate como entra...yo ahi lo puse para que lo escriba en un textbox, vos agarra y hace un codigo que lo escriba en un txt..es lo mismo, creo que ya tenes lo que necesitabas ahora depende de vos.

saludos.


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: nico56 en 30 Enero 2010, 00:18 am
No creo que ni en un dia mirando el codigo me hubiera dado cuenta que en la funcion keyhandler va parar las teclas pulsadas, pero te lo agradezco.


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: Tsurematsu en 30 Enero 2021, 00:44 am
Solo por si alguien quiere ver esto, sito a este codigo

https://social.msdn.microsoft.com/Forums/es-ES/e634ed1e-553e-4f31-981f-47a27a27b9ec/posicion-coordenadas-de-un-proceso?forum=vbes

Me funciono muy bien  ;D




Lo puse como modulo para no complicarme mucho:






Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Threading
Imports System.Windows.Forms
Module Capturar_Teclado
    Public Class KeyHot
        Public Shared KeyDetec As Char = ""
        Enum Constantes As Integer
            WH_KEYBOARD_LL = 13
            HC_ACTION = 0
            WM_KEYDOWN = &H100
            WM_KEYUP = &H101
            WM_SYSKEYDOWN = &H104
            WM_SYSKEYUP = &H105
        End Enum '-> Constantes utilizadas en el Hook Global
        <StructLayout(LayoutKind.Sequential)>
        Public Class KBDLLHOOKSTRUCT
            Public vkCode As UInt32
            Public scanCode As UInt32
            Public flags As UInt32
            Public time As UInt32
            Public dwExtraInfo As UIntPtr
        End Class '-> Estructura que contiene los mensajes interceptados por el Hook
#Region "Declaraciones_API"
        <DllImport("user32.dll")>
        Friend Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As HookProc, ByVal hInstance As IntPtr, ByVal threadId As Integer) As Integer
        End Function

        <DllImport("user32.dll")>
        Friend Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
        End Function
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
        Public Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
        End Function
        <DllImport("user32.dll", SetLastError:=True)>
        Public Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
#End Region '-> Declaraciones de APIs para el uso de Hooks (SetWindowsHookEx...)
        Enum HookType As Integer
            WH_JOURNALRECORD = 0
            WH_JOURNALPLAYBACK = 1
            WH_KEYBOARD = 2
            WH_GETMESSAGE = 3
            WH_CALLWNDPROC = 4
            WH_CBT = 5
            WH_SYSMSGFILTER = 6
            WH_MOUSE = 7
            WH_HARDWARE = 8
            WH_DEBUG = 9
            WH_SHELL = 10
            WH_FOREGROUNDIDLE = 11
            WH_CALLWNDPROCRET = 12
            WH_KEYBOARD_LL = 13
            WH_MOUSE_LL = 14
        End Enum '-> Tipos de Hooks para monitorizar mensajes

        'Declaramos un delegado y le asignamos sus respectivos argumentos
        Delegate Function HookProc(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
        Private Shared CallbackDelegate As HookProc = Nothing

        'Declaramos la variable Hook. Será la encargada de almacenar la direccion de memoria del Hook
        Shared hook As IntPtr = IntPtr.Zero


        'Procedimiento asociado al puntero AddressOf(CallBackDelegate)
        Private Shared Function HookprocHandler(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
            Try
                'Code es la variable encargada de decir si existe un mensaje. Si code !=0 no habra nada.
                If (code < 0) Then
                    'Damos paso al siguiente Hook y procedemos con el continuamiento del Sistema
                    Return CallNextHookEx(IntPtr.Zero, code, wParam, lParam)
                Else
                    Dim sr As New StreamWriter(CurDir() & "\log.txt", True)
                    'Segun el código devuelto a la pulsación de la tecla (257,258)
                    KeyDetec = ""
                    Select Case wParam
                        Case Constantes.WM_KEYDOWN, Constantes.WM_SYSKEYDOWN
                            Dim key As Char = ChrW(lParam.vkCode) 'Imprimimos el caracter ASCII en pantalla
                            sr.Write(key)
                            KeyDetec = key
                    End Select
                    sr.Close()
                    Return CallNextHookEx(IntPtr.Zero, code, wParam, lParam)
                End If
            Catch ex As Exception
            End Try
            Return 1
        End Function
        Public Shared Sub Iniciar_Hook()
            Try
                'Asociamos a dicho procedimiento un puntero hacia el controlador del Hook (HookProcHandler)
                CallbackDelegate = New HookProc(AddressOf HookprocHandler)
                If hook <> 0 Then
                    'Desinstalamos el Hook
                    UnhookWindowsHookEx(hook)
                    hook = IntPtr.Zero
                    'Label1.Text = "Hookear Teclado"
                Else
                    'Instalamos un Hook Global (LowLevelKeyBoard) y llamamos a la funcion HookProcHandler
                    'Los ultimos dos parametros indican el HINSTANCE y PID, se utilizarian en caso de Hook local _
                    'empleados en juegos y demás.
                    hook = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, CallbackDelegate, 0, 0)
                    'Label1.Text = "Desinstalar Hook"
                    FileSystem.Kill(CurDir() & "\log.txt")
                End If
            Catch ex As Exception
            End Try
        End Sub
    End Class
End Module















asi es como yo cite el modulo:







    Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
        KeyHot.Iniciar_Hook()
        End
    End Sub


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        KeyHot.Iniciar_Hook()
        Timer1.Start()
    End Sub


    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Dim kea As String = KeyHot.KeyDetec 'Obtiene tecla precionada
        If Not kea = "" Then
            Label1.Text = kea
            TextBox1.Text &= kea
        Else
            Label1.Text = ""
        End If
    End Sub





Estoy seguro que mas de uno podra mejorar este codigo,  ;D

Por cierto, soy nuevo y todavia no se aprovechar los elementos de esta web asi que pegue el codigo a lo seco, Dispudas.



Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: Serapis en 30 Enero 2021, 18:55 pm

Por cierto, soy nuevo y todavia no se aprovechar los elementos de esta web asi que pegue el codigo a lo seco, Dispudas.
Hay algo peor que eso (suele verse peor en los foros, por lo menos por parte d elos administradores)...

Responder a un tema muerto (en general cualquier tema que hace tiempo no tiene respuestas, y éste nada más y nada menos que 10 años).


Título: Re: Captar teclas pulsadas aunque la aplicacion no este atendida
Publicado por: Mr. NoBody en 4 Febrero 2021, 21:39 pm
Cuando escribes texto o simplemente interactuas con el ratón o el teclado sobre un elemento de la interfaz de usuario, se dice que este tiene el foco de entrada (Input focus). Si minimizas la ventana de la aplicación, esta pasa a ser una ventana en segundo plano, y el foco de entrada se desvía a la siguiente ventana en el índice de ventanas, que pasa a ser la ventana en primer plano (foreground window). Para permitir que tu aplicación / ventana sin foco de entrada siga capturando las pulsaciones del teclado, necesitas hacer uso directo de la API de Windows.

Sin embargo, el uso de un hook de bajo nivel del teclado o LLKH (low-level keyboard hook) es una técnica considerada actualmente obsoleta para la captura de pulsaciones del teclado. Esto no significa que esta técnica no te vaya a funcionar, pero funcionalmente hablando utiliza más recursos y es más lento que su técnica sucesora (RAW_INPUT), y además tiene sus limitaciones en comparación.

Ya te mostraron un ejemplo de LLH en C#, aquí tienes otro en VB.NET aunque es del 2013 y creo recordar que no es en absoluto compatible con todas las posibles circunstancias y combinaciones de teclas:
https://foro.elhacker.net/net/libreria_de_snippets_para_vbnet_compartan_aqui_sus_snippets-t378770.0.html;msg1857514#msg1857514

Lamentablemente no puedo compartir una API / implementación de RAW_INPUT ya que mi código es comercial, pero si puedo indicarte implementaciones de terceros:
https://github.com/mfakane/rawinput-sharp
https://csharp.hotexamples.com/examples/-/RawInput/-/php-rawinput-class-examples.html
https://www.codeproject.com/Articles/297312/Minimal-Key-Logger-using-RAWINPUT

EDITO: vaya, encontré una antigua implementación pública de RAW_INPUT en VB.NET aquí:
https://pastebin.com/u7uKf8ge
https://foro.elhacker.net/net/source_algoritmo_keylogger_rawinput-t437992.0.html;msg2036924
...aunque siendo del 2015 probablemente no esté del todo optimizado y pueda manifestarse algún bug (quizás en la portabilidad de los tipos Win32), ya que de buena mano se que el tal Elektro realizó muchas actualizaciones y correcciones a ese código desde entonces, pero eso es código privado.

EDITO2: De todas formas también hay algunas APIs open-source disponibles en github y nuget.org:
https://nugetmusthaves.com/Package/RawInputProcessor
https://nugetmusthaves.com/Package/RawInput.Sharp
https://nugetmusthaves.com/Package/RawInputManager

PD: las APIs publicadas en formato nuget puedes instalarlas directamente desde el administrador de paquetes nuget en Visual Studio.

Saludos!