5

USB HID Keyboard scan codes

 1 year ago
source link: https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

vv20 commented on Apr 20, 2020

niceeeee thanks

Thanks for the list!

But, I have a quick question on why are the key codes are different than the listed IDs in the table? For example, Left Shift is listed as 0xE1, but it's 0x02 here.

Author

MightyPork commented on Oct 9, 2020

@amosgwa modifiers and scan codes are a different thing, presumably you get 0xE1 when shift is pressed or released and the 0x02 modifier for keys pressed while the shift is held. though, I have not verified this.

I wrote a small Python script to parse this header file, to use its content in other programming languages.

Thanks!

I would need to send the ":" I see #define KEY_SEMICOLON 0x33 // Keyboard ; and : but when using it it always sends ";". How can I send the ":"?

Author

MightyPork commented on Nov 5, 2020

@wiwa1978 key codes are not the same as symbols. Apparently, you need to hold shift while the key is pressed. Try using the shift modifier or shift press and release events (also please comment here if you find a solution, it may help others)

benfmiller commented on Dec 4, 2020

edited

From what I understand, each time a key is pressed or released, the keyboard sends an 8 byte signal saying which keys are currently down.

    # press ctrl, press w, release w, then release all
    # These are all char's of the hex value
    press_key(KEY_MOD_LCTRL + KEY_NONE*7)
    press_key(KEY_MOD_LCTRL + KEY_NONE + KEY_W + KEY_NONE*5)
    press_key(KEY_MOD_LCTRL + KEY_NONE*7)
    press_key(KEY_NONE*8)

This works for my raspberry pi that I set up as a keyboard

My .org incest was stolen and ???

I converted them all to decimals.
It's useful for Arduino, etc.
Link

This is pretty useful!

Thank you! @MightyPork
I created a python script using the key data in this gist.
It takes some hex data from a packet capture and decodes it to output the input text.

thaolt commented on Nov 13, 2021

edited

Thank you for the sharing.

I want to share this array in case of anyone needed

#include "usb_hid_keys.h"

const char ascii_to_hid_key_map[95][2] = {
    {0, KEY_SPACE}, {KEY_MOD_LSHIFT, KEY_1}, {KEY_MOD_LSHIFT, KEY_APOSTROPHE},
    {KEY_MOD_LSHIFT, KEY_3}, {KEY_MOD_LSHIFT, KEY_4}, {KEY_MOD_LSHIFT, KEY_5},
    {KEY_MOD_LSHIFT, KEY_7}, {0, KEY_APOSTROPHE}, {KEY_MOD_LSHIFT, KEY_9},
    {KEY_MOD_LSHIFT, KEY_0}, {KEY_MOD_LSHIFT, KEY_8}, {KEY_MOD_LSHIFT, KEY_EQUAL},
    {0, KEY_COMMA}, {0, KEY_MINUS}, {0, KEY_DOT}, {0, KEY_SLASH}, {0, KEY_0},
    {0, KEY_1}, {0, KEY_2}, {0, KEY_3}, {0, KEY_4}, {0, KEY_5}, {0, KEY_6},
    {0, KEY_7}, {0, KEY_8}, {0, KEY_9}, {KEY_MOD_LSHIFT, KEY_SEMICOLON},
    {0, KEY_SEMICOLON}, {KEY_MOD_LSHIFT, KEY_COMMA}, {0, KEY_EQUAL},
    {KEY_MOD_LSHIFT, KEY_DOT}, {KEY_MOD_LSHIFT, KEY_SLASH}, {KEY_MOD_LSHIFT, KEY_2},
    {KEY_MOD_LSHIFT, KEY_A}, {KEY_MOD_LSHIFT, KEY_B}, {KEY_MOD_LSHIFT, KEY_C},
    {KEY_MOD_LSHIFT, KEY_D}, {KEY_MOD_LSHIFT, KEY_E}, {KEY_MOD_LSHIFT, KEY_F},
    {KEY_MOD_LSHIFT, KEY_G}, {KEY_MOD_LSHIFT, KEY_H}, {KEY_MOD_LSHIFT, KEY_I},
    {KEY_MOD_LSHIFT, KEY_J}, {KEY_MOD_LSHIFT, KEY_K}, {KEY_MOD_LSHIFT, KEY_L},
    {KEY_MOD_LSHIFT, KEY_M}, {KEY_MOD_LSHIFT, KEY_N}, {KEY_MOD_LSHIFT, KEY_O},
    {KEY_MOD_LSHIFT, KEY_P}, {KEY_MOD_LSHIFT, KEY_Q}, {KEY_MOD_LSHIFT, KEY_R},
    {KEY_MOD_LSHIFT, KEY_S}, {KEY_MOD_LSHIFT, KEY_T}, {KEY_MOD_LSHIFT, KEY_U},
    {KEY_MOD_LSHIFT, KEY_V}, {KEY_MOD_LSHIFT, KEY_W}, {KEY_MOD_LSHIFT, KEY_X},
    {KEY_MOD_LSHIFT, KEY_Y}, {KEY_MOD_LSHIFT, KEY_Z}, {0, KEY_LEFTBRACE},
    {0, KEY_BACKSLASH}, {0, KEY_RIGHTBRACE}, {KEY_MOD_LSHIFT, KEY_6},
    {KEY_MOD_LSHIFT, KEY_MINUS}, {0, KEY_GRAVE}, {0, KEY_A}, {0, KEY_B},
    {0, KEY_C}, {0, KEY_D}, {0, KEY_E}, {0, KEY_F}, {0, KEY_G}, {0, KEY_H},
    {0, KEY_I}, {0, KEY_J}, {0, KEY_K}, {0, KEY_L}, {0, KEY_M}, {0, KEY_N},
    {0, KEY_O}, {0, KEY_P}, {0, KEY_Q}, {0, KEY_R}, {0, KEY_S}, {0, KEY_T},
    {0, KEY_U}, {0, KEY_V}, {0, KEY_W}, {0, KEY_X}, {0, KEY_Y}, {0, KEY_Z},
    {KEY_MOD_LSHIFT, KEY_LEFTBRACE}, {KEY_MOD_LSHIFT, KEY_BACKSLASH},
    {KEY_MOD_LSHIFT, KEY_RIGHTBRACE}, {KEY_MOD_LSHIFT, KEY_GRAVE},
};

