Python利用PyExecJS庫執行JS函數!這也太厲害了吧

在Web滲透流程的暴力登錄場景和爬蟲抓取場景中,經常會遇到一些登錄表單用DES之類的加密方式來加密參數,也就是說,你不搞定這些前端加密,你的編寫的腳本是不可能Login成功的。針對這個問題,現在有三種解決方式:

  • ①看懂前端的加密流程,然後用腳本編寫這些方法(或者找開源的源碼),模擬這個加密的流程。缺點是:不懂JS的話,看懂的成本就比較高了;
  • ②selenium + Chrome Headless。缺點是:因為是模擬點擊,所以效率相對①、③低一些;
  • ③使用語言調用JS引擎來執行JS函數。缺點是:每個JS引擎執行的效果會不一致,導致一些小偏差;

第③種方式中,Python語言能利用的庫有PyExecJS、PyV8、Js2Py三種,PyV8使用就報錯(我暫時沒解決),Js2Py相當於將JS翻譯成Pyhton,Js2Py對於複雜JS而言非常容易出錯。所以本文主要討論通過Python語言的PyExecJS庫(切換不同的JS引擎)來執行JS函數的過程。

PyExecJS官網案例

pip 安裝: pip install PyExecJS

Demo:

<code>import execjs

print(execjs.eval("'red yellow blue'.split(' ')"))

ctx = execjs.compile("""
function add(x, y) {
return x + y;
}
""")
print(ctx.call("add", 1, 2))/<code>

輸出:

<code>['red', 'yellow', 'blue']
3/<code>

查看JS引擎信息

<code># 1.在windows上不需要其他的依賴便可運行execjs, 因為默認有個JScript庫,如果要運行其他JS引擎庫,就需要另外安裝了。
# windows默認執行的JS環境
execjs.get().name
#返回值: JScript
# 如果想要切換,用os.environ["EXECJS_RUNTIME"] = "XXX",如果剛安裝完其他JS引擎,必須配置環境變量,還可能需要重啟電腦或重啟IDE。
# 如果windows上裝有Node.js , 可以切換Node
os.environ["EXECJS_RUNTIME"] = "Node"
print(execjs.get().name)
#返回值: Node.js (V8)
# 如果windows上裝有PhantomJSs , 可以切換PhantomJS
os.environ["EXECJS_RUNTIME"] = "PhantomJS"
print(execjs.get().name)
#返回值: PhantomJS

# 2.在ubuntu下需要安裝執行JS環境依賴, 作者的環境為PhantomJS
execjs.get().name
#返回值: PhantomJS

# 3.源碼中給出, 可執行execjs的環境:
PyV8 = "PyV8"
Node = "Node"
JavaScriptCore = "JavaScriptCore"
SpiderMonkey = "SpiderMonkey"
JScript = "JScript"
PhantomJS = "PhantomJS"
SlimerJS = "SlimerJS"
Nashorn = "Nashorn"/<code>

安裝PhantomJS步驟 私信小編01 領取完整項目代碼!

下載地址: http://phantomjs.org/download.html

拷貝到腳本到你的Python環境裡: 把下載下來的文件解壓,找到目錄裡 .\\phantomjs-2.1.1\\bin\\ 下的phantomjs.exe,移動到使用的python文件夾下的Script中。

<code># 舉例 Anaconda3
D:\\programfiles\\Anaconda3\\Scripts/<code>

添加系統變量: D:\\programfiles\\Anaconda3\\Scriptsphantomjs.exe 添加到系統變量中。

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

驗證: 添加環境變量後,在cmd中驗證可以使用phantomjs命令,說明環境搭建好了。

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

在python中切換成PhantomJS:

<code>os.environ["EXECJS_RUNTIME"] = "PhantomJS"/<code>

案例1

1.訪問目標網站的登錄頁面並查看源碼

訪問 http://www.XXX.cn/login.html 查看一下在提交表單之前js對輸入的賬號、密碼做了什麼操作。(如下是偽代碼)

<code>






\t
/<code>

2.將js放到和py腳本同一級目錄下

我將整個a.js文件都粘貼到這裡,方便需要實驗的同學。

<code>/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k/<code>

3. 編寫Python腳本來調用js

<code>import execjs 


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

def get_des_psswd(acc, code):
jsstr = get_js()
# 加載JS文件
ctx = execjs.compile(jsstr)
# 調用js方法 第一個參數是JS的方法名,後面的為js方法的參數
return ctx.call('doencodeacc', acc, code)

if __name__ == '__main__':
print(get_des_psswd("zhangsan123456", "pYr6BTle")) # pYr6BTle = ralt code (加密的鹽值)/<code>

案例2

這個案例相對會複雜一些;

1.找登錄時的加密函數

看發包

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

登錄該站時,發現該網站先異步獲取了一個公鑰,然後賬號跟密碼都加密了,只能上調試了。建議調試都用Chrome F12,其它工具都不如他好使。

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

右鍵查看源碼,發現有JS,但是太多了,過濾一下。

2.監聽鼠標點擊事件查看流程

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

一頓操作之後,跳到登錄提交的函數,直接看代碼

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

往下看看代碼之後,發現代碼沒加混淆也沒有其他防護,那就一步到位解決了,破解這個加密還不跟切菜一樣簡單了。

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

3.寫代碼

導入js: 將jsencrypt.js導入到python項目中,這個js有5千多行,我就不粘貼上來了。

Python利用PyExecJS庫執行JS函數!這也太厲害了吧

<code>import execjs
import os

if __name__ == '__main__':
# 切換了JScript、Node後都無法執行JS,發現還是PhantomJS靠譜
# os.environ["EXECJS_RUNTIME"] = "JScript"
# os.environ["EXECJS_RUNTIME"] = "Node"
os.environ["EXECJS_RUNTIME"] = "PhantomJS"
print(execjs.get().name)


js = open('jsencrypt.js', encoding='utf-8').read()
jo = execjs.compile(js)
pwd = jo.call('myf')
print(pwd)/<code>

輸出:

<code>PhantomJS
Hu4Ujwqwe/PDAblIvjNyrX4NrltoRXXDdyC6+F+p0LaqPSegMZ16oIqeVPiHlh5x8zKeI2DC3DoPVf8ZlusUCQ==/<code>

不同瀏覽器內核版本對URL編碼處理也不同[冷知識]

當Html的表單被提交時,每個表單的參數都會被Url編碼之後才能被髮送。由於歷史的原因,表單使用的Url編碼實現並不符合最新的標準。例如對於空格使用的編碼並不是 %20 ,而是 + 號,如果表單使用的是Post方法提交的,我們可以在HTTP頭中看到有一個Content-Type的header,值為application/x-www-form-urlencoded。大部分應用程序均能處理這種非標準實現的Url編碼,但是在客戶端Javascript中,並沒有一個函數能夠將+號解碼成空格,只能自己寫轉換函數。還有,對於非ASCII字符,使用的編碼字符集取決於當前文檔使用的字符集。


分享到:


相關文章: