Tutorial: How to use kloak with USB keyboards

NOTE: This is my first forum post and I can’t figure out how to remove the code blocks. Assume the code blocks shouldn’t be there and the file contents include portions before and after the code block.

While experimenting, I found a way to use kloak with usb keyboards if anyone’s interested. This might work with some modifications for PS/2 keyboards, but my laptop has a built-in usb keyboard so I don’t have a way to test that and it would require running kloak in dom0, which is not ideal.

Using the script I made, it will work with several usb keyboards at once and will work if you unplug and plug back in a keyboard (should detect the new keyboard plugged in within 5 seconds).

This method will run kloak in sys-usb, so it will apply to all qubes while it is active, you can’t have it apply to only specific qubes.

This guide is assuming a static disposable sys-usb based off fedora-36-dvm. I also tried fedora-34, but kloak doesn’t run in fedora-34 because the version of libc is too old.

If at some point, you don’t want this running anymore and want it to go back to not using kloak, just remove the line that will be added to bashrc later to have it stop running the script at sys-usb startup, and then restart sys-usb.

Steps:

Run fedora-36-dvm (not a disposable based off it)

Open a disposable qube based off fedora-36

Install kernel-devel in the disposable qube:
sudo dnf -y install kernel-devel

(you can also install kernel-devel in the fedora template first if you want, but you only need kernel-devel temporarily for the compilation)

Follow the instructions on kloak’s github page to compile it from source in the disposable qube: https://github.com/vmonaco/kloak

Copy the compiled kloak executable to fedora-36-dvm in the /home/user/ directory.

Create a new file called getdevicename.c with the following contents in the disposable qube:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <termios.h>
#include <signal.h>

#include <linux/input.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>

void usage() {
    fprintf(stderr, "Usage: eventcap <device>\n");
    exit(1);
}

int main(int argc, char *argv[]) {
    struct input_event ev;
    int fd;
    char name[256] = "Unknown";
    char *device = NULL;

    if (argv[1] == NULL) {
        usage();
    }

    if ((getuid()) != 0)
        printf("You are not root! This may not work...\n");

    if (argc > 1)
        device = argv[1];

    //Open Device
    if ((fd = open(device, O_RDONLY)) == -1) {
        fprintf(stderr, "%s is not a valid device\n", device);
        exit(1);
    }

    //Print Device Name
    ioctl(fd, EVIOCGNAME(sizeof(name)), name);
    printf("%s", name);

}

(this file is the same as the eventcap file from the kloak repository just with a few lines changed)

compile getdevicename and make sure the executable is in the /home/user/ directory in fedora-36-dvm:

gcc getdevicename.c -o getdevicename

copy the getdevicename executable to the /home/user/ directory in fedora-36-dvm

In the /home/user/ directory of fedora-36-dvm, create a file called newkloakscript with the following contents:

#!/bin/bash

#max delay between keystrokes passed to kloak
delay=70

hostname | grep -q sys-usb

# if not running in sys-usb*
if [ $? -ne 0 ]
then
  exit
fi

lockfile="/tmp/newkloakscriptlockfile"
if [ -e $lockfile ]
then
  echo "script already running, exiting"
  exit
else
  sudo touch $lockfile
fi

while true
do
    sleep 5
    services=$(systemctl list-units --state running | grep qubes-input-sender-keyboard | awk '{print $1}')

    for service in $services
    do
        device=$(systemctl status $service | grep "/usr/bin/qrexec-client-vm dom0 qubes.InputKeyboard /usr/bin/input-proxy-sender" | awk '{print $7}')
        devicename=$(sudo ./getdevicename $device)

        echo $devicename | grep -qi keyboard

        # if the device name contains keyboard in it
        if [ $? -eq 0 ]
        then
            echo "$(date) running kloak for device $device, stopping service $service" >> /home/user/newkloakscriptlog
            sudo systemctl stop $service
            sudo /home/user/./kloak -d $delay -v -r $device & > /dev/null 2> /dev/null
        fi

    done

done

make the newkloakscript file executable:
chmod +x newkloakscript

At this point, you just need newkloakscript to run at startup. This can be done with a systemd unit file or by running the script at the end of bashrc. I went with the bashrc method because I’m too lazy to make a unit file.

At the end of the /home/user/.bashrc in fedora-36-dvm add the following line:

/home/user/./newkloakscript &

Reboot sys-usb

