© Marius Iulian Mihailescu and Stefania Loredana Nita 2021
M. I. Mihailescu, S. L. NitaPro Cryptography and Cryptanalysis with C++20https://doi.org/10.1007/978-1-4842-6586-4_21

21. Brute Force and Buffer Overflow Attacks

Marius Iulian Mihailescu1   and Stefania Loredana Nita1
(1)
Bucharest, Romania
 

This chapter covers two important attacks, the buffer overflow attack and the brute force attack, which are frequently employed against C++ applications and programs.

A special category of attackers will use applications/programs or devices to launch brute force or buffer overflow attacks. Their methods evaluate different combinations of words for confirmation forms. In some cases, the attackers attempt to corrupt web applications through a scanning process for sessions IDs, for example. The attacker’s goals include stealing data, corrupting destination machines with malware, and asking for a specific amount of money. Some of the attackers perform brute force attacks physically as a personal choice. Today, most brute force and buffer overflow attacks are performed by bots.

In order to protect organizations and businesses from these kinds of attacks, take into consideration the following recommendations:
  • Don’t use data or information that could be found online.

  • Use as many characters as possible.

  • Use combinations of letters, numbers, and special characters (e.g. symbols).

  • Don’t use common patterns (e.g. qwerty).

  • Use different passwords for each user account.

  • Change the password at frequent intervals (e.g. every two months).

  • Use and generate long and strong passwords. If you don’t have an idea for one, use a password generator (e.g. key generation from KeyPass).

  • Implement multifactor authentication [1].

  • Use biometrics if possible [2].

Brute Force Attack

A brute-force attack represents a complex attack in which the attacker will submit many passwords or passphrases with the goal of guessing the correct one. Each password or passphrase is checked one-by-one by the attacker until the correct one is found. Also, the attacker may guess the key. The key is generally created from the password by using a function for key derivation. This process is known as an exhaustive key search.

There are many types of brute-force attacks:
  • Attacks based on rainbow tables: A rainbow table is a predefined and precomputed table. The goal is to reverse the process of the cryptographic hash capacities.

  • Attacks based on reversing brute-force attacks: The attack is based on using a general password or a specific set of passwords against multiple usernames.

  • Credential attacks: The attack uses sets of passwords-usernames against a variety of websites.

  • Hybrid brute-force attacks: The attack is used to figure out what password variety is used to succeed. After, it proceeds with a general process for dealing with checking different varieties.

We will illustrate this type of attack with the following examples to show how the attack can be used and deployed in real-life situations (algorithms). The examples provided are
  • Brute-force attack on a Caesar cipher: The example (see Figure 21-1 and Listing 21-1) is based on a Caesar cipher. The example is chosen as the first case of showing a brute-force attack due to its simplicity.

  • String generation for a brute-force attack: The example (see Figure 21-2 and Listing 21-2) shows how basic string generation can be done with the goal of creating complex lists and dictionaries that can be used during brute-force attacks.

../images/496528_1_En_21_Chapter/496528_1_En_21_Fig1_HTML.jpg
Figure 21-1

Running the brute-force attack