Example usage

void hid_sendch(uint8_t c)
{
    uint8_t buffer[8] = {0};

    if (c > 127) return;
    if (c < 32) return;

    c -= 32; // offset ignore the first 32 symbols in ascii table

    buffer[0] = ascii_to_hid_key_map[c][0];
    buffer[2] = ascii_to_hid_key_map[c][1];

    FILE* f = fopen("/dev/hidg0", "wb");
    fwrite(buffer, sizeof (char), 8, f);
    fclose(f);

    usleep(10000);

    buffer[0] = 0;
    buffer[2]= 0;
    f = fopen("/dev/hidg0", "wb");
    fwrite(buffer, sizeof (char), 8, f);
    fclose(f);

    usleep(50000);
}
void hid_sendstr(char* str)
{
    uint8_t l = strlen(str);
    for (uint8_t i = 0; i < l; i++) {
        hid_sendch(str[i]);
    }
}
hid_sendstr("Hello World!");

That's a handy array! ...The implicit casts between char and uint8_t are probably going to be safe in most cases (so long as you don't enable compiler warnings) ...but be careful if you call sendkey(31) ...I'm curious: Why you close the device and immediately reopen it for the second keystroke?

Thank @csBlueChip for your suggestion, I've updated it into a safer function. My application only handles printable ASCII string, thus <32 and >127 indexes is not supported. In my actual application source, there is a delay between writes. The function simulates key-press and key-release. The reason for close and reopen the before second writing is because of tried and true. I think the written buffer isn't sent until the device is closed, I'm not sure. For more information: https://randomnerdtutorials.com/raspberry-pi-zero-usb-keyboard-hid/

Sherknob commented on Feb 4

Hey, I encountered a weird behavior. All the scan codes work, except for the 'g' Key. On linux the 'g' Key is no problem and gets send and arrives correctly. On Windows, nothing arrived. Anyone any idea? Thanks :)

Sherknob commented on Feb 5

edited

Okay, on closer look after the 'g' the transmission got cut. i.e \x00\x00\x0a\x00\x00\x00\x00\x00 would result in \x00\x00\x0a. Fix was to position the 'g' in the last spot of the sequence so \x00\x00\x00\x00\x00\x00\x00\x0a. In case anyone has the same problem :)

Hi @wiwa1978 @MightyPork ,

I am interested in using the key combination of alt + f4. But I am not able to find the required solution. Any kind of help is appreciated

Thanks

I am interested in using the key combination of alt + f4. But I am not able to find the required solution. Any kind of help is appreciated

