Reverse Engineering Webpack Bundles for Encryption Logic Extraction

When reverse‑engineering JavaScript‑heavy websites, sensitive operations such as encryption are often hidden inside Webpack bundles. By understanidng the bundle’s module system we can locate and directly reuse the relevant functions without re‑implementing complex cryptographic algorithms. This guide walks through three real‑world examples, showing how to extract and call Webpack‑packaged encryption routines.

1. RSA Password Encryption – gm99.com Login

The webpack bundle contains a module jiemi that wraps JSEncrypt for RSA public‑key encryption. After removing dead code, the callable entry point looks like:

(function(modules) {
    // bootstrap: mini require‑style loader
    var cache = {};
    function webpackRequire(id) {
        if (cache[id]) return cache[id].exports;
        var mod = cache[id] = { exports: {}, id: id, loaded: false };
        modules[id].call(mod.exports, mod, mod.exports, webpackRequire);
        mod.loaded = true;
        return mod.exports;
    }
    _webpackRequire = webpackRequire;
})({
    rsaEncrypt: function(module, exports, require) {
        var jsEncryptLib = require('jsencrypt');
        function PasswordEncryptor() {
            this.cipher = new jsEncryptLib.JSEncrypt();
            this.cipher.setPublicKey(
                '-----BEGIN PUBLIC KEY-----\n' +
                'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDq04c6My441Gj0UFKgrqUhAUg+\n' +
                'kQZeUeWSPlAU9fr4HBPDldAeqzx1UR92KJHuQh/zs1HOamE2dgX9z/2oXcJaqoRI\n' +
                'A/FXysx+z2YlJkSk8XQLcQ8EBOkp//MZrixam7lCYpNOjadQBb2Ot0U/Ky+jF2p+\n' +
                'Ie8gSZ7/u+Wnr5grywIDAQAB\n' +
                '-----END PUBLIC KEY-----'
            );
        }
        PasswordEncryptor.prototype.encode = function(text, seed) {
            var payload = seed ? seed + '|' + text : text;
            return encodeURIComponent(this.cipher.encrypt(payload));
        };
        module.exports = PasswordEncryptor;
    },
    jsencrypt: function(module, exports, require) {
        /* … JSEncrypt 2.3.1 source (omitted for brevity) … */
    }
});

// Usage
var EncryptorCtor = _webpackRequire('rsaEncrypt');
var enc = new EncryptorCtor();
console.log(enc.encode('12344', 1234));

2. Custom Cipher – qimingpian.cn encrypt_data

The encrypt_data XHR payload is protected by a custom Feistel‑like cipher located in the bundle. After isolating the decryption function (named o in the original) we can call it with the extracted key and IV.

// Simplified and renamed version of the custom decipher
function customDecrypt(ciphertext, key, mode, iv) {
    var sbox1 = [ /* … 256‑entry table … */ ];
    var sbox2 = [ /* … 256‑entry table … */ ];
    // … (8 more S‑boxes) …

    // Key schedule
    var roundKeys = generateSubkeys(key, sbox1, sbox2, /* … */);

    // Block processing (CBC or ECB)
    var plaintext = '';
    var blocks = ciphertext.match(/.{16}/g);
    var prevBlock = iv;
    for (var b of blocks) {
        var L = b.charCodeAt(0)<<24 | b.charCodeAt(1)<<16 | b.charCodeAt(2)<<8 | b.charCodeAt(3);
        var R = b.charCodeAt(4)<<24 | b.charCodeAt(5)<<16 | b.charCodeAt(6)<<8 | b.charCodeAt(7);
        // … Feistel rounds using roundKeys …
        plaintext += String.fromCharCode(L>>>24, L>>>16&255, L>>>8&255, L&255,
                                         R>>>24, R>>>16&255, R>>>8&255, R&255);
    }
    // Padding removal and optional URL‑decoding
    return decodeURIComponent(plaintext.replace(/\0+$/g, ''));
}

// The webpack‑exported module provides base64 decoding and the cipher call
var base64 = _webpackRequire('base64');   // aqBw module

function getDecryptedData(encryptedPayload) {
    var raw = base64.decode(encryptedPayload);
    var result = customDecrypt(raw, '5e5062e82f15fe4ca9d24bc5', 0, '012345677890123', 1);
    return JSON.parse(result);
}
console.log(getDecryptedData('...'));

3. Digest Header – yizhan.mamayz.com Login

The login endpoint requires a digest header cmoputed as the Base64‑encoded MD5 hash of the JSON‑serialized request body. The bundle already exports both MD5 and Base64 utilities; we simply import and combine them.

// Modules from the bundle: 72fe → MD5, 1132 → Base64
var md5 = _webpackRequire('72fe');
var base64 = _webpackRequire(1132);   // 1132 module

function computeDigest(payload) {
    var jsonStr = JSON.stringify(payload);
    // MD5 returns a WordArray, Base64.stringify converts it to a string
    var hash = md5(jsonStr);
    return base64.stringify(hash);
}

var loginData = {
    username: '13111111111',
    password: '123456',
    rand: '0420',
    ip: '106.7.59.28'
};
console.log(computeDigest(loginData));

Tags: webpack reverse engineering Encryption rsa JSEncrypt

Posted on Mon, 15 Jun 2026 18:08:51 +0000 by Jiin