Kernel-exploitation

decompress.sh

Extract file from CPIO archive

#!/bin/sh
mkdir fs
cd fs
cp ../initramfs.cpio.gz ./initramfs.cpio.gz
gunzip ./initramfs.cpio.gz
cpio -idm < ./initramfs.cpio
rm initramfs.cpio
cd ..

compress.sh

Compile the exploit, add it to fs, and run.

#!/bin/sh
gcc -w -o exploit -static exploit.c -pthread -lrt &&\
# musl-gcc -w -s -static -o3 exploit.c -o exploit -masm=intel &&\
mv exploit ./fs/ &&\
cd fs &&\
find . -print0 | cpio --owner root --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz &&\
cd .. &&\
# gunzip -f initramfs.cpio.gz &&\
./run.sh

In case ext4 filesystem archive

mount ./initramfs.cpio.gz ./fs/

Useful strcutures

ldt_struct - modify_ldt syscall

0x20 size struct, contains no checks for copy_to_user call

msg_msg

struct msg_msg {
    struct list_head m_list;
    long m_type;
    size_t m_ts;        /* message text size */
    struct msg_msgseg *next;
    void *security;
    /* the actual message follows immediately */
};

User msg stored right after msg_msg structure uptil 0x1000 - 0x30 after that singly linked list of chunks stored in struct msg_msgseg *next with size of each allocation upto 0x1000, is and should be NULL terminated. For arbitrary read: overwrite next and m_ts to be such that, it has to read from overwritten next pointer.

For arbitrary write:

msgsnd()        // Userland
    do_msgsnd() // Kernel land
        load_msg()  
            alloc_msg()         // Allocate all the necessary chunks
            copy_from_user()    // Race here to replace `struct msg_msgseg *next` before its used to copy userdata. Maybe use userfaultfd ;)

msg_msg do_msgsnd load_msg copy_msg

Misc

To restrict the process to run on specific CPU

cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(0,&cpu_set);
ret=sched_setaffinity(0,sizeof(cpu_set),&cpu_set);

References