vulnerable kernel driver

This commit is contained in:
Vitaly Nikolenko 2016-01-19 22:57:11 +11:00
parent 61b1d9b35b
commit d40047300c
5 changed files with 162 additions and 1 deletions

14
Makefile Normal file
View File

@ -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

View File

@ -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 Normal file
View File

@ -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");

3
drv.h Normal file
View File

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

40
trigger.c Normal file
View File

@ -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;
}