1

having a little bit of difficult with the CS50 crack. I've commented out a portion(s) of my code because for CS50 I "know" the salts used in the ciphers are 50, and thats what im wanting to test against.

The problem is, I know my file-open is working (I had a printf that printed the buffer each time and I am indeed getting all the words).

I've tried words I KNOW are in the dictionary file im using, and i've checked against the DES encrypted values. So I know at the very least that the words exist in the dictionary AND that im using a cipher in the command line that is the encrypted HASH of the dictionary word (assuming a salt of 50)

Anyways, not sure what's going wrong, here is my code. Something see:

#define _XOPEN_SOURCE
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int crackCheck(char *word, char *cipher);
int main(int argc, string argv[])
{
   if (argc != 2){
    printf("Usage: ./crack hash");
    return 1;
   }

   char *cipher = argv[1]; //cipher 
   int trials = 0;

   //Open File
   FILE *fp;
   char buff[255];
   fp = fopen("/usr/share/dict/words", "r");

   if(fp == NULL)
   {
       printf("Failed to Open File...");

   }

   bool success = false;
   while (fgets(buff, sizeof(buff), fp) != NULL && success != 1) 
    {  
        success = crackCheck(buff,cipher);
        trials++;
    } 
    printf("Trials: %i", trials);
    return 0;
}

int crackCheck(char *word, char *cipher)
{
    //char *salts = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890./";
    char *result;
    char salt[2] = "50";
   /* for(int i = 0; i < saltLen; i++){
        for(int j = 0; j < saltLen; j++){
        salt[0] = salts[i];
        salt[1] = salts[j];
        */
        result = crypt(word,salt);
        if(strcmp(result, cipher) == 0)
            {
            return 1;
            }
        else
        {
            return 0;
        }
    return 0;
}

For reference I was testing checking the word "zygote" which is in the dictionary the the hash SHOULD be "50yAd3fLVW1Do" but im getting "50vxdmA9m.T" for some reason.

3

Your problem is probably because of this line:

char salt[2] = "50";

If you recall, you have to end a string with an additional character, the null zero '\0', so technically salt is 3 characters long. Change it to

char salt[3] = "50";

or even better:

char salt[] = "50";

Edit

working code (yours actually, after some small modifications)

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int crackCheck(char *word, char *cipher);

int main(int argc, char* argv[]) {
    if (argc != 2) {
        printf("Usage: ./crack hash");
        return 1;
    }

    printf("\"zygote\" encrypted: %s\n", crypt("zygote", "50"));

    char *cipher = argv[1]; //cipher
    int trials = 0;

    // Open File
    FILE *fp = fopen("words", "r");
    if(fp == NULL) {
        printf("Failed to Open File...");
    }

    int success = 0;
    char buff[255];
    while (fgets(buff, sizeof(buff), fp) != NULL) {
        // remove the trailing \n left by fgets()
        buff[strlen(buff) - 1] = '\0';
        trials++;
        success = crackCheck(buff, cipher);
        if (success) {
            printf("Password was: %s\n", buff);
            break;
        }
    }

    printf("Trials: %d\n", trials);
    return 0;
}

int crackCheck(char *word, char *cipher) {
    // read the salt from the cipher and don't hardcode it
    char salt[3];
    strncpy(salt, cipher, 2);
    salt[2] = '\0';

    char *result = crypt(word, salt);
    if(strcmp(result, cipher) == 0) {
        return 1;
    }

    return 0;
}

Test output:

[x@x ~]$ cat words 
this
is
a
teststring
and
nothing
more
zygote
[x@x ~]$ gcc -o crack crack.c -lcrypt
[x@x ~]$ ./crack 50yAd3fLVW1Do
"zygote" encrypted: 50yAd3fLVW1Do
Password was: zygote
Trials: 8
[x@x ~]$ ./crack 509FECjmNRUG2
"zygote" encrypted: 50yAd3fLVW1Do
Password was: teststring
Trials: 4
7
  • What's funny is I tried doing char salt[3] and setting salt[2]='\0' and had the same issue, or is that not the same? – msmith1114 Jan 30 '17 at 14:42
  • Dang...was hoping that was the problem, no dice. I used char salt[] = "50"...so something else must be going wrong. – msmith1114 Jan 30 '17 at 15:40
  • The code works fine in my machine (Fedora 25) so I don't know what might be wrong with yours. Are you sure you are giving the correct hashed password as argument? One more thing you might want to check, is to remove the reailing new line character '\n' left in buff by fgets(). Let me know. – ChrisG Jan 30 '17 at 17:10
  • Maybe I can use strtok(buff, "\n"); or something? I can imagine what would be difference about the dict file..it's basically just words on a newline..... Can you try your program with zygote in the words and see if you get "50yAd3fLVW1Do" Im not seeing code modifications from mine (besides some printf statements and such that are different) that should change it. I know im using the correct hashed password, but even if I wasn't I would see the correct hash printed out (Which im not) – msmith1114 Jan 30 '17 at 17:30
  • 1
    Looks like it was the \n which is funny because I just realized in my printout statements (I was printing out the word read next to the cypher) and it was printing them each on a newline and I never had a newline on my printf statements....so that should've told me ha!. Anyways thanks for your help! It's working now. At least I was able to get most of the way there haha! – msmith1114 Jan 30 '17 at 19:38
1

Not sure what causes your problem, but found a few issues.

That one is dangerous, as you declare a two-byte array, but assign a three-byte string (two characters plus '\0' for string end):

    char salt[2] = "50";

You could omit the 2, and let the compiler determine the length

    char salt[] = "50";

or use something like

    char salt[3];
    snprintf(salt, 3, "%s", cipher);

I'm not sure about this particular implementation, but other implementations of crypt (such as Python's crypt function) also allow passing the complete hash for the salt, the algorithm then will evaluate only the first two characters to extract the 12 bit salt.

Also, I'd replace

    while (fgets(buff, sizeof(buff), fp) != NULL && success != 1)

with

    while (!success && fgets(buff, sizeof(buff), fp) != NULL) 

so you don't read another line after finding the word corresponding to the hash.

And please close fp, but valgrind would tell you to do so.

1
  • Darn, looks like the char salt[] = "50"; wasn't the issue. Still getting the same hashes everytime (although incorrect). I must be missing something. I had posted this issue somewhere else and someone suggested maybe it has something to do with what im reading in? maybe the characters aren't getting terminated at the end? – msmith1114 Jan 30 '17 at 15:41

You must log in to answer this question.

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