withsecurelabs / android-keystore-audit Goto Github PK
View Code? Open in Web Editor NEWLicense: Other
License: Other
Thank you for providing such great tooling. Extremely helpful.
However, 2 scripts do not work correctly on Android 9 and newer Frida version (>12.6).
after running the bypass() command, Frida >= 12.6 throws the following error message:
exception catched!Error: Wrapper is disposed; perhaps it was borrowed from a hook instead of calling Java.retain() to make a long-lived wrapper?
Unhandled exception in event loop:
File "c:\python38\lib\asyncio\proactor_events.py", line 768, in _loop_self_reading
f.result() # may raise
File "c:\python38\lib\asyncio\windows_events.py", line 808, in _poll
value = callback(transferred, key, ov)
File "c:\python38\lib\asyncio\windows_events.py", line 457, in finish_recv
raise ConnectionResetError(*exc.args)
Exception [WinError 995] The I/O operation has been aborted because of either a thread exit or an application request
Press ENTER to continue...
Do you know how to modify the execute() function to be compatible with newer Frida version, please?
Similarly, the showKeyguard() function of the script https://github.com/FSecureLABS/android-keystore-audit/blob/master/frida-scripts/keyguard-credential-intent.js crashes when executed on newer Frida versions:
showKeyguard()
Process crashed: Trace/BPT trap
***
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/sargo/sargo:9/PQ3B.190801.002/5674421:user/release-keys'
Revision: 'MP1.0'
ABI: 'arm64'
pid: 25273, tid: 25292, name: Thread-2 >>> [APPNAME] <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0x7ff5eaeae4'
x0 0000000000000000 x1 00000000000062cc x2 0000000000000006 x3 0000000000000000
x4 6461706b616572ff x5 0000000000000080 x6 0000000000000080 x7 8000000000000000
x8 0000000000000083 x9 0000000000000001 x10 0000000000000002 x11 00000075951bc140
x12 0000000018000004 x13 0000000000000058 x14 ffffffffffffffff x15 0029543fc8f56283
x16 00000074fca77188 x17 00000075925e2cd0 x18 00000074f78ec01a x19 0000000000000006
x20 00000000000062b9 x21 00000074f78ebb80 x22 00000074fcaeae90 x23 00000074fcaec0f0
x24 000000750f9cc7e0 x25 00000074fcaec000 x26 0000000046508001 x27 ffffffffffffffff
x28 00000074fcaea000 x29 00000074f78eb8d0
sp 00000074f78eb850 lr 00000074fa971d84 pc 00000074fa971d9c
backtrace:
#00 pc 0000000001dc1d9c /system/app/Chrome/Chrome.apk (offset 0xf2e000)
It would be great, if you could update the scripts.
Thank you again for great research and scripts.
Hello,
Thank you for the clear blog on Android Keystore authentication, very helpful.
However, I think it's not a good idea to store the IV in sharedPreferences and reuse it for subsequent encryption operations with AES-GCM, as this exposes ciphertexts to a known-plaintext attack.
Proof of concept:
The following plaintexts have been encrypted with the demo-app:
P1: With AES-GCM you should not reuse
C1: bCqRKGQjnr07Qnk4WW5jeo9ARrEgdvFuHv0Wjxoz+fv3Q9+wsZaAQLpL8CzqAyhuNQ==
P2: The initialization vector
C2: byuAYC0Mspp/ZFYcA3Z4ZsBdDqgweeEhAsGcqLwfNjq0Mtq
The second plaintext can be derived by doing
P2 = C1 ⊕ C2 ⊕ P1
An alternative approach could be to generate a fresh IV for each encryption operation and prepend it to the ciphertext.
For reference, the following key and IV were used for the example, above:
Application Key: 59F20FB3213DDE76F4D4F6598F70771035AB3F10DBF3D968B474C3A6B6786D08
IV: A4C8A8392FEEBC671D21FA3E71C8E8E7
Cyberchef recipe:
From_Base64('A-Za-z0-9+/=',true)
XOR({'option':'Base64','string':'byuAYC0Mspp/ZFYcA3Z4ZsBdDqgweeEhAsGcqLwfNjq0Mtq'},'Standard',false)
XOR({'option':'Latin1','string':'With AES-GCM you should not reuse'},'Standard',false)
It was reported to us that one of the Frida scripts has a bug. The fix is described here:
Step:
lintOptions {
abortOnError false
}
./gradlew build
App crashing immediately on start up
Output of adb logcat -b crash
:
01-01 19:24:52.070 24273 24273 E AndroidRuntime: FATAL EXCEPTION: main
01-01 19:24:52.070 24273 24273 E AndroidRuntime: Process: com.example.keystorecrypto, PID: 24273
01-01 19:24:52.070 24273 24273 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.keystorecrypto/com.example.keystorecrypto.MainActivity}: java.security.InvalidAlgorithmParameterException: java.lang.IllegalStateException: At least one biometric must be enrolled to create keys requiring user authentication for every use
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:107)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.os.Looper.loop(Looper.java:213)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:8178)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: Caused by: java.security.InvalidAlgorithmParameterException: java.lang.IllegalStateException: At least one biometric must be enrolled to create keys requiring user authentication for every use
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.security.keystore.AndroidKeyStoreKeyGeneratorSpi.engineInit(AndroidKeyStoreKeyGeneratorSpi.java:256)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.security.keystore.AndroidKeyStoreKeyGeneratorSpi$AES.engineInit(AndroidKeyStoreKeyGeneratorSpi.java:53)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at javax.crypto.KeyGenerator.init(KeyGenerator.java:519)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at javax.crypto.KeyGenerator.init(KeyGenerator.java:502)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at com.example.keystorecrypto.KeystoreManager.generateSymmetricKey(KeystoreManager.kt:86)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at com.example.keystorecrypto.KeystoreManager.generateMasterKeys(KeystoreManager.kt:33)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at com.example.keystorecrypto.SecureLocalManager.<init>(SecureLocalManager.kt:27)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at com.example.keystorecrypto.MainActivity.onCreate(MainActivity.kt:26)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8086)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8074)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1313)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3755)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: ... 11 more
01-01 19:24:52.070 24273 24273 E AndroidRuntime: Caused by: java.lang.IllegalStateException: At least one biometric must be enrolled to create keys requiring user authentication for every use
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.security.keystore.KeymasterUtils.addUserAuthArgs(KeymasterUtils.java:148)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: at android.security.keystore.AndroidKeyStoreKeyGeneratorSpi.engineInit(AndroidKeyStoreKeyGeneratorSpi.java:254)
01-01 19:24:52.070 24273 24273 E AndroidRuntime: ... 22 more
I was doing tests on android 13 (API 33) and it always fails with the following message:
`javax.crypto.IllegalBlockSizeException
at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:613)
at javax.crypto.Cipher.doFinal(Cipher.java:2056)Caused by: android.security.KeyStoreException: Key user not authenticated (internal Keystore code: -26 message: In KeystoreOperation::update
Caused by:
0: In update: KeyMint::update failed.
1: Error::Km(ErrorCode(-26))) (public error code: 2 internal Keystore code: -26)
at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:369)
at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
at android.security.KeyStoreOperation.update(KeyStoreOperation.java:115)
at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.update(KeyStoreCryptoOperationChunkedStreamer.java:222)
at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.update(KeyStoreCryptoOperationChunkedStreamer.java:156)
at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:179)
at android.security.keystore2.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:603)`
Android Device Info:
The app is crashing when biometric authentication is successful after clicking on LOCK button
From the logcat stacktrace :
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.keystorecrypto, PID: 20738
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:506)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: javax.crypto.AEADBadTagException
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:517)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
at com.example.keystorecrypto.KeystoreManager.encryptApplicationKey(KeystoreManager.kt:112)
at com.example.keystorecrypto.SecureLocalManager.loadOrGenerateApplicationKey(SecureLocalManager.kt:55)
at com.example.keystorecrypto.MainActivity.onAuthenticationSuccessful(MainActivity.kt:118)
at com.example.keystorecrypto.biometrix.BiometricCallbackV28.onAuthenticationSucceeded(BiometricCallbackV28.java:20)
at android.hardware.biometrics.BiometricPrompt$1.lambda$onAuthenticationSucceeded$1$BiometricPrompt$1(BiometricPrompt.java:548)
at android.hardware.biometrics.-$$Lambda$BiometricPrompt$1$ob5suq_ELA05xslg_M8nDaDCttg.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: android.security.KeyStoreException: Signature/MAC verification failed
at android.security.KeyStore.getKeyStoreException(KeyStore.java:1564)
at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
at android.security.keystore.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:373)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
at com.example.keystorecrypto.KeystoreManager.encryptApplicationKey(KeystoreManager.kt:112)
at com.example.keystorecrypto.SecureLocalManager.loadOrGenerateApplicationKey(SecureLocalManager.kt:55)
at com.example.keystorecrypto.MainActivity.onAuthenticationSuccessful(MainActivity.kt:118)
at com.example.keystorecrypto.biometrix.BiometricCallbackV28.onAuthenticationSucceeded(BiometricCallbackV28.java:20)
at android.hardware.biometrics.BiometricPrompt$1.lambda$onAuthenticationSucceeded$1$BiometricPrompt$1(BiometricPrompt.java:548)
at android.hardware.biometrics.-$$Lambda$BiometricPrompt$1$ob5suq_ELA05xslg_M8nDaDCttg.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
I/Process: Sending signal. PID: 20738 SIG: 9
Hello!
Please could this project get a license? We received a PR (sensepost/objection#452) in another project that uses code from this, and I'd like to make sure that contribution is ok.
Thanks!
Hello All,
I noticed that android 11 uses a different constructor for the BiometricPrompt$AuthenticationResult() function as you can find here: https://developer.android.com/reference/android/hardware/biometrics/BiometricPrompt.AuthenticationResult
Because of this the script will throw an error as it is expecting 2 arguments but gets 3.
Error: BiometricPrompt$AuthenticationResult(): argument types do not match any of:
.overload('android.hardware.biometrics.BiometricPrompt$CryptoObject', 'int')
at X (frida/node_modules/frida-java-bridge/lib/class-factory.js:563)
at value (frida/node_modules/frida-java-bridge/lib/class-factory.js:966)
at e (frida/node_modules/frida-java-bridge/lib/class-factory.js:547)
at <anonymous> (/fingerprint-bypass-via-exception-handling.js:65)
at apply (native)
at ne (frida/node_modules/frida-java-bridge/lib/class-factory.js:613)
at <anonymous> (frida/node_modules/frida-java-bridge/lib/class-factory.js:592)
Changing authenticationResultObj.$new(cryptoInst,null,0);
to authenticationResultObj.$new(cryptoInst,0);
And authenticationResultObj.$new(crypto,null,0);
to authenticationResultObj.$new(crypto,0);
respectively should fix the issue.
Made a quick fix and posted it on frida codeshare here:
https://codeshare.frida.re/@krapgras/android-biometric-bypass-update-android-11/
The applicationKey variable should be cleared from memory after locking the app.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.