How to Reverse Engineer Android Login: Frida Hooking and DES Encryption Uncovered
This article walks through reverse‑engineering an Android login flow using Frida to hook methods, analyzes the DES/CBC encryption and MD5 signing process, reproduces the algorithm in JavaScript with CryptoJS, and provides full code and results for verification.
Preface
The previous article briefly used Frida to hook a simple execution flow; this continuation focuses on implementing automatic login.
Process Analysis
login
login → requestNetwork → instantiate JsonRequest → call JsonRequest.addRequestMap (first‑level view of the flow).
The final call is addRequestMap; inspecting it reveals the inner workings.
addRequestMap
addRequestMap is straightforward, passing RequestUtil.paraMap's return value to RequestUtil.encodeDesMap.
Inside you can even see the keyword Encrypt, which is the key term in the request.
RequestUtil.paraMap
Examining RequestUtil.paraMap shows an MD5 call, with the returned value in all‑uppercase letters.
md5
This is a standard MD5 operation.
RequestUtil.encodeDesMap
Continuing the analysis, encodeDesMap requires three parameters.
It uses this.desKey and this.desIV:
this.desKey = 65102933
this.desIV = 32028092encodeDesMap creates a DesSecurity instance and calls its encrypt64 method.
DesSecurity
This implements a DES/CBC algorithm: the DES key is the MD5 hash of desKey, the IV is desIV, and the encrypted result is Base64‑encoded.
Frida Verification Process
Static analysis suggests the above flow; to confirm, we hook the relevant methods with Frida.
Code
Java.perform(function () {
let jsonRequest = Java.use("com.dodonew.online.http.JsonRequest");
jsonRequest.addRequestMap.overload('java.util.Map','int').implementation = function (addMap, a) {
console.log("==== jsonRequest.addRequestMap called");
console.log("addMap:", addMap);
console.log("a:", a);
return this.addRequestMap(addMap, a);
};
let requestUtil = Java.use("com.dodonew.online.http.RequestUtil");
requestUtil.paraMap.overload('java.util.Map','java.lang.String','java.lang.String').implementation = function (addMap, append, sign) {
console.log("==== requestUtil.paraMap called");
console.log("addMap:", addMap);
console.log("append:", append);
console.log("sign:", sign);
return this.paraMap(addMap, append, sign);
};
let utils = Java.use("com.dodonew.online.util.Utils");
utils.md5.implementation = function (string) {
console.log("==== utils.md5 called");
console.log("string:", string);
let ret = this.md5(string);
console.log("return:", ret);
return ret;
};
requestUtil.encodeDesMap.overload('java.lang.String','java.lang.String','java.lang.String').implementation = function (data, desKey, desIV) {
console.log("==== requestUtil.encodeDesMap called");
console.log("data:", data);
console.log("desKey:", desKey);
console.log("desIV:", desIV);
return this.encodeDesMap(data, desKey, desIV);
};
});Effect
The analysis proved correct; if a hook fails, retry.
Algorithm Reproduction
We recreate the signing and encryption logic in JavaScript using CryptoJS for cross‑language compatibility.
Get sign
Only a few parameters are fixed; constructing them yields the required sign.
Hook md5 code
Java.perform(function () {
let utils = Java.use("com.dodonew.online.util.Utils");
utils.md5.implementation = function (string) {
console.log("==== utils.md5 called");
console.log("string:", string);
let ret = this.md5(string);
console.log("return:", ret);
return ret;
};
});Hook encodeDesMap code
JS code
function getSign(user, pass, time) {
var signStr = "equtype=ANDROID&loginImei=Androidnull&timeStamp=" + time + "&userPwd=" + pass + "&username=" + user + "&key=sdlkjsdljf0j2fsjk";
return CryptoJS.MD5(signStr).toString().toUpperCase();
}
function encrypt(user, pass) {
var time = '1624379089014';
var sign = getSign(user, pass, time);
var plainText = '{"equtype":"ANDROID","loginImei":"Androidnull","sign":"' + sign + '","timeStamp":"' + time + '","userPwd":"' + pass + '","username":"' + user + '"}';
var key = CryptoJS.enc.Hex.parse(CryptoJS.MD5("65102933").toString());
var iv = CryptoJS.enc.Utf8.parse("32028092");
var result = CryptoJS.DES.encrypt(plainText, key, {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}).toString();
return result;
}Full code
File:
xxn.jsRun result
Summary
The static analysis and Frida hooks confirmed the login flow; however, hooks may need multiple attempts. Reproducing the algorithm in JavaScript with CryptoJS is recommended for broader applicability.
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.
