vulnerable kernel driver

master
Vitaly Nikolenko 8 years ago
parent 61b1d9b35b
commit d40047300c

@ -0,0 +1,14 @@
obj-m += drv.o
CC=gcc
ccflags-y += "-g"
ccflags-y += "-O0"
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
# compile the trigger
$(CC) trigger.c -O2 -o trigger
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
rm -fr ./trigger

@ -1 +1,15 @@
# kernel_rop
# Linux Kernl ROP demo
This is a vulnerable Linux kernel driver used to demonstrate in-kernel
privilege escalation ROP (Return Oriented Programming) chain in practice. The
article URL for Part 1 is available at
<https://cyseclabs.com/page?n=17012016>.
The driver module is vulnerable to OOB access and allows arbitrary code
execution. An arbitrary offset can be passed from user space via the provided
ioctl(). This offset is then used as the index for the 'ops' array to obtain
the function address to be executed.
* drv.c - vulnerable kernel driver
* trigger.c - user-space application to trigger the OOB access via the provided
ioctl

90
drv.c

@ -0,0 +1,90 @@
/**
* Vulnerable kernel driver
*
* This module is vulnerable to OOB access and allows arbitrary code
* execution.
* An arbitrary offset can be passed from user space via the provided ioctl().
* This offset is then used as an index for the 'ops' array to obtain the
* function address to be executed.
*
*
* Full article: https://cyseclabs.com/page?n=17012016
*
* Author: Vitaly Nikolenko
* Email: vnik@cyseclabs.com
**/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include "drv.h"
#define DEVICE_NAME "vulndrv"
#define DEVICE_PATH "/dev/vulndrv"
static int device_open(struct inode *, struct file *);
static long device_ioctl(struct file *, unsigned int, unsigned long);
static int device_release(struct inode *, struct file *f);
static struct class *class;
unsigned long *ops[3];
static int major_no;
static struct file_operations fops = {
.open = device_open,
.release = device_release,
.unlocked_ioctl = device_ioctl
};
static int device_release(struct inode *i, struct file *f) {
printk(KERN_INFO "device released!\n");
return 0;
}
static int device_open(struct inode *i, struct file *f) {
printk(KERN_INFO "device opened!\n");
return 0;
}
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long args) {
struct drv_req *req;
void (*fn)(void);
switch(cmd) {
case 0:
req = (struct drv_req *)args;
printk(KERN_INFO "size = %lx\n", req->offset);
printk(KERN_INFO "fn is at %p\n", &ops[req->offset]);
fn = &ops[req->offset];
fn();
break;
default:
break;
}
return 0;
}
static int m_init(void) {
printk(KERN_INFO "addr(ops) = %p\n", &ops);
major_no = register_chrdev(0, DEVICE_NAME, &fops);
class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(class, NULL, MKDEV(major_no, 0), NULL, DEVICE_NAME);
return 0;
}
static void m_exit(void) {
device_destroy(class, MKDEV(major_no, 0));
class_unregister(class);
class_destroy(class);
unregister_chrdev(major_no, DEVICE_NAME);
printk(KERN_INFO "Driver unloaded\n");
}
module_init(m_init);
module_exit(m_exit);
MODULE_LICENSE("GPL");

@ -0,0 +1,3 @@
struct drv_req {
unsigned long offset;
};

@ -0,0 +1,40 @@
/**
* User-space trigger application for OOB in drv.c
*
*
* Full article: https://cyseclabs.com/page?n=17012016
*
* Author: Vitaly Nikolenko
* Email: vnik@cyseclabs.com
*
**/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "drv.h"
#define DEVICE_PATH "/dev/vulndrv"
int main(int argc, char **argv) {
int fd;
struct drv_req req;
req.offset = atoll(argv[1]);
//map = mmap((void *)..., ..., 3, 0x32, 0, 0);
fd = open(DEVICE_PATH, O_RDONLY);
if (fd == -1) {
perror("open");
}
ioctl(fd, 0, &req);
return 0;
}
Loading…
Cancel
Save