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.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
How to Reverse Engineer Android Login: Frida Hooking and DES Encryption Uncovered

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 = 32028092

encodeDesMap 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.js

Run 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.

JavaScriptMD5DEScryptojs
Python Crawling & Data Mining
Written by

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!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.