USB კლავიატურის ყველა ღილაკის მდგომარეობის დაფიქსირება: დაბალდონიანი Linux-ის თავგადასავალი

USB კლავიატურის ყველა ღილაკის მდგომარეობის დამპი: დაბალი დონის Linux-ის თავგადასავალი
ოდესმე გიფიქრიათ, რა ხდება ქვეშ, როდესაც USB კლავიატურაზე ღილაკს აჭერთ? რა იქნებოდა, თუ შეძლებდით ნახვას, თუ რა ნედლ მონაცემებს აგზავნის კლავიატურა თქვენს კომპიუტერში? ამ ბლოგში ჩვენ ჩავუღრმავდებით USB HID (Human Interface Device) პროტოკოლების სამყაროს და დავწერთ დაბალი დონის Linux-ის პროგრამას, რომელიც დაამპავს USB კლავიატურის ყველა ღილაკის მიმდინარე მდგომარეობას. არანაირი მაღალი დონის აბსტრაქციები—მხოლოდ ნედლი, გაუფილტრავი წვდომა ტექნიკაზე.
პრობლემა: კლავიატურის მდგომარეობის წაკითხვა მოვლენების გარეშე
როდესაც კლავიატურაზე ღილაკს აჭერთ, ოპერაციული სისტემა მას აღიქვამს როგორც მოვლენას. ეს მოვლენები მოსახერხებელია უმეტესი აპლიკაციებისთვის, მაგრამ რა მოხდება, თუ გსურთ იცოდეთ ყველა ღილაკის მიმდინარე მდგომარეობა—არა მხოლოდ იმ ღილაკების, რომლებმაც გამოიწვიეს მოვლენები? მაგალითად:
- რომელი ღილაკებია ამჟამად დაჭერილი?
- როგორია მოდიფიკატორი ღილაკების მდგომარეობა (Shift, Ctrl, Alt)?
- რა შეიძლება ითქვას LED-ების მდგომარეობაზე (Caps Lock, Num Lock, Scroll Lock)?
ეს არის საერთო გამოწვევა:
- უსაფრთხოების მკვლევარებისთვის, რომლებიც აანალიზებენ კლავიატურის შეყვანას.
- ჩაშენებული სისტემების დეველოპერებისთვის, რომლებიც ახდენენ USB მოწყობილობების დებაგინგს.
- ცნობისმოყვარე ჰაკერებისთვის, რომლებსაც სურთ გაიგონ, როგორ მუშაობს USB კლავიატურები.
მაგრამ აქ არის ერთი პრობლემა: თუ ღილაკი დაიჭირეს სისტემის გამორთვის დროს, Linux-ის ბირთვი არ გამოიმუშავებს არცერთ მოვლენას, სანამ სხვა ღილაკი არ დაიჭირება. ეს ნიშნავს, რომ თქვენ ვერ დაეყრდნებით ბირთვის შეყვანის ქვესისტემას იმ ღილაკების გამოსავლენად, რომლებიც დაიჭირეს სისტემის ჩართვამდე. ამის გადასაჭრელად, ჩვენ უნდა გავვლეთ მაღალი დონის შეყვანის ქვესისტემას და პირდაპირ ურთიერთქმედება USB კლავიატურასთან ყველაზე დაბალ დონეზე.
გამოსავალი: libusb
-ის გამოყენება კლავიატურის მდგომარეობის გასაგებად
ჩვენ გამოვიყენებთ libusb
ბიბლიოთეკას USB კლავიატურასთან პირდაპირი ურთიერთქმედებისთვის. აქ არის ის, რასაც ჩვენ გავაკეთებთ:
- ჩამოვთვლით ყველა USB მოწყობილობას კლავიატურების მოსაძებნად.
- გამოვყოფთ HID ინტერფეისებს ამ მოწყობილობებზე.
- გავაგზავნით
HID GET_REPORT
მოთხოვნას მიმდინარე შეყვანის ანგარიშის მისაღებად (ღილაკების მდგომარეობა). - გავშიფრავთ შეყვანის ანგარიშს იმის დასადგენად, რომელი ღილაკებია დაჭერილი.
კოდი: ღილაკების მდგომარეობის დამპი
ქვემოთ მოცემულია C პროგრამა, რომელიც ასრულებს ყველა მძიმე სამუშაოს. ის იყენებს libusb
-ს USB მოწყობილობებთან ურთიერთქმედებისთვის და აბრუნებს შეყვანის ანგარიშს ყველა დაკავშირებული კლავიატურისთვის.
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
// HID GET_REPORT მოთხოვნა
#define HID_GET_REPORT 0x01
#define HID_REPORT_TYPE_INPUT 0x01
// ფუნქცია HID კლავიატურის შესამოწმებლად
int is_hid_keyboard(libusb_device *device) {
struct libusb_device_descriptor desc;
int ret = libusb_get_device_descriptor(device, &desc);
if (ret < 0) {
fprintf(stderr, "მოწყობილობის დესკრიპტორის მიღება ვერ მოხერხდა\n");
return 0;
}
// შევამოწმოთ, არის თუ არა მოწყობილობა HID მოწყობილობა
if (desc.bDeviceClass == LIBUSB_CLASS_PER_INTERFACE) {
struct libusb_config_descriptor *config;
ret = libusb_get_config_descriptor(device, 0, &config);
if (ret < 0) {
fprintf(stderr, "კონფიგურაციის დესკრიპტორის მიღება ვერ მოხერხდა\n");
return 0;
}
for (int i = 0; i < config->bNumInterfaces; i++) {
const struct libusb_interface *interface = &config->interface[i];
for (int j = 0; j < interface->num_altsetting; j++) {
const struct libusb_interface_descriptor *iface_desc = &interface->altsetting[j];
if (iface_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
libusb_free_config_descriptor(config);
return 1; // ეს არის HID მოწყობილობა
}
}
}
libusb_free_config_descriptor(config);
}
return 0; // ეს არ არის HID მოწყობილობა
}
// ფუნქცია HID კლავიატურის შეყვანის ანგარიშის მისაღებად
void get_input_report(libusb_device_handle *handle) {
unsigned char input_report[8]; // უმეტესი კლავიატურები იყენებენ 8-ბაიტიან შეყვანის ანგარიშებს
int ret = libusb_control_transfer(
handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
HID_GET_REPORT,
(HID_REPORT_TYPE_INPUT << 8) | 0x00, // ანგარიშის ტიპი (შეყვანა) და ანგარიშის ID (0)
0, // ინტერფეისი
input_report,
sizeof(input_report),
1000 // დროის ლიმიტი მილიწამებში
);
if (ret < 0) {
fprintf(stderr, "შეყვანის ანგარიშის მიღება ვერ მოხერხდა: %s\n", libusb_error_name(ret));
} else {
printf("შეყვანის ანგარიში:\n");
for (int i = 0; i < ret; i++) {
printf("%02x ", input_report[i]);
}
printf("\n");
}
}
int main() {
libusb_device **devices;
ssize_t count;
int ret;
// libusb-ის ინიციალიზაცია
ret = libusb_init(NULL);
if (ret < 0) {
fprintf(stderr, "libusb-ის ინიციალიზაცია ვერ მოხერხდა: %s\n", libusb_error_name(ret));
return 1;
}
// USB მოწყობილობების სიის მიღება
count = libusb_get_device_list(NULL, &devices);
if (count < 0) {
fprintf(stderr, "მოწყობილობების სიის მიღება ვერ მოხერხდა: %s\n", libusb_error_name((int)count));
libusb_exit(NULL);
return 1;
}
// ყველა მოწყობილობის გადაკვეთა
for (ssize_t i = 0; i < count; i++) {
libusb_device *device = devices[i];
// შევამოწმოთ, არის თუ არა მოწყობილობა HID კლავიატურა
if (is_hid_keyboard(device)) {
struct libusb_device_descriptor desc;
ret = libusb_get_device_descriptor(device, &desc);
if (ret < 0) {
fprintf(stderr, "მოწყობილობის დესკრიპტორის მიღება ვერ მოხერხდა\n");
continue;
}
printf("ნაპოვნია HID კლავიატურა: %04x:%04x\n", desc.idVendor, desc.idProduct);
// მოწყობილობის გახსნა
libusb_device_handle *handle;
ret = libusb_open(device, &handle);
if (ret < 0) {
fprintf(stderr, "მოწყობილობის გახსნა ვერ მოხერხდა: %s\n", libusb_error_name(ret));
continue;
}
// ბირთვის დრაივერის გამორთვა (თუ ჩართულია)
if (libusb_kernel_driver_active(handle, 0) == 1) {
ret = libusb_detach_kernel_driver(handle, 0);
if (ret < 0) {
fprintf(stderr, "ბირთვის დრაივერის გამორთვა ვერ მოხერხდა: %s\n", libusb_error_name(ret));
libusb_close(handle);
continue;
}
}
// ინტერფეისის მოთხოვნა
ret = libusb_claim_interface(handle, 0);
if (ret < 0) {
fprintf(stderr, "ინტერფეისის მოთხოვნა ვერ მოხერხდა: %s\n", libusb_error_name(ret));
libusb_close(handle);
continue;
}
// შეყვანის ანგარიშის მიღება
get_input_report(handle);
// ინტერფეისის გათავისუფლება
libusb_release_interface(handle, 0);
// ბირთვის დრაივერის ჩართვა (თუ გამორთულია)
libusb_attach_kernel_driver(handle, 0);
// მოწყობილობის დახურვა
libusb_close(handle);
}
}
// მოწყობილობების სიის გათავისუფლება
libusb_free_device_list(devices, 1);
// libusb-ის დასუფთავება
libusb_exit(NULL);
return 0;
}
როგორ მუშაობს
-
მოწყობილობების ჩამოთვლა:
- პროგრამა ჩამოთვლის ყველა USB მოწყობილობას და გამოყოფს HID კლავიატურებს მათი ინტერფეისის კლასის შემოწმებით.
-
მოწყობილობის გახსნა:
- ყოველი HID კლავიატურისთვის, პროგრამა ხსნის მოწყობილობას და გამორთავს ბირთვის დრაივერს (თუ საჭიროა).
-
ინტერფეისის მოთხოვნა:
- პროგრამა მოითხოვს HID ინტერფეისს, რათა პირდაპირ ურთიერთქმედება მოხდეს მოწყობილობასთან.
-
HID GET_REPORT
-ის გაგზავნა:- პროგრამა აგზავნის
GET_REPORT
მოთხოვნას შეყვანის ანგარიშის მისაღებად, რომელიც შეიცავს ყველა ღილაკის მიმდინარე მდგომარეობას.
- პროგრამა აგზავნის
-
შეყვანის ანგარიშის გაშიფვრა:
- შეყვანის ანგარიში იბეჭდება თექვსმეტობით ფორმატში. თითოეული ბაიტი შეესაბამება კონკრეტულ ღილაკს ან მოდიფიკატორს.
პროგრამის გაშვება
- დააინსტალირეთ
libusb
:
sudo apt install libusb-1.0-0-dev
- დააკომპილირეთ პროგრამა:
gcc -o dump_keys dump_keys.c -lusb-1.0
- გაუშვით პროგრამა root-ის უფლებებით:
sudo ./dump_keys
მაგალითი გამოტანის
კლავიატურისთვის, რომელზეც დაჭერილია F9 ღილაკი, გამოტანა შეიძლება ასე გამოიყურებოდეს:
ნაპოვნია HID კლავიატურა: 046d:c31c
შეყვანის ანგარიში:
00 00 42 00 00 00 00 00
ეს ნიშნავს:
- არცერთი მოდიფიკატორი ღილაკი არ არის დაჭერილი (`00`).
- F9 ღილაკი დაჭერილია (`42`).
- არცერთი სხვა ღილაკი არ არის დაჭერილი (`00 00 00 00 00`).
რატომ არის ეს მნიშვნელოვანი
ეს დაბალი დონის მიდგომა გაძლევთ სრულ კონტროლს USB კლავიატურაზე, რაც საშუალებას გაძლევთ:
- გააკეთოთ USB მოწყობილობების დებაგინგი.
- აანალიზოთ კლავიატურის შეყვანა უსაფრთხოების კვლევისთვის.
- შექმნათ საკუთარი კლავიატურის ფირმვერი ან დრაივერები.
შემდეგი ნაბიჯები
- ექსპერიმენტი გააკეთეთ სხვადასხვა კლავიატურებთან და დააკვირდით მათ შეყვანის ანგარიშებს.
- გააფართოვეთ პროგრამა LED-ების მდგომარეობის გაშიფვრისთვის ან მრავალი კლავიატურის ერთდროულად დამუშავებისთვის.
- ჩაუღრმავდით USB HID სპეციფიკაციას უფრო რთული მოწყობილობების გასაგებად.
გისურვებთ წარმატებებს! გვაცნობეთ, თუ რაიმე შეკითხვა გაქვთ ან დამატებითი დახმარება გჭირდებათ. 🚀