在挖src中如何利用mitmproxy代理实现自动化加解密,我们通过编写2个脚本一个上游,一个下游。
2025-04-24T14:01:53.png
如图所示,图中的实现步骤如下:浏览器发送加密数据-->下游(do.py)代理实现请求解密-->burp接收明文请求体-->上游(up.py)代理加密请求体-->服务器接收加密请求体-->服务器返回加密响应体-->上游(up.py)代理解密响应体-->burp接收明文响应体-->下游(do.py)代理加密响应体-->浏览器接收加密响应体

下面开始实战
查看请求内容发现加密数据包,加密值为encryptdata
2025-04-24T14:02:31.png
通过断点确认加密函数new p.a(e).encryptData_ECB(o()(t.data)),跳转js查看加密过程
2025-04-24T14:03:53.png
2025-04-24T14:04:15.png
把获取加密函数和解密函数把函数趴下来保存
2025-04-24T14:04:41.png
运行发现缺少h()函数在js搜索
2025-04-24T14:05:25.png
在js中添加h()
2025-04-24T14:06:38.png
接着找m()函数,记得要看函数调用的参数脚本中m(t.sk, e)调用了2个参数,而且这个m函数也需要传两个参数,所以可以确认就是调用的这个函数
2025-04-24T14:06:52.png
添加到本地js脚本中
2025-04-24T14:07:17.png
接着添加u()函数
2025-04-24T14:07:37.png
在把脚本中encryptData_ECB函数里面Object(a.b)补全
2025-04-24T14:07:49.png
通过断点获取调用的参数
2025-04-24T14:08:04.png
获取到e.b函数
2025-04-24T14:08:16.png
添加到本地js脚本中改调用参数名称
2025-04-24T14:08:44.png
在修改加密的调用方式
2025-04-24T14:08:54.png
decryptData_ECB参数也是一样,后面的参数也是一样在js里面搜索然后慢慢补全即可,这里在不赘述
完整js脚本des.js如下

const base64js = require('base64-js');
aa = function aa(t) {
    this.seckey = t;
    this.encryptData_ECB = function(t) {
        var e, i = new h;
        i.isPadding = !0,
        i.mode = 1;
        try {
            if (null == this.seckey)
                throw new Error("key 不规范");
            e = a1(this.seckey)
        } catch (t) {
            throw new Error(t.message)
        }
        (function(t, e) {
            if (void 0 == t) throw new Error("ctx is null!");
            if (void 0 == e || 16 !== e.length) throw new Error("key error!");
            t.mode = 1,
            m(t.sk, e)
        })(i, e);
        var r = B(i, a1(t));
        var n = base64js.fromByteArray(r);
        if (n) {
            n = n.replace(/(\s*|\t|\r|\n)/g, "")
              .replace(/=/g, "!")
              .replace(/\+/g, "@");
        }
        return n;
    };
    this.decryptData_ECB = function(t) {
        try {
            var e = new h;
            e.isPadding = !0,
            e.mode = 0;
            t = t.replace(/!/g, "=").replace(/@/g, "+");
            var i = a1(this.seckey);
            (function(t, e) {
                if (null == t) throw new Error("ctx is null!");
                if (null == e || 16 !== e.length) throw new Error("key error!");
                t.mode = 0,
                m(t.sk, e),
                t.sk = t.sk.reverse();
            })(e, i);
            var r = B(e, base64js.toByteArray(t));
            return a1(r); // 修复:直接调用d2处理结果
        } catch (t) {
            console.error("Decryption error:", t);
            return null;
        }
    };
}
;
function h() {
    this.mode = 1,
    this.sk = new Array(32),
    this.isPadding = !0
}
function u(t, e) {
    return (255 & t[e]) << 24 | (255 & t[e + 1]) << 16 | (255 & t[e + 2]) << 8 | 255 & t[e + 3]
}
function c(t, e, i) {
    e[i] = 255 & t >> 24,
    e[i + 1] = 255 & t >> 16,
    e[i + 2] = 255 & t >> 8,
    e[i + 3] = 255 & t
}
function p(t, e) {
    return function(t, e) {
        return t << e
    }(t, e) | t >> 32 - e
}
var F = [214, 144, 233, 254, 204, 225, 61, 183, 22, 182, 20, 194, 40, 251, 44, 5, 43, 103, 154, 118, 42, 190, 4, 195, 170, 68, 19, 38, 73, 134, 6, 153, 156, 66, 80, 244, 145, 239, 152, 122, 51, 84, 11, 67, 237, 207, 172, 98, 228, 179, 28, 169, 201, 8, 232, 149, 128, 223, 148, 250, 117, 143, 63, 166, 71, 7, 167, 252, 243, 115, 23, 186, 131, 89, 60, 25, 230, 133, 79, 168, 104, 107, 129, 178, 113, 100, 218, 139, 248, 235, 15, 75, 112, 86, 157, 53, 30, 36, 14, 94, 99, 88, 209, 162, 37, 34, 124, 59, 1, 33, 120, 135, 212, 0, 70, 87, 159, 211, 39, 82, 76, 54, 2, 231, 160, 196, 200, 158, 234, 191, 138, 210, 64, 199, 56, 181, 163, 247, 242, 206, 249, 97, 21, 161, 224, 174, 93, 164, 155, 52, 26, 85, 173, 147, 50, 48, 245, 140, 177, 227, 29, 246, 226, 46, 130, 102, 202, 96, 192, 41, 35, 171, 13, 83, 78, 111, 213, 219, 55, 69, 222, 253, 142, 47, 3, 255, 106, 114, 109, 108, 91, 81, 141, 27, 175, 146, 187, 221, 188, 127, 17, 217, 92, 65, 31, 16, 90, 216, 10, 193, 49, 136, 165, 205, 123, 189, 45, 116, 208, 18, 184, 229, 180, 176, 137, 105, 151, 74, 12, 150, 119, 126, 101, 185, 241, 9, 197, 110, 198, 132, 24, 240, 125, 236, 58, 220, 77, 32, 121, 238, 95, 62, 215, 203, 57, 72]
  , f = [462357, 472066609, 943670861, 1415275113, 1886879365, 2358483617, 2830087869, 3301692121, 3773296373, 4228057617, 404694573, 876298825, 1347903077, 1819507329, 2291111581, 2762715833, 3234320085, 3705924337, 4177462797, 337322537, 808926789, 1280531041, 1752135293, 2223739545, 2695343797, 3166948049, 3638552301, 4110090761, 269950501, 741554753, 1213159005, 1684763257]
  , l = [2746333894, 1453994832, 1736282519, 2993693404];
