0

I have tested the following code to read the tester.txt file and it outputted my expectation, however, when I inserted similar code in my complete code, it just stuck at: "Data from the file:" Why it is not outputting my expectation?

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

char c[1000];
FILE *fptr;

int fileReader(){
    if ((fptr = fopen("tester.txt", "r")) == NULL) {
        printf("Error! File cannot be opened.");
        // Program exits if the file pointer returns NULL.
        exit(1);
    }
    // reads text until newline is encountered
    fscanf(fptr, "%[^\n]", c);
    fclose(fptr);
}
int main() {

    fileReader();
    printf("Data from the file:\n%s", c);
    char* anotherone = (char*) c; 
    printf(anotherone);

    return 0;
}

Another code to read file:

int fileReader() {

   fp = fopen("tester.txt", "r");
   fscanf(fp, "%s", c);
   fclose(fp);

}

The complete code is:

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int success = 0;

void handleOpenSSLErrors(void)
{
    ERR_print_errors_fp(stderr);
    abort();
}

unsigned char* decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv ){

    EVP_CIPHER_CTX *ctx;
    unsigned char *plaintexts;
    int len;
    int plaintext_len;
    
    unsigned char* plaintext = malloc(ciphertext_len);
    bzero(plaintext,ciphertext_len);

  
    if(!(ctx = EVP_CIPHER_CTX_new())) handleOpenSSLErrors();

    
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
        handleOpenSSLErrors();

  
    EVP_CIPHER_CTX_set_key_length(ctx, EVP_MAX_KEY_LENGTH);

    if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
        handleOpenSSLErrors();
   
    plaintext_len = len;
    
    // return 1 if decryption successful, otherwise 0
    if(1 == EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) 
        success = 1;
    plaintext_len += len;

   
    /* Add the null terminator */
    plaintext[plaintext_len] = 0;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);
    //delete [] plaintext;
    return plaintext;
}


size_t calcDecodeLength(char* b64input) {
    size_t len = strlen(b64input), padding = 0;

    if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
        padding = 2;
    else if (b64input[len-1] == '=') //last char is =
        padding = 1;
    return (len*3)/4 - padding;
}

void Base64Decode( char* b64message, unsigned char** buffer, size_t* length) {

    
    BIO *bio, *b64;  // A BIO is an I/O strean abstraction

    int decodeLen = calcDecodeLength(b64message);
    *buffer = (unsigned char*)malloc(decodeLen + 1);
    (*buffer)[decodeLen] = '\0';

    bio = BIO_new_mem_buf(b64message, -1);
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_push(b64, bio);

    //BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
    *length = BIO_read(bio, *buffer, strlen(b64message));
    BIO_free_all(bio);
}

void initAES(const unsigned char *pass, unsigned char* salt, unsigned char* key, unsigned char* iv )
{
    //initialisatio of key and iv with 0
    bzero(key,sizeof(key)); 
    bzero(iv,sizeof(iv));
  
    EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, pass, strlen(pass), 1, key, iv);
}


int checkPlaintext(char* plaintext, char* result){

    int length = 10; // we just check the first then characters
    return strncmp(plaintext, result, length);

}

char *cas[1000];
FILE *fptr;

int fileReader(){
    if ((fptr = fopen("tester.txt", "r")) == NULL) {
        printf("Error! File cannot be opened.");
        // Program exits if the file pointer returns NULL.
        exit(1);
    }
    // reads text until newline is encountered
    fscanf(fptr, "%[^\n]", cas);
    fclose(fptr);

}

