ubuntu monitoring keyboard input

Keywords: Linux Ubuntu

background

        In the project, I used a hook function of windows, mainly the keyboard hook, which is very interesting. So I want to see the hook function under linux and realize a function of monitoring keyboard input, so that I can shield the input of some keys.

process

        I only have a computer with Ubuntu 20.04 system, so I use this to study. At the beginning, I went to find the hook function of linux, but I found it on the Internet. So far, I'm not sure whether linux has a keyboard hook function such as windows. If any God knows, please give me some advice.

        I didn't find the hook under linux, but I saw some articles saying that device files can be used. I refer to this article. Thank you.

An experiment of capturing keyboard input under U buntu_ utt@Delimola CSDN blog has always wondered how applications get keyboard input. First, it must be related to the keyboard driver, but how does the driver pass keyboard input to the user process? This problem reached its peak after using the next key wizard under windows. The wizard in this case used a script to express the simulated keyboard keys and mouse movement, and then it can operate automatically, which shows that the upper application has the ability to operate the mouse and keyboard. After searching the data, it was found that for linux, The mouse and keyboard drivers are written as follows: the input of mouse / keyboard will be converted to io event * under / dev/input, and the event number corresponding to the device can be viewed through cat /proc/bus/input/devices. For examplehttps://blog.csdn.net/weixin_44333998/article/details/117772604         Here are a few paths to understand

          (1)   / dev/input/by-id   You can see that there are some device files under this path, such as event0, but now you can't know the device corresponding to the device file.

  So you can go to the by ID directory and look again. You will find that there are soft connections in it, so you can clearly understand the device files corresponding to the device.

There is also a by path directory that works the same way.

 

          (2)   / proc/bus/input    --->  There is a device file, which is the device file corresponding to the device. For example, you can look at this file when you want to obtain other devices. Like a camera or something.

        Finally, I just read the device file, so the program mainly reads the device file.

code

#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <errno.h>
#include <fstream>

using namespace std;

/*  
 *Function: find the event file corresponding to the keyboard device, such as event7
 *     linux Insert keyboard devices, and each device will have an event number, but at present, the ls -l sorting is arranged according to the device name, so
 *     The top keyboard device will not be the latest device, so this function will get an uncertain keyboard event file when there are many keyboard devices
        usb-026d_0002-event-if01 -> ../event12
        usb-026d_0002-event-kbd -> ../event6
        usb-413c_Dell_KB216_Wired_Keyboard-event-if01 -> ../event14
        usb-413c_Dell_KB216_Wired_Keyboard-event-kbd -> ../event13     This is the latest keyboard device, but it's not at the top
        usb-Logitech_USB_Receiver-if01-event-mouse -> ../event2
        usb-Logitech_USB_Receiver-if01-mouse -> ../mouse0
        usb-SONiX_USB_Keyboard-event-if01 -> ../event4
        usb-SONiX_USB_Keyboard-event-kbd -> ../event3

 */

string FindKdbEvet()
{
    FILE *stream;
    FILE *wstream;
    char buf[20];
    memset( buf, '\0', sizeof(buf) );//Initialize buf to prevent it from being written into the file
    //Read the output of the command through the pipe (the "r" parameter) to FILE* stream
    stream = popen("cd /dev/input/by-id ; ls -l | grep \"kbd\" | head -1 | cut -d \"/\" -f 2", "r"); 
    fread( buf, sizeof(char), sizeof(buf), stream); //Read the data stream of FILE* stream into buf
    pclose(stream);
    string str = buf;
    return str;
}
  
/*  
 *Function: open event file  
 *Input:_ File rheology corresponding to infile
 *Return value: int returns 0 as opening success and - 1 as opening failure
 */
int OpenEventFile(ifstream & _infile)
{
    string kdbevet = FindKdbEvet();   //Get keyboard events, such as event7 
    int isize = kdbevet.size();
    if(isize > 0 && kdbevet[isize-1]) //Here, we need to remove the line feed symbol at the end. The ascii code is 10
    {
        kdbevet = kdbevet.substr(0,kdbevet.size()-1); 
    }
    string shCommand = "/dev/input/" + kdbevet;

    _infile.open(shCommand.c_str(),ios_base::in);
    if(!_infile.is_open())
    {
        cout <<"open Keyboard device error, error code = <<" << errno << "!" <<endl;
        return -1;
    }
    return 0;
}



int main ()  
{  
  struct input_event t;  
  ifstream infile;

  if(OpenEventFile(infile) == -1)
  {
      return 0;
  }

  bool blPressIsCtrl = false;
  bool blPressIsC    = false;

  while (1)  
  {
       if(infile.read((char *)&t,sizeof(t)))
       {//Read file successfully
           if(t.type == EV_KEY)
           {
               if((t.code == KEY_LEFTCTRL || t.code == KEY_RIGHTCTRL) && t.value == 1)
               {
                   blPressIsCtrl = true;
               }

               if ((t.code == KEY_LEFTCTRL || t.code == KEY_RIGHTCTRL) && t.value == 0)
               {
                   blPressIsCtrl = false;
               }

               if(t.code == KEY_C && t.value == 1 && blPressIsCtrl == true)
               {
                   cout<<"press ctrl + c"<<endl;
               }
               
               cout << "you use key value is "<<t.code<<endl;
           }
       }
       else
       {//Failed to read the file. You need to read it again
           cout <<"read file error"<<endl;
           infile.close();  
           if(OpenEventFile(infile) == -1)
           {
              return 0;
           }
       }
  }  
  infile.close();  
  return 0;  
}  

Postscript

        At present, this small code can monitor the key input of keyboard equipment (USB interface) under linux system. If you monitor the input of Ctrl+C, you will output the log. The plug-in program of the same keyboard device can still be monitored.

        The disadvantage is that you can't monitor the input of multiple keyboard devices at the same time, because now you just read a device file (windows Hook function). Moreover, if you end the program, insert multiple keyboard devices, and execute the program again, you may not continue to monitor the last monitored keyboard device. This is because the sorting of soft links in the by ID directory is not stable, and the shell statement is to query the first corresponding device file. This needs to be improved.

Posted by aragon1337 on Fri, 24 Sep 2021 07:22:13 -0700