#include<iostream>
using namespace std;
// the function will be used to encrypt the plaintext
// string msg - the message
// int keytValue - the key
string encrypt(string msg,int keyValue)
{
     // variable used to hold the cipher value of the plaintext
    string cipher="";
     // parse the string
    for(int i=0;i<msg.length();i++)
    {
        // verify if the character is upper case
        if(isupper(msg[i]))
           // add to the cipher the character plus the key and subtract ASCII 65 value ('A').
           // the value obtained do modulo 26 (english alphabet letters) and add ASCII value 65 back.
           cipher += (msg[i] + keyValue - 65)%26 + 65;
          // verify if the character is lower case
          else if(islower(msg[i]))
               //** the same as above. ASCII value 97 ('a')
               cipher += (msg[i] + keyValue - 97)%26 + 97;
          else
               cipher += msg[i];
    }
    return cipher;
}
// The decryption will be done using the brute force attack by
// checking all possible keys
// string encMessage - the encrypted message
void decrypt(string encMessage)
{
     // the variable for storing the plaintext
    string plaintext;
     // we will try for each key and we will do the decryption
    for(int keyTry=0;keyTry<26;keyTry++)
    {
        plaintext = "";
          // parse accordingly based on the message length
        for(int i=0;i<encMessage.length();i++)
        {
               // check if the character is upper case
            if(isupper(encMessage[i]))
            {
                if((encMessage[i] - keyTry - 65)<0)
                    plaintext += 91 + (encMessage[i] - keyTry - 65);
                else
                    plaintext += (encMessage[i] - keyTry - 65)%26 + 65;
            }
               // check if the character is lower case
            else if(islower(encMessage[i]))
            {
                if((encMessage[i] - keyTry - 97) < 0)
                    plaintext += 123 + (encMessage[i] - keyTry - 97);
                else
                    plaintext += (encMessage[i] - keyTry - 97)%26 + 97;
            }
            else
                plaintext += encMessage[i];
        }
        cout << "BRUTE-FORCE ATTACK (DECRYPTION) - The clear text for key -> " << keyTry << " :- " << plaintext << endl;
    }
}
int main()
{
     int encKey;
     string cleartext;
     cout << "ENCRYPTION - Enter the text for encryption -> ";
     getline(cin,cleartext);
     cout << "Enter the key for encryption the text -> ";
     cin >> encKey;
     string encryptedMessage = encrypt(cleartext,encKey);
     cout << "ENCRYPTED MESSAGE - The encrypted message is -> " << encryptedMessage << endl << endl;
     //** brute force attack
     decrypt(encryptedMessage);
}
Listing 21-1

Brute Force Attack on a Caesar Cipher

../images/496528_1_En_21_Chapter/496528_1_En_21_Fig2a_HTML.jpg../images/496528_1_En_21_Chapter/496528_1_En_21_Fig2b_HTML.jpg
Figure 21-2

Basic string generation for a brute-force attack (different states of generating strings)

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// We are using a linked list data structure.
// The reasong is to avoid some of the restrictions
//      based on the generation of the string length.
// Our list has to be converted to string in
//      such way that it can be used. The current conversion
//      might be a little slower comparing with other methods
//      due to the fact that the conversion is happening with
//      each cycle.
// Another solution consists in implementing a solution based
//      on the generation of the allocation for the string with
//      a fixed size equal with 20 characters (which is more than
//      enough.
// the structure definition for holding the characters (strings)
typedef struct charactersList charlist_t;
struct charactersList
{
     // the character
    unsigned char character;
     // the next character
    charlist_t* nextCharacter;
};
// The method will return a new initialized charlist_t element.
// The element returned is charlist_t
charlist_t* new_characterList_element()
{
    charlist_t* elementFromTheList;
     if ((elementFromTheList = (charlist_t*) malloc(sizeof(charlist_t))) != 0)
    {
        elementFromTheList->character = 0;
        elementFromTheList->nextCharacter = NULL;
    }
    else
    {
        perror("The allocation using malloc() has failed.");
    }
    return elementFromTheList;
}
 // allocation free memory by the characters list
 // listOfCharacters - represents a pointer for the first element within the list
