Kirokyri

C8

Nov 27th, 2020
749
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5.  
  6. #include <unistd.h>
  7. #include <crypt.h>
  8. #include <time.h>
  9.  
  10. #include <pthread.h>
  11. #include <semaphore.h>
  12.  
  13. typedef enum
  14. {
  15.     BM_ITER,
  16.     BM_REC,
  17. } brute_mode_t;
  18.  
  19. typedef enum                                                                //
  20. {
  21.     RM_SINGLE,
  22.     RM_MULTI,
  23. } run_mode_t;
  24.  
  25. typedef struct config_t {
  26.     brute_mode_t brute_mode;
  27.     run_mode_t run_mode;                                              //
  28.     int length;
  29.     char * alphabet;
  30.     char * hash;
  31. } config_t;
  32.  
  33. typedef struct task_t {
  34.     char password[8];
  35. } task_t;
  36.  
  37. typedef struct queue_t {
  38.     task_t queue[8];
  39.     int head, tail;
  40.     pthread_mutex_t head_mutex, tail_mutex;
  41.     sem_t empty, full;
  42. } queue_t;
  43.  
  44. typedef struct {
  45.     config_t * config;
  46.     task_t found;
  47.     queue_t queue;
  48. } pc_context_t;
  49.  
  50. typedef bool (*password_handler_t) (void * context, char * password);
  51.  
  52. void queue_init (queue_t * queue)
  53. {
  54.     queue->head = 0;
  55.     queue->tail = 0;
  56.     pthread_mutex_init (&queue->head_mutex, NULL);
  57.     pthread_mutex_init (&queue->tail_mutex, NULL);
  58.     sem_init (&queue->empty, 0, sizeof (queue->queue) / sizeof (queue->queue[0]));
  59.     sem_init (&queue->full, 0, 0);
  60. }
  61.  
  62. void queue_push (queue_t * queue, task_t * task)
  63. {
  64.     //7
  65.     sem_wait (&queue->empty);
  66.     pthread_mutex_lock (&queue->tail_mutex);
  67.     queue->queue[queue->tail] = *task;
  68.     if (++queue->tail == sizeof (queue->queue) / sizeof (queue->queue[0]))
  69.         queue->tail = 0;
  70.     pthread_mutex_unlock (&queue->tail_mutex);
  71.     sem_post (&queue->full);
  72.  
  73. }
  74.  
  75. void queue_pop (queue_t * queue, task_t * task)
  76. {
  77.     //7
  78.     sem_wait(&queue->full);
  79.     pthread_mutex_lock (&queue->head_mutex);
  80.     if (++queue->head == sizeof (queue->queue) / sizeof (queue->queue[0]))
  81.         queue->head = 0;
  82.     pthread_mutex_unlock (&queue->head_mutex);
  83.     sem_post (&queue->empty);
  84. }
  85.  
  86. bool rec(config_t* config, char* password, int pos, password_handler_t password_handler, void * context)
  87. {
  88.     int i;
  89.     if (pos >= config->length)
  90.     {
  91.         if (password_handler (context, password))
  92.         {
  93.             return (true);
  94.         }
  95.     }
  96.     else
  97.     {
  98.         for (i = 0; config->alphabet[i]; ++i)
  99.         {
  100.             password[pos] = config->alphabet[i];
  101.             if (rec (config, password, pos + 1, password_handler, context))
  102.                 return (true);
  103.         }
  104.     }
  105.     return (false);
  106. }
  107.  
  108. void rec_wrapper(config_t* config, char* password, password_handler_t password_handler, void * context)
  109. {
  110.     rec (config, password, 0, password_handler, context);
  111. }
  112.  
  113. void iter(config_t* config, char* password, password_handler_t password_handler, void * context)
  114. {
  115.     int alph_length_1 = strlen(config->alphabet) - 1;
  116.     int idx[config->length];
  117.     int i;
  118.  
  119.     for (i = 0; i < config->length; i++)
  120.     {
  121.         idx[i] = 0;
  122.         password[i] = config->alphabet[0];
  123.     }
  124.  
  125.     for (;;)
  126.     {
  127.          if (password_handler (context, password))
  128.             break;
  129.         for (i = config->length - 1; (i >= 0) && (idx[i] == alph_length_1); i--)
  130.         {
  131.             idx[i] = 0;
  132.             password[i] = config->alphabet[0];
  133.         }
  134.  
  135.         if (i < 0)
  136.             break;
  137.  
  138.         password[i] = config->alphabet[++idx[i]];
  139.     }
  140. }
  141.  
  142. void parse_params(config_t* config, int argc, char* argv[])
  143. {
  144.     for (;;)
  145.     {
  146.         int opt = getopt(argc, argv, "a:l:h:irsm");                         //
  147.         if (opt == -1)
  148.             break;
  149.         switch (opt)
  150.         {
  151.         case 's':
  152.             config->thread_mode = TM_SINGLE;                                //
  153.             break;
  154.  
  155.         case 'm':
  156.             config->thread_mode = TM_MULTI;                                 //
  157.             break;
  158.  
  159.         case 'i':
  160.             config->brute_mode = BM_ITER;
  161.             break;
  162.  
  163.         case 'r':
  164.             config->brute_mode = BM_REC;
  165.             break;
  166.  
  167.         case 'a':
  168.             config->alphabet = optarg;
  169.             break;
  170.  
  171.         case 'h':
  172.             config->hash = optarg;
  173.             break;
  174.  
  175.         case 'l':
  176.             config->length = atoi(optarg);
  177.             break;
  178.  
  179.         default:
  180.             break;
  181.         }
  182.     }
  183. }
  184.  
  185. bool print_password (config_t * config, char * password)
  186. {
  187.     printf ("%s\n", password);
  188.     return (false);
  189. }
  190.  
  191. bool check_password (void * context, char * password)
  192. {
  193.     config_t * config = context;
  194.     char * hash = crypt (password, config->hash);
  195.     int cmp = strcmp (hash, config->hash);
  196.     return (0 == cmp);
  197. }
  198.  
  199. void run_single (config_t * config, char * password)
  200. {
  201.     switch (config->brute_mode)
  202.     {
  203.         case BM_ITER:
  204.             iter (&config, password, check_password, config);
  205.             break;
  206.         case BM_REC:
  207.             rec_wrapper(&config, password, check_password, config);
  208.             break;
  209.     }
  210. }
  211.  
  212. void * consumer (void * arg)
  213. {
  214.     pc_context_t * pc_context = arg;
  215.     for (;;)
  216.     {
  217.         task_t task;
  218.         queue_pop (&pc_context->queue, &task);
  219.         if (check_password (&pc_context->config, task.password))
  220.         {
  221.             pc_context->found = task;
  222.         }
  223.     }
  224. }
  225.  
  226. bool push_to_queue (void * context, char * password)
  227. {
  228.     pc_context_t * pc_context = context;
  229.     task_t task;
  230.     strcpy (task.password, password);
  231.     queue_push (&pc_context->queue, &task);
  232.     return (pc_context->found.password[0]);
  233. }
  234.  
  235. void run_multi (config_t * config, char * password)
  236. {
  237.     pc_context_t pc_context;
  238.     int num_cpu= sysconf (_SC_NPROCESSORS_ONLN);
  239.     int i;
  240.    
  241.     pc_context.found.password[0] = 0;
  242.     queue_init (&pc_context.queue);
  243.    
  244.     for (i = 0; i < num_cpu; ++i)
  245.     {
  246.         pthread_t id;
  247.         pthread_create (&id, NULL, consumer, &pc_context);
  248.     }
  249.    
  250.     switch (config->brute_mode)
  251.     {
  252.         case BM_ITER:
  253.             iter (&config, password, push_to_queue, &pc_context);
  254.             break;
  255.         case BM_REC:
  256.             rec_wrapper(&config, password, push_to_queue, &pc_context);
  257.             break;
  258.     }
  259.     password = pc_context.found.password;
  260. }
  261.  
  262. int main(int argc, char* argv[])
  263. {
  264.     config_t config =
  265.     {
  266.         .run_mode = RM_SINGLE,                                           //
  267.         .brute_mode = BM_ITER,
  268.         .alphabet = "01",
  269.         .length = 6,
  270.         .hash = strdup (crypt ("111101", "11")),
  271.     };
  272.  
  273.     parse_params(&config, argc, argv);
  274.  
  275.     char password[config.length + 1];
  276.     password[config.length] = 0;
  277.  
  278.     switch ( config.run_mode)
  279.     {
  280.         case RM_SINGLE:
  281.             run_single (&config, password);
  282.             break;
  283.         case RM_MULTI:
  284.             run_multi (&config, password);
  285.     }
  286.    
  287.     printf ("%s\n", password);
  288.     return (EXIT_SUCCESS);
  289. }
  290.  
RAW Paste Data