What this script does is first checks to see if the qube it’s running in is sys-ub, exits if not. Then checks to see if an instance of the script is already running using a lock file at /tmp/newkloakscriptlockfile, exits if it is. Then loops endlessly checking each instance of the qubes-input-sender services, checks to see which it they are using, checks to see if it’s a keyboard based off the devicename, then kills the qubes-input-sender service and replaces it with kloak. After kloak is started, a new qubes-input-sender service will be started for the output of kloak automatically.

Since it continuously checks, it should work regardless of the number of usb keyboards plugged in, and should catch new usb keyboards plugged in within 5 seconds. You can change the max keystroke delay passed to kloak by changing the value of the delay variable in the newkloakscript. When it’s activating kloak for a new usb keyboard, it will log an entry to /home/user/newkloakscriptlog. That line can be removed from the script if you don’t want the

There are definitely better ways to accomplish this, but it works.

2 Likes

Welcome to the Qubes OS world, I updated your post with fancy code blocks…

1 Like

Thank you very much!

Good job @TheChunkyBoi1990 !

This might be a promising extension for Whonix Workstation qubes. Currently, docs state following:

Qubes-Whonix ™ is unfortunately unsupported.

Might be useful to relativize this statement and link this tutorial in their docs.

@adrelanos Any thoughts on this?

1 Like

Edited a bit just now.
(Improve the Documentation / Edit the Whonix ™ Wiki)

3 Likes

The 70 max ms delay in the script is what I found I could use without noticing too much of a difference in how I type, but that delay still has a decent match on the keytrac demo, so I would recommend periodically increasing the delay as you get used to it.

1 Like

Is it possible to install kloak into the Qubes GUI daemon VM? (sys-gui) and then use this VM for all user I/O?

Upon reflection, this seems to complex for a forum or wiki page. It would have to be contributed (pull requests) to the upstream source code repositories.

Step 1, the C program seems useful to contribute to kloak upstream?

@adrelanos

I’ve been working on a tool to obfuscate mouse movements and realized the method of detecting whether a device is a keyboard/mouse based on the name isn’t very reliable, so I’m testing some other methods. Detecting whether it’s running in qubes would also be useful.

Once I have more I’ll definitely make a pull request.

I haven’t tried the gui vm yet, but I don’t think it would work with usb devices since the device files will still be located in sys-usb. You might be able to mount the usb controller in sys-gui instead of sys-usb, but that’s likely very dangerous.

Kloak has git branch that does “a lot mouse” obfuscation. (Mouse movements but not yet clicks as far as I can see.) References:

But kloak development seems slow, stalled. Could use another upstream if you’re up for that.

I think the idea is to use a ProxyVM between the Sys-USB VM and the Sys-GUI VM its not a direct link.
And yeah the tough part is locating and connecting the I/O interface, because sometimes the 0-7 option does not show a clear connection to the keyboard or mouse.

Are they suggesting using ChatGPT for biometrics obfuscation? Could it be used to inject randomness?
Could it be used for cryptography?

No. Different topics.

versus

I wonder if ChatGPT could be used to produce chains of command bytes that would increase the noise level of keyboard and mouse I/O

No, that makes zero sense. ChatGPT is a non-freedom web service. Big server. Thin client. All source code is only known to OpenAI. Even if it was Open Source, it wouldn’t be very useful without the gigantic database and vastly huge datacenter. ChatGPT can only be used with account, which means that 1 company can log all outputs and correlate to the same account. That’s just a few technical blockers. There’s probably more.

Also it would violate Whonix policy on non-freedom software. Therefore not going to happen.

Qubes might have a similar policy (in fact it doesn’t bundle unnecessary non-freedom “high-level” applications) but I don’t know if it is written down similarly, considered too obvious to write down or just “out of habit”.

Furthermore, kloak (or any application) currently does not suffer from low entropy. That’s just a non-issue. I don’t think there are currently critical low entropy issues. Theoretic issues and things that could be implemented better yes, but no critical issues specifucally. More on entropy:

This is getting off-topic for this forum topic. Therefore I would kindly request to move this discussion into a separate forum thread.

So there would need to be a FOSS version of ChatGPT due to its proprietary nature.

And for starters, it would have to run locally, not on somebody else’s remote server. (Speed, privacy, security.)

kloak and AI is mostly unrelated.

  • :no_entry_sign: No: AI being a magic solution for everything.
  • :white_check_mark: Yes: AI being helpful in some cases.

chatgpt has been useful for source code review (chatgpt by adrelanos · Pull Request #49 · vmonaco/kloak · GitHub) but that’s about it. There’s no reason to directly combine kloak with AI. Only “normal” programming required. Nothing fancy.

Could someone please explain what kloak actually is?

From the OP: https://github.com/vmonaco/kloak