This repository is meant to serve as a hands on guide to Linux kernel exploitation with a special interest in Android. All the resources you need for setting up an exploitation play ground will be explained below. Each folder should have it's own challenge in the form of a loadable kernel module, it's own solution - code that will be executed from userspace to take advantage of the vulnerability (usually to gain us root), and a bit of a writeup about the vulnerability and the exploit.
I am hoping that this will serve as a jumpstart for people to get started with kernel exploitation as well as a learning exercise for myself. Feel free to fork and submit pull reqs for new challenges, documentations, etc..
git clone https://android.googlesource.com/platform/external/elfutils git clone https://android.googlesource.com/platform/prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.6 cp elfutils/0.153/libelf/elf.h /usr/local/include
git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6
The patch we are applying to the emulator kernel enables debugging symbols and builds our vulnerabilities into the kernel tree. ```
git clone https://android.googlesource.com/kernel/goldfish && \ git clone [email protected]:Fuzion24/AndroidKernelExploitation.git kernelexploitchallenges && \ cd goldfish && git checkout -t origin/android-goldfish-3.4 && \ git am --signoff < ../kernelexploitchallenges/kernelbuild/debugsymbolsandchallenges.patch && \ cd .. && ln -s $(pwd)/kernelexploitchallenges/ goldfish/drivers/vulnerabilities ```
export ARCH=arm SUBARCH=arm CROSS_COMPILE=arm-linux-androideabi- &&\ export PATH=$(pwd)/arm-linux-androideabi-4.6/bin/:$PATH && \ cd goldfish && make goldfish_armv7_defconfig && make -j8
android create avd --force -t "Google Inc.:Google APIs:19" -n kernel_challenges
emulator -show-kernel -kernel arch/arm/boot/zImage -avd kernel_challenges -no-boot-anim -no-skin -no-audio -no-window -qemu -monitor unix:/tmp/qemuSocket,server,nowait -s
While in the goldfish folder,
You should see something like the following:
GNU gdb (GDB) 7.3.1-gg2 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-apple-darwin --target=arm-linux-android". For bug reporting instructions, please see: ... Reading symbols from /goldfish/vmlinux...done. (gdb)
Connect to the running emulator:
(gdb) target remote :1234 Remote debugging using :1234 cpu_v7_do_idle () at arch/arm/mm/proc-v7.S:74 74 mov pc, lr (gdb)
If you see this, then congrats! You're up and running!
Once we have managed to cause some memory corruption that we can control, we usually need to know where some of the symbols (pointers to functions, fields, structures, etc..) are located in memory. There exists a kernel proc entry which lists all of the symbols and their locations. This information can be read from userspace from the file located at
/proc/kallsyms. There is a proc interface kallsyms which names the exported kernel symbol as well as the address at which it is located.
In recent kernel versions, in order to make exploitation of kernel bugs more difficult, the kernel has restricted these symbols for viewing only by those with CAPSYSADMIN privledeges. You can read the semantics of kptr_restrict submitted by Dan Rosenberg, et al. here and with respect to Android here.
Reading kallsyms with kptr restrict enabled:
adb shell cat /proc/kallsyms | grep commit_creds 00000000 T commit_creds
In order for this exploit to resolve symbols, you need to `
adb shell su -c "echo 0 > /proc/sys/kernel/kptr_restrict"
And now we can properly see the kernel symbols and their addresses:
adb shell cat /proc/kallsyms | grep commit_creds c008e138 T commit_creds
We will make the assumption that we know the location of all kernel symbols. While this not strictly true in practice, it is fairly safe to assume that we will be able to access to kernel symbols one way or another. Locations of items in memory change with every compilation of the kernel. OEMs build a kernel for each device/product and that kernel is used across all instances of that device (the kernel can change with sytem upgrades, different regions of the phone, small hardware changes in same device). If you can obtain the OTA update, factory image, etc for the device, you can extract the necessary symbols in a static manner. Also, if you are able to obtain root on the device in some other manner (unlocked bootloaders, an 0-day you are holding, etc), you can use that to bootsrap yourself to get the necessary symbols