Click here to Skip to main content
16,004,568 members
Articles / Security / Cryptography
Tip/Trick

Attack AES-CTR encryption using C++ and OpenSSL

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
11 Jul 2024CPOL3 min read 3.5K   3   3
C++ (CygWin GCC) and OpenSSL code to Attack upon AES-CTR encryption

Introduction

I wrote an article in my LinkedIn profile, so I thought to post it also in code project. This attack is originally written by Prof Bill Buchanan OBE in the following link,

https://billatnapier.medium.com/can-i-break-aes-encryption-yes-31bdf539aba0

It explains in detail, how this attack work. He is originally using OpenSSL through command line.

I have automated the attack using C++ (CygWin GCC with Eclipse over Windows OS) OpenSSL library.

Background

1. It generates the key from the password using Password-Based Key Derivation Function.

2. Using the key it encrypts the message "Pay Bob 1 dollar" using AES counter mode.

3. The 9th byte contains the amount and with simple bitwise operation I modify the amount on the cipher text.

Image 1

4. Decrypting the cipher text give the modified message "Pay Bob 9 dollar".

This is how man-in-the-middle sitting between two parties attack by capturing the data and modifying it without knowing the key and without decrypting and it happens between 2 and 3.

The output of the code is as follows.

Image 2

How It Works

The process of encryption of data in AES Counter mode is as shown in the image below.

Image 3

The process of decryption of data in AES counter mode is as shown in the image below.

Image 4

Image 5The process of encryption and decryption is almost the same. It take the counter and encrypts it with the key to get the encrypted counter [EC]. There are lot of article on the internet about how AES-CTR works.

They both perform the encryption of the counter and get the encrypted counter [EC]. The plaintext is performed XOR operation with [EC] to get the cipher text during encryption process or the ciphertext is performed XOR operation with [EC] during decryption process as shown in the image.

Example

Assume, as in the case above, that Bob's hired attacker Eve is able to decipher the cypher text while Alice is sending a transaction to the bank. The transaction appears as "Pay Bob 1 dollar" but is encrypted, as shown below. Assume once more that the attacker using the educated estimate is aware that the ninth byte contains the number 1. Before the transaction reaches the bank, Eve, the attacker, wants to alter the amount from 1 to 9 using only the ciphertext.

Quote:

0x7b 0xfe 0x7c 0x81 0x60 0x3e 0x86 0xe3 - 0x12 0x82 0x8e 0x1e 0x1e 0xc2 0xd6 0x42

Let Pi be the one-byte plan text (as determined by the attacker) at ith location, Ci bet the one-byte cypher text at ith position, and ECi be the one-byte encrypted counter at ith position. Thus, by encrypting data in AES counter mode, the cipher text,

Ci = ECi xor Pi

Considering that ECi is unknown and Ci and Pi are known. Let NPi represent the new plain text that has to be altered at the attacker-determined ith place.

The attacker's objective is to use Ci to determine the new cypher text NCi, so that the plain text should be the new plain text NPi once the cypher text has been decrypted by the bank. That is, based on the picture above.

NCi = ECi xor NPi

Let,

Ci=ECi xor Pi, xor on both side with Pi.

Ci xor Pi = (ECi xor Pi xor Pi). Since (Pi xor Pi)= 0, therefore,

Ci xor Pi = ECi.

XOR both side with NPi, so,

Ci xor Pi xor NPi = ECi xor NPi = NCi, from the above definition.

Therefore,

NCi = Ci xor Pi xor NPi.

From the above example

NCi = 0x12 xor 0x01 xor 0x09 = 0x1a.

Therefore the new cipher is,

Quote:

0x7b 0xfe 0x7c 0x81 0x60 0x3e 0x86 0xe3 - 0x1a 0x82 0x8e 0x1e 0x1e 0xc2 0xd6 0x42

Decrypting the above cipher text using AES Counter mode will result in

Quote:

Pay Bob 9 dollar

Using the code

The code is as follows and is self explanatory.

C++
#include <string.h>

#include <iostream>
using namespace std;

#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/bioerr.h>
#include <openssl/evp.h>
#include <openssl/evperr.h>

