某五百js逆向分析

声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!(手动狗头)

url:  aHR0cHM6Ly93d3cuMDk5YzUwMC52aXAvbG9naW4=

1.抓包分析

多次抓包后发现咱请求头没啥加密,就负载这里搞个random和password加密,我们先试试random固定|不带random,看看能不能请求成功

1.1 不带random请求

1.2 带固定的random请求

发现请求的random根本不影响msg,不必管他,咱去搞pwd加密

2.分析加密参数位置

来到调用堆栈,一眼看出这login不同寻常,咱先来到第二个login这,看看参数有没有生成。

进来断点断住,发现还没加密,咱们看看o.b.Login()是不是动了手脚,执行一下看看

发现此时就已经开始加密了,咱跟进去这函数看看,到底是什么牛马干的,给pwd加密了

发现是这么个函数

var t = "dafacloud_" + Math.random()//首先t是一个字符串加上随机的数,不用管
                  , a = {
    random: o.encode(t)//random跟咱想的一样,随机的给它固定就好,不用带都可以,不用管
                }
 , i = c(e.userName, e.password);//通过c函数对pwd和username进行处理(估计是进行了加密)
return localStorage.setItem("temporaryPass", i),//返回了i,储存在local Storage里
                e.password = s()(i + t),//这里就是i 和一个随机字符串相加然后再加密了
                e.random = a.random,
                n.a.post(l, e)
            }

为了追求细节,咱也搞个random过来(可能人家后端就专门比较random和pwd)话不多说,直接全部copy过来

折叠起来发现是webpack,同时最开头的(window.webpackJsonp = window.webpackJsonp || []).push可以简化成a()

我们来到a函数

function a(a) {
        for (var f, b, r = a[0], n = a[1], o = a[2], u = 0, l = []; u < r.length; u++)
            b = r[u],
            d[b] && l.push(d[b][0]),
            d[b] = 0;
        for (f in n)
            Object.prototype.hasOwnProperty.call(n, f) && (e[f] = n[f]);
        for (i && i(a); l.length; )
            l.shift()();
        return t.push.apply(t, o || []),
        c()
    }
//可以看到调用了c函数
//咱省的事多,全copy下来
!function (e) {
    function r(a) {
        if (f[a])
            return f[a].exports;
        var c = f[a] = {
            i: a,
            l: !1,
            exports: {}
        };
        return e[a].call(c.exports, c, c.exports, r),
            c.l = !0,
            c.exports
    }
​
    function a(a) {
        for (var f, b, r = a[0], n = a[1], o = a[2], u = 0, l = []; u < r.length; u++)
            b = r[u],
            d[b] && l.push(d[b][0]),
                d[b] = 0;
        for (f in n)
            Object.prototype.hasOwnProperty.call(n, f) && (e[f] = n[f]);
        for (t.push(a); l.length;)
            l.shift()();
        return t.push.apply(t, o || []),
            c()
    }
​
    window.xxx = a//给a放到全局变量中
​
    function c() {
        for (var e, a = 0; a < t.length; a++) {
            for (var c = t[a], f = !0, b = 1; b < c.length; b++) {
                var n = c[b];
                0 !== d[n] && (f = !1)
            }
            f && (t.splice(a--, 1),
                e = r(r.s = c[0]))
        }
        return e
    }
​
    var f = {}
        , b = {
        85: 0
    }
        , d = {
        85: 0
    }
        , t = [];
​
​
}([]);

下面我们再重新来到加密函数的位置

//咱先 扣一层代码
JhLU: function (e, t, a) {
        "use strict";
    //关键在于怎么调用这个代码,得到Login
        t.b = {
            Login: function (e) {
                var t = "dafacloud_" + Math.random()
                    , a = {
                    random: encode(t)
                }
                    , i = c(e.userName, e.password);
                window.yufan = [s()(i + t).toString(), a.random]//只有调用了才能赋值给window
​
​
            },
​
        }
        window.dog = t.b;//再给t.b赋值到全局对象里
​
    }

通过以上分析,咱需要先通过调用JhLU,拿到里面的函数,获得t.b,接着调用t.b里的Login,将我们要的结果变量,赋值到全局变量中,开整

3.扣代码&python模拟

打印发现JhLU里面的参数,前两个随便给个{},而最后一个则是要r函数,而定位到r函数中,正是和咱a函数处在一起,巧巧巧(七巧板)

