¿Hay alguna forma de que una aplicación que se ejecuta en una PC sepa si una entrada de teclado es el resultado de presionar realmente el teclado de la PC?

En los días de DOS, cualquier aplicación podía determinar el origen de la entrada porque estaba accediendo al hardware directamente.

Por lo tanto, un programador podría determinar si la entrada de texto provenía del puerto del teclado o (la alternativa más probable) del puerto RS-232C.

Esto no significa que tales máquinas fueran infalibles. Muchos escáneres de códigos de barras se insertan entre el teclado y la PC. La PC no tiene forma de determinar si las pulsaciones de teclas que ingresaron a través del puerto fueron generadas por el teclado o el escáner. Un programa que inserte directamente “código macro” en el búfer del BIOS dejaría una aplicación igual de desorientada.

En Windows moderno, a la mayoría de las aplicaciones no les importa. Windows administra múltiples dispositivos (incluidos varios teclados) y presenta todos los datos a la aplicación activa de una manera, con suerte, coherente. Si todavía usa un escáner de código de barras que intercepta un teclado PS / 2, el software aún no podrá notar la diferencia. Si todo es solo USB, entonces el software puede interrogar a la API de Windows sobre qué dispositivo USB generó datos específicos. Una aplicación que presta atención a la identificación USB de un dispositivo son las macros HID. HM reasignará teclados específicos de acuerdo con sus ID. Puede tener su teclado principal para escribir en general, y un par de teclados reasignados para comandos especiales. Solo funcionarán los teclados que se hayan reasignado: el intercambio de uno por otro perderá el mapa y deberá reasignarse en HM.

Tenga en cuenta que las macros HID han sido descontinuadas. El autor lo desarrolló como un proyecto completamente de código abierto y ahora se está moviendo a una plataforma diferente para desarrollar una alternativa más nueva.

Por lo tanto, una solicitud cuidadosamente escrita para, por ejemplo, una empresa de manejo de carga podría tener dos o más ventanas abiertas. La entrada del código de barras se enrutará automáticamente a la ventana correcta, y la ventana de texto del operador permanecerá intacta o completamente actualizada al nuevo producto.

Para la mayoría de los sistemas operativos y aplicaciones modernos, no. En teoría, las aplicaciones podrían hacer algunas cosas para tratar de garantizar que las pulsaciones de teclas provengan realmente de los teclados. Sin embargo, generalmente hay varias capas de abstracción entre la aplicación y el teclado. Esas capas están ahí para permitir que los programadores de aplicaciones no se preocupen de dónde provienen las pulsaciones de teclas, y en su mayoría no hacen nada para evitar esas capas de abstracción.

Es una de las principales virtudes del buen diseño dejar que cada capa haga lo que hace mejor, y simplemente usar los métodos prescritos para comunicarse entre capas. Uno de los conceptos más elegantes que Unix y Linux trajeron a la mesa fue la idea de entrada estándar y salida estándar, y la capacidad de reorganizar esas cosas independientemente de las aplicaciones que las usan. Por lo tanto, los programadores de aplicaciones tenían la costumbre de leer desde la entrada estándar y escribir en la salida estándar. Los programas podrían entonces interconectarse, para producir una aplicación general más grande. Este concepto también se aplica de otras maneras. Un servidor X proporciona pulsaciones de teclas. Una aplicación de cliente X solo escucha la entrada del teclado en el servidor X y supone que el servidor X proporciona la entrada del teclado desde un teclado. Dudo que haya algún mecanismo en X para permitir que una aplicación inspeccione el verdadero origen de la entrada del teclado.

Aún así, existen mecanismos que permiten que los programas de aplicaciones al menos intenten acercarse al verdadero teclado. Cuando ejecuta el comando de inicio de sesión (o más probablemente, cuando un servidor SSH lo ejecuta por usted), la parte de entrada de contraseña del código evita deliberadamente que la secuencia de entrada estándar lea las pulsaciones de teclas. Esto se hace para evitar que las contraseñas sean redirigidas desde los archivos de datos donde serían visibles, y porque el flujo de entrada estándar haría eco de los datos en un terminal donde sería visible y, por lo tanto, menos seguro. Las aplicaciones GUI usan un mecanismo comparable.

Entonces, ¿qué es realmente un teclado? La mayoría de las computadoras (PC al menos) utilizan entradas USB para obtener datos de pulsación de teclas. El subsistema USB consulta los dispositivos USB que se conectan al sistema, y ​​cuando un dispositivo responde que es un teclado, no hay más autenticación para verificar que el dispositivo es en realidad un teclado. Por lo tanto, esto permite que el hardware que se comporta como un teclado interactúe con una computadora, aunque en realidad no lo sea. Y no hay ningún mecanismo que pueda filtrar los posers. No es muy difícil usar un Arduino de $ 10 para interactuar con un host USB como si fuera un teclado completo.

En sistemas operativos más antiguos como MS-DOS que no tenían protección de memoria, era posible leer y escribir las interfaces de palanca baja y la cola de datos del teclado. En ese escenario, a veces era posible distinguir entre las pulsaciones de teclas falsas y las reales. Algunas aplicaciones hicieron eso, pero como realmente no tenían que “comportarse”, en realidad no importaba mucho. Se realizó principalmente por razones de rendimiento.

Todo lo que la aplicación sabe es que la entrada del teclado se colocó en el búfer del teclado. No tiene forma de saber si fue colocado allí por la rutina de servicio del teclado o por otro proceso de “relleno” (escritura directa en) el búfer. Esto fue mucho más fácil en los días de MS-DOS, cuando se conocía la dirección del búfer y sus punteros. En Windows y Linux probablemente requiera un alto nivel de privilegio.

No si se implementa utilizando la API estándar para la entrada de teclado. Si está haciendo lo contrario, no es una aplicación estándar, pero está profundizando en las capas inferiores de cómo se maneja la E / S. Normalmente no esperarías esto, ya que hay pocas razones para hacerlo.

Tendría que interceptar las llaves a medida que entran en el puerto USB y luego devolverlas a la placa base todo lo rápido que sea posible para evitar un retraso.

No creo que haya otra manera de estar seguro de que se utilizó un teclado real.

Usando C # (y supongo que C ++) puede conectar la interrupción del teclado. No le diré exactamente cómo, porque podría usar ese conocimiento para escribir un registrador de claves. Se llama a esta interrupción cuando se escanea un código clave. Esto estaría más cerca de lo que desea, pero no sería una respuesta completa, ya que un programa de nivel de ensamblaje puede llamar fácilmente a la misma interrupción.