int main()
{
	unsigned char szPass[] = { "strongestpassword" };
	cout << "Password:" << endl;
	BIO_dump_fp(stdout, (const char*)szPass, strlen((const char*)szPass));
	cout << endl << endl;
	unsigned char szKey[16];
	PKCS5_PBKDF2_HMAC((const char*)szPass, strlen((const char*)szPass), NULL, 0, 5, EVP_md5(), 16, szKey);
	cout << "Key derived from password using MD5:" << endl;
	BIO_dump_fp(stdout, (const char*)szKey, 16);
	cout << endl << endl;

	unsigned char szMessage[] = { "Pay Bob 1 dollar" };
	cout << "Transaction message:" << endl;
	BIO_dump_fp(stdout, (const char*)szMessage, strlen((const char*)szMessage));
	cout << endl << endl;
	unsigned char szCipher[16];
	int nCipherLen = 0;
	int nTotCipherLen = 0;

	EVP_CIPHER_CTX* pAES128Ctx = EVP_CIPHER_CTX_new();;
	EVP_EncryptInit(pAES128Ctx, EVP_aes_128_ctr(), szKey, NULL);
	EVP_EncryptUpdate(pAES128Ctx, szCipher, &nCipherLen, szMessage, strlen((const char*)szMessage));
	nTotCipherLen = nCipherLen;
	nCipherLen = 0;
	EVP_EncryptFinal(pAES128Ctx, szCipher, &nCipherLen);
	nTotCipherLen += nCipherLen;
	EVP_CIPHER_CTX_free(pAES128Ctx);
	cout << "Encrypted message:" << endl;
	BIO_dump_fp(stdout, (const char*)szCipher, nTotCipherLen);
	cout << "If you pass this cipher over the network," << endl << "attacker Bob (Man-In-The-Middle) may capture and modify 9th encrypted byte and send the encrypted transaction!" << endl;
	cout << endl << endl;

	// MAN-IN-THE-MIDDLE ATTACK mofified the 9th byte and increase the value.
	szCipher[8] ^= 0x01; // Remove One dollar.
	szCipher[8] ^= 0x09; // Add Nine dollar.

	cout << "Modified Encrypted message:" << endl;
	BIO_dump_fp(stdout, (const char*)szCipher, nTotCipherLen);
	cout << endl << endl;

	unsigned char szDycMsg[16];
	int nDycMsgLen = 0;
	int nTotDycMsgLen = 0;
	EVP_CIPHER_CTX* pMSG128Ctx = EVP_CIPHER_CTX_new();
	EVP_DecryptInit(pMSG128Ctx, EVP_aes_128_ctr(), szKey, NULL);
	EVP_DecryptUpdate(pMSG128Ctx, szDycMsg, &nDycMsgLen, szCipher, nTotCipherLen);
	nTotDycMsgLen = nDycMsgLen;
	nDycMsgLen = 0;
	EVP_DecryptFinal(pMSG128Ctx, szDycMsg, &nDycMsgLen);
	nTotDycMsgLen += nDycMsgLen;
	EVP_CIPHER_CTX_free(pMSG128Ctx);

	cout << "Modified derypted message the bancker receives:" << endl;
	BIO_dump_fp(stdout, (const char*)szDycMsg, nTotDycMsgLen);
	cout << endl << endl;

	return 0;
}

Conclusion

There are many encryption algorithms available but not all are recommended, such as AES-CTR but there are other counter modes that are highly recommended such as GCM and CCM.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
C++ Data Security Developer and Visual C++ programmer, CompTIA Security+.

Look at my other post in codeproject.
https://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=1584774

Comments and Discussions

 
QuestionImages are missing... Pin
Ștefan-Mihai MOGA11-Jul-24 0:39
professionalȘtefan-Mihai MOGA11-Jul-24 0:39 
AnswerRe: Images are missing... Pin
Daniel Ramnath11-Jul-24 1:42
Daniel Ramnath11-Jul-24 1:42 
Now the image is updated. I had given a request to change for the update and now after a delay have done it.
Jesus saves

GeneralRe: Images are missing... Pin
Ștefan-Mihai MOGA11-Jul-24 2:06
professionalȘtefan-Mihai MOGA11-Jul-24 2:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.