You need to do the check in two parts ...first check the modifier keys to see that KEY_MOD_LALT is (the only modifier) being pressed ...then check to see if KEY_F4 is (the only key) being pressed

This video may help you understand why: https://youtu.be/wdgULBpRoXk?t=1545

Sherknob commented on Mar 18

So maybe I can help with this. A string send over by a keyboard or for instance a rubber ducky consists of 8 bytes. The first byte is the modifier key. This value can be everything you see in the first post of this thread @line 19 - 26. You can also use combinations of modifiers by simply adding them together (LALT + LSHIFT = 0x06). So the first value of your string would be 0x04, because this is the value of left Alt. The second byte is reserved, so we'll leave it 0. Now the keys will follow. In your case the next key would be F4 (0x3d). Throwing everything into a sequence of 8 bytes and you'll get \04\0\3d\0\0\0\0\0. Don't forget to let go of all the keys by sending a string full of 0's. :))
I have made a project where I turn a linux phone into a rubber ducky using exactly this. You may have a look :)
https://github.com/Sherknob/PineDucky

Hey @Sherknob

Thanks for your response

I am currently using this library from Github. I am also using the key_code function as given here. As it is given that, the arguments to the key_code function is only integers. But the solution that you have given contains strings. How can I use that?

Thanks and regards

Sherknob commented on Mar 19

Hey @suburban-daredevil
Since the code you provided in your latest comment is pretty much uncommented and I don't have much time at hand, I think it would be great to have a look at your existing code. Is this possible?

Have a nice day :)

Sherknob commented on Mar 20

Hello @suburban-daredevil :)

Good news I think. I found the function that does, what I've been explaining in my initial comment.

int USBKeyboard::_putc(int c)
{
    return key_code(c, keymap[c].modifier);
}

Above is the function that calls key_code and returns a boolean if it was successful or not. You are using the key_code function directly, and that is okay I guess.

bool USBKeyboard::key_code(uint8_t key, uint8_t modifier)
{
    _mutex.lock();

    // Send a simulated keyboard keypress. Returns true if successful.
    HID_REPORT report;

    report.data[0] = REPORT_ID_KEYBOARD;
    report.data[1] = modifier;
    report.data[2] = 0;
    report.data[3] = keymap[key].usage;
    report.data[4] = 0;
    report.data[5] = 0;
    report.data[6] = 0;
    report.data[7] = 0;
    report.data[8] = 0;

    report.length = 9;

    if (!send(&report)) {
        _mutex.unlock();
        return false;
    }

    report.data[1] = 0;
    report.data[3] = 0;

    if (!send(&report)) {
        _mutex.unlock();
        return false;
    }

    _mutex.unlock();
    return true;

}

The function shown above it doing the thing I was explaining earlier. It is expecting a key code (in your case MY_SHUTDOWN) and a modifier value (in your case KEY_LALT). Then it is inserting these values into an array of ints. This array is the "string" I was talking of. One more thing, as you can see, keymap[key].usage is written to report.data[3]. Since you are not using a keymap you could just change keymap[key].usage to key. And this function seems to send a "let go of all keys" afterwards, so you don't need your key.key_code(KEY_NONE);.
For now, to make it simplest, you could define your key separate from your modifier. So this would be

#define KEY_LALT 0x04
#define MY_SHUTDOWN 0x3d

and then call the function with key_code(MY_SHUTDOWN, KEY_LALT);.
Note: I did not test any of this :)

Hope this helps

Hey @Sherknob

Thank you so much for your guidance

I actually found the fix through your guidance. We must actually use the index of the key that is required, f4 in our case, from the keymap table in the USBKeyboard.cpp file. The index of f4 was 131. Giving that along with the predefined KEY_ALT as modifier works as expected.

#define MY_KEY_F4 131

key.key_code(MY_KEY_F4, KEY_ALT);

Similarly any other key combinations can be used. Just find the index of the required key in the USBKeyboard.cpp file and replace the first parameter of key_code with that value and second parameter with that of the required modifier.

The predefined modifiers are KEY_CTRL, KEY_SHIFT, KEY_ALT. Please take a look here for further clarity!

Thanks to @Sherknob

Thanks and regards

Sherknob commented on Mar 20

@suburban-daredevil
Your welcome. Happy to hear that you got it working :)
Have a nice day :))

NessDan commented on Apr 1

Is there no key code for the Context Menu key (or would that be the "Props" key?)

Is there no key code for the Context Menu key (or would that be the "Props" key?)

It is #define KEY_COMPOSE 0x65 // Keyboard Application.