function g(t) {
    return F[255 & t]
}
function d(t, e, i, r, n) {
    return t ^ (s = e ^ i ^ r ^ n,
    a = new Array(4),
    h = new Array(4),
    c(s, a, 0),
    h[0] = g(a[0]),
    h[1] = g(a[1]),
    h[2] = g(a[2]),
    h[3] = g(a[3]),
    (o = u(h, 0)) ^ p(o, 2) ^ p(o, 10) ^ p(o, 18) ^ p(o, 24));
    var s, o, a, h
}
function m(t, e) {
    var i, r, n, s, o = new Array(4), a = new Array(36), h = 0;
    for (o[0] = u(e, 0),
    o[1] = u(e, 4),
    o[2] = u(e, 8),
    o[3] = u(e, 12),
    a[0] = o[0] ^ l[0],
    a[1] = o[1] ^ l[1],
    a[2] = o[2] ^ l[2],
    a[3] = o[3] ^ l[3]; h < 32; h++)
        a[h + 4] = a[h] ^ (i = a[h + 1] ^ a[h + 2] ^ a[h + 3] ^ f[h],
        r = void 0,
        void 0,
        s = void 0,
        n = new Array(4),
        s = new Array(4),
        c(i, n, 0),
        s[0] = g(n[0]),
        s[1] = g(n[1]),
        s[2] = g(n[2]),
        s[3] = g(n[3]),
        (r = u(s, 0)) ^ p(r, 13) ^ p(r, 23)),
        t[h] = a[h + 4]
}
function y(t, e, i) {
    var r = 0
      , n = new Array(36);
    for (n[0] = u(e, 0),
    n[1] = u(e, 4),
    n[2] = u(e, 8),
    n[3] = u(e, 12); r < 32; )
        n[r + 4] = d(n[r], n[r + 1], n[r + 2], n[r + 3], t[r]),
        r++;
    c(n[35], i, 0),
    c(n[34], i, 4),
    c(n[33], i, 8),
    c(n[32], i, 12)
}
function v(t, e) {
    if (void 0 == t) return null;
    var i = [];
    if ((i = i.concat(t)), 1 == e) {
      // 加密时填充
      var r = 16 - (t.length % 16);
      for (var n = 0; n < r; n++) i.push(r);
    } else {
      // 解密时移除填充
      var r = t[t.length - 1];
      for (var n = 0; n < r; n++) i.pop();
    }
    return i;
  }
function B(t, e) {
    null == e | "" == e && Error("input is null!"),
    t.isPadding && 1 == t.mode && (e = v(e, 1));
    for (var i = e.length, r = [], n = 0; n < i; n += 16) {
        var s = []
          , o = [];
        s.push(e[n + 0], e[n + 1], e[n + 2], e[n + 3], e[n + 4], e[n + 5], e[n + 6], e[n + 7], e[n + 8], e[n + 9], e[n + 10], e[n + 11], e[n + 12], e[n + 13], e[n + 14], e[n + 15]),
        y(t.sk, s, o),
        r = r.concat(o)
    }
    return t.isPadding && 0 == t.mode && (r = v(r, 0)),
    r
}



a1 = function(t) {
    if (typeof t === "string") return d2(t);
    if (!t || typeof t.length === 'undefined') throw new Error("Invalid input");
    let e = "";
    for (let r = 0; r < t.length; r++) {
      let n = t[r].toString(2).padStart(8, '0');
      let s = n.match(/^1+?(?=0)/);
      if (s && n.length === 8) {
        let o = s[0].length;
        let a = n.slice(o + 1);
        for (let h = 1; h < o; h++) {
          a += t[r + h].toString(2).padStart(8, '0').slice(2);
        }
        e += String.fromCharCode(parseInt(a, 2));
        r += o - 1;
      } else {
        e += String.fromCharCode(t[r]);
      }
    }
    return e;
  };   