int main (void)
{
    
    fileReader();
    printf("Data from the file:\n%s", cas);
    char* ciphertext_base64 = (char*) cas;   

    char* plaintext = "to be or not to be is the question";
    char dict[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        
    int decryptedtext_len, ciphertext_len, dict_len;

    // cipher (binary) pointer and length
    size_t cipher_len; // size_t is sizeof(type)
    unsigned char* ciphertext;
  
    unsigned char salt[8];
    
    ERR_load_crypto_strings();
    
    Base64Decode(ciphertext_base64, &ciphertext, &cipher_len);

    unsigned char key[16];
    unsigned char iv[16];

    unsigned char plainpassword[] = "00000";
    unsigned char* password = &plainpassword[0];
    
    // retrive the slater from ciphertext (binary)
    if (strncmp((const char*)ciphertext,"Salted__",8) == 0) { // find the keyword "Salted__"
        
        memcpy(salt,&ciphertext[8],8);
        ciphertext += 16; 
        cipher_len -= 16;
    
    }

    dict_len = strlen(dict);
    
    time_t begin = time(NULL);


    for(int i=0; i<dict_len; i++)
        for(int j=0; j<dict_len; j++)
            for(int k=0; k<dict_len; k++)
                for(int l=0; l<dict_len; l++)
                    for(int m=0; m<dict_len; m++){
                        *password = dict[i];
                        *(password+1) = dict[j];
                        *(password+2) = dict[k];
                        *(password+3) = dict[l];
                        *(password+4) = dict[m];

                        
                        initAES(password, salt, key, iv);
                        unsigned char* result = decrypt(ciphertext, cipher_len, key, iv);
                        
                        if (success == 1){
                            if(checkPlaintext(plaintext, result)==0){
                                
                                printf("Password is %s\n", password);
                                
                                time_t end = time(NULL);
                                printf("Time elpased is %ld seconds", (end - begin));
 
                                return 0;
                            }

                        }
                       
                        free(result);
                        
                        
                    }

            
    // Clean up
    
    EVP_cleanup();
    ERR_free_strings();


    return 0;
}
James Z
  • 12,209
  • 10
  • 24
  • 44
  • 1
    Maybe not what's causing the problem but `fileReader()` is supposed to return an int. – anastaciu Apr 22 '21 at 13:18
  • But the strangest thing here is that the sample code works perfectly, the replica of it is what is in the full code, I am really confused. – Adeolu Temitope Olofintuyi Apr 22 '21 at 13:22
  • I can't say for sure, try running your code through a debugger, make sure you are not trying to change read only string literals, or that you're not using unitialized pointers to store data, those would be my first two checks. – anastaciu Apr 22 '21 at 13:41
  • Your `initAES` also looks suspicious, you are, those `sizeof` will give you the size of the pointers not the size of the containers you pass as aguments. – anastaciu Apr 22 '21 at 13:47
  • 1
    Did you mean to make `cas` an array of character pointers? Because you seem to be using it as an array of characters. – Emanuel P Apr 22 '21 at 13:48
  • Looks like it was the second, using unitialized pointers to store data. Still your code needs cleaning up, at first glance I see several problems, use compiler warnings at full blast and preferably treat warnings as errors. – anastaciu Apr 22 '21 at 13:51
  • @anastaciu but if you look at the two codes they are actually similar. I actually don't get where you pointed out to be the source of error. Even if cracking will not work(as you pointed out initAES) at least it suppose to print out the file data. – Adeolu Temitope Olofintuyi Apr 22 '21 at 13:57
  • To make @EmanuelP 's hint more blunt: there is a very large difference between `char c[1000];` and `char *cas[1000];` – deamentiaemundi Apr 22 '21 at 14:22
  • I will be glad if you can all look at the fix and another strange error I get at this place https://stackoverflow.com/questions/67217647/automatically-calling-the-exit-function-without-performing-the-next-task . Thanks a lot for your time. – Adeolu Temitope Olofintuyi Apr 22 '21 at 16:57

1 Answers1

1
  1. char *cas[1000]; should be char cas[1000];, I would say this is the main issue, you are using an array of pointers as if it was a character array, this is very likely what's causing your program to fail.

  1. Fix bzero, pass the size of the array as argument. When you use sizeof(key) in initAES(), what you are actually getting is the size of the pointer, not the size of the container it points to. More oh this in How to find the 'sizeof' (a pointer pointing to an array)?

You can add size of the array as a global constant with a macro:

#define SIZE 16 // size of the arrays

//...

void initAES(const unsigned char *pass, unsigned char* salt, unsigned char* key, unsigned char* iv )
{
    //initialisatio of key and iv with 0
    bzero(key, SIZE); 
    bzero(iv, SIZE);
  
    EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, pass, strlen(pass), 1, key, iv);
}

You can use it to define the size in main making your code more consistent.

int main (void)
{
    //...
    unsigned char key[SIZE];
    unsigned char iv[SIZE];
    //...
}

  1. For good measure make fileReader have void return type if you don't want it to return an int.

I always advise the use of compiler warnings at full blast and preferably to treat warnings as errors.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • I actually get the fix for 1 and 3, but I really don't get what you want me to do in 2. Please can you make it clear for me? If you can write what you expect me to write, I will really appreciate. – Adeolu Temitope Olofintuyi Apr 22 '21 at 14:14
  • @AdeoluTemitopeOlofintuyi, what do you expect the result of `sizeof(key)` to be? – anastaciu Apr 22 '21 at 14:16
  • @AdeoluTemitopeOlofintuyi well now I'm confused, you declare it as `unsigned char key[16];` so it will only have 16 characters. The point is that the array size is not detected by sizeof inside the function, only where the array was declared, read more about it [here](https://stackoverflow.com/q/492384/6865932). – anastaciu Apr 22 '21 at 14:22
  • Yeah, when you asked, what my brain was processing then was my expected file, the key and the iv are going to be 16 characters. I'm just a little bit frustrated here, that's why I answered your question for something diffrent. – Adeolu Temitope Olofintuyi Apr 22 '21 at 14:27
  • @AdeoluTemitopeOlofintuyi no problem, the fact is you need to pass the correct size of the array to `bzero`, if you don't want to pass it as argument just define it in a global constant. – anastaciu Apr 22 '21 at 14:29
  • Please, can you do me a favor of dumping the fixed complete code pointed out, here? When it runs, as expected, then I will understand where I am doing it wrong with ease. Please. – Adeolu Temitope Olofintuyi Apr 22 '21 at 14:35
  • @AdeoluTemitopeOlofintuyi I added some code for clarity. – anastaciu Apr 22 '21 at 18:41
  • thanks a lot for the guide, you are really appreciated. The code is actually working as expected now, I really appreciate your time to and clear explanation. Thanks once again. – Adeolu Temitope Olofintuyi Apr 22 '21 at 18:52
  • @AdeoluTemitopeOlofintuyi I'm glad we finally solved that ;) don't forget to [vote and/or accept](https://meta.stackexchange.com/a/5235/684852) if you feel it solved your problem. – anastaciu Apr 22 '21 at 18:55