PGP Decryption Bypass in Flutter Application

Reading time: Reading time 3 minutes

During the assessment of one of the financial applications built upon the flutter framework, we came across that the application was using PGP encryption for encrypting the API requests. It is pretty common for financial applications to be implementing traffic encryption, with AES seen to be the preferred algorithm for encrypting traffic. There is plenty of research already available on decrypting AES encrypted traffic.

In this blog post, I would like to explain the methodology we followed for decrypting the PGP encrypted traffic in this case along with the challenges that flutter possess from the point of view of reverse engineering and dynamic instrumentation. 

 

Requirements

  • Burp Suite
  • Frida
  • Re-Flutter
  • Doldrums

Methodology

Examining the application traffic in burp, one can see that the request and response are encrypted. To conduct a thorough security assessment, it is necessary to figure out a way to get plain text traffic of an application. 

request-1

The first step usually is to figure out what kind of encryption mechanism the application is using for encrypting the traffic. In this case, this was pretty straightforward. Just by base64 decoding the request/response data we could see that the application is using the OpenPGP library. 

 

request-base64

The next step usually is to decompile the application and go through the source code to see if there are any hard-coded encryption keys. This can easily be done by just opening the application in jadx for java/kotlin-based applications. But since this application is written using the flutter framework, the core application logic will be in libapp.so file which we cannot just throw into jadx. 

Before moving forward, a few details about the libapp.so format.

Good Read: Gaming Application Penetration Testing - My Favorite 9 Business Logical Flaws

The libapp.so file of a Flutter release build contains two snapshots: one for the VM isolate, and another for the isolate with actual substance. Each of these is split into a data section and an instructions section. The data section contains the isolate’s heap, whereas the instructions section contains the natively compiled code. Since the compiled code needs to be loaded into executable memory, it is placed in the .text section of the ELF file. The rest of the isolate’s heap, containing the VM object descriptions, is placed in the non-executable .rodata section.

You can refer to the following blog post for more details regarding the flutter architecture.

One good tool for reverse engineering flutter application is reflutter. ReFlutter modifies dart.cc to print classes, functions and rebuilds the flutter engine (libflutter.so). Once the apk is rebuilt with ReFlutter we can launch the application on the device and run the following command:

➜  ~ adb logcat -e reflutter | sed 's/.*DartVM//' >> reflutter.txt

Examining the reflutter.txt file, I could get the encryption key, decryption key, and passcode used for encrypting the traffic. 

reflutter

Here, the decryption key is basically a base64 encoded RSA private key. Using this private key along with the keyPassword, it was possible to decrypt the response data.

response-decrypt

But, the request body couldn't be decrypted using this private key. Comparing the public key (EncryptionKey) with the private key, it could be concluded that the application was using different pairs of public-private keys for encryption and decryption. 

request-decrypt-failed

One approach that can be used to get a plain text request body is to hook into the method responsible for encryption and then print out the plain text request passed to the encryption function passed as a parameter. Again going back to ReFlutter output, one function that looks interesting for our use case is “getEncryptedPGPRequest”.

reflutter-getencryption

For hooking into getEncryptedPGPRequest function using frida, we would need to know the offset of this function. For this, I will be using Doldrums.  

Doldrums is a reverse engineering tool for Flutter apps targeting Android. Concretely, it is a parser and information extractor for the Flutter/Dart Android binary. It outputs a full dump of all classes and functions present in the isolate snapshot, along with its offsets. 

doldrums

So now we launch the application with frida and search for the base address of libapp.so library. We would be adding the offset of getEncryptedPGPRequest function to the base address of libapp.so library.

var address = Module.findBaseAddress('libapp.so').add(0x3e8eb4)
console.log("Address: " + address)

Now, we can use Interceptor to print out the parameter passed to this function:

function hook_get_encrypted_pgp_request(address)
{
  Interceptor.attach(address, {
    onEnter: function(args,key) {
      console.log("Inside getEncryptedPGPRequest: ")
      console.log("Printing args: " + args[0].toString() )
     
      var retctn = 200

      var buf = Memory.readCString(ptr(args[0].toString()), retctn);
  console.log("Read Bytes: " + buf.toString() )

    },
    onLeave: function(retval)
    {
      console.log("Retval: " + retval.toString())
    }
  });
}

Running the application with the above script gives us the plain text request body.
cbq-request-encryption

The output is not perfect, but does the job :)

Good read: Understanding Insecure Direct Object References (IDOR)

Conclusion

As of the writing of this blog, Doldrums only supports parsing of VM snapshots that are produced using Dart SDK 2.12 and below. This is mainly because the format of Dart snapshot changes constantly. The developers of any Dart RE tool like doldrums will have a huge task of constantly monitoring for changes in the snapshot format and maintaining the tool. 

 

Published on Apr 25, 2022
Abhinav Vasisth
Written by Abhinav Vasisth
Abhinav Vasisth is a certified ethical hacker and the security research lead at Appknox, a mobile security suite that helps enterprises automate mobile security. Abhinav has been a critical member of Appknox for 5 years, reinventing the standards of mobile app security against evolving threats. He is highly regarded in the industry for his expertise, speaks at various security conferences like PHDays, and has collaborated with numerous enterprises to safeguard their digital assets.
When he's not outsmarting hackers, he listens to metal music or is lost in books.

Questions?

Chat With Us

Using Other Product?

Switch to Appknox

2 Weeks Free Trial!

Get Started Now