d2 = function(t) {
var e, i, r = new Array;
e = t.length;
for (var n = 0; n < e; n++)
    (i = t.charCodeAt(n)) >= 65536 && i <= 1114111 ? (r.push(i >> 18 & 7 | 240),
    r.push(i >> 12 & 63 | 128),
    r.push(i >> 6 & 63 | 128),
    r.push(63 & i | 128)) : i >= 2048 && i <= 65535 ? (r.push(i >> 12 & 15 | 224),
    r.push(i >> 6 & 63 | 128),
    r.push(63 & i | 128)) : i >= 128 && i <= 2047 ? (r.push(i >> 6 & 31 | 192),
    r.push(63 & i | 128)) : r.push(255 & i);
return r
}

module.exports = {
aa: aa,
enc: function(t) {
    var a = new aa("43pejo2xwy9h3pse");
    return a.encryptData_ECB(t);
},
dec: function(t) {
    var a = new aa("43pejo2xwy9h3pse");
    return a.decryptData_ECB(t);
}
};

在通过test.js加载des.js尝试加密和解密
test.js代码如下

const dec1 = require('./dec.js');
function dec(t){
    return dec1.dec(t);
}
function enc(t){
    return dec1.enc(t);
}
console.log(enc("aaa"))
console.log(dec("T527tpbYYkHQKDuQFSvDFw!!"))

2025-04-24T14:19:41.png

回过头来发现this.seckey是随机生成的
2025-04-24T14:23:47.png
2025-04-24T14:25:06.png
通过l()函数随机生成16位
2025-04-24T14:26:10.png
这里我们直接修改js固定key值方便后面的脚本调用,点击替换内容选择任意目录
2025-04-24T14:30:41.png
输入16位固定key
2025-04-24T14:32:31.png
之后在dec.js脚本中固定key即可

接下就是编写up.py上游脚本代码如下

import json
import execjs
from mitmproxy import flowfilter,ctx
from mitmproxy.http import HTTPFlow

with open("dec.js","r",encoding="utf-8") as f:
    js =f.read()
    js =execjs.compile(js)
#请求体加密
def request(flow: HTTPFlow):
    if "/gateway/" in flow.request.url:
        data = json.loads(flow.request.get_text())
        ctx.log.info(data)
        encrypt_text = data['encryptdata']  # 直接获取字符串值
        decrypt_text = js.call('enc', encrypt_text)  # 假设应为解密,可能函数名应改为'dec'
        ctx.log.info(decrypt_text)
        data['encryptdata'] = decrypt_text
        flow.request.content = json.dumps(data).encode()
#响应体解密
def response(flow: HTTPFlow):
    if "/gateway/" in flow.request.url:
        # 注意:响应处理应使用flow.response而非flow.request
        data = json.loads(flow.response.get_text())
        encrypt_text = data['encryptdata']  # 直接获取字符串值
        ctx.log.info(encrypt_text)
        decrypt_text = js.call('dec', encrypt_text)
        data['encryptdata'] = decrypt_text
        flow.response.content = json.dumps(data, ensure_ascii=False).encode()

通过mitmdump执行上游脚本mitmdump -p 9090 -s up.py --ssl-insecure
2025-04-24T14:43:34.png
接着就是编写下游脚本do.py代码如下

import json
import execjs
from mitmproxy import flowfilter,ctx
from mitmproxy.http import HTTPFlow

with open("test.js","r",encoding="utf-8") as f:
    js =f.read()
    js =execjs.compile(js)
#请求体解密
def request(flow: HTTPFlow):
    if "/gateway/" in flow.request.url:
        data = json.loads(flow.request.get_text())
        encrypt_text = data['encryptdata']  # 直接获取字符串值
        decrypt_text = js.call('dec', encrypt_text)  # 假设应为解密,可能函数名应改为'dec'
        data['encryptdata'] = decrypt_text
        flow.request.content = json.dumps(data).encode()
#响应体加密 
def response(flow: HTTPFlow):
    if "/gateway/" in flow.request.url:
        data = json.loads(flow.response.get_text())
        encrypt_text = data['encryptdata'] # 直接获取字符串值
        decrypt_text = js.call('enc', encrypt_text)
        data['encryptdata'] = decrypt_text
        flow.response.content = json.dumps(data, ensure_ascii=False).encode()

通过mitmdump执行下游脚本mitmdump -q -p 9091 -s do.py --mode upstream:http://127.0.0.1:8080/ --ssl-insecure
2025-04-24T14:43:52.png
在浏览器中挂着下游代理
2025-04-24T14:44:51.png
在burp中挂着上游代理
2025-04-24T14:45:46.png
解密前
2025-04-24T15:06:16.png
解密后
2025-04-24T15:06:52.png