xkeysnail is yet another keyboard remapping tool for X environment written in Python

Overview

xkeysnail

xkeysnail is yet another keyboard remapping tool for X environment written in Python. It's like xmodmap but allows more flexible remappings.

screenshot

  • Pros
    • Has high-level and flexible remapping mechanisms, such as
      • per-application keybindings can be defined
      • multiple stroke keybindings can be defined such as Ctrl+x Ctrl+c to Ctrl+q
      • not only key remapping but arbitrary commands defined by Python can be bound to a key
    • Runs in low-level layer (evdev and uinput), making remapping work in almost all the places
  • Cons
    • Runs in root-mode (requires sudo)

The key remapping mechanism of xkeysnail is based on pykeymacs (https://github.com/DreaminginCodeZH/pykeymacs).

Installation

Requires root privilege and Python 3.

Ubuntu

sudo apt install python3-pip
sudo pip3 install xkeysnail

# If you plan to compile from source
sudo apt install python3-dev

Fedora

sudo dnf install python3-pip
sudo pip3 install xkeysnail
# Add your user to input group if you don't want to run xkeysnail
# with sudo (log out and log in again to apply group change)
sudo usermod -a -G input $USER

# If you plan to compile from source
sudo dnf install python3-devel

Manjaro/Arch

# Some distros will need to compile evdev components 
# and may fail to do so if gcc is not installed.
sudo pacman -Syy
sudo pacman -S gcc

Solus

# Some distros will need to compile evdev components 
# and may fail to do so if gcc is not installed.
sudo eopkg install gcc
sudo eopkg install -c system.devel

From source

git clone --depth 1 https://github.com/mooz/xkeysnail.git
cd xkeysnail
sudo pip3 install --upgrade .

Usage

sudo xkeysnail config.py

When you encounter the errors like Xlib.error.DisplayConnectionError: Can't connect to display ":0.0": b'No protocol specified\n' , try

xhost +SI:localuser:root
sudo xkeysnail config.py

If you want to specify keyboard devices, use --devices option:

sudo xkeysnail config.py --devices /dev/input/event3 'Topre Corporation HHKB Professional'

If you have hot-plugging keyboards, use --watch option.

If you want to suppress output of key events, use -q / --quiet option especially when running as a daemon.

How to prepare config.py?

(If you just need Emacs-like keybindings, consider to use example/config.py, which contains Emacs-like keybindings).

Configuration file is a Python script that consists of several keymaps defined by define_keymap(condition, mappings, name)

define_keymap(condition, mappings, name)

Defines a keymap consists of mappings, which is activated when the condition is satisfied.

Argument condition specifies the condition of activating the mappings on an application and takes one of the following forms:

  • Regular expression (e.g., re.compile("YYY"))
    • Activates the mappings if the pattern YYY matches the WM_CLASS of the application.
    • Case Insensitivity matching against WM_CLASS via re.IGNORECASE (e.g. re.compile('Gnome-terminal', re.IGNORECASE))
  • lambda wm_class: some_condition(wm_class)
    • Activates the mappings if the WM_CLASS of the application satisfies the condition specified by the lambda function.
    • Case Insensitivity matching via casefold() or lambda wm_class: wm_class.casefold() (see example below to see how to compare to a list of names)
  • None: Refers to no condition. None-specified keymap will be a global keymap and is always enabled.

Argument mappings is a dictionary in the form of {key: command, key2: command2, ...} where key and command take following forms:

  • key: Key to override specified by K("YYY")
  • command: one of the followings
    • K("YYY"): Dispatch custom key to the application.
    • [command1, command2, ...]: Execute commands sequentially.
    • { ... }: Sub-keymap. Used to define multiple stroke keybindings. See multiple stroke keys for details.
    • pass_through_key: Pass through key to the application. Useful to override the global mappings behavior on certain applications.
    • escape_next_key: Escape next key.
    • Arbitrary function: The function is executed and the returned value is used as a command.
      • Can be used to invoke UNIX commands.

Argument name specifies the keymap name. This is an optional argument.

Key Specification

Key specification in a keymap is in a form of K("( -)* ") where

is one of the followings

  • C or Ctrl -> Control key
  • M or Alt -> Alt key
  • Shift -> Shift key
  • Super or Win -> Super/Windows key

You can specify left/right modifiers by adding any one of prefixes L/R.

And is a key whose name is defined in key.py.

Here is a list of key specification examples:

  • K("C-M-j"): Ctrl + Alt + j
  • K("Ctrl-m"): Ctrl + m
  • K("Win-o"): Super/Windows + o
  • K("M-Shift-comma"): Alt + Shift + comma (= Alt + >)

Multiple stroke keys

When you needs multiple stroke keys, define nested keymap. For example, the following example remaps C-x C-c to C-q.

define_keymap(None, {
    K("C-x"): {
      K("C-c"): K("C-q"),
      K("C-f"): K("C-q"),
    }
})

Checking an application's WM_CLASS with xprop

To check WM_CLASS of the application you want to have custom keymap, use xprop command:

xprop WM_CLASS

and then click the application. xprop tells WM_CLASS of the application as follows.

WM_CLASS(STRING) = "Navigator", "Firefox"

Use the second value (in this case Firefox) as the WM_CLASS value in your config.py.

Example config.py

See example/config.py.

Here is an excerpt of example/config.py.

from xkeysnail.transform import *

define_keymap(re.compile("Firefox|Google-chrome"), {
    # Ctrl+Alt+j/k to switch next/previous tab
    K("C-M-j"): K("C-TAB"),
    K("C-M-k"): K("C-Shift-TAB"),
}, "Firefox and Chrome")

define_keymap(re.compile("Zeal"), {
    # Ctrl+s to focus search area
    K("C-s"): K("C-k"),
}, "Zeal")

define_keymap(lambda wm_class: wm_class not in ("Emacs", "URxvt"), {
    # Cancel
    K("C-g"): [K("esc"), set_mark(False)],
    # Escape
    K("C-q"): escape_next_key,
    # C-x YYY
    K("C-x"): {
        # C-x h (select all)
        K("h"): [K("C-home"), K("C-a"), set_mark(True)],
        # C-x C-f (open)
        K("C-f"): K("C-o"),
        # C-x C-s (save)
        K("C-s"): K("C-s"),
        # C-x k (kill tab)
        K("k"): K("C-f4"),
        # C-x C-c (exit)
        K("C-c"): K("M-f4"),
        # cancel
        K("C-g"): pass_through_key,
        # C-x u (undo)
        K("u"): [K("C-z"), set_mark(False)],
    }
}, "Emacs-like keys")

Example of Case Insensitivity Matching

terminals = ["gnome-terminal","konsole","io.elementary.terminal","sakura"]
terminals = [term.casefold() for term in terminals]
termStr = "|".join(str(x) for x in terminals)

# [Conditional modmap] Change modifier keys in certain applications
define_conditional_modmap(lambda wm_class: wm_class.casefold() not in terminals,{
    # Default Mac/Win
    Key.LEFT_ALT: Key.RIGHT_CTRL,   # WinMac
    Key.LEFT_META: Key.LEFT_ALT,    # WinMac
    Key.LEFT_CTRL: Key.LEFT_META,   # WinMac
    Key.RIGHT_ALT: Key.RIGHT_CTRL,  # WinMac
    Key.RIGHT_META: Key.RIGHT_ALT,  # WinMac
    Key.RIGHT_CTRL: Key.RIGHT_META, # WinMac
})

# [Conditional modmap] Change modifier keys in certain applications
define_conditional_modmap(re.compile(termStr, re.IGNORECASE), {

    # Default Mac/Win
    Key.LEFT_ALT: Key.RIGHT_CTRL,   # WinMac
    Key.LEFT_META: Key.LEFT_ALT,    # WinMac
    Key.LEFT_CTRL: Key.LEFT_CTRL,   # WinMac
    Key.RIGHT_ALT: Key.RIGHT_CTRL,  # WinMac
    Key.RIGHT_META: Key.RIGHT_ALT,  # WinMac
    Key.RIGHT_CTRL: Key.LEFT_CTRL,  # WinMac
})

FAQ

How do I fix Firefox capturing Alt before xkeysnail?

In the Firefox location bar, go to about:config, search for ui.key.menuAccessKeyFocuses, and set the Value to false.

License

xkeysnail is distributed under GPL.

xkeysnail
Copyright (C) 2018 Masafumi Oyamada

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
   
   .

xkeysnail is based on pykeymacs (https://github.com/DreaminginCodeZH/pykeymacs), which is distributed under GPL.

pykeymacs
Copyright (C) 2015 Zhang Hai

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
   
   .
Owner
Masafumi Oyamada
Masafumi Oyamada
PyFUD - Fully Undetectable payload generator for metasploit

PyFUD fully Undetectable payload generator for metasploit Usage: pyfud.py --host

3 Mar 25, 2022
Delta Sharing: An Open Protocol for Secure Data Sharing

Delta Sharing: An Open Protocol for Secure Data Sharing Delta Sharing is an open protocol for secure real-time exchange of large datasets, which enabl

Delta Lake 497 Jan 02, 2023
Strapi Framework Vulnerable to Remote Code Execution

CVE-2019-19609 Strapi Framework Vulnerable to Remote Code Execution well, I didnt found any exploit for CVE-2019-19609 so I wrote one. :/ Usage pytho

Dasith Vidanage 7 Mar 08, 2022
Meterpreter Reverse shell over TOR network using hidden services

Poiana Reverse shell over TOR network using hidden services Features - Create a hidden service - Generate non-staged payload (python/meterpreter_rev

calfcrusher 80 Dec 21, 2022
JS Deobfuscation is a Python script that deobfuscate JS code and it's time saver for you.

JS Deobfuscation is a Python script that deobfuscate JS code and it's time saver for you. Although it may not work with high degrees of obfuscation, it's a pretty nice tool to help you even if it's j

Quatrecentquatre 3 May 01, 2022
CVE-2021-22986 & F5 BIG-IP RCE

Vuln Impact This vulnerability allows for unauthenticated attackers with network access to the iControl REST interface, through the BIG-IP management

Al1ex 85 Dec 02, 2022
CVE-2021-26855: PoC (Not a HoneyPoC for once!)

Exch-CVE-2021-26855 ProxyLogon is the formally generic name for CVE-2021-26855, a vulnerability on Microsoft Exchange Server that allows an attacker b

ZephrFish 24 Nov 14, 2022
😭 WSOB is a python tool created to exploit the new vulnerability on WSO2 assigned as CVE-2022-29464.

😭 WSOB (CVE-2022-29464) 😭 WSOB is a python tool created to exploit the new vulnerability on WSO2 assigned as CVE-2022-29464. CVE-2022-29464 details:

0p 25 Oct 14, 2022
Industry ready custom API payload with an easy format for building Python APIs (Django/Django Rest Framework)

Industry ready custom API payload with an easy format for building Python APIs (Django/Django Rest Framework) Yosh! If you are a django backend develo

Abram (^o^) 7 Sep 30, 2022
Passphrase-wordlist - Shameless clone of passphrase wordlist

This repository is NOT official -- the original repository is located on GitLab

Jeff McJunkin 2 Feb 05, 2022
利用NTLM Hash读取Exchange邮件

GetMail 利用NTLM Hash读取Exchange邮件:在进行内网渗透时候,我们经常拿到的是账号的Hash凭据而不是明文口令。在这种情况下采用邮件客户端或者WEBMAIL的方式读取邮件就很麻烦,需要进行破解,NTLM的破解主要依靠字典强度,破解概率并不是很大。

<a href=[email protected]"> 388 Dec 27, 2022
Security tool to test different bypass of forbidden

notForbidden Security tool to test different bypass of forbidden Usage python3 notForbidden.py URL Features Bypass with different methods (POST, OPT

6 Sep 08, 2022
Acc-Data-Gen - Allows you to generate a password, e-mail & token for your Minecraft Account

Acc-Data-Gen Allows you to generate a password, e-mail & token for your Minecraft Account How to use the generator: Move all the files in a single dir

KarmaBait 2 May 16, 2022
Brute-Force-Connected

Brute-Force-Connected Guess the password for Connected accounts the use : Create a new file and put usernames and passwords in it Example : joker:1234

4 Jun 05, 2022
RDP Stealer

RDP Stealer RDP Stealer by lamp Require Python How To Use Download This Source Extract The Zip File Change webhook url Convert to exe send to target I

Lamp 14 Nov 26, 2022
orfipy is a tool written in python/cython to extract ORFs in an extremely and fast and flexible manner

Introduction orfipy is a tool written in python/cython to extract ORFs in an extremely and fast and flexible manner. Other popular ORF searching tools

Urminder Singh 34 Nov 21, 2022
Let's you scan the entire internet in a couple of hours and identify all Minecraft servers on IPV4

Minecraft-Server-Scanner Let's you scan the entire internet in a couple of hours and identify all Minecraft servers on IPV4 Installation and running i

116 Jan 08, 2023
Jolokia Exploitation Toolkit (JET) helps exploitation of exposed jolokia endpoints.

jolokia-exploitation-toolkit Jolokia Exploitation Toolkit (JET) helps exploitation of exposed jolokia endpoints. Core concept Jolokia is a protocol br

Laluka 194 Jan 01, 2023
AnonStress-Stored-XSS-Exploit - An exploit and demonstration on how to exploit a Stored XSS vulnerability in anonstress

AnonStress Stored XSS Exploit An exploit and demonstration on how to exploit a S

صلى الله على محمد وآله 3 Jun 22, 2022
ssh-audit is a tool for ssh server & client configuration auditing.

SSH server & client auditing (banner, key exchange, encryption, mac, compression, compatibility, security, etc)

Joe Testa 1.4k Dec 31, 2022