void freeAllocation_CharactersList(charlist_t* listOfCharacters)
{
    charlist_t* currentCharacter = listOfCharacters;
    charlist_t* nextCharacter;
    while (currentCharacter != NULL)
    {
        nextCharacter = currentCharacter->nextCharacter;
        free(currentCharacter);
        currentCharacter = nextCharacter ;
    }
}
// the function display the current list of characters
// the function will iterate through the whole list and it will print all the characters
void showCharactersList(charlist_t* list)
{
    charlist_t* nextCharacter = list;
    while (nextCharacter != NULL)
    {
        printf("%d ", nextCharacter->character);
        nextCharacter = nextCharacter->nextCharacter;
    }
    printf(" ");
}
// the function will return the next sequence of characters.
// the characters are treated as numbers 0-255
// the function proceeds by incrementation of the character from the first position
void nextCharactersSequence(charlist_t* listOfCharacters)
{
    listOfCharacters->character++;
    if (listOfCharacters->character == 0)
    {
        if (listOfCharacters->nextCharacter == NULL)
        {
            listOfCharacters->nextCharacter = new_characterList_element();
        }
        else
        {
            nextCharactersSequence(listOfCharacters->nextCharacter);
        }
    }
}
int main()
{
    charlist_t* sequenceOfCharacters;
    sequenceOfCharacters = new_characterList_element();
    // this while will work for all possibles combinations
    // this has to be stopped manually
    while (1)
    {
        nextCharactersSequence(sequenceOfCharacters);
        showCharactersList(sequenceOfCharacters);
    }
    freeAllocation_CharactersList(sequenceOfCharacters);
}
Listing 21-2

Basic String Generation Source Code

Buffer Overflow Attack

A buffer represents a temporary area that is used for storing data. At the moment when more data is placed by the programs or system processes, an extra data overflow will occur.

In a buffer-overflow attack , the extra data being stored can store specific instructions to take actions designed by hackers or malicious users. As an example, the data could trigger an event (function or process) to destroy files or reveal private data about users.

The attacker uses a buffer overflow to get an advantage from a program that is being executed and is waiting for user interaction. There are two types of buffer overflows: stack-based and heap-based. In a heap-based overflow, it is very difficult to launch and execute attacks based on flooding the memory space reserved for the program and its execution. In a stack-based overflow, the exploitation of the applications and programs is done on the memory stack, which is the memory space used to store the input data from the user.

The following example (see Figure 21-3 and Listing 21-3) shows the danger of such situations for C++ applications. In the example provided, we won’t do any implementation for malicious code injection. We show the main process for buffer overflow. As a comparison between modern compilers vs. old compilers, modern compilers provide options for overflow checking during the compile or linking process but at the running time it is quite difficult to check the situation without having a protection mechanism such as the handling process of the exceptions.
../images/496528_1_En_21_Chapter/496528_1_En_21_Fig3_HTML.jpg
Figure 21-3

Buffer overflow execution

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
        // We allocate a buffer of 5 bytes which includes also the termination, NULL.
        // The allocation should be done as 8 bytes which is two double words.
        // For overflowing process we will need more than 8 bytes.
        // if the user provides more than 8 characters for the input,
        // an access violation and fault segmentation
       char buffer_test_example[5];
        // execution of the program
       if (argc < 2)
       {
              printf("Function strcpy() will not be executed... ");
              printf("The syntax: %s <characters> ", argv[0]);
              exit(0);
       }
        // Take the input from the user and copy it to the buffer.
        // The process is done without verifying the bound
       strcpy(buffer_test_example, argv[1]);
       printf("The content of thebuffer -> %s ", buffer_test_example);
       printf("The function strcpy() is being executed... ");
       return 0 ;
}
Listing 21-3

Implementation of the Buffer Overflow Example

Conclusion

The current chapter covered two important attacks, brute-force attacks and buffer overflow attacks. You are now capable of
  • Understanding the brute-force and buffer overflow attacks

  • Understanding the main concepts that form the basics of designing such attacks

  • Understanding the limitations between stack-based and heap-based buffer overflows

References

  1. [1]

    M. I. Mihailescu and S. Loredana Nita, “Three-Factor Authentication Scheme Based on Searchable Encryption and Biometric Fingerprint” in 2020 13th International Conference on Communications (COMM). Bucharest, Romania, 2020, pp. 139-144, doi: 10.1109/COMM48946.2020.9141956.

     
  2. [2]

    M. I. Mihailescu, S. L. Nita, and V. C. Pau. “Applied Cryptography in Designing e-Learning Platforms” in 16th International Scientific Conference “eLearning and Software for Education.” Bucharest, Apr. 2020, vol. 2, pp. 179–189, doi: 10.12753/2066-026X-20-108.

     
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.150.80