These days many smartphone applications implement some cryptographic encryption on the data in transit even though if SSL is in place. Now if you are doing a vulnerability assessment of such application, it becomes necessary to break this encryption in order to manipulate parameter values and uncover vulnerabilities.
One of my friend asked me if I could help him in decrypting the traffic of one such application. This being the 4th application that I came across with such behavior so thought of writing a blog post about it.
There can be multiple approach to workaround this encryption but we will cover the following two methods that I generally follow,
Data decryption with Cycript can be a bit easier as Key/IV, passphrase or other required conditions are already set. Your first goal will be to identify the encryption used which can be achieved by identifying the dumped headers. In this case, the encryption used was AES-256.
Next, identify methods that encrypt/decrypt requests and responses. To make sure that the identified methods are the right one, we can use THEOS logify to log these methods in system logs and check for argument types and values.
Once you have identified these details, let us see how we can decrypt the data with Cycript.
The output will contain the decrypted data in plaintext. To encrypt the plaintext data (or data with your added payloads), similar approach was there.
To automate the entire process, a shell script can be written. For example, following shell script will automate the data decryption,
You run the above shell script with "bash decrypt.sh encrypted_base64_data pid_of_app"
Since Introspy performs Crypto profiling, most of the cryptographic related details that we require will be logged inside the introspy.db file. Generate a report out of this SQLite database using Introspy Analyzer. Open report.html file with any of your browser and you will see details similar to the one given below.
Click on Hide All button as we are only interested in the Crypto related logged details. You can see that there are three calls registered. As you can guess, one for generating key and other for actual encryption and decryption of the data.
Following screenshot shows the argument values of PBKDF method call and a Base64 encoded derived key.
Let us decode and convert the key to hex bytes as shown below. It looks like 32 bytes i.e. 256-bit key.
echo -n "+P3+CC+wKFhkZMhj2PqcHur9e6WbZAUQlmfoLPLWVgc=" | base64 -D | xxd -p
To verify if the derived key is correct, generate a key based on available values i.e. salt, password and iteration counts (rounds).
So the 256-bit key is f8fdfe082fb028586464c863d8fa9c1eeafd7ba59b6405109667e82cf2d65607 which is exactly what we have.
Looking at the other method call, we can see the encrypted data and the resultant plaintext data as logged by the Introspy.
Let us go ahead and decrypt the data using OpenSSL with the following command,
echo -n encrypted_base64_data | base64 -D | openssl aes-256-cbc -d -nosalt -K our_key -iv 0
Yes, we got the command right. Plaintext data logged by Introspy and the plaintext data output from OpenSSL are similar. Similarly, we can encrypt the data back with the following command,
echo -n plaintext_data | openssl aes-256-cbc -e -nosalt -K our_key -iv 0 | base64
You can easily automate this with a shell script. However, I went ahead and checked for a script in python so that we can create a Burp suite extension out of it.
Reference for Python code: http://passingcuriosity.com/2009/aes-encryption-in-python-with-m2crypto/
One of my friend asked me if I could help him in decrypting the traffic of one such application. This being the 4th application that I came across with such behavior so thought of writing a blog post about it.
There can be multiple approach to workaround this encryption but we will cover the following two methods that I generally follow,
- Decrypting the data with Cycript.
- Obtaining key and encryption info using Introspy and then decrypting/re-encrypting the data with OpenSSL.
1. Decrypting data with Cycript
Data decryption with Cycript can be a bit easier as Key/IV, passphrase or other required conditions are already set. Your first goal will be to identify the encryption used which can be achieved by identifying the dumped headers. In this case, the encryption used was AES-256.
Next, identify methods that encrypt/decrypt requests and responses. To make sure that the identified methods are the right one, we can use THEOS logify to log these methods in system logs and check for argument types and values.
Once you have identified these details, let us see how we can decrypt the data with Cycript.
# Store encrypted data in a variable cy# var encdata = "HHNxq8n5ow95Nw9meMu6GfHGHN+5SpF/gX3vPOONk0vmicGgJdsmT/BMYR6M9jNZT82v6PDnS1POnhI4i8gK0VicZBlxI7zn43KECpfJLM7HFXt4AMQL1/Ad/rTwljwRwE9TC0dALCU9Sekkccv8vva5w4RIFuBwcj4zczj+MSuZrsYuWRwjAj9N1QYeu2X7J+QtPUwxt7mKXW6x252lQg=="; # Convert NSString to NSData cy# var mydata = [encdata dataUsingEncoding:4]; # Call class method with required parameters cy# var decdata = [OLDataEncryptor decryptResponse:mydata]; # Convert the output data from NSData back to NSString cy# var ptstring = [[NSString alloc] initWithData:decdata encoding:4];
The output will contain the decrypted data in plaintext. To encrypt the plaintext data (or data with your added payloads), similar approach was there.
# Store encrypted data in a variable cy# var ptstring = “name=aditya&uname=oldmanlab'&isnewuser=true“; # Convert NSString to NSData cy# var mydata = [ptstring dataUsingEncoding:4]; # Get instance of a class. choose() will return an array (if multiple instances, so pick up the right one) cy# var myobj = choose(OLDataEncryptor); # Call instance method with required parameters cy# var encdata = [myobj encryptRequest:mydata]; # Convert the output data from NSData back to NSString cy# var encrequest = [[NSString alloc] initWithData:encdata encoding:4];
To automate the entire process, a shell script can be written. For example, following shell script will automate the data decryption,
#!/bin/sh data=$1 echo "var encdata = @\"$data\";" > /tmp/oldman.cy echo -e "var mydata = [encdata dataUsingEncoding:4];" >> /tmp/oldman.cy echo -e "var decdata = [OLDataEncryptor decryptResponse:mydata]" >> /tmp/oldman.cy echo -e "var ptstring = [[NSString alloc] initWithData:decdata encoding:4];" >> /tmp/oldman.cy cycriptoutput=`cycript -p $2 /tmp/oldman.cy`
You run the above shell script with "bash decrypt.sh encrypted_base64_data pid_of_app"
2. Introspy + OpenSSL
Since Introspy performs Crypto profiling, most of the cryptographic related details that we require will be logged inside the introspy.db file. Generate a report out of this SQLite database using Introspy Analyzer. Open report.html file with any of your browser and you will see details similar to the one given below.
Click on Hide All button as we are only interested in the Crypto related logged details. You can see that there are three calls registered. As you can guess, one for generating key and other for actual encryption and decryption of the data.
Following screenshot shows the argument values of PBKDF method call and a Base64 encoded derived key.
Let us decode and convert the key to hex bytes as shown below. It looks like 32 bytes i.e. 256-bit key.
echo -n "+P3+CC+wKFhkZMhj2PqcHur9e6WbZAUQlmfoLPLWVgc=" | base64 -D | xxd -p
To verify if the derived key is correct, generate a key based on available values i.e. salt, password and iteration counts (rounds).
So the 256-bit key is f8fdfe082fb028586464c863d8fa9c1eeafd7ba59b6405109667e82cf2d65607 which is exactly what we have.
Looking at the other method call, we can see the encrypted data and the resultant plaintext data as logged by the Introspy.
Let us go ahead and decrypt the data using OpenSSL with the following command,
echo -n encrypted_base64_data | base64 -D | openssl aes-256-cbc -d -nosalt -K our_key -iv 0
Yes, we got the command right. Plaintext data logged by Introspy and the plaintext data output from OpenSSL are similar. Similarly, we can encrypt the data back with the following command,
echo -n plaintext_data | openssl aes-256-cbc -e -nosalt -K our_key -iv 0 | base64
You can easily automate this with a shell script. However, I went ahead and checked for a script in python so that we can create a Burp suite extension out of it.
import M2Crypto import binascii from base64 import b64encode, b64decode ENC=1 DEC=0 def AES_build_cipher(key, iv, op=ENC): return M2Crypto.EVP.Cipher(alg='aes_256_cbc', key=key, iv=iv, op=op) def AES_encryptor(key,msg, iv=None): #Decode the key and iv key = b64decode(key) if iv is None: iv = '\0' * 16 else: iv = b64decode(iv) # Return the encryption function def encrypt(data): cipher = AES_build_cipher(key, iv, ENC) v = cipher.update(data) v = v + cipher.final() del cipher v = b64encode(v) return v print "AES encryption successful\n" return encrypt(msg) def AES_decryptor(key,msg, iv=None): #Decode the key and iv key = b64decode(key) if iv is None: iv = '\0' * 16 else: iv = b64decode(iv) # Return the decryption function def decrypt(data): data = b64decode(data) cipher = AES_build_cipher(key, iv, DEC) v = cipher.update(data) v = v + cipher.final() del cipher return v print "AES dencryption successful\n" return decrypt(msg) if __name__ == "__main__": key="+P3+CC+wKFhkZMhj2PqcHur9e6WbZAUQlmfoLPLWVgc=" msg="HHNxq8n5ow95Nw9meMu6GfHGHN+5SpF/gX3vPOONk0vmicGgJdsmT/BMYR6M9jNZT82v6PDnS1POnhI4i8gK0VicZBlxI7zn43KECpfJLM7HFXt4AMQL1/Ad/rTwljwRwE9TC0dALCU9Sekkccv8vva5w4RIFuBwcj4zczj+MSuZrsYuWRwjAj9N1QYeu2X7J+QtPUwxt7mKXW6x252lQg==" dec = AES_decryptor(key,msg=msg) print dec enc = AES_encryptor(key,msg=dec) print enc print msg






