python编译执行js代码(pyexecjs)、补环境
pyexecjs是一个可以帮助我们运行js代码的一个第三方模块. 其使用是非常容易上手的.
但是它的运行是要依赖能运行js的第三方环境的. 这里我们选择用node作为我们运行js的位置.
1.1 安装Nodejs
-
测试js代码
node 1.js -
python执行执行本地命令:
node 1.js
import os import subprocess # 根据自己的操作系统去修改(相当于python的sys.path,加载安装的模块) # 这不是你的node安装路径,是第三方包安装路径,输入:npm root -g os.environ["NODE_PATH"] = "/usr/local/lib/node_modules/" signature = subprocess.getoutput('node 1.js')
2.2 安装pyexecjs
pip install pyexecjs
测试一下:
import execjs print(execjs.get().name) # Node.js (V8)
1.3 简单使用
import execjs print(execjs.get().name) # execjs.eval 可以直接运行js代码并得到结果 js = """ "鲁班_王昭君_猴子_亚瑟_蔡文姬".split("_") """ res = execjs.eval(js) print(res) # execjs.compile(), call() # execjs.compile() 事先加载好一段js代码, jj = execjs.compile(""" function an(a, b){ return a + b } """) # call() 运行代码中的xxx函数. 后续的参数是xxx的参数 ret = jj.call("an", 10, 20) print(ret)
windows中如果出现编码错误. 在引入execjs之前. 插入以下代码即可.
import subprocess from functools import partial subprocess.Popen = partial(subprocess.Popen, encoding='utf-8') import execjs
完事儿. 你没有看错. execjs就这几个功能就够咱用的了.
1.4 游览器调试工具讲解
按钮从左往右
第一个: 释放掉当前断点debug. 程序继续向后运行. 直到结束或下一个断点。 (下一个断点处)
第二个: 运行下一步. 它的作用是会直接执行完这个函数,不显示执行细节。 (看当前行这个函数运行的结果是什么)
第三个: 它的作用和上面那个刚好相反。如果遇到一个函数,它进入函数内部一步一步地执去行,这样可以观察到执行过程。 (看看当前行的这个函数是怎么运行的)
1.5 补js第三方库环境
示例1
如逆向时遇到这种公开的第三方库(CryptoJS)。 可以直接用node中的npm来安装
设置镜像源
npm config set registry http://registry.npm.taobao.org
使用npm安装js库
npm install crypto-js
var CryptoJS = require("crypto-js"); // 引入 function b(a, b) { // 抠到这种公开的第三方库。 可以直接用node中的npm来安装. var c = CryptoJS.enc.Utf8.parse(b) , d = CryptoJS.enc.Utf8.parse("0102030405060708") , e = CryptoJS.enc.Utf8.parse(a) , f = CryptoJS.AES.encrypt(e, c, { iv: d, mode: CryptoJS.mode.CBC }); return f.toString() }
示例2
npm install crypto
const crypto = require('crypto'); var t="_jsUyA02rwkOJ4enKX7c4dhd7CjvGkcKfbRx0BjNGW8lA7S2l8R3Ry5QLg9sMmKp72I4gQZHoGRX433rxXwjKmy5yFuVCe4HL1-8YeYQoyv5xBo29ruVPY2ApicRkT7O" function data(t){ var key='ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl' var iv='ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4' if (!t) return null; const a = Buffer.alloc(16, crypto.createHash("md5").update(key).digest()) , r = Buffer.alloc(16, crypto.createHash("md5").update(iv).digest()) console.log(a) console.log(r) const i = crypto.createDecipheriv("aes-128-cbc", a, r); console.log(i) let s = i.update(t, "base64", "utf-8"); return s += i.final("utf-8"), s } console.log(data(t))
示例3 rsa
npm install node-jsencrypt npm install jsencrypt 不维护了
var JSEncrypt = require("node-jsencrypt") var encrypt = new JSEncrypt(); function getParams(bdata) { var c = Date.parse(new Date()); var d = getUuid(); // var c = 1694614752000; // var d = '6985dd00f9514f4cf5f88f8f09ea2f7e'; var e = JSON.stringify(sort_ASCII(dataTojson(bdata || '{}'))); // console.log(dataTojson(bdata || '{}')) newbdata = encrypt.encryptUnicodeLong(e); // var f = MD5(e + d + c); // console.log(f) return {timestamp:c,requestId:d,newbdata:newbdata,e:e} }
<html> <script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script> <script type="text/javascript"> //公钥 var PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALyBJ6kZ/VFJYTV3vOC07jqWIqgyvHulv6us/8wzlSBqQ2+eOTX7s5zKfXY40yZWDoCaIGk+tP/sc0D6dQzjaxECAwEAAQ==-----END PUBLIC KEY-----'; //私钥 var PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvIEnqRn9UUlhNXe84LTuOpYiqDK8e6W/q6z/zDOVIGpDb545NfuznMp9djjTJlYOgJogaT60/+xzQPp1DONrEQIDAQABAkEAu7DFsqQEDDnKJpiwYfUE9ySiIWNTNLJWZDN/Bu2dYIV4DO2A5aHZfMe48rga5BkoWq2LALlY3tqsOFTe3M6yoQIhAOSfSAU3H6jIOnlEiZabUrVGqiFLCb5Ut3Jz9NN+5p59AiEA0xQDMrxWBBJ9BYq6RRY4pXwa/MthX/8Hy+3GnvNw/yUCIG/3Ee578KVYakq5pih8KSVeVjO37C2qj60d3Ok3XPqBAiEAqGPvxTsAuBDz0kcBIPqASGzArumljkrLsoHHkakOfU0CIDuhxKQwHlXFDO79ppYAPcVO3bph672qGD84YUaHF+pQ-----END PRIVATE KEY-----'; //使用公钥加密 var encrypt = new JSEncrypt();//实例化加密对象 encrypt.setPublicKey(PUBLIC_KEY);//设置公钥 var encrypted = encrypt.encrypt('hello bobo!');//对指定数据进行加密 alert(encrypted) //使用私钥解密 var decrypt = new JSEncrypt(); decrypt.setPrivateKey(PRIVATE_KEY);//设置私钥 var uncrypted = decrypt.decrypt(encrypted);//解密 alert(uncrypted); </script> </html>
crypto 和 crypto-js 区别
crypto 和 crypto-js 是两个不同的库,用于不同的目的。
crypto 是 Node.js 的内置模块,用于提供加密和解密功能。它提供了一系列的加密算法,包括对称加密、哈希函数、数字签名、随机数生成等。你可以直接在 Node.js 环境中使用 crypto 模块,无需安装额外的依赖。它提供了对安全通信和数据存储的基本加密支持。
crypto-js 是一个独立的第三方 JavaScript 加密库,提供了多种加密算法的实现。它可以在浏览器和 Node.js 环境中使用。crypto-js 提供了对称加密、哈希函数、消息认证码等的实现,包括 AES、DES、SHA-256 等常见算法。相对于 Node.js 内置的 crypto 模块,crypto-js 提供了更多的加密算法选项,并且在浏览器端也可使用。
总结区别:
crypto 是 Node.js 内置的加密模块,而 crypto-js 是一个第三方 JavaScript 加密库。
crypto 提供了基本的加密功能,并且不需要额外安装依赖;crypto-js 提供了更丰富的加密算法实现,并可用于浏览器和 Node.js 环境,但需要通过 npm 安装。
crypto 适用于 Node.js 环境,而 crypto-js 可在浏览器和 Node.js 环境中使用。
crypto 提供的加密算法和功能相对较少,而 crypto-js 提供了更多的加密算法选项。
1.6 补游览器环境
环境准备:
-
node.js
-
jsdom(通过后端node+js代码实现伪造浏览器环境)
npm install node-gyp@latest sudo npm explore -g npm -- npm i node-gyp@latest npm install jsdom -g 注意:上述安装成功后已可以模拟浏览器环境,由于今天的头条他的内容。
npm install canvas -g npm install -g canvas --canvas_binary_host_mirror=https://registry.npmmirror.com/-/binary/canvas/
如果执行出现错误,请去官方网站下载并安装最新的稳定版的node即可。
方式1
const jsdom = require("jsdom"); const {JSDOM} = jsdom; const resourceLoader = new jsdom.ResourceLoader({ userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36", }); const html = `<!DOCTYPE html><p>Hello world</p>`; const dom = new JSDOM(html, { url: "https://www.toutiao.com", referrer: "https://example.com/", contentType: "text/html", resources: resourceLoader, }); console.log(dom.window.location) console.log(dom.window.navigator.userAgent) console.log(dom.window.document.referrer)
方式2
const jsdom = require("jsdom"); const {JSDOM} = jsdom; const resourceLoader = new jsdom.ResourceLoader({ userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36" }); const html = `<!DOCTYPE html><p>Hello world</p>`; const dom = new JSDOM(html, { url: "https://www.toutiao.com", referrer: "https://example.com/", contentType: "text/html", resources: resourceLoader, }); //window = {} window = global; const params = { location: { hash: "", host: "www.toutiao.com", hostname: "www.toutiao.com", href: "https://www.toutiao.com", origin: "https://www.toutiao.com", pathname: "/", port: "", protocol: "https:", search: "", }, navigator: { appCodeName: "Mozilla", appName: "Netscape", appVersion: "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", cookieEnabled: true, deviceMemory: 8, doNotTrack: null, hardwareConcurrency: 4, language: "zh-CN", languages: ["zh-CN", "zh"], maxTouchPoints: 0, onLine: true, platform: "MacIntel", product: "Gecko", productSub: "20030107", userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", vendor: "Google Inc.", vendorSub: "", webdriver: false } }; Object.assign(global,params); document = dom.window.document; //在下面如果你使用 location.href navigator.appCodeName window.location.href window.appCodeName
注意:在nodejs中默认代码中会有一个global的关键字(全局变量)。
v1 = 123; console.log(global);
global.v1 = 123 global.v2 = 123 global.navigator = { ... } console.log(v1,v2); navigator.userAgent
找加密入口的几种方法
1.直接搜索加密参数 搜索值的一部分 搜索加密参数的名字 2.调用栈往前寻找,边看scope,边看call stack 来找加密入口 - 如果没有调用栈,可以看看提交表单时绑定的事件,来寻找加密位置 3.找url 不要找整个url,搜索?前面的url
1.7 实战案例(调试工具)
接下来. 我们来破解真正的百度翻译
简单流程:
1.分析url:真正的一句话的翻译其实它的url应该是:https://fanyi.baidu.com/v2transapi?from=en&to=zh
2.进入initiator,看js代码
3.找到发送ajax的请求,看data是如何生成的。
4.把js代码提取出来,用python调用js。
代码:
import requests import execjs f = open("baidu加密.js", mode="r", encoding='utf-8') js = execjs.compile(f.read()) url = "https://fanyi.baidu.com/v2transapi?from=en&to=zh" content = input("请输入一段英文:") data = { "from": "en", "to": "zh", "query": content, "transtype": "realtime", "simple_means_flag": "3", "sign": js.call("e", content), "token": "c63d27ea65fdf259bf4d56b792e47b17", "domain": "common", } headers = { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Referer": "https://fanyi.baidu.com/", "Cookie": "REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BIDUPSID=7214BF57BA799CC46A76979BF673523E; PSTM=1623064780; __yjs_duid=1_7946e25e70873bbe5515a663714cef991623067825398; BAIDUID=C434B9AC411BEFD0688E2DD206C8429A:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; MCITY=-131%3A; BDUSS=kl4RWZySlNaNlRrdWNkSVRXYjYtNGkyUzFCZlhmeklhMDFtcjRLM01GdG4zMVZoRVFBQUFBJCQAAAAAAAAAAAEAAACh3e-019TDvczlwfnB-bjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdSLmFnUi5hM; BDUSS_BFESS=kl4RWZySlNaNlRrdWNkSVRXYjYtNGkyUzFCZlhmeklhMDFtcjRLM01GdG4zMVZoRVFBQUFBJCQAAAAAAAAAAAEAAACh3e-019TDvczlwfnB-bjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGdSLmFnUi5hM; H_PS_PSSID=34438_34440_34380_34496_33848_34450_34092_34107_26350_34425_22160; delPer=0; PSINO=2; BA_HECTOR=a08k202181a52h208d1gj6e0m0q; BAIDUID_BFESS=DDAD1DC127ED72714BFB37825559ACDB:FG=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1628330239,1628390196,1629451250,1630747372; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1630747372; ab_sr=1.0.1_ODBhYjIwYzRhMjk4NDNhZDYwYjRmZWZjM2QwY2E3MGNlMDRjYTI1ZjViODM2MDgxODk5NzJjNDFkZTAxYzc0OTVkYmNhYjZiMWMzZDFmNWFkN2QxMzAwMzZlZjhjYmE3ODkxZGRkNDJkNTY2N2M0NTQxODU5YmU4YTA1NGZjYTJkMDUzN2ZkMGVkMzlmOTU1M2ZlZTRhYWY4ZDQ5YTZmNTJjYmExYzk1ZTdiY2I5MTA4YjcyZDE3MWE1MTE5YjBj", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36" } resp = requests.post(url, data=data, headers=headers) print(resp.json())
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步