Определить USB аппаратный кейлоггер

Мне нужно определить, есть ли аппаратный кейлоггер, который был подключен к ПК с USB-клавиатурой. Это должно быть сделано с помощью программного метода, из земли пользователя. тем не мение вики говорит, что невозможно определить HKL с помощью программного обеспечения, существует несколько методов. Лучшее, и я думаю, что только один обзор, который присутствует в сети, касающийся этой темы, — «Обнаружение аппаратных кейлоггеров» Фабиана Михайловича — YouTube».

Используя этот обзор, я разрабатываю инструмент для обнаружения аппаратных клавиатурных шпионов USB. Источники для обнаружения клавиатурных шпионов PS / 2 уже предоставлены автором и доступны Вот. Поэтому моя задача — заставить его работать только на USB.

Как и предполагалось, я использую библиотеку libusb для взаимодействия с USB-устройствами в системе.

Итак, есть методы, которые я выбрал для обнаружения HKL:

  1. Найдите USB-клавиатуру, которая прослушивается HKL. Обратите внимание, что HKL обычно
    невидимы из списка устройств в системе или возвращены libusb.
  2. Обнаружение Keyghost HKL по: Прерыванию чтения с устройства USB HID, отправке сброса usb (libusb_reset_device), повторному считыванию прерывания. Если данные, возвращенные при последнем чтении, не равны нулю, обнаружен кейлоггер. Это описано на странице 45 Презентация Михайловича
  3. Измерение времени Идея состоит в том, чтобы измерить время отправки / получения пакетов с помощью контрольной передачи для оригинальной клавиатуры в тысячи раз. Если HKL был подключен, программа снова измеряет время и затем сравнивает время с исходным значением. Для HKL это должно быть намного (или не так много) больше.
    Алгоритм это:

    • Отправить отчет о выводе на клавиатуру (как передача управления) (HID_REPORT_TYPE_OUTPUT 0x02)
    • Ждите ACKed пакета
    • Повторите цикл (10.000 раз)
    • Измерить время

Ниже мой код в соответствии с этапами обнаружения.

1. Найти USB-клавиатуру

libusb_device * UsbKeyboard::GetSpecifiedDevice(PredicateType pred)
{
if (_usbDevices == nullptr) return nullptr;
int i = 0;
libusb_device *dev = nullptr;
while ((dev = _usbDevices[i++]) != NULL)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r >= 0)
{
if (pred(desc))
return dev;
}
}

return nullptr;
}

libusb_device * UsbKeyboard::FindKeyboard()
{
return GetSpecifiedDevice([&](libusb_device_descriptor &desc) {
bool isKeyboard = false;
auto dev_handle = libusb_open_device_with_vid_pid(_context, desc.idVendor, desc.idProduct);
if (dev_handle != nullptr)
{
unsigned char buf[255] = "";

// product description contains 'Keyboard', usually string is 'USB Keyboard'
if (libusb_get_string_descriptor_ascii(dev_handle, desc.iProduct, buf, sizeof(buf)) >= 0)
isKeyboard = strstr((char*)buf, "Keyboard") != nullptr;
libusb_close(dev_handle);
}

return isKeyboard;
});
}

Здесь мы перебираем все USB-устройства в системе и проверяем их строку Product. В моей системе эта строка для клавиатуры — «клавиатура USB» (очевидно).
Это стабильный способ обнаружения клавиатуры через строку продукта? Есть ли другие способы?

2. Определите Keyghost HKL, используя Прерывание чтения

int UsbKeyboard::DetectKeyghost(libusb_device *kbdev)
{
int r, i;

int transferred;
unsigned char answer[PACKET_INT_LEN];
unsigned char question[PACKET_INT_LEN];
for (i = 0; i < PACKET_INT_LEN; i++) question[i] = 0x40 + i;
libusb_device_handle *devh = nullptr;
if ((r = libusb_open(kbdev, &devh)) < 0)
{
ShowError("Error open device", r);
return r;
}

r = libusb_set_configuration(devh, 1);
if (r < 0)
{
ShowError("libusb_set_configuration error ", r);
goto out;
}
printf("Successfully set usb configuration 1\n");

r = libusb_claim_interface(devh, 0);
if (r < 0)
{
ShowError("libusb_claim_interface error ", r);
goto out;
}

r = libusb_interrupt_transfer(devh, 0x81 , answer, PACKET_INT_LEN,
&transferred, TIMEOUT);
if (r < 0)
{
ShowError("Interrupt read error ", r);
goto out;
}
if (transferred < PACKET_INT_LEN)
{
ShowError("Interrupt transfer short read %", r);
goto out;
}

for (i = 0; i < PACKET_INT_LEN; i++) {
if (i % 8 == 0)
printf("\n");
printf("%02x, %02x; ", question[i], answer[i]);
}
printf("\n");

out:
libusb_close(devh);
return 0;
}

