Skip to content

Commit

Permalink
Merge pull request #1 from sigseg5/ref-global
Browse files Browse the repository at this point in the history
Global refactoring: fix proper device shutdown and proc kill
  • Loading branch information
sigseg5 authored Dec 4, 2023
2 parents 96c0d2b + 6f01af9 commit e6b80e3
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 147 deletions.
23 changes: 18 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
VERSION = 5
PATCHLEVEL = 15
SUBLEVEL = 0
VERSION = 6
PATCHLEVEL = 5
SUBLEVEL = 6

# Default values
USB_VENDOR_ID ?= 0x18a5
USB_PRODUCT_ID ?= 0x0302

obj-m += kern_kill.o

ccflags-y += -fanalyzer -std=gnu11 -Wall -Werror
ccflags-y += -DUSB_VENDOR_ID=$(USB_VENDOR_ID) -DUSB_PRODUCT_ID=$(USB_PRODUCT_ID)

ifeq ($(MODE),reboot)
ccflags-y += -DMODE_REBOOT
else
ccflags-y += -DMODE_KILL
endif

obj-m += kernKill.o
ccflags-y += -fanalyzer -std=gnu11 -Wall #-pedantic

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
Expand Down
74 changes: 73 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,74 @@
# kernKill
Repo for DemHack-5

kernKill is a work-in-progress Linux kernel loadable module designed for emergency system management. It's primary function is to enable immediate shutdown or termination specific processes when a specified USB device is removed from a machine running a compatible Linux operating system.

## Warning about the USB Stack

It's important to be aware of the nuances and potential risks associated with the USB stack when using kernKill. Detailed information about these aspects is provided in the following sections.

## Configuration process

To configure kernKill, you need to know some system information about your system's USB devices. You can gather this information using the following commands:

```bash
# List all connected USB devices
lsusb

# Display driver information for USB devices
lsusb -t
```

You'll need to note USB Vendor and Product IDs. Next you should set these as environment variables with `export ...` or pass IDs like `USB_PRODUCT_ID=0xXXXX USB_VENDOR_ID=XXXX ...`. If you don't pass any IDs, the default values from the [Makefile](/Makefile) will be used.

## Building the module

### About build modes

There are two modes:

- `kill` (default) – in this mode, processes specified in [proc_list.h](/proc_list.h) are immediately killed from kernel space via SIGKILL.
- `reboot` – in this mode, the kernel module will perform `emergency_restart()` exec from kernel space.

kernKill is configurable via the [Makefile](/Makefile) included in the source code. By default, it operates in 'kill' mode, but you can switch to 'reboot' mode if necessary. Here's how to build in each mode:

```bash
# Building in 'kill' mode (default)
USB_PRODUCT_ID=0x5678 \
USB_VENDOR_ID=0x1234 \
make

# Building in 'reboot' mode
USB_PRODUCT_ID=0x5678 \
USB_VENDOR_ID=0x1234 \
make MODE=reboot
```

## Installation guide

To install kernKill, run the provided script. This installation will also disable the `uas` and `usb-storage` drivers. This is to prevent the standard usb-storage stack from taking control of the USB device. In fact, it is enough to write a udev-rule to achieve feature parity with this kernel module. But that's boring, right? :)

```bash
./install.sh
```

## Uninstallation procedure

To uninstall kernKill and revert all changes made to your system, including re-enabling the `uas` and `usb-storage` drivers, use the following command:

```bash
./rollback.sh
```

## Debugging tips

For debugging, you can monitor kernel messages related to kernKill using:

```bash
sudo dmesg | grep kernKill
```

## Additional information

Note: This module was developed during dem-hack5 and is currently not recommended for real-world use. It has been tested on the x86_64 architecture with the Linux kernel version `6.5.6-76060506-generic`. The module theoretically supports any x86/x86_64 machine with relatively modern linux kernel, but has not been extensively tested in different environments.

Always use caution and don't use it in a production environment.
16 changes: 16 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

sudo rmmod uas
if [ $? -ne 0 ]; then
echo "Error in removing uas module"
fi

