PyV8、PyExecJS、js2py区别

PyV8、PyExecJS---->模拟js执行

js2py区别 ------> 装换代码本身,改为python可执行的,本质完全不同

目前发现PyV8、PyExecJS比较靠谱,MacOS 安装PyV8的话用https://github.com/emmetio/pyv8-binaries,pip安装有问题。

js2py虽然很方便,但是有时候代码会报错。

PyV8例子

import PyV8

ctxt = PyV8.JSContext()
ctxt.enter()
test=ctxt.eval("""
(function(p){
    function abc(t) {
        return "hello,"+t;
    }
    return abc(p);
})
""")
if __name__ == "__main__":
    print(test('world'))
输出

hello,world

但是传python字典给js的函数,似乎没有用。不过可以json.dumps(dict) 传给js函数,js函数再JSON.parse(json_str)。

pyv8自带的这种方法很奇怪,有的函数运行会得到和真正js不一样的结果,但是PyExecJS走PyV8就没有这种问题,真是奇怪。

pyexecjs速度慢与pyv8的安装

  1. 1. 安装pyv8
  2. 2. pyexecjs修复
  3. 3. Js2Py

使用PyExecjs写的代码,放在服务器上每次执行都需要好几秒钟才能返回,经过排查发现PyExecjs的锅,官方也有如下声明:

One of cons of PyExecJS is performance. PyExecJS communicate JavaScript runtime by text and it is slow. The other cons is that it does not fully support runtime specific features.
PyV8 might be better choice for some use case.

原来PyExecjs是通过将要运行的js代码写到/tmp下面的随机文件里,然后调用相关的解释器执行该文件。没办法只能改用PyV8。
使用pip install PyV8安装怎么装都不成功,老提示找不到<v8.h>,最后发现此github上有编译好的相关文件。

安装pyv8

安装步骤:

  1. 下载相应系统的压缩文件
  2. 解压得到PyV8.py与_PyV8.so(如果so文件不是这个名字要将它改成这样)
  3. 打开python解释器,查看sys.path找到site-packages目录位置(我这里是/usr/local/lib/python3.5/site-packages)
  4. 将上面两个文件复制到site-packages目录就可以了。

pyexecjs修复

安装pyv8后,pyexecjs默认会使用pyv8运行时。pyexecjs支持的运行时及优先级如下

First-class support (runtime class is provided and tested)

  • PyV8 - A python wrapper for Google V8 engine,
  • Node.js
  • PhantomJS
  • Nashorn - Included with Oracle Java 8

Second-class support (runtime class is privided but not tested)

  • Apple JavaScriptCore - Included with Mac OS X
  • Microsoft Windows Script Host (JScript)
  • SlimerJS
  • Mozilla SpiderMonkey

相同的代码部署在服务器上运算慢的原因估计就是开发环境使用的是Apple JSCore运行时,部署在服务器上只有Nashorn。
安装完pyv8后使用pyexecjs会报如下错误:

AttributeError: module ‘contextlib’ has no attribute ‘nested’

这是由于在python3中,contextlib的nested函数被去掉了,因为with语法可以达到相同的作用,要想让pyexecjs正常运行,需要修改pyexecjs下的_pyv8runtime.py。将第51行代码
with contextlib.nested(PyV8.JSContext(), PyV8.JSEngine()) as (ctxt, engine):
改为
with PyV8.JSContext() as ctxt, PyV8.JSEngine() as engine:

Js2Py

mac os下代码可以正常运行,但部署到centos上PyV8老崩溃,提示segmentation fault。努力了两天也不行,最终找到这个js2py,它可以将js代码转成python代码,也内置了一个js运行环境。笔者将js转换成python代码后成功运行。

python-js2py模块的应用

分享一个破解js方法的模块吧。
在工作中有些网站是涉及到加密的问题,因为作者所做的网站大部分涉及到登录问题,那么在登录的时候我们知道最有可能遇到的是账号密码的加密,今天就分享一下自己在工作中实际遇到的问题以及解决方法,直接上代码如下:

{"LoginKey":"46fd82c2-3108-b2a4-3056-0eaa426f975b","data":"{\"User_Oid\":\"账号\",\"User_Password\":\"密码\"}"}

自己想要模拟登录的时候发现无缘无故的多了一个键值对:"LoginKey":"46fd82c2-3108-b2a4-3056-0eaa426f975b",此时不禁在想难道是个固定值,又或者在其他页面上生成的数据吗?然而当作者实际测试的时候发现固定值这个想法太简单了,可是也没有从其他的页面获取到值呀?不禁猜想一定是js文件进行了加密,于是那就找js文件吧,查找js文件这里作者就不教大家怎样查找了,如果不会可以去作者之前的分享看一下,因为涉及到工作网站,这里作者也不对外提供网址了,今天分享的是我们找到js文件是怎样才能破解和实现。这里作者贴出来找到的js函数:

