Python 下执行 JS 破解网站加密信息

Python 下利用 ExecJS 执行 JS 来破解部分网站的加密,结论,我建议别走这条路径,我的最终方法是 用 nodejs 写个小程序专门执行 js, 将结果通过 HTTP 返回给 Python 使用。 先执行 pip install PyExecJS 有些网站会对一些登录和认证相关的信息进行加密,但是密文都在前端里,我遇到的情形是使用的是 Crypto-JS 库,使用默认密钥"secretkey123" AES 加密。但是这个库的 AES 加密有一个默认的 iv,是随机的,在 python 下的 AES 没法模拟,于是想到用 Python 去调用 JS。 正文
能够正常执行之前需要安装 node 或者 PyV8 等 JS引擎,没有JS环境会报错: "Could not find an available JavaScript runtime." 由于镜像是 Docker 下继续 Alpine 的系统,可以通过一下命令在 Alpine 下安装 NodeJS apk add nodejs
apk add npm
import execjs

def get_decrypt_data(ctx, data, key):
    jscode = 'CryptoJS.AES.decrypt("{0}","{1}").toString(CryptoJS.enc.Utf8)'.format(data, key)
    return ctx.eval(jscode)

def get_decrypt_data_by_call(ctx, data, key):
    #调用js方法  第一个参数是JS的方法名,后面的data和key是js方法的参数
    return (ctx.call('CryptoJS.AES.decrypt', data, key))

def get_encrypt_data(ctx, data, key):
    jscode = 'CryptoJS.AES.encrypt("{0}","{1}")'.format(data, key)
    print (jscode)
    return ctx.eval(jscode)

def get_js():
    f = open("./aes.js", 'r', encoding='utf-8') # 打开JS文件
    line = f.readline()
    jsCtx = ''
    while line:
        jsCtx = jsCtx+line
        line = f.readline()
    return jsCtx


if __name__ == '__main__':
    
    name = execjs.get().name
    print("JS 引擎: " + name)
    jsstr = get_js()
    ctx = execjs.compile(jsstr) #加载JS文件
   
    # print(get_decrypt_data(ctx,"密文", "secretkey123"))

    print(get_encrypt_data(ctx, "abcssssss", "secretkey123"))
在 Node 的环境下,我在 Mac 下 和 Alpine 环境下都尝试通过 node引擎执行加密代码,都抛出"execjs._exceptions.ProgramError: None"的错误,如果执行解密代码是可以正常执行的,但是这些代码在浏览器都好好的,网上没有找到解决方式,于是尝试更换已经为 PyV8 引擎,因为 Chrome浏览器也是 V8 引擎。
但是 Alpine 下没有对 PyV8 程序的支持,安装程序都是针对 ubuntu, debian, centos 之类的。 直接 pip install 是不行的,需要系统上安装一些支持包。尝试编译了几个网上的 Dockerfile 失败了,主要原因是信息过时还有外网环境了。 giang/pyv8-python3 Dockerfile - Docker Hub
https://hub.docker.com/r/giang/pyv8-python3/dockerfile/ 这个 Dockerfile 需要从 googleapi 上拉取信息,编译时间很久而且还失败了 pyv8-docker/Dockerfile at master · new-mind/pyv8-docker
https://github.com/new-mind/pyv8-docker/blob/master/Dockerfile 这一个也失败了,首先它是 py2.7 的我需要的是 py3 系列的,ubuntu 最新版默认有 py3 的支持,然后 PyV8 的 google仓库也过期了,换成了 github,但是 wget 获取文件不完整,没法解压。 最终我直接在我的 CentOS 服务器上安装,先安装支持环境
yum install boost
yum install boost-devel
yum install boost-doc
然后下载库
https://raw.githubusercontent.com/emmetio/pyv8-binaries/master/pyv8-linux64-p3.zip
用 wget 下载会文件不完整导致解压不了,我是直接浏览器下载后自己解压的,解压后将 _PyV8.cpython-33m.so 重新命名为 _PyV8.so, 并将_PyV8.so 和 PyV8.py 复制到 Python3 的 site-packages 目录下,我这里是 /usr/local/lib/python3.6/site-packages。 之后在 python3 下执行 import PyV8 没有报错表示安装成功
通过 os.environ["EXECJS_RUNTIME"] = "Node" 可以选定 ExecJS 的 JS引擎,然而 PyV8 同样出现致命错误 Segmentation fault。
一些其他的引擎比如 PhantomJS 之类的,我也折腾了一下,都不大方便。最终我决定自己写 Node程序来专门为 Python提供加密服务
var CryptoJS = require("crypto-js");

var express = require('express');
var app = express();

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.get('/', function (req, res) {
     res.send('hello');
});

app.post('/encrypt', function(req, res){
  // console.log(req);
    console.log(req.body);
    var data = req.body.data;
    var encrypt = CryptoJS.AES.encrypt(data, "secretkey123");
    console.log(encrypt.toString());
    res.send(encrypt.toString());
});

var server = app.listen(8300, function() {
    console.log('Listening on port %d', server.address().port);
});
完美解决问题。
参考: Python爬虫杂记 - python运行js - 简书
https://www.jianshu.com/p/e01a3d504700 【Python3】 PyV8的安装与使用 - 依然范儿特西 - 博客园
https://www.cnblogs.com/richerdyoung/p/8535149.html

评论

发表回复