0

When I run my crack.c, the program never responds. It just sits there and wastes time. I even tried debugging it on the CS50 IDE, and it was normal. Here is my code:

#include <cs50.h>
#include <stdio.h>
#include <crypt.h>
#include <string.h>

string crack(string hashed);

// Deals with input and stuff and feeds info into functions.
int main(int argc, string argv[])
{
    // Returns 1 because this is an error (because there is no hashed pw).
    if (argc != 2)
    {
        printf("Usage: ./crack hash\n");
        return 1;
    }
    else
    {
        // Makes crack do all the 'hard work' of guess/checking.
        string pw = crack(argv[1]);
        // Prints the pw.
        printf("%s\n", pw);
        return 0;
    }
}

// Does all the 'hard work'.
string crack(string hashed)
{
    // A string is a list of chars, so this is easier than doing characters[0] = '\0'; ...
    string characters = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
           // A temporary variable that is useful for guessing.
           temp = malloc(6),
           // The salt for crypt() (salt will be defined in next two lines).
           salt = malloc(3),
           // The output.
           out = malloc(6);
    salt[0] = hashed[0];
    salt[1] = hashed[1];
    salt[2] = '\0';
    // Length will be used in the for loops in the next lines.
    int length = strlen(characters),
        c1 = 0,    // c1-4 are counters for the while loops.
        c2 = 0,
        c3 = 0,
        c4 = 0,
        c5 = 0;
    // These things check if each loop is done.
    bool done = false,
         done1 = false,
         done2 = false,
         done3 = false,
         done4 = false,
         done5 = false;
    while (!done1)
    {
        while (!done2)
        {
            while (!done3)
            {
                while (!done4)
                {
                    while (!done5)
                    {
                        temp[0] = characters[c1];   // Sets temp to characters[c1] characters[c2] etc.
                        temp[1] = characters[c2];
                        temp[2] = characters[c3];
                        temp[3] = characters[c4];
                        temp[4] = characters[c5];
                        temp[5] = '\0';
                        if (temp == NULL)   // Prevents segmentation errors.
                        {
                            printf("Segmentation error found.\nEnding Program");
                            done = true;
                        }

                        else if (strcmp(crypt(temp, salt), hashed) == 0)    // Checks if it is done.
                        {
                            out = temp;
                            done = true;
                        }
                        else if (c5 > strlen(characters) - 1)   // Checks when to exit THIS loop
                        {
                            done5 = true;
                        }
                        c5++;
                    }
                    if (done)   // Increments c4 and sets c5 to 0.
                    {
                        break;
                    }
                    else if (c4 > strlen(characters) - 1)     // Checks when to exit THIS loop
                    {
                        done4 = true;
                    }
                    else
                    {
                        c5 = 0;
                        c4++;
                        done5 = false;
                    }
                }
                if (done)   // Increments c3 and sets c4 to 0.
                {
                    break;
                }
                else if (c3 > strlen(characters) - 1) // Checks when to exit THIS loop
                {
                    done3 = true;
                }
                else
                {
                    c4 = 0;
                    c3++;
                    done4 = false;
                }
            }
            if (done)   // Increments c2 and sets c3 to 0.
            {
                break;
            }
            else if (c2 > strlen(characters) - 1) // Checks when to exit THIS loop
            {
                done2 = true;
            }
            else
            {
                c3 = 0;
                c2++;
                done3 = false;
            }
        }
        if (done)   // Increments c1 and sets c2 to 0.
        {
            break;
        }
        else if (c1 > strlen(characters) - 1) // Checks when to exit THIS loop
        {
            done1 = true;
        }
        else
        {
            c2 = 0;
            c1++;
            done2 = false;
        }
    }
    return out;
}

string deleteAll(string s, char target)
{
    // Gets a string length.
    int length = (int) strlen(s), count = 0;
    // Sets the length of the output to the length of the input string (which is faster than calculating).
    string out = malloc(length);
    // Scans the input string and checks for target.
    for (int i = 0; i < length; i++)
    {
        if (!(s[i] == target))
        {
            out[count] = s[i];
            count++;
        }
    }
    return out;
}

Is my computer slow (because it sometimes is) or does the program have problems? Everytime I run it, it skips right over the hash. (You can see the code ████, but please don't do anything bad. I WILL SEE IT)

1

I'd remove the space from the pool of valid password characters, and try again. Maybe you saw a less than 5 character password with some space character in front.

You don't have a break; after done = true;, which means the password is shortened by one character. Also, it's pretty pointless to allocate memory for both temp and out, but then assign one to the other (rendering one allocation unreachable). strcpy(out, temp); would make some sense, but after fixing the break;, you should no longer change the matching string either.

I'm not exactly sure what your doneN variables do, and whether they work correctly. I guess you spent more time on those than I did. Interesting way to use > strlen(characters) - 1, which means c1..c5 go up to strlen(characters). That way, you can handle passwords shorter than 5 (by copying '\0'), but you test all the different combinations like {'h','i','\0','N','t'} and {'h','i','\0','y','A'}, even though both represent the password "hi".

Have you tried changing your implementation to three or four characters, and test some passwords of same length or shorter? Using a shorter maximum password length (and testing for that length or shorter passwords) might help in bugfixing.

Changing the code to some approach that does not require one loop per character could make it easier to change those parameters, for developing with a smaller number of combinations and later expanding to the length/alphabet required by problem description.

Some fun with that one:

                        temp[0] = characters[c1];   // Sets temp to characters[c1] characters[c2] etc.
                        temp[1] = characters[c2];
                        temp[2] = characters[c3];
                        temp[3] = characters[c4];
                        temp[4] = characters[c5];
                        temp[5] = '\0';
                        if (temp == NULL)   // Prevents segmentation errors.
                        {
                            printf("Segmentation error found.\nEnding Program");
                            done = true;
                        }

The segmentation fault would happen when dereferencing the pointer, e.g. with temp[0] (array[index] is same as *(array + index), so temp[0] is *temp). You see how futile this check is? Should go directly behind the corresponding malloc.

| improve this answer | |
  • I can't think of any ways to loop it. I've tried for loops, but they are useless. – Mayonnaise2124 Apr 3 '19 at 3:53
  • I took your advice and tried it out. IT WORKS 🎉 – Mayonnaise2124 Apr 4 '19 at 4:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .