Hook Android Java Encryption APIs with Frida: MD5, SHA1, MAC, Cipher & Signature
This tutorial demonstrates how to use Frida to hook Java-level encryption functions on Android, covering MD5, SHA1, MAC, DES/AES/RSA ciphers, and signature algorithms by intercepting update, digest, init, and doFinal methods and logging their inputs and outputs in various formats.
Preface
Hello everyone, I am a developer sharing a tutorial for learning purposes only; using the techniques for illegal activities is prohibited.
Prerequisites
Since encryption results are usually represented in Base64 or hex, we first define helper functions to convert and log data in these formats.
function showStacks() {
console.log("Stack trace:", Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
}
var ByteString = Java.use("com.android.okhttp.okio.ByteString");
function toBase64(tag, data) {
console.log(tag + " Base64:", ByteString.of(data).base64());
}
function toHex(tag, data) {
console.log(tag + " Hex:", ByteString.of(data).hex());
}
function toUtf8(tag, data) {
console.log(tag + " Utf8:", ByteString.of(data).utf8());
}What Is a Self‑Extraction Hook?
When an Android app uses Java‑level encryption APIs, the relevant methods (e.g., MessageDigest.update, MessageDigest.digest, Mac.init, Cipher.init, etc.) are always invoked. By hooking these methods we can capture the plaintext, key material, and ciphertext without modifying the app.
MD5 and SHA1 Hooking
Both MD5 and SHA1 share the same workflow; the only difference is the algorithm name passed to MessageDigest. Hooking update (all overloads) and digest allows us to log the data being hashed and the resulting digest.
var messageDigest = Java.use("java.security.MessageDigest");
messageDigest.update.overload('byte').implementation = function(data) {
console.log("--- MD5/SHA1 update(byte) called ---");
showStacks();
return this.update(data);
};
messageDigest.update.overload('java.nio.ByteBuffer').implementation = function(data) {
console.log("--- MD5/SHA1 update(ByteBuffer) called ---");
showStacks();
return this.update(data);
};
messageDigest.update.overload('[B').implementation = function(data) {
console.log("--- MD5/SHA1 update([B]) called ---");
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
showStacks();
return this.update(data);
};
messageDigest.digest.overload().implementation = function() {
console.log("--- MD5/SHA1 digest() called ---");
var result = this.digest();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest result";
toHex(tag, result);
toBase64(tag, result);
showStacks();
return result;
};
// Additional overloads for digest with parameters are hooked similarly.MAC Hooking
MAC algorithms require a secret key. By hooking Mac.init, Mac.update, and Mac.doFinal we can capture the key, the data fed into the MAC, and the final MAC value.
var mac = Java.use("javax.crypto.Mac");
mac.init.overload('java.security.Key').implementation = function(key) {
console.log("--- MAC init(Key) called ---");
var algorithm = this.getAlgorithm();
var tag = algorithm + " init Key";
var keyBytes = key.getEncoded();
toUtf8(tag, keyBytes);
toHex(tag, keyBytes);
toBase64(tag, keyBytes);
showStacks();
return this.init(key);
};
mac.update.overload('byte').implementation = function(data) {
console.log("--- MAC update(byte) called ---");
showStacks();
return this.update(data);
};
mac.doFinal.overload().implementation = function() {
console.log("--- MAC doFinal() called ---");
var result = this.doFinal();
var algorithm = this.getAlgorithm();
var tag = algorithm + " doFinal result";
toHex(tag, result);
toBase64(tag, result);
showStacks();
return result;
};DES/DESede/AES/RSA Hooking
These symmetric and asymmetric ciphers are instantiated via Cipher. Hooking init, update, and doFinal across their overloads captures keys, IVs, plaintext, and ciphertext.
var cipher = Java.use("javax.crypto.Cipher");
cipher.init.overload('int', 'java.security.Key').implementation = function(opmode, key) {
console.log("--- Cipher init(int, Key) called ---");
var algorithm = this.getAlgorithm();
var tag = algorithm + " init Key";
var keyBytes = key.getEncoded();
toUtf8(tag, keyBytes);
toHex(tag, keyBytes);
toBase64(tag, keyBytes);
showStacks();
return this.init(opmode, key);
};
// Additional overloads for init with AlgorithmParameterSpec, SecureRandom, etc.
cipher.doFinal.overload('[B').implementation = function(data) {
console.log("--- Cipher doFinal([B]) called ---");
var algorithm = this.getAlgorithm();
var tag = algorithm + " doFinal data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.doFinal(data);
var resTag = algorithm + " doFinal result";
toHex(resTag, result);
toBase64(resTag, result);
showStacks();
return result;
};Signature Hooking
Signature objects combine hashing and asymmetric encryption. Hooking Signature.update and Signature.sign reveals the data being signed and the generated signature.
var signature = Java.use("java.security.Signature");
signature.update.overload('byte').implementation = function(data) {
console.log("--- Signature update(byte) called ---");
showStacks();
return this.update(data);
};
signature.sign.overload().implementation = function() {
console.log("--- Signature sign() called ---");
var result = this.sign();
var algorithm = this.getAlgorithm();
var tag = algorithm + " sign result";
toHex(tag, result);
toBase64(tag, result);
showStacks();
return result;
};Practical Effect
When any Java‑level encryption method is used in the target APK, the above hooks automatically log the relevant inputs and outputs, making reverse‑engineering of cryptographic flows straightforward.
Conclusion
The self‑extraction hooks serve as a convenient auxiliary tool for analyzing Android encryption. They log stack traces and data in readable formats, but they are not a universal bypass; they simply expose the cryptographic material when the app invokes the standard Java APIs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
