Beispiel #1
0
static void limsw_exit( void)
{
  // Gracefully handle exit
  for (int i = 0 ; i < nr_limits ; ++i) {
    if (gpio_fd[ i]) {
      close( gpio_fd[ i]);
      gpio_fd[ i] = -1;
    }
    gpio_write_value_to_pin_file( limit_gpios[ i], "edge", "none");
    if (get_kernel_type() == e_kernel_3_2) {
      gpio_write_int_value_to_file( "unexport", limit_gpios[ i]);
    }
  }
}
Beispiel #2
0
int64_t 
find_sysent(const uint8_t *buffer, const uint64_t data_address, const uint64_t data_size)
{
#if DEBUG
    printf("[DEBUG] Executing %s\n", __FUNCTION__);
#endif
    uint64_t i = 0;
    if (get_kernel_type()) // 64 bits
    {
        while (i < data_size)
        {
            struct sysent64 *table = (struct sysent64*)(&buffer[i]);
            if(table[SYS_exit].sy_narg      == 1 &&
               table[SYS_fork].sy_narg      == 0 &&
               table[SYS_read].sy_narg      == 3 &&
               table[SYS_wait4].sy_narg     == 4 &&
               table[SYS_ptrace].sy_narg    == 4 &&
               table[SYS_getxattr].sy_narg  == 6 &&
               table[SYS_listxattr].sy_narg == 4 &&
               table[SYS_recvmsg].sy_narg   == 3 )
            {
                printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call);
                return(data_address+i);
            }
            i++;
        }
    }
    else // 32bits
    {
        while (i < data_size)
        {
            struct sysent *table = (struct sysent*)(&buffer[i]);
            if(table[SYS_exit].sy_narg      == 1 &&
               table[SYS_fork].sy_narg      == 0 &&
               table[SYS_read].sy_narg      == 3 &&
               table[SYS_wait4].sy_narg     == 4 &&
               table[SYS_ptrace].sy_narg    == 4 &&
               table[SYS_getxattr].sy_narg  == 6 &&
               table[SYS_listxattr].sy_narg == 4 &&
               table[SYS_recvmsg].sy_narg   == 3 )
            {
                printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call);
                return(data_address+i);
            }
            i++;
        }
    }
    return(0);
}
Beispiel #3
0
int64_t 
find_sysent(const uint8_t *buffer, const uint64_t data_address, const uint64_t data_size)
{
    uint64_t i = 0;
    if (get_kernel_type()) // 64 bits
    {
        int major = get_kernel_version();

        /* Mavericks or higher uses new sysent table format */
        if (major >= 13)
        {
            while (i < data_size)
            {
                struct newsysent *table = (struct newsysent*)(&buffer[i]);
                if(table[SYS_exit].sy_narg      == 1 &&
                   table[SYS_fork].sy_narg      == 0 &&
                   table[SYS_read].sy_narg      == 3 &&
                   table[SYS_wait4].sy_narg     == 4 &&
                   table[SYS_ptrace].sy_narg    == 4 &&
                   table[SYS_getxattr].sy_narg  == 6 &&
                   table[SYS_listxattr].sy_narg == 4 &&
                   table[SYS_recvmsg].sy_narg   == 3 )
                {
                    printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call);
                    return(data_address+i);
                }
                i++;
            }
        }
        else
        {
            while (i < data_size)
            {
                struct sysent64 *table = (struct sysent64*)(&buffer[i]);
                if(table[SYS_exit].sy_narg      == 1 &&
                   table[SYS_fork].sy_narg      == 0 &&
                   table[SYS_read].sy_narg      == 3 &&
                   table[SYS_wait4].sy_narg     == 4 &&
                   table[SYS_ptrace].sy_narg    == 4 &&
                   table[SYS_getxattr].sy_narg  == 6 &&
                   table[SYS_listxattr].sy_narg == 4 &&
                   table[SYS_recvmsg].sy_narg   == 3 )
                {
                    printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call);
                    return(data_address+i);
                }
                i++;
            }
        }
    }
    else // 32bits
    {
        while (i < data_size)
        {
            struct sysent *table = (struct sysent*)(&buffer[i]);
            if(table[SYS_exit].sy_narg      == 1 &&
               table[SYS_fork].sy_narg      == 0 &&
               table[SYS_read].sy_narg      == 3 &&
               table[SYS_wait4].sy_narg     == 4 &&
               table[SYS_ptrace].sy_narg    == 4 &&
               table[SYS_getxattr].sy_narg  == 6 &&
               table[SYS_listxattr].sy_narg == 4 &&
               table[SYS_recvmsg].sy_narg   == 3 )
            {
                printf("[DEBUG] exit() address is %p\n", (void*)table[SYS_exit].sy_call);
                return(data_address+i);
            }
            i++;
        }
    }
    return(0);
}
Beispiel #4
0
int
main(int argc, char ** argv)
{
    int option = 0;
    struct config cfg = {0};

    header();
    if (argc < 2)
    {
        usage();
    }
        
    while( (option=getopt(argc,argv,"ha:Aco:Ci:rRs")) != -1 )
    {
        switch(option)
        {
            case 'h':
                usage();
                exit(1);
            case 'a':
                cfg.interrupt = atoi(optarg);
                break;
            case 'A': 
                cfg.show_all_descriptors = 1;
                break;
            case 'c': 
                cfg.create_file_archive = 1;
                break;
            case 'r': 
                cfg.read_file_archive = 1;
                break;
            case 'R': 
                cfg.restore_idt = 1;
                break;
            case 'o':
                if(strlen(optarg) > MAXPATHLEN - 1)
                {
                    ERROR_MSG("File name too long.");
                    return -1;
                }
                strncpy(cfg.out_filename, optarg, sizeof(cfg.out_filename));
                break;
            case 'C': 
                cfg.compare_idt = 1;
                break;
            case 'i': 
                if(strlen(optarg) > MAXPATHLEN - 1)
                {
                    ERROR_MSG("File name too long.");
                    return -1;
                }
                strncpy(cfg.in_filename, optarg, sizeof(cfg.in_filename));
                break;
            case 's': 
                cfg.resolve = 1;
                break;
        }
    }
    OUTPUT_MSG("");
    
    if (getuid() != 0)
    {
        ERROR_MSG("This program needs to be run as root!");
        return -1;
    }
    
    cfg.kernel_type = get_kernel_type();
    if (cfg.kernel_type == -1)
    {
        ERROR_MSG("Unable to retrieve kernel type.");
        return -1;
    }
    else if (cfg.kernel_type == X86)
    {
        ERROR_MSG("32 bits kernels not supported.");
        return -1;
    }
    
    cfg.idt_addr = get_addr_idt(cfg.kernel_type);
    cfg.idt_size = get_size_idt();
    cfg.idt_entries = cfg.idt_size / sizeof(struct descriptor_idt);
    /* we need to populate the size variable else syscall fails */
    cfg.kaslr_size = sizeof(cfg.kaslr_size);
    get_kaslr_slide(&cfg.kaslr_size, &cfg.kaslr_slide);
    
    OUTPUT_MSG("[INFO] Kaslr slide is 0x%llx", cfg.kaslr_slide);
    OUTPUT_MSG("[INFO] IDT base address is: 0x%llx", cfg.idt_addr);
    OUTPUT_MSG("[INFO] IDT size: 0x%x\n", cfg.idt_size);

    /* test if we can read kernel memory using processor_set_tasks() vulnerability */
    /* vulnerability presented at BlackHat Asia 2014 by Ming-chieh Pan, Sung-ting Tsai. */
    /* also described in Mac OS X and iOS Internals, page 387 */
    host_t host_port = mach_host_self();
    mach_port_t proc_set_default = 0;
    mach_port_t proc_set_default_control = 0;
    task_array_t all_tasks = NULL;
    mach_msg_type_number_t all_tasks_cnt = 0;
    kern_return_t kr = 0;
    int valid_kernel_port = 0;
    
    kr = processor_set_default(host_port, &proc_set_default);
    if (kr == KERN_SUCCESS)
    {
        kr = host_processor_set_priv(host_port, proc_set_default, &proc_set_default_control);
        if (kr == KERN_SUCCESS)
        {
            kr = processor_set_tasks(proc_set_default_control, &all_tasks, &all_tasks_cnt);
            if (kr == KERN_SUCCESS)
            {
                DEBUG_MSG("Found valid kernel port using processor_set_tasks() vulnerability!");
                cfg.kernel_port = all_tasks[0];
                valid_kernel_port = 1;
            }
        }
    }
    /* if we can't use the vulnerability then try /dev/kmem */
    if (valid_kernel_port == 0)
    {
        if( (cfg.fd_kmem = open("/dev/kmem",O_RDWR)) == -1 )
        {
            ERROR_MSG("Error while opening /dev/kmem. Is /dev/kmem enabled?");
            ERROR_MSG("Verify that /Library/Preferences/SystemConfiguration/com.apple.Boot.plist has kmem=1 parameter configured.");
            return -1;
        }
    }
    
    if (cfg.resolve == 1)
    {
        retrieve_kernel_symbols(&cfg);
    }
    
    if(cfg.interrupt >= 0 || cfg.show_all_descriptors == 1)
    {
        show_idt_info(&cfg);
    }
    if(cfg.create_file_archive == 1)
    {
        create_idt_archive(&cfg);
    }
    if(cfg.read_file_archive == 1)
    {
        read_idt_archive(&cfg);
    }
    if(cfg.compare_idt == 1)
    {
        compare_idt(&cfg);
    }
    if(cfg.restore_idt == 1)
    {
        compare_idt(&cfg);
    }
    return 0;
}
Beispiel #5
0
static void* limsw_watcher( void* arg)
{
  int i;
  unsigned int gpio[ nr_limits];
  char buf[ 3];
  int len;

  if (debug_flags & DEBUG_LIMSW) {
    printf( "Limit switches watcher thread: opening fds");
  }

  for (i = 0 ; i < nr_limits ; ++i) {
    gpio[ i] = limit_gpios[ i];
    if (get_kernel_type() == e_kernel_3_2) {
      gpio_write_int_value_to_file( "export", gpio[ i]);
      gpio_write_value_to_pin_file( gpio[ i], "direction", "in");
    }
    gpio_write_value_to_pin_file( gpio[ i], "edge", "both");
    gpio_fd[ i] = gpio_open_file( gpio[ i], "value");
    if (gpio_fd[ i] < 0) {
      fprintf( stderr, ", open failed for gpio%d, bailing out\n", gpio[ i]);
      pthread_exit( NULL);
    }
  }
  atexit( limsw_exit);
  for (i = 0 ; i < nr_limits ; ++i) {
    (*fdset)[ i].fd = gpio_fd[ i];
    (*fdset)[ i].events = POLLPRI;
  }
  if (debug_flags & DEBUG_LIMSW) {
    printf( ", start polling on:");
    for (i = 0 ; i < nr_limits ; ++i) {
      printf( " gpio%d", gpio[ i]);
    }
    printf( "\n");
  }

  while (1) {
    const int timeout = -1;     /* no timeout */

    int rc = poll( *fdset, nr_limits, timeout);      
    if (rc < 0) {
      if (errno == EINTR) {
        continue;
      }
      perror( "limsw_watcher: poll() failed, bailing out!");
      break;
    }
    if (rc == 0) {
      // poll timeout, shouldn't happen with 'timeout' == -1 !!!
      fprintf( stderr, "\nlimsw_watcher: poll() unexpected timeout, bailing out!\n");
      break;
    }
    for (i = 0 ; i < nr_limits ; ++i) {
      if ((*fdset)[ i].revents & POLLPRI) {
        int state = 0;
        len = read( (*fdset)[ i].fd, buf, sizeof( buf));
        if (len == 2 && (buf[ 0] == '0' || buf[ 0] == '1')) {
          // Get initial state info
          state = buf[ 0] - '0';
          if (debug_flags & DEBUG_LIMSW) {
            printf( "*** GPIO %2d event, state %d ***\n", gpio[ i], state);
          }
        } else {
          fprintf( stderr, "\n*** GPIO %2d unexpected event, BUG??? ***\n", gpio[ i]);
        }
        switch (gpio[ i]) {
        case XMIN_GPIO: x_min_state = state; break;
        case XMAX_GPIO: x_max_state = state; break;
        case YMIN_GPIO: y_min_state = state; break;
        case YMAX_GPIO: y_max_state = state; break;
        case ZMIN_GPIO: z_min_state = state; break;
        case ZMAX_GPIO: z_max_state = state; break;
        }
        lseek( (*fdset)[ i].fd, 0, SEEK_SET);
      }
    }
  }
  pthread_exit( NULL);
}
Beispiel #6
0
int
main(int argc, char ** argv)
{
    	
	header();
    	
	// we need to run this as root
	if (getuid() != 0)
	{
		printf("[ERROR] Please run me as root!\n");
		exit(1);
	}
	
	int8_t kernel_type = get_kernel_type();
	if (kernel_type == -1)
	{
		printf("[ERROR] Unable to retrieve kernel type!\n");
		exit(1);
	}
	
	if((fd_kmem = open("/dev/kmem",O_RDWR)) == -1)
	{
		fprintf(stderr,"[ERROR] Error while opening /dev/kmem. Is /dev/kmem enabled?\n");
		fprintf(stderr,"Add parameter kmem=1 to /Library/Preferences/SystemConfiguration/com.apple.Boot.plist\n");
		exit(1);
	}
	    
	// retrieve int80 address
    idt_t idt_address = get_addr_idt(kernel_type);
    uint64_t int80_address = calculate_int80address(idt_address, kernel_type);
    
    uint64_t kernel_base = find_kernel_base(int80_address, kernel_type);
    if (kernel_base == 0)
    {
        fprintf(stderr, "[ERROR] Could not find kernel base address!\n");
        exit(1);
    }
    uint64_t data_address = 0;
    uint64_t data_size    = 0;
    
    process_header(kernel_base, &data_address, &data_size);
    
    uint8_t *read = malloc((size_t)data_size);
	if (read == NULL)
    {
        printf("[ERROR] Memory allocation failed!\n");
        exit(1);
    }

	// read kernel memory and find sysent
    readkmem(fd_kmem, read, data_address, (size_t)data_size);
    uint64_t sysent_address = find_sysent(read, data_address, data_size);
    
    if (sysent_address)
    {
        printf("[OK] Found sysent address at %p\n",(void*)sysent_address);
    }
    else
    {
        printf("[ERROR] Could not found sysent address!\n");
    }

    free(read);
	return 0;
}