コード例 #1
0
int main(int argc, char **argv)
{
  unsigned int nb_threads = 1;
  pthread_t *decryption_threads;
  char *filename;
  unsigned int **indexes;
  int fd, i, ret, c;
  struct stat file_stats;

  OpenSSL_add_all_algorithms();

  /* Get options and parameters */
  opterr = 0;
  while((c = getopt(argc, argv, "1aB:b:c:d:e:hL:l:M:m:Ns:t:")) != -1)
    switch(c)
      {
      case '1':
        only_one_password = 1;
        break;

      case 'a':
        list_algorithms();
        exit(EXIT_FAILURE);
        break;

      case 'B':
        binary = optarg;
        break;

      case 'b':
        prefix = optarg;
        break;

      case 'c':
        cipher = EVP_get_cipherbyname(optarg);
        if(cipher == NULL)
          {
            fprintf(stderr, "Error: unknown cipher: %s.\n\n", optarg);
            exit(EXIT_FAILURE);
          }
        break;

      case 'd':
        digest = EVP_get_digestbyname(optarg);
        if(digest == NULL)
          {
            fprintf(stderr, "Error: unknown digest: %s.\n\n", optarg);
            exit(EXIT_FAILURE);
          }
        break;

      case 'e':
        suffix = optarg;
        break;

      case 'h':
        usage(argv[0]);
        exit(EXIT_FAILURE);
        break;

      case 'L':
        limit = (long unsigned int) atol(optarg);
        break;

      case 'l':
        min_len = (unsigned int) atoi(optarg);
        break;

      case 'M':
        magic = optarg;
        break;

      case 'm':
        max_len = (unsigned int) atoi(optarg);
        break;

      case 'N':
        no_error = 1;
        break;

      case 's':
        charset = optarg;
        break;

      case 't':
        nb_threads = (unsigned int) atoi(optarg);
        if(nb_threads == 0)
          nb_threads = 1;
        break;

      default:
        usage(argv[0]);
        switch(optopt)
          {
          case 'B':
          case 'b':
          case 'c':
          case 'd':
          case 'e':
          case 'L':
          case 'l':
          case 'M':
          case 'm':
          case 's':
          case 't':
            fprintf(stderr, "Error: missing argument for option: '-%c'.\n\n", optopt);
            break;

          default:
            fprintf(stderr, "Error: unknown option: '%c'.\n\n", optopt);
            break;
          }
        exit(EXIT_FAILURE);
        break;
      }

  if(optind >= argc)
    {
      usage(argv[0]);
      fprintf(stderr, "Error: missing filename.\n\n");
      exit(EXIT_FAILURE);
    }

  filename = argv[optind];

  /* Check variables */
  if(cipher == NULL)
    cipher = EVP_aes_256_cbc();
  if(digest == NULL)
    digest = EVP_md5();
  if(prefix == NULL)
    prefix = "";
  prefix_len = strlen(prefix);
  if(suffix == NULL)
    suffix = "";
  suffix_len = strlen(suffix);
  if(charset && binary)
    {
      fprintf(stderr, "Error: options -B and -s can't be both set.\n\n");
      exit(EXIT_FAILURE);
    }
  else if(binary)
    charset = binary_charset;
  else if(charset == NULL)
    charset = default_charset;
  charset_len = strlen(charset);
  if(charset_len == 0)
    {
      fprintf(stderr, "Error: charset must have at least one character.\n\n");
      exit(EXIT_FAILURE);
    }
  if(nb_threads > charset_len)
    {
      fprintf(stderr, "Warning: number of threads (%u) bigger than character set length (%u). Only using %u threads.\n\n", nb_threads, charset_len, charset_len);
      nb_threads = charset_len;
    }
  if(min_len < prefix_len + suffix_len + 1)
    {
      fprintf(stderr, "Warning: minimum length (%u) isn't bigger than the length of specified password characters (%u). Setting minimum length to %u.\n\n", min_len, prefix_len + suffix_len, prefix_len + suffix_len + 1);
      min_len = prefix_len + suffix_len + 1;
    }
  if(max_len < min_len)
    {
      fprintf(stderr, "Warning: maximum length (%u) is smaller than minimum length (%u). Setting maximum length to %u.\n\n", max_len, min_len, min_len);
      max_len = min_len;
    }

  /* Check header */
  fd = open(filename, O_RDONLY);
  if(fd == -1)
    {
      perror("open file");
      exit(EXIT_FAILURE);
    }
  memset(salt, 0, sizeof(salt));
  ret = read(fd, salt, 8);
  if(strncmp(salt, "Salted__", 8) != 0)
    {
      close(fd);
      fprintf(stderr, "Error: %s is not a salted openssl file.\n\n", filename);
      exit(EXIT_FAILURE);
    }

  /* Read salt */
  ret = read(fd, salt, 8);
  if(ret != 8)
    {
      close(fd);
      fprintf(stderr, "Error: could not read salt.\n\n");
      exit(EXIT_FAILURE);
    }

  /* Read encrypted data */
  ret = fstat(fd, &file_stats);
  data_len = file_stats.st_size - 16;
  data = (char *) malloc(data_len);
  if(data == NULL)
    {
      fprintf(stderr, "Error: memory allocation failed.\n\n");
      exit(EXIT_FAILURE);
    }
  for(i = 0; i < data_len;)
    {
      ret = read(fd, data + i, data_len - i);
      if(ret == -1)
        {
          close(fd);
          fprintf(stderr, "Error: could not read data.\n\n");
          exit(EXIT_FAILURE);
        }
      else if(ret > 0)
        i += ret;
    }
  close(fd);

  pthread_mutex_init(&found_password_lock, NULL);
  
  /* Start decryption threads */
  decryption_threads = (pthread_t *) malloc(nb_threads * sizeof(pthread_t));
  indexes = (unsigned int **) malloc(nb_threads * sizeof(unsigned int *));
  if((decryption_threads == NULL) || (indexes == NULL))
    {
      fprintf(stderr, "Error: memory allocation failed.\n\n");
      exit(EXIT_FAILURE);
    }
  for(i = 0; i < nb_threads; i++)
    {
      indexes[i] = (unsigned int *) malloc(2 * sizeof(unsigned int));
      if(indexes[i] == NULL)
        {
          fprintf(stderr, "Error: memory allocation failed.\n\n");
          exit(EXIT_FAILURE);
        }
      indexes[i][0] = i * (charset_len / nb_threads);
      if(i == nb_threads - 1)
        indexes[i][1] = charset_len - 1;
      else
        indexes[i][1] = (i + 1) * (charset_len / nb_threads) - 1;
      ret = pthread_create(&decryption_threads[i], NULL, &decryption_func, indexes[i]);
      if(ret != 0)
        {
          perror("decryption thread");
          exit(EXIT_FAILURE);
        }
    }

  for(i = 0; i < nb_threads; i++)
    {
      pthread_join(decryption_threads[i], NULL);
      free(indexes[i]);
    }
  free(indexes);
  free(decryption_threads);
  pthread_mutex_destroy(&found_password_lock);
  free(data);
  EVP_cleanup();

  exit(EXIT_SUCCESS);
}
コード例 #2
0
int main(int argc, char **argv)
{
  pthread_t *decryption_threads;
  char *filename;
  int fd, i, ret, c;
  struct stat file_stats;

  setlocale(LC_ALL, "");
  OpenSSL_add_all_algorithms();

  /* Get options and parameters */
  opterr = 0;
  while((c = getopt(argc, argv, "1aB:b:c:d:e:f:hL:l:M:m:Nns:t:v:w:")) != -1)
    switch(c)
    {
    case '1':
      only_one_password = 1;
      break;

    case 'a':
      list_algorithms();
      exit(EXIT_FAILURE);
      break;

    case 'B':
      binary = optarg;
      break;

    case 'b':
      prefix_len = mbstowcs(NULL, optarg, 0);
      if(prefix_len == (unsigned int) -1)
      {
        fprintf(stderr, "Error: invalid character in prefix.\n\n");
        exit(EXIT_FAILURE);
      }
      prefix = (wchar_t *) calloc(prefix_len + 1, sizeof(wchar_t));
      if(prefix == NULL)
      {
        fprintf(stderr, "Error: memory allocation failed.\n\n");
        exit(EXIT_FAILURE);
      }
      mbstowcs(prefix, optarg, prefix_len + 1);
      break;

    case 'c':
      cipher = EVP_get_cipherbyname(optarg);
      if(cipher == NULL)
      {
        fprintf(stderr, "Error: unknown cipher: %s.\n\n", optarg);
        exit(EXIT_FAILURE);
      }
      break;

    case 'd':
      digest = EVP_get_digestbyname(optarg);
      if(digest == NULL)
      {
        fprintf(stderr, "Error: unknown digest: %s.\n\n", optarg);
        exit(EXIT_FAILURE);
      }
      break;

    case 'e':
      suffix_len = mbstowcs(NULL, optarg, 0);
      if(suffix_len == (unsigned int) -1)
      {
        fprintf(stderr, "Error: invalid character in suffix.\n\n");
        exit(EXIT_FAILURE);
      }
      suffix = (wchar_t *) calloc(suffix_len + 1, sizeof(wchar_t));
      if(suffix == NULL)
      {
        fprintf(stderr, "Error: memory allocation failed.\n\n");
        exit(EXIT_FAILURE);
      }
      mbstowcs(suffix, optarg, suffix_len + 1);
      break;

    case 'f':
      dictionary = fopen(optarg, "r");
      if(dictionary == NULL)
      {
        fprintf(stderr, "Error: can't open dictionary file.\n\n");
        exit(EXIT_FAILURE);
      }
      break;

    case 'h':
      usage(argv[0]);
      exit(EXIT_FAILURE);
      break;

    case 'L':
      limit = (long unsigned int) atol(optarg);
      break;

    case 'l':
      min_len = (unsigned int) atoi(optarg);
      break;

    case 'M':
      magic = optarg;
      break;

    case 'm':
      max_len = (unsigned int) atoi(optarg);
      break;

    case 'N':
      no_error = 1;
      break;

    case 'n':
      no_salt = 1;
      break;

    case 's':
      charset_len = mbstowcs(NULL, optarg, 0);
      if(charset_len == 0)
      {
        fprintf(stderr, "Error: charset must have at least one character.\n\n");
        exit(EXIT_FAILURE);
      }
      if(charset_len == (unsigned int) -1)
      {
        fprintf(stderr, "Error: invalid character in charset.\n\n");
        exit(EXIT_FAILURE);
      }
      charset = (wchar_t *) calloc(charset_len + 1, sizeof(wchar_t));
      if(charset == NULL)
      {
        fprintf(stderr, "Error: memory allocation failed.\n\n");
        exit(EXIT_FAILURE);
      }
      mbstowcs(charset, optarg, charset_len + 1);
      break;

    case 't':
      nb_threads = (unsigned int) atoi(optarg);
      if(nb_threads == 0)
        nb_threads = 1;
      break;

    case 'v':
      status_interval = (unsigned int) atoi(optarg);
      break;

    case 'w':
      state_file = optarg;
      break;

    default:
      usage(argv[0]);
      switch(optopt)
      {
      case 'B':
      case 'b':
      case 'c':
      case 'd':
      case 'e':
      case 'f':
      case 'L':
      case 'l':
      case 'M':
      case 'm':
      case 's':
      case 't':
      case 'v':
      case 'w':
        fprintf(stderr, "Error: missing argument for option: '-%c'.\n\n", optopt);
        break;

      default:
        fprintf(stderr, "Error: unknown option: '%c'.\n\n", optopt);
        break;
      }
      exit(EXIT_FAILURE);
      break;
    }

  if(optind >= argc)
  {
    usage(argv[0]);
    fprintf(stderr, "Error: missing filename.\n\n");
    exit(EXIT_FAILURE);
  }

  filename = argv[optind];

  /* Check variables */
  if(cipher == NULL)
    cipher = EVP_aes_256_cbc();
  if(digest == NULL)
    digest = EVP_md5();
  if(dictionary != NULL)
  {
    fprintf(stderr, "Warning: using dictionary mode, ignoring options -b, -e, -l, -m and -s.\n\n");
  }
  else
  {
    if(prefix == NULL)
    {
      prefix_len = mbstowcs(NULL, "", 0);
      prefix = (wchar_t *) calloc(prefix_len + 1, sizeof(wchar_t));
      if(prefix == NULL)
      {
        fprintf(stderr, "Error: memory allocation failed.\n\n");
        exit(EXIT_FAILURE);
      }
      mbstowcs(prefix, "", prefix_len + 1);
    }
    if(suffix == NULL)
    {
      suffix_len = mbstowcs(NULL, "", 0);
      suffix = (wchar_t *) calloc(suffix_len + 1, sizeof(wchar_t));
      if(suffix == NULL)
      {
        fprintf(stderr, "Error: memory allocation failed.\n\n");
        exit(EXIT_FAILURE);
      }
      mbstowcs(suffix, "", suffix_len + 1);
    }
    if(charset && binary)
    {
      fprintf(stderr, "Error: options -B and -s can't be both set.\n\n");
      exit(EXIT_FAILURE);
    }
    else if(binary)
    {
      charset_len = strlen(binary_charset);
      prefix_len = wcstombs(NULL, prefix, 0);
      suffix_len = wcstombs(NULL, suffix, 0);
    }
    else if(charset == NULL)
    {
      charset_len = mbstowcs(NULL, default_charset, 0);
      charset = (wchar_t *) calloc(charset_len + 1, sizeof(wchar_t));
      if(charset == NULL)
      {
        fprintf(stderr, "Error: memory allocation failed.\n\n");
        exit(EXIT_FAILURE);
      }
      mbstowcs(charset, default_charset, charset_len + 1);
    }
    if(charset_len == 0)
    {
      fprintf(stderr, "Error: charset must have at least one character.\n\n");
      exit(EXIT_FAILURE);
    }
    if(min_len < prefix_len + suffix_len + 1)
    {
      fprintf(stderr, "Warning: minimum length (%u) isn't bigger than the length of specified password characters (%u). Setting minimum length to %u.\n\n", min_len, prefix_len + suffix_len, prefix_len + suffix_len + 1);
      min_len = prefix_len + suffix_len + 1;
    }
    if(max_len < min_len)
    {
      fprintf(stderr, "Warning: maximum length (%u) is smaller than minimum length (%u). Setting maximum length to %u.\n\n", max_len, min_len, min_len);
      max_len = min_len;
    }
  }

  last_pass[0] = '\0';

  /* Check header */
  fd = open(filename, O_RDONLY);
  if(fd == -1)
  {
    perror("open file");
    exit(EXIT_FAILURE);
  }
  if(no_salt == 0)
  {
    memset(salt, 0, sizeof(salt));
    ret = read(fd, salt, 8);
    if(strncmp(salt, "Salted__", 8) != 0)
    {
      close(fd);
      fprintf(stderr, "Error: %s is not a salted openssl file.\n\n", filename);
      exit(EXIT_FAILURE);
    }

    /* Read salt */
    ret = read(fd, salt, 8);
    if(ret != 8)
    {
      close(fd);
      fprintf(stderr, "Error: could not read salt.\n\n");
      exit(EXIT_FAILURE);
    }
  }

  /* Read encrypted data */
  ret = fstat(fd, &file_stats);
  if(no_salt)
    data_len = file_stats.st_size;
  else
    data_len = file_stats.st_size - 16;
  data = (char *) malloc(data_len);
  if(data == NULL)
  {
    fprintf(stderr, "Error: memory allocation failed.\n\n");
    exit(EXIT_FAILURE);
  }
  for(i = 0; i < data_len;)
  {
    ret = read(fd, data + i, data_len - i);
    if(ret == -1)
    {
      close(fd);
      fprintf(stderr, "Error: could not read data.\n\n");
      exit(EXIT_FAILURE);
    }
    else if(ret > 0)
      i += ret;
  }
  close(fd);

  signal(SIGUSR1, handle_signal);
  if(status_interval > 0)
  {
    signal(SIGALRM, handle_signal);
    progress_timer.it_value.tv_sec = status_interval;
    progress_timer.it_value.tv_usec = 0;
    progress_timer.it_interval.tv_sec = status_interval;
    progress_timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &progress_timer, NULL);
  }

  pthread_mutex_init(&found_password_lock, NULL);
  pthread_mutex_init(&get_password_lock, NULL);
  
  decryption_threads = (pthread_t *) malloc(nb_threads * sizeof(pthread_t));
  thread_locals = (struct decryption_func_locals *) calloc(nb_threads, sizeof(struct decryption_func_locals));
  if((decryption_threads == NULL) || (thread_locals == NULL))
  {
    fprintf(stderr, "Error: memory allocation failed.\n\n");
    exit(EXIT_FAILURE);
  }

  start_time = time(NULL);

  if(state_file != NULL)
  {
    restore_state();

    signal(SIGVTALRM, save_state);
    state_timer.it_value.tv_sec = 60 * nb_threads;
    state_timer.it_value.tv_usec = 0;
    state_timer.it_interval.tv_sec = 60 * nb_threads;
    state_timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_VIRTUAL, &state_timer, NULL);
  }

  /* Start decryption threads */
  for(i = 0; i < nb_threads; i++)
  {
    ret = pthread_create(&decryption_threads[i], NULL, &decryption_func, &thread_locals[i]);
    if(ret != 0)
    {
      perror("Error: decryption thread");
      exit(EXIT_FAILURE);
    }
  }

  for(i = 0; i < nb_threads; i++)
  {
    pthread_join(decryption_threads[i], NULL);
  }
  if(found_password == 0)
  {
    handle_signal(SIGUSR1); /* Print some stats */
    fprintf(stderr, "Password not found\n");
  }

  free(thread_locals);
  free(decryption_threads);
  pthread_mutex_destroy(&found_password_lock);
  pthread_mutex_destroy(&get_password_lock);
  free(data);
  EVP_cleanup();

  exit(EXIT_SUCCESS);
}