function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
};
function guid() {
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}

这就是生成LoginKey值的js文件,那么进行破解吧,js2py模块的应用正式开始。

  1. 安装
pip install js2py

  1. 应用
#coding=utf-8

import js2py

LoginKey = js2py.eval_js('''
function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
};
function guid() {
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
var a = guid()  // 在这里是需要调用的
''')
print LoginKey 

好了是不是破解到这里就结束了,是不是这个模块的应用是非常简单的,破解js说明白了就是怎样找到加密的函数才是关键。

js的逆向解析

过程:

  知道如何寻找登录的接口

  知道如何确定js的位置

  知道如何观察js的执行过程

  知道js的执行方法

1. 确定网站的登录的接口

  1. 登录的form表单中action对应的url地址
  2. 通过抓包可以发现,在这个url地址和请求体中均有参数,切换到手机版,参数的个数少,分析js

2. 确定js的位置

  1. 通过点击按钮,然后点击Event Listener,部分网站可以找到绑定的事件,对应的,只需要点击即可跳转到js的位置
  2. 部分网站的按钮可能并没有绑定js事件监听,那么这个时候可以通过搜索请求中的关键字来找到js的位置,比如livecell

3. 观察js的执行过程

  1. 找到js的位置之后,我们可以来通过观察js的位置,找到js具体在如何执行,后续我们可以通过python程序来模拟js的执行,或者是使用类似js2py直接把js代码转化为python程序去执行
  2. 观察js的执行过程最简单的方式是添加断点
  3. 添加断点之后继续点击登录,每次程序在断点位置都会停止,通过如果该行有变量产生,都会把变量的结果展示在Scoope中

4. 执行js

观察代码知晓需要哪些参数,比如:

  1. 我们要登录需要对密码进行加密和获取rkey字段的值
  2. rkey字段的值我们直接发送请求rkey请求就可以获得
  3. 密码是先反转然后使用RSA进行加密, js代码很复杂, 我们希望能通过在python中执行js来实现

实现思路:

  1. 使用session发送rKey获取登录需要信息
  2. 根据获取信息对密码进行加密
  3. 使用session发送登录请求
import requests
import json
import js2py

# - 实现思路:
#   - 使用session发送rKey获取登录需要信息
#     - url: http://activity.renren.com/livecell/rKey
#     - 方法: get
#  获取session对象
session = requests.session()
headers = {
    "User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36",
    "X-Requested-With": "XMLHttpRequest",
    "Content-Type":"application/x-www-form-urlencoded"
}
# 设置session的请求头信息
session.headers = headers

response = session.get("http://activity.renren.com/livecell/rKey")
# print(response.content.decode())
n = json.loads(response.content)['data']

#   - 根据获取信息对密码进行加密
#     - 准备用户名和密码
phoneNum = "131..."
password = "****"
#     - 使用js2py生成js的执行环境:context
context = js2py.EvalJs()
#     - 拷贝使用到js文件的内容到本项目中
#     - 读取js文件的内容,使用context来执行它们
with open("BigInt.js", 'r', encoding='utf8') as f:
    context.execute(f.read())

with open("RSA.js", 'r', encoding='utf8') as f:
    context.execute(f.read())
with open("Barrett.js", 'r', encoding='utf8') as f:
    context.execute(f.read())

# - 向context环境中添加需要数据
context.t = {'password': password}
context.n = n
#     - 执行加密密码的js字符
js = '''
       t.password = t.password.split("").reverse().join(""),
       setMaxDigits(130);
       var o = new RSAKeyPair(n.e,"",n.n)
        , r = encryptedString(o, t.password);
      '''
context.execute(js)
# - 通过context获取加密后密码信息
# print(context.r)
password = context.r
#   - 使用session发送登录请求
#     - URL: http://activity.renren.com/livecell/ajax/clog
#     - 请求方法: POST
#     - 数据:
#       - phoneNum: 15565280933
#       - password: (加密后生产的)
#       - c1: 0
#       - rKey: rkey请求获取的
data = {
    'phoneNum': '131....',
    'password': password,
    'c1':0,
    'rKey':n['rkey']
}

# print(session.headers)
response = session.post("http://activity.renren.com/livecell/ajax/clog", data=data)
print(response.content.decode())

# 访问登录的资源
response = session.get("http://activity.renren.com/home#profile")
print(response.content.decode())
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,744评论 0 10
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,096评论 1 32
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,093评论 4 62
  • 听到有人在大喊哀求对方放过他! 看到一个年轻人,被两个人按在一把椅子上,一个人拿了一把刀,在伤害他。地上也有好多血...
    jessica的记忆阅读 197评论 0 0
  •  来点小料  Window(这里☞的不是微软)   document.getElementById(""); ① ...
    梦云之巅阅读 422评论 0 0