對某登錄站點的JS前端逆向思路

前言

js逆向一直沒有相關了解,雖然目前滲透遇見的不是很多,大多數遇見的要麼不加密,要麼無法實現其加密流程,不過最近看到了一個較爲簡單的站點正好能夠逆向出來,就做了簡單記錄。本文旨在介紹js逆向的一些基礎思路,希望能對初學js前端逆向的師傅有所幫助。

JS定位

在我們尋找JS源代碼時,如果直接翻看全部的js文件以來尋找自己想要的一部分,無疑是複雜繁瑣的,且工作量巨大,有點類似大海撈針,因此這裏我們需要藉助一些巧妙的辦法來快速定位某標籤的js語句,具體方法如下。

元素審查定位

當我們不確定某處的js文件位置時,可以使用F12,點擊元素審查,然後點擊登錄處,觀察事件監聽器

此時可以觀察到login.js文件出現,接下來就可以去對應文件下繼續深入。

image-20231128234811191

發現check函數,尋找check函數

image-20231128234845796

此時發現加密是secret函數,再繼續跟secert函數就可以瞭解其整體流程。

全局搜索法

像我們常見的登錄框,他們要提交的加密參數一般名爲password,或者加密爲Crypto加密,因此我們可以全局搜索此類關鍵字,進而尋找我們需要找的關鍵加密js語句,進而實現js逆向。

具體操作也很簡單,這裏簡單舉個例子。

首先打開F12,隨便點擊一個元素,而後ctrl+shift+f,接下來全局搜索關鍵詞即可

此時含關鍵詞的語句映入眼簾,像一些css文件中的直接略過即可,而後即可找到真正生成密碼的地方

image-20231128235456040

接下來便可以深入secret,瞭解加密方法。

Onclick定位

像一些登錄點是存在着onclick屬性的,如若該屬性值是js函數,那麼就極有可能是我們要尋找的js加密函數,而後進行尋找相關函數即可。

注:圖參考自cony1大師傅。

cony1大師傅的圖爲例進行簡單講解

圖1-通過onClick屬性定位

這裏發現ssologin函數,接下來尋找該函數

圖2-通過onClick定位到的方法

此時即可發現相關js語句。

【----幫助網安學習,以下所有學習資料免費領!加vx:yj009991,備註 “博客園” 獲取!】

 ① 網安學習成長路徑思維導圖
 ② 60+網安經典常用工具包
 ③ 100+SRC漏洞分析報告
 ④ 150+網安攻防實戰技術電子書
 ⑤ 最權威CISSP 認證考試指南+題庫
 ⑥ 超1800頁CTF實戰技巧手冊
 ⑦ 最新網安大廠面試題合集(含答案)
 ⑧ APP客戶端安全檢測指南(安卓+IOS)

實戰

某登錄站點js逆向

找到一個登錄站點,隨意輸入

image-20231128005329129

發現用戶名和密碼均被加密,接下來ctrl+shift+f,全局搜索password字段,尋找加密點

image-20231128005449247

第一個這裏明顯是輸入框的password,且是註釋,肯定不是這裏,接着尋找,後來到

image-20231128005609606

整體代碼如下

        function check() {
            //這裏將用戶名,密碼加密
            var code = 'letu@levle';
            var yname = $("#yname").val();
            if (yname == '') {
                alert("用戶名不能爲空");
                return false;
            } else {
                var newName = secret(yname, code, false);
                $("#xname").val(newName);
            }
​
            var ypassword = $("#ypassword").val();
            if (ypassword == '') {
                alert("密碼不能爲空");
                return false;
            } else {
                var newPassword = secret(ypassword, code, false);
                $("#xpassword").val(newPassword);
            }
        }

可以看出js代碼邏輯並不難,首先提取出ypassword標籤下的內容,而後驗證其是否爲空,若不爲空,則對其進行secret函數處理,很明顯,這個secret函數就是加密函數,所以我們接下來跟進此加密函數

image-20231128005806351

這裏直接給出了iv和key,所以接下來打斷點調試就行了,而後打上斷點

image-20231128005848675

接下來開始隨便輸入密碼提交,而後來到調試界面

選中code.substring(16)得到keyf3991777154f4bd0

image-20231128010001183

選中code.substring(0,16)得到偏移量ace43e65106a77f6

image-20231128010041413

下方也給出了Padding和mode分別是Pkcs7CBC,所以接下來直接解密即可,在網絡中我們可以看到提交後加密的賬密

image-20231128010129402

拿去隨便找個AES解密網站

image-20231128010305797

與所輸入的進行比對

image-20231128010334911

成功得到正確結果

接下來編寫腳本即可,直接將字典的內容全部進行加密,而後放入burp進行爆破

import base64
from Crypto.Cipher import AES
from Crypto.Hash import MD5
from Crypto.Util.Padding import pad
​
#填入AES的key和iv
key = 'f3991777154f4bd0'
iv = 'ace43e65106a77f6'
​
def AES_Encrypt(data):
    global key
    global iv
    cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    paddingdata = pad(data.encode('utf-8'),AES.block_size)
    encrypted = cipher.encrypt(paddingdata)
    #print(base64.b64encode(encrypted).decode())
    return base64.b64encode(encrypted).decode()