!function (e) {
    //这个函数正是第三个参数
    function r(a) {
        if (f[a])
            return f[a].exports;
        var c = f[a] = {
            i: a,
            l: !1,
            exports: {}
        };
        return e[a].call(c.exports, c, c.exports, r),
            c.l = !0,
            c.exports
    }
    
    function a(a) {
        //观察发现,传过来的a = [6], {}, [["Vtdi", 85, 0]],所以a[1]刚好包含咱要的参数,锁定n
        for (var f, b, r = a[0], n = a[1], o = a[2], u = 0, l = []; u < r.length; u++)
            b = r[u],
            d[b] && l.push(d[b][0]),
                d[b] = 0;
        for (f in n)
            Object.prototype.hasOwnProperty.call(n, f) && (e[f] = n[f]);
        for (t.push(a); l.length;)
            l.shift()();
        n.JhLU({}, {}, r)//在a函数调用时,我们去执行n.JhLU,拿的window.dog(t.b)
        return t.push.apply(t, o || []),
            c()
    }
​
    window.xxx = a
​
    function c() {
        for (var e, a = 0; a < t.length; a++) {
            for (var c = t[a], f = !0, b = 1; b < c.length; b++) {
                var n = c[b];
                0 !== d[n] && (f = !1)
            }
            f && (t.splice(a--, 1),
                e = r(r.s = c[0]))
        }
        return e
    }
​
    var f = {}
        , b = {
        85: 0
    }
        , d = {
        85: 0
    }
        , t = [];
​
​
}([]);
​
​
​


//通过调用window.xxx(a),乘机把咱的JhLU搞过去
window.xxx([6], {
    //这里正是咱的JhLU,简化一下,只要核心的Login
    JhLU: function (e, t, a) {
        "use strict";
        t.b = {
            Login: function (e) {
                var t = "dafacloud_" + Math.random()
                    , a = {
                    random: encode(t)
                }
                    , i = c(e.userName, e.password);
                window.yufan = [s()(i + t).toString(), a.random]
            },
​
        }
        window.dog = t.b;
​
    }
}, [["Vtdi", 85, 0]])
​
//最后咱对window.dog里的Login进行调用,传进去咱的账号和密码
window.dog.Login({
        'password': "123456",
        'userName': "123456"
    }
)
console.log(window.yufan)//打印出结果

话不多说,开始运行

发现咱的o.encode没有,去网站上看看

发现就是encode函数,还是个三目运算符,很明显,我们的e是undefined。什么?不信,你看看

信了吧,直接简化成_encode(String(t)) , _encode又在哪呢,诶,您别急,往上看看

可不就在上面吗?那我全扣?太麻烦了,搞的代码又臭又长,鼠标悬浮在_encode,您才怎么找,直接定位

到这来很明显的btoa、atob,base64啊

        var cb_utob = function (t) {
            if (t.length < 2)
                return (e = t.charCodeAt(0)) < 128 ? t : e < 2048 ? fromCharCode(192 | e >>> 6) + fromCharCode(128 | 63 & e) : fromCharCode(224 | e >>> 12 & 15) + fromCharCode(128 | e >>> 6 & 63) + fromCharCode(128 | 63 & e);
            var e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
            return fromCharCode(240 | e >>> 18 & 7) + fromCharCode(128 | e >>> 12 & 63) + fromCharCode(128 | e >>> 6 & 63) + fromCharCode(128 | 63 & e)
        }
            , re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g
            , utob = function (t) {
            return t.replace(re_utob, cb_utob)
        }
        var encode = function (t, e) {
            return btoa(utob(String(t)))
        }
        encode搞定,继续运行

发现c没有定义,去网站上看看

s()又是哪里来的呢?

发现是出来的乱七八糟的玩意,new t(!0).update,在网站是打印看看是啥

这又是啥?相信熟悉MD5的已经能够猜出来了,什么?猜不出来,没事,咱往前看看

哈哈,这是啥,看人家煞费苦心,生怕咱认不出来是Md5,那很好办了走起

//npm install crypto-js
var CryptoJS = require('crypto-js')
var s = function (){
    return function(n) {
        return CryptoJS.MD5(n)
    }
}
function c(e, t) {
    return s()(e.toLowerCase() + s()(t))
}

好,咱都分析完了,去第四步

4.代码整合

