JS逆向基础

各位小伙伴想要博客相关资料的话,关注公众号:chuanyeTry即可领取相关资料!

一、什么是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函数,将代码中相关函数全部复制

在这里插入图片描述
源码

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")
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,再与爬虫相结合最后写出代码

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)
### JavaScript逆向工程技巧和工具 #### 使用Node.js模拟浏览器环境 对于JavaScript逆向工程而言,创建一个接近真实的运行环境至关重要。Node.js提供了强大的能力来执行JavaScript代码,并且可以通过引入额外模块如`jsdom`来构建DOM结构,使得前端脚本可以在服务器环境中正常工作[^3]。 ```javascript const jsdom = require("jsdom"); const { JSDOM } = jsdom; // 创建一个新的 DOM 环境实例 let dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`); console.log(dom.window.document.querySelector("p").textContent); ``` #### 构建后端服务仿真接口 当处理依赖于特定HTTP交互的应用程序时,建立自己的API服务器用于模仿原始网络行为是非常有用的。这不仅有助于绕过可能存在的反爬虫机制,还能让工程师更加灵活地控制输入输出数据流[^2]。 ```javascript var express = require('express'); var app = express(); app.get('/mock-api', function (req, res) { // 返回自定义响应给客户端 res.json({ message: 'This is a mock response' }); }); app.listen(3000, () => console.log('Mock server running on port 3000')); ``` #### 利用调试工具辅助分析 现代Web开发中有许多优秀的调试工具可用于帮助理解和修改正在加载中的网页资源。Chrome DevTools就是一个很好的例子;它可以用来查看页面上的所有请求、设置断点并逐步跟踪函数调用过程等操作[^1]。 #### 应用静态代码审查技术 除了动态执行之外,在不实际运行的情况下研究源码也是一种有效的策略。通过解析语法树(AST),可以识别潜在的安全漏洞或者加密算法的具体实现细节。ESLint插件生态系统也包含了多个针对不同需求定制化的规则集,便于自动化检测某些类型的错误或异常模式。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值