A recent feature of Jadx allows to easily hook functions in Frida.
Problem
I recently used an application on Android where I could buy documents and read them inside the applications but I was not able to read them on my computer of on by E-reader.
In addition the application is not really convenient, it does not allow to jump to a specific page or chapter and it does not remember what which page you where last time you open it. It is quite annoying while reading a 800-page book and having to swipe until the end of the book each time you open it. Thus I investigated on how I could solve that problem. I am not an Android expert thus I tried to find the easiest way to solve that and hopefully I was helped by @SamZorSec and @cryptax.
I opened the application inside Android Studio Emulator and hopefully the debug logs where activated. When I opened a document, I got the following:
1
2
3
4
5
6
7
8
9
2023-11-12 16:15:05.822 D MasterKey: MasterKey{keyAlias=_androidx_security_master_key_, isKeyStoreBacked=true}
2023-11-12 16:15:05.852 D decryptionFile - outputFile: /data/user/0/com.application/cache/file3947809231687767649.pdf
2023-11-12 16:15:06.800 D app_time_stats: avg=6.71ms min=1.73ms max=27.31ms count=28
2023-11-12 16:15:07.220 I Background young concurrent copying GC freed 74231(15MB) AllocSpace objects, 0(0B) LOS objects, 27% free, 36MB/50MB, paused 251us,254us total 117.475ms
2023-11-12 16:15:07.814 D app_time_stats: avg=8.20ms min=3.56ms max=34.33ms count=27
2023-11-12 16:15:08.815 D app_time_stats: avg=7.11ms min=2.97ms max=25.29ms count=30
2023-11-12 16:15:09.093 I Background young concurrent copying GC freed 74191(15MB) AllocSpace objects, 0(0B) LOS objects, 27% free, 36MB/50MB, paused 412us,279us total 100.955ms
2023-11-12 16:15:09.830 D app_time_stats: avg=8.87ms min=3.81ms max=62.28ms count=25
2023-11-12 16:15:10.644 D Deleting /data/user/0/com.application/cache/file3947809231687767649.pdf
Thus the file I was reading is decrypted with a key, store in the application cache, displayed and deleted right after even though I did not close the document in the application. I was able to locate the PDF file in the file system:
But as described in the log it is encrypted.
Jadx
I opened the application in Jadx and search fo the string “decryptionFile”. I found out that the the file was decrypted in a function with the same name which also prints the log messages.
Thus I thought that if I would be able to stop at the end of the decryptionFile function I should have the decrypted file in the file system at the path display in the logs. At this point, I discovered a very nice feature of Jadx which I was not aware of previously. If you right click on the function name, you would have in the menu the option “Copy as frida snippet”
This feature was introduced in version 1.3.3 of Jadx. Then I pasted the snippet in my editor I obtained:
1
2
3
4
5
letFileSec=Java.use("com.application.utils.FileSec");FileSec["decryptionFile"].implementation=function(encryptedInputFile,outputFile){console.log(`FileSec.decryptionFile is called: encryptedInputFile=${encryptedInputFile}, outputFile=${outputFile}`);this["decryptionFile"](encryptedInputFile,outputFile);};
The hook for Frida is ready to be used and it is really convenient. Lets see how to use it.
Frida
First I launched the application in the emulator and checked that Frida would see the process:
1
2
3
4
5
6
7
8
9
10
frida-ps -Ua
PID Name Identifier
----- ----------- ---------------------------------------
1869 Google com.google.android.googlequicksearchbox
1869 Google com.google.android.googlequicksearchbox
1630 Messages com.google.android.apps.messaging
1774 Photos com.google.android.apps.photos
1087 SIM Toolkit com.android.stk
11213 Settings com.android.settings
10447 Application com.application
Then I modified my hook to exit the application as soon at the file is decrypted so it would not delete the file in clear in the file system:
1
2
3
4
5
6
7
8
letFileSec=Java.use("com.application.utils.FileSec");FileSec["decryptionFile"].implementation=function(encryptedInputFile,outputFile){console.log(`FileSec.decryptionFile is called: encryptedInputFile=${encryptedInputFile}, outputFile=${outputFile}`);this["decryptionFile"](encryptedInputFile,outputFile);console.log("Exiting application")varsysexit=Java.use("java.lang.System");sysexit.exit(0);};
Then I executed my script with Frida:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ frida -U -l decryption_file.js Application
____
/ _ | Frida 16.1.5 - A world-class dynamic instrumentation toolkit
|(_|| > _ | Commands:
/_/ |_|help -> Displays the help system
. . . . object? -> Display information about 'object' . . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to Android Emulator 5554(id=emulator-5554)[Android Emulator 5554::Application ]-> FileSec.decryptionFile is called: encryptedInputFile=/data/user/0/com.application/files/pdfs/inapp.en.r2.pdf, outputFile=/data/user/0/com.application/cache/file818285190354043103.pdf
Exiting application
Process terminated
[Android Emulator 5554::Application ]->
Thank you for using Frida!
As soon as I opened the file in the application, the decryption function is called and the process is killed. I open the device filesystem and the file was still there and I could save it in clear on my host machine.