我怎样才能让这个蛮力算法逐步检查字母

How can I get this brute force algorithm to check letters incrementally

对于这个作业,我必须在 C 中使用 pthreads 来制作暴力密码破解器。

下面的代码使用 for 循环生成一个 6 个字母的密码(最好是 8 个字母长)然后我使用 crypt_r 对其进行散列并将其与我在执行时给程序的散列和盐进行比较.

哈希和盐在开始时被接收,存储在一个名为 dataStr 的结构中,然后将其提供给 pthreadCreate。

这看起来很简单,但即使我将数组 memset 为空终止字符,在执行时程序仍将整个设置为 'aaaaaa'。这个问题是它忽略了 1-4 个字符长的密码。

这是我使用的数据结构:

typedef struct {

    char * hash;            //hashed code given in argv[1]
    char * salt;            //salt for hashed code given in argv[2]

    int start;              //starting char in alphabet for first letter
    int end;                //ending char in alphabet for first letter

    int id;                 //thread id

} dataStruct;

尺寸定义:

//Definitions
#define PW_SIZE 8
#define ALPHABET_SIZE 66
#define HASH_MAX_SIZE 128

这是代码本身

void * thread(void * arg) {

    struct timespec start, finish;          //Data structure for time.h library
    clock_gettime(CLOCK_MONOTONIC, &start); //Start chronometer
    double elapsed;

    struct crypt_data* cdata = (struct crypt_data *)malloc(sizeof(struct crypt_data));
    cdata->initialized = 0;

    dataStruct dataStr = *((dataStruct*)(arg)); //receive structure in arguement

    const char * alphabet = get_alphabet();     //create alphabet

    bool pw_found = false;                      //boolean used for 
    int retDone = 1;

    char * pwd = malloc(PW_SIZE * sizeof(char));
    memset(pwd, '[=12=]', PW_SIZE);

    int i,j,k,l,m,n;

    for (i = dataStr.start; i <= dataStr.end; i++) {            
        for (j = 0; j <= ALPHABET_SIZE; j++) {
            for (k = 0; k <= ALPHABET_SIZE; k++) {
                for (l = 0; l <= ALPHABET_SIZE; l++) {
                    for (m = 0; m <= ALPHABET_SIZE; m++) {
                        for (n = 0; n <= ALPHABET_SIZE; n++) {

                            if (pw_found) {
                                clock_gettime(CLOCK_MONOTONIC, &finish);        
                                elapsed = finish.tv_sec - start.tv_sec;
                                elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0; 
                                printf("Time elapsed : %f sec(s) \n\n", elapsed);   //Time

                                pthread_exit(&retDone);                                 
                            }                           

                            pwd[0] = alphabet[i];   
                            pwd[1] = alphabet[j];   
                            pwd[2] = alphabet[k];
                            pwd[3] = alphabet[l];
                            pwd[4] = alphabet[m];
                            pwd[5] = alphabet[n];

                            printf("%s\n", pwd);

                            char * hash = crypt_r(pwd, dataStr.salt, cdata);

                            if (strcmp(hash, dataStr.hash) == 0) {
                                printf("\nPassword     : %s\n", pwd);
                                pw_found = true;
                            }
                        }
                    }
                }
            }
        }                       
    }

    pthread_exit(&retDone); 
}

这是它在执行时产生的结果:

我想了解如何以某种方式更改 6 个循环,以便让程序首先只搜索 1 个字母字符,然后搜索 2 个,然后搜索 3 个,然后从那里递增。

感谢任何帮助。非常感谢!

PS - 我不介意将全局视图的代码通过电子邮件发送给某人。

可以使用指针来实现这一点。 ppw 将指向 pw 数组中的某处。 pch 将指向 characters 数组中的某处。递增 (++) 和递减 (--) 指针会在各自数组的元素内移动指针。 Dereferencing(*) 可以访问指针指向的值。 usedpw 中已使用的元素数。它从第一个元素的 0 开始,并向 SIZE 增加。 characters 可以修改为包括有效的字母、数字和符号。请注意不要重复。例如,如果字母 u 出现不止一次,程序将进入无限循环。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 5

int main( void)
{
    char pw[SIZE + 1] = "";
    char *ppw = NULL;
    char *pch = NULL;
    char characters[] = "abcdefghijklmnopqrstuvwxyz";
    int used = 0;
    int out = 1;
    int last = strlen ( characters) - 1;

    //set pw
    pw[used] = characters[0];
    pw[used + 1] = '[=10=]';

    while ( used < SIZE) {//loop until all elements of pw have been used
        ppw = &pw[used];//set ppw to point to last used element of pw
        while ( ppw >= pw) {//so ppw always points to an element of pw
            if ( ( pch = strchr ( characters, *ppw)) != NULL) {//get pointer into characters for current value that ppw point to
                if ( out) {//print when appropriate
                    printf ( "%s\n", pw);
                }
                if ( pch < &characters[last]) {//pch does not point to last element of characters
                    ++pch;//pch points to next element of characters
                    *ppw = *pch;//set what ppw points to to be the same as what pch points to
                    if ( ppw != &pw[used]) {//ppw is not pointing to last element of pw
                        ppw = &pw[used];
                    }
                    out = 1;//allow printing
                }
                else {//pch is pointing to last element of characters
                    *ppw = characters[0];//set what ppw points to to be the first element of characters
                    ppw--;//ppw points to next lower element of pw. ex from pw[n] to pw[n-1]
                    out = 0;//disable printing
                }
            }
        }//exit loop when ppw points to address less than pw
        used++;//increase elements in use
        memset ( pw, characters[0], used);//reset all elements to first element of characters
        pw[used + 1] = '[=10=]';//just in case, terminate
    }//exit loop when all elements have been used

    exit ( 0);
}

这似乎有效。添加了两行以将 out 设置为 1,并将 used + 1 添加到对 memset 的调用中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// one more than the desired size
#define SIZE 4

int main( void)
{
    char pw[SIZE] = "";
    char *ppw = NULL;
    char *pch = NULL;
    char characters[] = "abc";
    int used = 0;
    int out = 1;
    int last = strlen ( characters) - 1;

    //set pw as character[0]
    pw[used] = characters[0];
    pw[used + 1] = '[=11=]';

    while ( used < SIZE - 1) {//loop until all elements of pw have been used
        ppw = &pw[used];//set ppw to point to last used element of pw
        out = 1;
        while ( ppw >= pw) {//so ppw always points to an element of pw
            if ( ( pch = strchr ( characters, *ppw)) != NULL) {//get pointer into characters for current value that ppw point to
                if ( out) {//print when appropriate
                    printf ( "%s\n", pw);
                }
                out = 1;
                if ( pch < &characters[last]) {//pch does not point to last element of characters
                    ++pch;//pch points to next element of characters
                    *ppw = *pch;//set what ppw points to to be the same as what pch points to
                    if ( ppw != &pw[used]) {//ppw is not pointing to last element of pw
                        ppw = &pw[used];
                    }
                }
                else {//pch is pointing to last element of characters
                    *ppw = characters[0];//set what ppw points to to be the first element of characters
                    ppw--;//ppw points to next lower element of pw. ex from pw[n] to pw[n-1]
                    out = 0;//disable printing
                }
            }
        }//exit loop when ppw points to address less than pw
        used++;//increase elements in use
        memset ( pw, characters[0], used + 1);//reset all elements to first element of characters
        pw[used + 1] = '[=11=]';//just in case, terminate
    }//exit loop when all elements have been used

    exit ( 0);
}