JS逆向基础

JS逆向基础

一、什么是JS逆向?

我们在网站进行账号登录的时候对网页源进行抓包就会发现我们输入的密码在后台会显示为一串由字母或数字等符号,这就是经过加密呈现的一段加密文字,而分析这些接口的加密算法并实现模拟调用的过程就叫做「逆向」。

逆向对于爬虫说是一个永远绕不开的话题,而我们所做的解密工作,通过解密步骤得到密码的过程,称为JS逆向。

我们将通过一个简单的案例来讲解JS的分析思路。

二、接口抓包

首先我们先点击网站的的登陆页面,打开网站的控制台,点击1(网络),再点击2(fetch/XHR),然后再点击3(清空信息),我们在进行输入(4)账号密码和验证码,为了教学,故意输错密码,点击登录,控制台跳出6(登陆包),在其中可以获取Signature(7)

点击1,在点击2,即可出现搜索页面(3),我们将Signature输入,即可获取Signature在网页源代码中的生成函数

可知3即为需要逆向分析的数据

三、逆向分析

U.Signature = Object(f.a)(U, M, l.j ? l.g : l.c);

按照下图操作获取Object(f.a)函数和U,M,和 l.j ? l.g : l.c的值



将代码复制到js文件中,运行代码报错,提示找不到f函数,将代码中相关函数全部复制

源码