window = this
window = {};
var CryptoJS = require('crypto-js')
!function (e) {
    function r(a) {
        if (f[a])
            return f[a].exports;
        var c = f[a] = {
            i: a,
            l: !1,
            exports: {}
        };
        return e[a].call(c.exports, c, c.exports, r),
            c.l = !0,
            c.exports
    }
​
    function a(a) {
        for (var f, b, r = a[0], n = a[1], o = a[2], u = 0, l = []; u < r.length; u++)
            b = r[u],
            d[b] && l.push(d[b][0]),
                d[b] = 0;
        for (f in n)
            Object.prototype.hasOwnProperty.call(n, f) && (e[f] = n[f]);
        for (t.push(a); l.length;)
            l.shift()();
        n.JhLU({}, {}, r)
        return t.push.apply(t, o || []),
            c()
    }
​
    window.xxx = a
​
    function c() {
        for (var e, a = 0; a < t.length; a++) {
            for (var c = t[a], f = !0, b = 1; b < c.length; b++) {
                var n = c[b];
                0 !== d[n] && (f = !1)
            }
            f && (t.splice(a--, 1),
                e = r(r.s = c[0]))
        }
        return e
    }
​
    var f = {}
        , b = {
        85: 0
    }
        , d = {
        85: 0
    }
        , t = [];
​
​
}([]);
//通过调用window.xxx(a),乘机把咱的JhLU搞过去
window.xxx([[6], {
    JhLU: function (e, t, a) {
        "use strict";
        //JS_md5
​
        var s = function (){
            return function(n) {
                        return CryptoJS.MD5(n)
                    }
        }
        function c(e, t) {
            return s()(e.toLowerCase() + s()(t))
        }
        var cb_utob = function (t) {
            if (t.length < 2)
                return (e = t.charCodeAt(0)) < 128 ? t : e < 2048 ? fromCharCode(192 | e >>> 6) + fromCharCode(128 | 63 & e) : fromCharCode(224 | e >>> 12 & 15) + fromCharCode(128 | e >>> 6 & 63) + fromCharCode(128 | 63 & e);
            var e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
            return fromCharCode(240 | e >>> 18 & 7) + fromCharCode(128 | e >>> 12 & 63) + fromCharCode(128 | e >>> 6 & 63) + fromCharCode(128 | 63 & e)
        }
            , re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g
            , utob = function (t) {
            return t.replace(re_utob, cb_utob)
        }
        var encode = function (t, e) {
            return btoa(utob(String(t)))
        }
        t.b = {
            Login: function (e) {
                var t = "dafacloud_" + Math.random()
                    , a = {
                    random: encode(t)
                }
                    , i = c(e.userName, e.password);
                window.yufan = [s()(i + t).toString(), a.random]
            }
        }
        window.dog = t.b;
​
    },
}, [["Vtdi", 85, 0]]]);
​
window.dog.Login({
        'password': "123456",
        'userName': "123456"
    }
)
console.log(window.yufan)

运行结果

出来了,咱们成热打铁,换到python中去试试

# -*- coding: utf-8 -*-
'''
@IDE : PyCharm
@version : 3.9
@Auth : gouzi
@time : 2023/9/30 12:17
@Description:
'''
import requests
import execjs
​
headers = {
    'authority': 'www.099c500.vip',
    'accept': 'application/json, text/plain, */*',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'no-cache',
    'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
    'cookie': '_uab_collina=168994263384070692985472',
    'origin': 'https://www.099c500.vip',
    'pragma': 'no-cache',
    'publish-version': '2023/07/14_10:52:50 pc-v1.187.0',
    'referer': 'https://www.099c500.vip/login',
    'sec-ch-ua': '"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
    'x-token': '',
}
with open('login.js',encoding='utf-8') as f:
    js_code = f.read()
code = execjs.compile(js_code)
data_ = code.call('get_data','123456','123456')
print(data_)
data = {
    'userName': '123456',
    'password': data_[0],
    'random': data_[1]
}
​
response = requests.post('https://www.099c500.vip/v1/users/login', headers=headers, data=data)
print(response.json())

运行成功

5.总结:

这东西嵌套真™多,想要调用这复杂,同时它本身的md5方法也看不懂,不晓得咋扣,就只能自己搞md5进行加密了,总体来说

难度:适中(对我这种萌新小白来说,大佬肯定轻而易举的~~,好吧,大佬也不会看我这文章)

学会了如何去找到调用的对象,又熟悉了js呢

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值