tomek-szczesny commented on May 3

edited

@PaddleStroke the page this came from doesn't list anything. If you have a keyboard with them, you can try catching them with xev here's something about the Fn key, maybe it'll work. https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html

Hi, this link leads to extra information about PS/2 keyboard if I'm not mistaken. I found this page as I too am seeking the keycode for display brightness and others under Fn combo.
So if anyone knows the answer, please share. :)

EDIT: Okay, found it. USB HID Usage Tables defines "Display Brightness Increment/Decrement" codes as 0x6F and 0x70 respectively, but on Consumer Page (0x0C) rather than Keyboard Page (0x07).

QQ: is this hid actions limited to android or will apply to ios as well?

I made a JSON dict version for anyone working on CTFs using Python/Javascript:

{
    "0x00":"KEY_NONE",
    "0x01":"KEY_ERR_OVF", 
    "0x04":"KEY_A", 
    "0x05":"KEY_B", 
    "0x06":"KEY_C", 
    "0x07":"KEY_D", 
    "0x08":"KEY_E", 
    "0x09":"KEY_F", 
    "0x0a":"KEY_G", 
    "0x0b":"KEY_H", 
    "0x0c":"KEY_I", 
    "0x0d":"KEY_J", 
    "0x0e":"KEY_K", 
    "0x0f":"KEY_L", 
    "0x10":"KEY_M", 
    "0x11":"KEY_N", 
    "0x12":"KEY_O", 
    "0x13":"KEY_P", 
    "0x14":"KEY_Q", 
    "0x15":"KEY_R", 
    "0x16":"KEY_S", 
    "0x17":"KEY_T", 
    "0x18":"KEY_U", 
    "0x19":"KEY_V", 
    "0x1a":"KEY_W", 
    "0x1b":"KEY_X", 
    "0x1c":"KEY_Y", 
    "0x1d":"KEY_Z", "0x1e":"KEY_1", 
    "0x1f":"KEY_2", 
    "0x20":"KEY_3", 
    "0x21":"KEY_4", 
    "0x22":"KEY_5", 
    "0x23":"KEY_6", 
    "0x24":"KEY_7", 
    "0x25":"KEY_8", 
    "0x26":"KEY_9", 
    "0x27":"KEY_0", "0x28":"KEY_ENTER", 
    "0x29":"KEY_ESC", 
    "0x2a":"KEY_BACKSPACE", 
    "0x2b":"KEY_TAB", 
    "0x2c":"KEY_SPACE", 
    "0x2d":"KEY_MINUS", 
    "0x2e":"KEY_EQUAL", 
    "0x2f":"KEY_LEFTBRACE", 
    "0x30":"KEY_RIGHTBRACE", 
    "0x31":"KEY_BACKSLASH", 
    "0x32":"KEY_HASHTILDE", 
    "0x33":"KEY_SEMICOLON", 
    "0x34":"KEY_APOSTROPHE", 
    "0x35":"KEY_GRAVE", 
    "0x36":"KEY_COMMA", 
    "0x37":"KEY_DOT", 
    "0x38":"KEY_SLASH", 
    "0x39":"KEY_CAPSLOCK", "0x3a":"KEY_F1", 
    "0x3b":"KEY_F2", 
    "0x3c":"KEY_F3", 
    "0x3d":"KEY_F4", 
    "0x3e":"KEY_F5", 
    "0x3f":"KEY_F6", 
    "0x40":"KEY_F7", 
    "0x41":"KEY_F8", 
    "0x42":"KEY_F9", 
    "0x43":"KEY_F10", 
    "0x44":"KEY_F11", 
    "0x45":"KEY_F12", "0x46":"KEY_SYSRQ", 
    "0x47":"KEY_SCROLLLOCK", 
    "0x48":"KEY_PAUSE", 
    "0x49":"KEY_INSERT", 
    "0x4a":"KEY_HOME", 
    "0x4b":"KEY_PAGEUP", 
    "0x4c":"KEY_DELETE", 
    "0x4d":"KEY_END", 
    "0x4e":"KEY_PAGEDOWN", 
    "0x4f":"KEY_RIGHT", 
    "0x50":"KEY_LEFT", 
    "0x51":"KEY_DOWN", 
    "0x52":"KEY_UP", "0x53":"KEY_NUMLOCK", 
    "0x54":"KEY_KPSLASH", 
    "0x55":"KEY_KPASTERISK", 
    "0x56":"KEY_KPMINUS", 
    "0x57":"KEY_KPPLUS", 
    "0x58":"KEY_KPENTER", 
    "0x59":"KEY_KP1", 
    "0x5a":"KEY_KP2", 
    "0x5b":"KEY_KP3", 
    "0x5c":"KEY_KP4", 
    "0x5d":"KEY_KP5", 
    "0x5e":"KEY_KP6", 
    "0x5f":"KEY_KP7", 
    "0x60":"KEY_KP8", 
    "0x61":"KEY_KP9", 
    "0x62":"KEY_KP0", 
    "0x63":"KEY_KPDOT", "0x64":"KEY_102ND", 
    "0x65":"KEY_COMPOSE", 
    "0x66":"KEY_POWER", 
    "0x67":"KEY_KPEQUAL", "0x68":"KEY_F13", 
    "0x69":"KEY_F14", 
    "0x6a":"KEY_F15", 
    "0x6b":"KEY_F16", 
    "0x6c":"KEY_F17", 
    "0x6d":"KEY_F18", 
    "0x6e":"KEY_F19", 
    "0x6f":"KEY_F20", 
    "0x70":"KEY_F21", 
    "0x71":"KEY_F22", 
    "0x72":"KEY_F23", 
    "0x73":"KEY_F24", "0x74":"KEY_OPEN", 
    "0x75":"KEY_HELP", 
    "0x76":"KEY_PROPS", 
    "0x77":"KEY_FRONT", 
    "0x78":"KEY_STOP", 
    "0x79":"KEY_AGAIN", 
    "0x7a":"KEY_UNDO", 
    "0x7b":"KEY_CUT", 
    "0x7c":"KEY_COPY", 
    "0x7d":"KEY_PASTE", 
    "0x7e":"KEY_FIND", 
    "0x7f":"KEY_MUTE", 
    "0x80":"KEY_VOLUMEUP", 
    "0x81":"KEY_VOLUMEDOWN", "0x85":"KEY_KPCOMMA", "0x87":"KEY_RO", 
    "0x88":"KEY_KATAKANAHIRAGANA", 
    "0x89":"KEY_YEN", 
    "0x8a":"KEY_HENKAN", 
    "0x8b":"KEY_MUHENKAN", 
    "0x8c":"KEY_KPJPCOMMA", "0x90":"KEY_HANGEUL", 
    "0x91":"KEY_HANJA", 
    "0x92":"KEY_KATAKANA", 
    "0x93":"KEY_HIRAGANA", 
    "0x94":"KEY_ZENKAKUHANKAKU", "0xb6":"KEY_KPLEFTPAREN", 
    "0xb7":"KEY_KPRIGHTPAREN", "0xe0":"KEY_LEFTCTRL", 
    "0xe1":"KEY_LEFTSHIFT", 
    "0xe2":"KEY_LEFTALT", 
    "0xe3":"KEY_LEFTMETA", 
    "0xe4":"KEY_RIGHTCTRL", 
    "0xe5":"KEY_RIGHTSHIFT", 
    "0xe6":"KEY_RIGHTALT", 
    "0xe7":"KEY_RIGHTMETA", "0xe8":"KEY_MEDIA_PLAYPAUSE",
    "0xe9":"KEY_MEDIA_STOPCD",
    "0xea":"KEY_MEDIA_PREVIOUSSONG",
    "0xeb":"KEY_MEDIA_NEXTSONG",
    "0xec":"KEY_MEDIA_EJECTCD",
    "0xed":"KEY_MEDIA_VOLUMEUP",
    "0xee":"KEY_MEDIA_VOLUMEDOWN",
    "0xef":"KEY_MEDIA_MUTE",
    "0xf0":"KEY_MEDIA_WWW",
    "0xf1":"KEY_MEDIA_BACK",
    "0xf2":"KEY_MEDIA_FORWARD",
    "0xf3":"KEY_MEDIA_STOP",
    "0xf4":"KEY_MEDIA_FIND",
    "0xf5":"KEY_MEDIA_SCROLLUP",
    "0xf6":"KEY_MEDIA_SCROLLDOWN",
    "0xf7":"KEY_MEDIA_EDIT",
    "0xf8":"KEY_MEDIA_SLEEP",
    "0xf9":"KEY_MEDIA_COFFEE",
    "0xfa":"KEY_MEDIA_REFRESH",
    "0xfb":"KEY_MEDIA_CALC",
}

QQ: is this hid actions limited to android or will apply to ios as well?

I've had success with the same keymap on MacOS. Can't say anything on IOS.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK