Skip to content

Bariskizilkaya/android-kernel-exploit-development

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 

Repository files navigation

android-kernel-exploit-development

Installing cuttlefish

sudo apt install -y git devscripts equivs config-package-dev debhelper-compat golang curl
git clone https://github.com/google/android-cuttlefish
cd android-cuttlefish
tools/buildutils/build_packages.sh
sudo dpkg -i ./cuttlefish-base_*_*64.deb || sudo apt-get install -f
sudo dpkg -i ./cuttlefish-user_*_*64.deb || sudo apt-get install -f
sudo usermod -aG kvm,cvdnetwork,render $USER
sudo reboot

Installation of libinfo5 for ubuntu 24.04 if its needed

sudo apt update
wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb
sudo apt install ./libtinfo5_6.3-2ubuntu0.1_amd64.deb

Android kernel compilation

mkdir kernel && cd kernel
repo init -u https://android.googlesource.com/kernel/manifest -b \
  common-android-mainline // or common-android14-5.15
repo sync -j
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist

After the copilation of cuttlefish we need to download artifacts

http://ci.android.com/

Download the latest build

aosp_cf_x86_64_phone-img-xxxxxx.zip
cvd-host_package.tar.gz

Under the aosp_cf_x86_64_phone Extract it as this guide says

https://source.android.com/docs/devices/cuttlefish/get-started
cvd create \
    -kernel_path=./out/virtual_device_x86_64/dist/bzImage \
    -initramfs_path=./out/virtual_device_x86_64/dist/initramfs.img

This is the run.sh's content

HOME=$PWD cvd create \
    -kernel_path=/home/asd/Documents/pixel6/aosp_cf_x86_64_phone-img-13243112/cvd-host_package/bzImage \
    -initramfs_path=/home/asd/Documents/pixel6/aosp_cf_x86_64_phone-img-13243112/cvd-host_package/initramfs.img

I added a kernel driver to the

./common/drivers/hello/hello_timer.c
./common/drivers/hello/Makefile
./common/drivers/hello/Kconfig

hello_timer.c (Prints hello world every 1 sec to the dmesg so we can check if its loaded or not)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/timer.h>

#define TIMER_INTERVAL 1  // 1 second

static struct timer_list my_timer;

// Timer callback function
static void timer_callback(struct timer_list *timer)
{
    printk(KERN_INFO "Hello, World!\n");

    // Re-arm the timer
    mod_timer(&my_timer, jiffies + HZ * TIMER_INTERVAL);
}

static int __init hello_init(void)
{
    printk(KERN_INFO "Loading Hello World Timer Module...\n");

    // Initialize and start the timer
    timer_setup(&my_timer, timer_callback, 0);
    mod_timer(&my_timer, jiffies + HZ * TIMER_INTERVAL);

    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Unloading Hello World Timer Module...\n");
    
    // Delete the timer
    del_timer(&my_timer);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Test User");
MODULE_DESCRIPTION("Kernel module that prints Hello, World! every second.");
MODULE_VERSION("1.0");

module_init(hello_init);
module_exit(hello_exit);

Makefile:

obj-m += hello_timer.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD  := $(shell pwd)

all:
        $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
        $(MAKE) -C $(KDIR) M=$(PWD) clean

Kconfig:

menuconfig HELLO_TIMER
    tristate "Hello World Timer Module"
    help
      This is a simple kernel module that prints "Hello, World!" every second.

if HELLO_TIMER
config HELLO_TIMER_DEBUG
    bool "Enable debug messages"
    default n
    help
      Enable additional debug messages in the Hello Timer module.
endif

In the /common/drivers i modified 2 files Kconfig and Makefile Kconfig:

source "drivers/hello/Kconfig"

Makefile:

obj-y                           += hello/

and build again

tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist

If the build fails dont worry find the hello_timer.ko by

find . -name hello_timer.ko

and

adb push /location/of/the/hello_timer.ko /data/local/tmp
adb root
adb shell
cd /data/local/tmp
insmod hello_timer.ko

Now we are going to put our vullnerable driver to the android kernel and compile again it will fail and we take the vuln.ko and insmod, simple

if anyone of you suceeded to the integrating the kernel driver to the kernel i would really appreciate to see your pull request ,

Our vulnerable kernel module

#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/ioctl.h>
#include <linux/slab.h>

#define DEVICE_NAME "uaf_device"
#define IOCTL_MAGIC 'U'

// IOCTL Commands
#define IOCTL_ALLOC_MEM _IO(IOCTL_MAGIC, 0)
#define IOCTL_FREE_MEM _IO(IOCTL_MAGIC, 1)
#define IOCTL_READ_MEM _IOR(IOCTL_MAGIC, 2, char *)
#define IOCTL_WRITE_MEM _IOW(IOCTL_MAGIC, 3, char *)

static int major_num = 100;  // Set the major number to 100
static char *buffer = NULL;

static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
        case IOCTL_ALLOC_MEM:
            pr_info("Allocating memory for device\n");
            buffer = kmalloc(128, GFP_KERNEL);
            if (!buffer) {
                pr_err("Memory allocation failed\n");
                return -ENOMEM;
            }
            memset(buffer, 0, 128);
            pr_info("Memory allocated at %p\n", buffer);
            break;

        case IOCTL_FREE_MEM:
            pr_info("Freeing memory\n");
            if (buffer) {
                kfree(buffer);
                pr_info("Memory freed\n");
            } else {
                pr_err("Memory not allocated yet\n");
            }
            break;

        case IOCTL_READ_MEM:
            pr_info("Reading memory\n");
            if (buffer) {
                if (copy_to_user((char *)arg, buffer, 128)) {
                    return -EFAULT;
                }
            } else {
                pr_err("Memory not allocated\n");
                return -EFAULT;
            }
            break;

        case IOCTL_WRITE_MEM:
            pr_info("Writing to memory\n");
            if (buffer) {
                if (copy_from_user(buffer, (char *)arg, 128)) {
                    return -EFAULT;
                }
                pr_info("Memory written: %s\n", buffer);
            } else {
                pr_err("Memory not allocated\n");
                return -EFAULT;
            }
            break;

        default:
            pr_err("Invalid ioctl command\n");
            return -EINVAL;
    }

    return 0;
}

static int device_open(struct inode *inode, struct file *file)
{
    pr_info("Device opened\n");
    return 0;
}

static int device_release(struct inode *inode, struct file *file)
{
    pr_info("Device closed\n");
    return 0;
}

static struct file_operations fops = {
    .open = device_open,
    .release = device_release,
    .unlocked_ioctl = device_ioctl,
};

static int __init uaf_driver_init(void)
{
    int ret;

    // Register the device with major number 100
    ret = register_chrdev(major_num, DEVICE_NAME, &fops);
    if (ret < 0) {
        pr_err("Failed to register device with major number %d\n", major_num);
        return ret;
    }

    pr_info("UAF driver registered with major number %d\n", major_num);
    return 0;
}

static void __exit uaf_driver_exit(void)
{
    if (buffer) {
        kfree(buffer);
    }
    unregister_chrdev(major_num, DEVICE_NAME);
    pr_info("UAF driver unregistered\n");
}

module_init(uaf_driver_init);
module_exit(uaf_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple UAF driver with IOCTLs and write to memory");

after insmod we need to mknod to see under the /dev folder

mknod /dev/uaf_device c 100 0

Yo ucan undo the adb root by

adb unroot

You can see that the driver is accessible now,

vsoc_x86_64:/ $ ls /dev/uaf_device
/dev/uaf_device
vsoc_x86_64:/ $ 

Change the context of the uaf_device because SELinux blocks the access to the driver Binder context is suitable for the use

adb root
adb shell
chcon u:object_r:binder_device:s0 /dev/uaf_device
chown shell:shell /dev/uaf_device
adb unroot
adb shell
cd /data/local/tmp
./uaf
vsoc_x86_64:/data/local/tmp $ ./uaf                                                                                                     
[+] Opened device /dev/uaf_device
[+] Wrote data to device: UAF Test Data
[+] Closed device, buffer should be freed now
[+] Reopened device
[+] Read from device after free: Test data in the kernel buffer
vsoc_x86_64:/data/local/tmp $ 

Now we have 100byte uaf

image

Firstly we need to find out that where the allocated object stays in the slab caches We simple spay and allocate many uaf object and see which slab cache is getting bigger.

cat /proc/slabinfo

Before image After image

Spray code

#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEVICE_PATH "/dev/uaf_device"
// IOCTL Commands
#define IOCTL_MAGIC 'U'
#define IOCTL_ALLOC_MEM _IO(IOCTL_MAGIC, 0)
#define IOCTL_FREE_MEM _IO(IOCTL_MAGIC, 1)
#define IOCTL_READ_MEM _IOR(IOCTL_MAGIC, 2, char *)
#define IOCTL_WRITE_MEM _IOW(IOCTL_MAGIC, 3, char *)

int main() {
    int fd = open(DEVICE_PATH, O_RDWR);
    if (fd < 0) {
        perror("Failed to open device");
        return -1;
    }
    for(int i = 0; i < 1000000; i++) {
    // Execute IOCTL Command 1
        ioctl(fd, IOCTL_ALLOC_MEM);
    }
 
    return 0;
}

As we can see that spraying vulnerable object is allocated in kmalloc-128 Because the uaf object is < 128 and > 64

In order to make the process easy if you get crash of your emulator create config.sh with the content as following.

adb root
adb shell insmod /data/local/tmp/hello_timer.ko
adb shell mknod /dev/uaf_device c 100 0
adb shell setenforce 0
adb shell chcon u:object_r:system_app:s0 /dev/uaf_device
adb shell setenforce 1
adb shell chown shell:shell /dev/uaf_device
adb unroot

Eventhough alot of attempts are made for to getting the right permission i couldnt succedded so that i will disable SELinux to continue to playing around. :(

adb root
setenforce 0
adb unroot

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published