sudo rmmod usb_storage
if [ $? -ne 0 ]; then
echo "Error in removing usb_storage module"
fi

sudo insmod kern_kill.ko
if [ $? -ne 0 ]; then
echo "Error in inserting kern_kill module"
fi
107 changes: 0 additions & 107 deletions kernKill.c

This file was deleted.

144 changes: 144 additions & 0 deletions kern_kill.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*******************************************************************************
* \file kern_kill.c
*
* \details kern_kill USB driver
*
* \author sigseg5
*
* \Tested on 6.5.6-76060506-generic Linux kernel
*
*******************************************************************************/

#define _GNU_SOURCE

#include <linux/reboot.h>
#include <linux/usb.h>

#include "proc_list.h"

static int usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
char serial_number[256];
if (udev->descriptor.iSerialNumber > 0)
{
int ret = usb_string(udev,
udev->descriptor.iSerialNumber,
serial_number,
sizeof(serial_number));
if (ret > 0)
{
printk(KERN_INFO "kernKill: USB device connected (Vendor ID: 0x%04X, Product ID: 0x%04X, Serial Number: %s)\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
serial_number);
}
else
{
printk(KERN_INFO "kernKill: Error retrieving USB device serial number\n");
}
}
else
{
printk(KERN_INFO "kernKill: USB device does not have a serial number\n");
}
return 0;
}

static void usb_disconnect(struct usb_interface *interface)
{
struct usb_device *udev = interface_to_usbdev(interface);
printk(KERN_INFO "kernKill: USB device disconnected (Vendor ID: 0x%04X, Product ID: 0x%04X)\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));

if (unlikely(udev->descriptor.idVendor == USB_VENDOR_ID && udev->descriptor.idProduct))
{
printk(KERN_INFO "kernKill: USB device signature matches!");

#ifdef MODE_REBOOT
emergency_restart();

// Thus, this code is only compatible with x86_64
// The __NR_REBOOT system call is used
// But it doesn't really work as expected :)

// asm volatile(
// "mov $0xa9, %al\n\t"
// "mov $0xfee1dead, %edi\n\t"
// "mov $0x28121969, %esi\n\t"
// "mov $0x4321fedc, %edx\n\t"
// "syscall\n\t");

// This for some reason disables bluetooth and the ability to correctly perform a kekw shutdown
// STP instruction (0xDB):
// STP stops the clock input of the 65C02, effectively shutting down the 65C02 until a hardware reset occurs

// asm volatile("mov $0xDB, %ax\n\t"
// "ltr %ax");
#endif

#ifdef MODE_KILL
struct task_struct *task;
for_each_process(task)
{
for (int i = 0; i < PROC_COUNT; i++)
{
if (unlikely(strcmp(task->comm, KILL_PROC[i]) == 0))
{
printk(KERN_INFO "kernKill: Matched proc: %s, pid = %d\n", task->comm, task->pid);
struct siginfo info;
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = SIGKILL;
info.si_code = SI_QUEUE;
info.si_int = 1;
if (task != NULL)
{
printk(KERN_INFO "kernKill: Sending signal to app\n");
if (send_sig_info(SIGKILL, (struct kernel_siginfo *)&info, task) < 0)
{
printk(KERN_WARNING "kernKill: Unable to send signal\n");
}
}
break;
}
}
}
#endif
}
}

static struct usb_device_id usb_table[] = {
{USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID)},
{}
};

MODULE_DEVICE_TABLE(usb, usb_table);

static struct usb_driver usb_driver = {
.name = "kern_kill",
.probe = usb_probe,
.disconnect = usb_disconnect,
.id_table = usb_table,
};

static int __init usb_notify_init(void)
{
int result = usb_register(&usb_driver);
if (result)
printk(KERN_ERR "kernKill: USB driver registration failed: %d\n", result);
return result;
}

static void __exit usb_notify_exit(void)
{
usb_deregister(&usb_driver);
}

module_init(usb_notify_init);
module_exit(usb_notify_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("sigseg5");
MODULE_DESCRIPTION("kern_kill");
MODULE_VERSION("0.1");
Loading

0 comments on commit e6b80e3

Please sign in to comment.