У меня такая ошибка на libusb_interrupt_transfer:

libusb: error [hid_submit_bulk_transfer] HID transfer failed: [5] Access denied
Interrupt read error  - Input/Output Error (LIBUSB_ERROR_IO) (GetLastError() - 1168)

Понятия не имею, почему «доступ запрещен», затем ошибка ввода-вывода и GetLastError () возвращает 1168, что означает — Элемент не найден (Какой элемент?). Нужна помощь здесь.

  1. Измерение времени Отправьте отчет о выходе и дождитесь пакета ACK.

    int UsbKeyboard :: SendOutputReport (libusb_device * kbdev)
    {
    const int PACKET_INT_LEN = 1;
    int r, i;
    ответ без знака [PACKET_INT_LEN];
    вопрос о неподписанных символах [PACKET_INT_LEN];
    для (я = 0; я < PACKET_INT_LEN; i ++) вопрос [i] = 0x30 + i;
    для (я = 1; я < PACKET_INT_LEN; i ++) answer [i] = 0;

    libusb_device_handle *devh = nullptr;
    if ((r = libusb_open(kbdev, &devh)) < 0)
    {
    ShowError("Error open device", r);
    return r;
    }
    
    r = libusb_set_configuration(devh, 1);
    if (r < 0)
    {
    ShowError("libusb_set_configuration error ", r);
    goto out;
    }
    printf("Successfully set usb configuration 1\n");
    
    r = libusb_claim_interface(devh, 0);
    if (r < 0)
    {
    ShowError("libusb_claim_interface error ", r);
    goto out;
    }
    printf("Successfully claim interface\n");
    
    r = libusb_control_transfer(devh, CTRL_OUT, HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT << 8) | 0x00, 0, question, PACKET_INT_LEN, TIMEOUT);
    if (r < 0) {
    ShowError("Control Out error ", r);
    goto out;
    }
    
    r = libusb_control_transfer(devh, CTRL_IN, HID_GET_REPORT, (HID_REPORT_TYPE_INPUT << 8) | 0x00, 0, answer, PACKET_INT_LEN, TIMEOUT);
    if (r < 0) {
    ShowError("Control In error ", r);
    goto out;
    }
    

    из:
    libusb_close (devh);
    вернуть 0;
    }

Ошибка та же, что и для прерывания чтения:
Ошибка управления выходом — ошибка ввода / вывода (LIBUSB_ERROR_IO) (GetLastError () — 1168
)

Как исправить пожалуйста? Также, как ждать пакет ACK?

Спасибо.

ОБНОВИТЬ:
Я потратил день на поиск и отладку. Так что в настоящее время моя проблема заключается только в
отправить отчет о выходе через libusb_control_transfer. Второй метод с прерыванием чтения не требуется для реализации, потому что Windows запрещает доступ для чтения с USB-устройства с использованием ReadFile.
Остался только материал libusb, вот код, который я хотел заставить работать (из третьего примера):

// sending Output report (LED)
// ...
unsigned char buf[65];
buf[0] = 1; // First byte is report number
buf[1] = 0x80;

r = libusb_control_transfer(devh, CTRL_OUT,
HID_SET_REPORT/*0x9*/, (HID_REPORT_TYPE_OUTPUT/*0x2*/ << 8) | 0x00,
0, buf, (uint16_t)2, 1000);
...

Ошибка, которую я получил:

[ 0.309018] [00001c0c] libusb: debug [_hid_set_report] Failed to Write HID Output Report: [1] Incorrect function
Control Out error  - Input/Output Error (LIBUSB_ERROR_IO) (GetLastError() - 1168)

Эта ошибка возникает сразу после DeviceIoControl позвоните в libusb.
Что значит «неправильная функция» там?

2

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]