js 复制代码
l = {
    key: cryptoJs.enc.Utf8.parse("fX@VyCQVvpdj8RCa"),
    iv: cryptoJs.enc.Utf8.parse(function (t) {
        for (var e = "", i = 0; i < t.length - 1; i += 2) {
            var n = parseInt(t[i] + "" + t[i + 1], 16);
            e += String.fromCharCode(n)
        }
        return e
    }("00000000000000000000000000000000"))
}
    , v = function (data) {
    return function (data) {
        return cryptoJs.AES.encrypt(data, l.key, {
            iv: l.iv,
            mode: cryptoJs.mode.CBC,
            padding: cryptoJs.pad.Pkcs7
        }).toString()
    }(data)
}
    , d = function (data) {
    return cryptoJs.MD5(data).toString()
}
    , f = function (t) {
    var e = "";
    return Object.keys(t).sort().forEach((function (n) {
            e += n + ("object" === typeof (t[n]) ? JSON.stringify(t[n], (function (t, e) {
                    return "number" == typeof e && (e = String(e)),
                        e
                }
            )).replace(/\//g, "\\/") : t[n])
        }
    )),
        e
}

h = function (t) {
    var data = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
        , e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "a75846eb4ac490420ac63db46d2a03bf"
        , n = e + f(data) + f(t) + e;
    return n = d(n),
        n = v(n)
}


U = {
    "App-Ver": "",
    "Os-Ver": "",
    "Device-Ver": "",
    "Imei": "",
    "Access-Token": "",
    "Timestemp": 1700571511,
    "NonceStr": "170057151176dni",
    "App-Id": "4ac490420ac63db4",
    "Device-Os": "web"
};

let L = {
    "username": "qweqweqeqweqwe",
    "password": "qweqweqweqweqwe",
    "code": "65xv",
    "hdn_refer": "https://www.epwk.com/"
};

C = 'a75846eb4ac490420ac63db46d2a03bf'

console.log(h(U, L, C))

又报错

导入crypto-js库替换o函数

const cryptoJs = require("crypto-js")
js 复制代码
const cryptoJs = require("crypto-js")

l = {
    key: cryptoJs.enc.Utf8.parse("fX@VyCQVvpdj8RCa"),
    iv: cryptoJs.enc.Utf8.parse(function (t) {
        for (var e = "", i = 0; i < t.length - 1; i += 2) {
            var n = parseInt(t[i] + "" + t[i + 1], 16);
            e += String.fromCharCode(n)
        }
        return e
    }("00000000000000000000000000000000"))
}
    , v = function (data) {
    return function (data) {
        return cryptoJs.AES.encrypt(data, l.key, {
            iv: l.iv,
            mode: cryptoJs.mode.CBC,
            padding: cryptoJs.pad.Pkcs7
        }).toString()
    }(data)
}
    , d = function (data) {
    return cryptoJs.MD5(data).toString()
}
    , f = function (t) {
    var e = "";
    return Object.keys(t).sort().forEach((function (n) {
            e += n + ("object" === typeof (t[n]) ? JSON.stringify(t[n], (function (t, e) {
                    return "number" == typeof e && (e = String(e)),
                        e
                }
            )).replace(/\//g, "\\/") : t[n])
        }
    )),
        e
}

h = function (t) {
    var data = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
        , e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "a75846eb4ac490420ac63db46d2a03bf"
        , n = e + f(data) + f(t) + e;
    return n = d(n),
        n = v(n)
}


U = {
    "App-Ver": "",
    "Os-Ver": "",
    "Device-Ver": "",
    "Imei": "",
    "Access-Token": "",
    "Timestemp": 1700571511,
    "NonceStr": "170057151176dni",
    "App-Id": "4ac490420ac63db4",
    "Device-Os": "web"
};

let L = {
    "username": "qweqweqeqweqwe",
    "password": "qweqweqweqweqwe",
    "code": "65xv",
    "hdn_refer": "https://www.epwk.com/"
};

C = 'a75846eb4ac490420ac63db46d2a03bf'

console.log(h(U, L, C))

运行又报错,替换r.a函数,

"object" === typeof (t[n]) 

最后代码运行出Signature

最后将js代码转成python,再与爬虫相结合最后写出代码

python 复制代码
import requests

cookies = {
    'Hm_lvt_387b8f4fdb89d4ea233922bdc6466394': '1698224816,1699438386,1700570522',
    'PHPSESSID': 'ca8646d868cd69a35397b2a42dba42d0e7a8f02b',
    'time_diff': '0',
    'XDEBUG_SESSION': 'XDEBUG_ECLIPSE',
    'adbanner_city': '%E5%8C%97%E4%BA%AC%E5%B8%82',
    'banners_show_cookie_ip': '221.216.142.177',
    'login_referer': 'https%3A%2F%2Fwww.epwk.com%2F',
    'Hm_lpvt_387b8f4fdb89d4ea233922bdc6466394': '1700570526',
    'login_fail_need_graphics': '0',
}

headers = {
    'Accept': 'application/json, text/plain, */*',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Access-Token': '',
    'App-Id': '4ac490420ac63db4',
    'App-Ver': '',
    'CHOST': 'www.epwk.com',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Content-Type': 'application/x-www-form-urlencoded',
    # 'Cookie': 'Hm_lvt_387b8f4fdb89d4ea233922bdc6466394=1698224816,1699438386,1700570522; PHPSESSID=ca8646d868cd69a35397b2a42dba42d0e7a8f02b; time_diff=0; XDEBUG_SESSION=XDEBUG_ECLIPSE; adbanner_city=%E5%8C%97%E4%BA%AC%E5%B8%82; banners_show_cookie_ip=221.216.142.177; login_referer=https%3A%2F%2Fwww.epwk.com%2F; Hm_lpvt_387b8f4fdb89d4ea233922bdc6466394=1700570526; login_fail_need_graphics=0',
    'Device-Os': 'web',
    'Device-Ver': '',
    'Imei': '',
    'NonceStr': '1700570738pdcom',
    'Origin': 'https://www.epwk.com',
    'Os-Ver': '',
    'Pragma': 'no-cache',
    'Referer': 'https://www.epwk.com/login.html',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'Signature': 'Ks5z+mbEmnNOLXsZKuOq84sn8ATLQmZxN9RmH1Gi4yuPWQWo+GYbhylLq4jxFy3F',
    'Timestemp': '1700570738',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
    'sec-ch-ua': '"Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"macOS"',
}

data = {
    'username': 'qweqweqeqweqwe',
    'password': 'qweqweqweqweqwe',
    'code': 'aaaa',
    'hdn_refer': 'https://www.epwk.com/',
}

response = requests.post('https://www.epwk.com/api/epwk/v1/user/login', cookies=cookies, headers=headers, data=data)
print(response.text)
相关推荐
魏大帅。3 分钟前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
好喜欢吃红柚子7 分钟前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
花花鱼10 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
小馒头学python12 分钟前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
k093313 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
神奇夜光杯21 分钟前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
Themberfue23 分钟前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
plmm烟酒僧25 分钟前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
千天夜33 分钟前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流
EricWang135834 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端