​
password = []
with open('password.txt','r',encoding='utf-8') as f:
    for i in f:
        password.append(i.strip())
with open('password_aes.txt','w',encoding='utf-8') as w:
    for i in password:
        data = AES_Encrypt(i)+'\n'
        w.write(data)

image-20231128155605940

數據長度明顯與錯誤時不一致,不過這裏也未成功進入後臺,有二次驗證,Google驗證碼無從下手,故點到爲止。

某道js逆向

image-20231128211913019

接下來進行抓包

image-20231128212052117

這裏我們首先注意一下每次不同點在哪,以此爲入口點來進行下去,因此我們多次刷新界面抓包,同樣的參數觀察包的參數哪個值是不同的

image-20231128213215702

從上圖可以看出signmysticTime是變化的,因此接下來針對這兩個變量進行深入,如果我們能夠控制這兩個變量,那麼我們就可以實現直接腳本請求得到翻譯對應的語句。

所以接下來首先從sign開始,我們首先進行F12,而後輸入ctrl+shift+f全局搜索關鍵詞

image-20231128213435952

這裏可以發現出現了js中含有sign關鍵字的,但像這個inpage.js他明顯不是我們要找的js語句,因此繼續往下尋找(輸入sign:更容易找到對應函數)。這裏我們找到如下語句

image-20231128213728883

相關代碼如下

const u = "fanyideskweb"
              , d = "webfanyi"
              , m = "client,mysticTime,product"
              , p = "1.0.0"
              , g = "web"
              , b = "fanyi.web"
              , A = 1
              , h = 1
              , f = 1
              , v = "wifi"
              , O = 0;
            function y(e) {
                return c.a.createHash("md5").update(e).digest()
            }
            function j(e) {
                return c.a.createHash("md5").update(e.toString()).digest("hex")
            }
            function k(e, t) {
                return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
            }
            function E(e, t) {
                const o = (new Date).getTime();
                return {
                    sign: k(o, e),
                    client: u,
                    product: d,
                    appVersion: p,
                    vendor: g,
                    pointParam: m,
                    mysticTime: o,
                    keyfrom: b,
                    mid: A,
                    screen: h,
                    model: f,
                    network: v,
                    abtest: O,
                    yduuid: t || "abcdefg"
                }
            }

這裏可以看到sign是由函數k構成的,同時注意到這裏也給出了k的參數,k是由client=fanyideskweb&mysticTime=${e}&product=webfanyi&key=${t}所組成的,此時再看函數E,o是時間戳,e這裏未知,這時候該怎麼辦呢,先看看他是不是固定值,當自己不確定在哪下斷點調試時,就在附近的幾個可疑點都打下斷點,觀察e的值即可

image-20231128232434494

經觀察,這裏的e值是固定的,即fsdsogkndfokasodnaso,此時k(o,e)中的參數我們都瞭解了,但我們注意到k函數中是有j在外包裹的,因此我們需要對j函數進行相關了解

function j(e) {
                return c.a.createHash("md5").update(e.toString()).digest("hex")
            }

明顯的md5加密,因此到這裏也就都清楚了。

當我們進行請求時,首先獲取當前的時間戳,此作爲參數之一,同時與client等參數值組合,進行md5加密,就組成了sign的值。對於mysticTime這個參數,我們從k函數也瞭解到它其實就是時間戳,因此兩個變化的參數到目前就都瞭解其生成過程了。

接下來嘗試寫python腳本

import hashlib
import time
import requests
​
requests.packages.urllib3.disable_warnings()
headers = {"Content-Length": "312",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Sec-Ch-Ua": "\"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"",
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/x-www-form-urlencoded",
"Sec-Ch-Ua-Mobile":"?0",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
"Sec-Ch-Ua-Platform": "\"Windows\"",
"Origin": "https://fanyi.youdao.com",
"Sec-Fetch-Site": "same-site",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Dest": "empty",
"Referer": "https://fanyi.youdao.com/",
"Accept-Encoding": "gzip, deflate",
}
Cookie = {
"OUTFOX_SEARCH_USER_ID":"[email protected]",
"OUTFOX_SEARCH_USER_ID_NCOO":"520521807.43848985"
}
url = ""
word = input("請輸入翻譯內容:")
localtime = str(int(time.time() * 1000))
canshu = "client=fanyideskweb&mysticTime={}&product=webfanyi&key=fsdsogkndfokasodnaso".format(localtime)
sign = hashlib.md5(canshu.encode(encoding='utf8')).hexdigest()
data = {
    "i": f"{word}",
    "from": "auto",
    "to": "",
    "dictResult": "true",
    "keyid": "webfanyi",
    "sign": sign,
    "client": "fanyideskweb",
    "product": "webfanyi",
    "appVersion": "1.0.0",
    "vendor": "web",
    "pointParam": "client,mysticTime,product",
    "mysticTime": localtime,
    "keyfrom": "fanyi.web"
}
res = requests.post(url=url,headers=headers,cookies=Cookie,data=data,verify=False)
print(res.text)

image-20231128232510212

此時便得到了加密數據,解密同理,不再闡述。

更多網安技能的在線實操練習,請點擊這裏>>

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章