1

My program is supposed to be a brute force password cracker (school assignment). The input arguments are as follows..

./crack threads keysize target

The program needs to check passwords of length keysize, but also need to check shorter ones. I am unsure of how to go about writing something that will just change one letter at a time, and then continue doing this.. (keysize max is going to 8)

Example..

keysize = 5, so a loop (I think) would need to modify something that is equal to "aaaaa" to "aaaab" to "aaaac", putting each result into crypt_r(), along with the salt (first two characters of target) until a match is found.

I'm using crypt_r because the next step is to add multi-threading.

Unsure if anything else is really needed to explain this question. Would be glad to clarify.

m96
  • 199
  • 1
  • 3
  • 10
  • How can we verify that this is a school assignment? –  Sep 26 '13 at 02:23
  • 1
    If you really are just marching through "aaaa...a" through "zzzz...z" then you could treat it like a base 26 number and "increment" it in a loop. If you can allow strings of less than the maximum length, then start with "a" (consider the top positions as empty) and allow for roll over into empty positions on overflow of `z + 1`. – lurker Sep 26 '13 at 02:24
  • 3
    @enginefree: If it were not a school assignment, a far superior implementation would already exist in [John the Ripper](http://www.openwall.com/john/). –  Sep 26 '13 at 02:24
  • @enginefree I could always post the pdf from my professors website. But as someone already said, there has to be something far more superior to what I'm trying to do somewhere else. – m96 Sep 26 '13 at 02:28
  • @mbratch Well.. after trying to figure out how to do that for a little while.. I'm not really sure how. Any further instruction you can give on how to do this? I sometimes forget how to do very simple things, so forgive me if it is. – m96 Sep 26 '13 at 03:52
  • You could make a very simple and clean solution using recursion to generate the password. However, if you don't know about recursion and then you use it, you professor may suspect you've had outside help. – paddy Sep 26 '13 at 05:08
  • 1
    @paddy: recursion is not panacea. I would actually avoid using it at all. – mvp Sep 26 '13 at 05:26
  • 1
    You could represent the key as a long (64-bit) integer, and treat it like a base-26 number. So 0 becomes "aaaaaaaa", etc. Then all you need is something to convert a longint to its base-26 representation, which is probably something you already know how to do. (Think of how you'd output an integer in decimal or hexadecimal if you didn't have `printf` or `itoa`, etc.) – Jim Mischel Sep 26 '13 at 14:14

2 Answers2

2

Let's see. There are 10^n possible n-digit decimal numbers. So there are 26^8 possible 8-character passwords that use only the letters a-z. That works out to 208,827,064,576.

You can keep track of the numbers with a simple 64-bit counter, and then convert the number to a base-26 representation. Something like:

long max = 208827064576;
longlong counter = 0;

while (counter < max)
{
    char password[9];
    GetPassword(counter, password);
    // do whatever you want with the password
    ++counter;
}

void GetPassword(longlong count, char* pass)
{
    int i;
    int rem;
    if (count == 0)
    {
        pass[0] = 'a';
        pass[1] = '\0';
        return;
    }
    i = 0;
    do
    {
        int rem = count % 26;
        pass[i] = 'a' + rem;
        ++i;
        count /= 26;
    } while (count > 0)
}

You can easily make this available to multiple threads by using interlocked increments of the counter variable. Or you can split the search space so that one thread starts at 0, one thread starts at 26^7 (which would be baaaaaaa), etc.

200 billion is a reasonably large number. A billion seconds works out to something close to 32 years. Even if you could check a few thousand of these per second (unlikely), it would take you quite some time to do an exhaustive search.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • Thanks, Jim. I think the real purpose of the assignment is to learn how to implement multithreading. We're supposed to allow the program to use up to 8 threads. It was suggested we either chop up the possible range of choices for each thread to search through or to use a "shared current password to try" and to use locks to go through them. – m96 Sep 27 '13 at 05:14
  • Your `do {}` must be a loop to make any sense, but it is not, thus it won't work. – mvp Sep 28 '13 at 07:37
  • After trying to implement this code (I had to add a while condition to the `do{}`, I got a seg fault. While I may have placed it in my program wrong, I also included a line to print out whatever `pass` was equal to and was met with a continuous stream of a's until a segmentation fault. – m96 Sep 28 '13 at 22:46
  • @m96: I've corrected the code. Without seeing what code you wrote, I can't say what the problem might have been. – Jim Mischel Sep 29 '13 at 05:15
1

This code will cycle through all passwords no longer than given lengh and containing only letters from a to z:

#include <stdio.h>
int main(void) {
    char password[9] = {0};
    int keysize = 5;
    for (;;) {
        // get next password value
        // we do it by adding 1 in 26-al system
        int level = 0; // current level, starts at 0
        while (level < keysize) {
            if (password[level] == 0) {
                password[level] = 'a';
                break;
            }
            if (password[level] >= 'a' && password[level] < 'z') {
                password[level]++;
                break;
            }
            if (password[level] == 'z') {
                password[level] = 'a';
                level++;
            }
        }
        if (level >= keysize)
            break; // we have checked all passwords!
        // check if password matches:
        //printf("Checking password: '%s'\n", password);
        if (check_password(password)) {
            printf("Hooray! Password found: %s\n", password);
            break;
        }
    }
    return 0;
}

If you limit aphabet to a, b, c and set keysize=4, it checks following passwords:

a b c aa ba ca ab bb cb ac bc cc aaa baa caa aba bba cba aca bca cca aab bab cab abb bbb cbb acb bcb ccb aac bac cac abc bbc cbc acc bcc ccc aaaa baaa caaa abaa bbaa cbaa acaa bcaa ccaa aaba baba caba abba bbba cbba acba bcba ccba aaca baca caca abca bbca cbca acca bcca ccca aaab baab caab abab bbab cbab acab bcab ccab aabb babb cabb abbb bbbb cbbb acbb bcbb ccbb aacb bacb cacb abcb bbcb cbcb accb bccb cccb aaac baac caac abac bbac cbac acac bcac ccac aabc babc cabc abbc bbbc cbbc acbc bcbc ccbc aacc bacc cacc abcc bbcc cbcc accc bccc cccc

See this example at IdeOne DEMO.

mvp
  • 111,019
  • 13
  • 122
  • 148
  • Thanks. Looks really good. I'll try and see how this works. If you don't mind me asking.. what does the 'for(;;)' do? Haven't seen that before – m96 Sep 26 '13 at 05:53
  • `for(;;)` is the same as `while(true)` - endless loop – mvp Sep 26 '13 at 05:55
  • Of the two things given, yours seems to be the best. I am now only having trouble actually getting my program to verify which password is the correct one. I set up another question for this if you think you might be able to help. http://stackoverflow.com/questions/19071145/using-strcmp-and-crypt-to-find-a-password-from-an-already-hashed-password – m96 Sep 28 '13 at 22:47