這個網站的邏輯大致如下:第一次访问后:https://auth.fedex.com/am/json/realms/root/realms/alpha/authenticate?authIndexType=service&authIndexValue=LP_user_login&_si=0获取網頁返回的authId后作为第二个url:https://auth.fedex.com/am/json/realms/root/realms/alpha/authenticate?authIndexType=service&authIndexValue=LP_user_login&_si=1的请求体获取第二个url返回的authId网页内容,作为第三个url的请求体:https://auth.fedex.com/am/json/realms/root/realms/alpha/authenticate?authIndexType=service&authIndexValue=LP_user_login&_si=2最後獲取到結果。雖然這個邏輯搞清了,但是實際操作好像有點麻煩,有個參數似乎蠻難辦的,如下
找到登陸包,看到需要兩個參數,comp_d 和 uLogin(下面password的加密算法相同。)我先找的 uLogin,抓包定位,然後找到 crypt.encode 方法,跟進去,這個方法只會執行後面那個,所以從後面開始扒下。直接給出算法cb_utob = function(R) { let oe = null; return R.length < 2 ? (oe = R.charCodeAt(0), oe < 128 ? R : oe < 2048 ? fromCharCode(192 | oe >>> 6) + fromCharCode(128 | oe & 63) : fromCharCode(224 | oe >>> 12 & 15) + fromCharCode(128 | oe >>> 6 & 63) + fromCharCode(128 | oe & 63)) : (oe = 65536 + (R.charCodeAt(0) - 55296)
測試過了,headers并沒有加密的東西,必須携帶Cookie才能獲取響應内容,經過篩選,找到如下三個必備參數.bm_sz 參數是第一次訪問這個網頁,網站返回的,JSESSIONID 在不同網頁訪問返回的,第三個是固定值。那麽主要就是獲取 JSESSIONID,發現請求頭有加密,測試了,只要解決這個參數就順水推舟了。找到 this.calculateDigest(V + z + K + W["x-dbi-app-id"] + W["x-dbi-app-version"] + W["x-dbi-build-number"]);webpack,扣解釋器后傳入模塊就好了,這裏遇到一個問題,解釋器上面的好像有些問題,改成以下就行了。那麽下面是全部代碼:var encryption_obj; var window = global; !function(g){ // var e, g = {}, v = {}; v = {} function t(e) { var f = v[e]; if (void 0 !== f)
一般的網站接口都是固定的url地址,但是這個網站有點特殊。以下是正常請求網頁地址,會返回一些cookie,後面發包需要用到。這個是登陸包,箭頭指向的是會變化的。也就是説,根據每次打開瀏覽器訪問這個登錄接口,都會生成不同的地址,構成不同的url(我在這裏卡了好久,明明headers和cookies還有請求内容都正確但是一直訪問失敗。)搜索這個值,回到第一個請求包的響應内容裏面。這個網站沒什麽難度,考驗的是細心。第一次訪問頁面會返回csrf、cookie,保存后第二次用之前獲取的參數拼接url,配置好headers和cookies,最後發包就行了。
在請求頭裏面有這麽個參數,嘗試逆向。看到如下代碼,找到了h和x,代碼類型為 webpack我盡力了,雖然沒有報錯,但是輸出不了結果,如下是代碼,有解決方案可以在下面評論var encryption_obj; var window = global; !function(e){ t = {}; function n(r) { var i = t[r]; if (void 0 !== i) return i.exports; var a = t[r] = { id: r, loaded: !1, exports: {} }; console.log(r) return e[r].call(a.exports, a, a.exports, n), a.loaded = !0, a.exports } n.o = function(e,
測試過了如果沒有這個參數或者這個參數錯誤,就會訪問失敗,看似是uuid,但是網站隨機生成的不可用。然後斷點,搜索關鍵詞,不停的斷點和刷新網頁繼續跟,在uc這裏繼續跟找到了,以下是代碼: const Dr = []; for (let t = 0; t < 256; ++t) Dr.push((t + 256).toString(16).slice(1)); function SD(t, e=0) { return Dr[t[e + 0]] + Dr[t[e + 1]] + Dr[t[e + 2]] + Dr[t[e + 3]] + "-" + Dr[t[e + 4]] + Dr[t[e + 5]] + "-" + Dr[t[e + 6]] + Dr[t[e + 7]] + "-" + Dr[t[e + 8]] + Dr[t[e + 9]] + "-" + Dr[t[e + 10]] + Dr[t[e + 11]] + Dr[t[e + 12]] + Dr[t[e + 13]] + Dr
這裏看到參數只有一個需要解密然後下斷點,找到這個位置,Object(c.b)(data.password, "AmrGowGCtUwd/2PgTyrJuV==")進入 Object(c.b)可以看到是一個通用庫加密方式,找到在綫網站,輸入密鑰 AmrGowGCtUwd/2PgTyrJuV== 測試分析 Object(c.b) 對應的函數函數功能根據提供的函數定義,可以得出以下結論:功能: 這個函式 r 主要用於 加密 資料。加密方式: 使用的是 TripleDES 加密算法,以 ECB 模式進行加密,並採用 PKCS7 填充。輸入參數:e: 需要加密的原始資料(明文)。t: 加密使用的密鑰,以 UTF-8 格式解析。輸出結果:返回加密後的密文,以字符串形式表示。函數解析引入加密庫: 函數中使用了 o 物件,這個物件很可能是引入的加密庫(例如 CryptoJS)的一個命名空間,提供了加密相關的函數和常量。密鑰解析: o.enc.Utf8.parse(t) 這部分將傳入的密鑰 t 從 UTF-8 字符串轉換為加密庫可以使用的內部表示形式。加密操作: o.TripleDES.encrypt(
看登陸包,驗證碼先不管,可以看到加密參數只有password。找到位置,斷點,可以發現調用的是 E.fM 來加密明文數據。往上面翻就找到了E的位置,s(802123)斷點並刷新網頁,去尋找分發器,跳轉到了o的位置,那麽o就是分發器。文件全部複製,新建一個js文件來測試。外部定義一個變量來接收 o ,并在o裏面打印調試信息找到 802123: 發現裏面調用的太多了,乾脆全部複製,添加到我們的調試函數裏面。我們只要内容,外邊的就去掉粘貼到 e 裏面運行發現報錯,找到那一行,注釋掉就可以了,我也不清楚這這行代碼有什麽用。繼續調試,面板輸出的模塊名,從網頁裏面搜了再補充就好了。最後看看效果:全部代碼
查看登錄包,ts明顯是時間戳,通過斷點可以知道password是經過md5加密,所以把焦點放到sign上面。看到了h的内容,其中後面的key是固定的找到d函數斷點,跳轉到這裏,可以看到這符合 webpack格式經過測試 e 為傳進去的明文數據,n 則是未定義,我們往上面找 t 賦值函數,t 再跳轉到 n 對n那裏斷點,刷新頁面,就找到了解釋器的位置複製全部的内容,然後在後面添加執行函數,同時在函數結束前聲明一個變量接收看下面就是加密解析成功了全部代碼:var encryption_obj; var window = global; (function(t) { function e(e) { for (var i, a, r = e[0], c = e[1], u = e[2], p = 0, l = []; p < r.length; p++) a = r[p], Object.prototype.hasOwnProperty.call(n, a) && n[a] && l
RSA 加密詳解什麼是 RSA 加密?RSA 是一種非對稱加密演算法,廣泛應用於資訊安全領域,尤其是網路通訊。它的名稱來自於三位發明者 Rivest、Shamir 和 Adleman 的姓氏首字母。RSA 的工作原理非對稱加密: RSA 使用一對密鑰:公鑰和私鑰。公鑰可以公開分發,而私鑰必須嚴格保密。加密與解密:加密: 使用公鑰對明文進行加密,得到密文。解密: 使用私鑰對密文進行解密,恢復出原始的明文。數學基礎: RSA 的安全性基於大整數分解問題的難解性。也就是說,要從公鑰中推算出私鑰在計算上是不可行的。RSA 的關鍵組成模數 (modulus): 是一個大整數,用於模運算。公鑰指數 (public exponent): 一個小於模數的整數,用於公鑰加密。私鑰指數 (private exponent): 一個大整數,用於私鑰解密。公鑰: 由模數和公鑰指數組成。私鑰: 由模數和私鑰指數組成。RSA 的加密過程生成密鑰對: 選擇兩個大素數 p 和 q,計算模數 n = p * q,再根據歐拉函數計算出其他參數,生成公鑰和私鑰。加密: 使用公鑰對明文進行模冪運算,得到密文。解密: 使用私鑰
從登陸包可以看到用戶名和密碼的加密方法為同一個繼續搜尋相關參數,找到如下代碼,即通過 encryptByAES 函數加密。提取出來以後,可以看到結果和登陸包的請求内容是一樣的相關js代碼:function encryptByAES(message, key) { let CBCOptions = { iv: CryptoJS.enc.Utf8.parse(key), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }; let aeskey = CryptoJS.enc.Utf8.parse(key); let secretData = CryptoJS.enc.Utf8.parse(message); let encrypted = CryptoJS.AES.encrypt( secretData, aeskey, CBCOptions ); return CryptoJS.e
觀察登錄包,貌似只有sign加密了,是連同輸入的密碼一起加密的,timestamp很明顯是時間戳看上去是層層相扣,要找到sign的參數,就要找到 cr 的值,要找到 cr 的值,就要找到 we 的值不管了,直接全部扣下來,他媽的, var Qe = { exports: {} }; (function(t) { (function() { var e = "input is invalid type" , n = "finalize already called" , o = typeof window == "object" , r = o ? window : {}; r.JS_MD5_NO_WINDOW && (o = !1); var a = !o && typeof self =
!function(a, b) { "object" == typeof exports ? module.exports = exports = b() : "function" == typeof define && define.amd ? define([], b) : a.CryptoJS = b() }(this, function() { var a = a || function(a, b) { var n, c = Object.create || function() { function a() {} return function(b) { var c; return a.prototype = b, c = new a, a.prototype = null, c
API_KEY為2captcha的API import requests creat_task_url = 'https://2captcha.com/in.php?key=API_KEY&method=userrecaptcha&googlekey=WEBSITE_KEY&pageurl=URL' id = '' res = requests.get(creat_task_url) if res.status_code == 200: id = str(re.findall('\|(\d*)', res.text)[0]) time.sleep(20) code_res = requests.get(f'https://2captcha.com/res.php?key=API_KEY&action=get&id={id}') print(code_res.text)
找登錄包后看到三個參數:1.token(網頁刷新直接頁面就可以通過f12搜尋到)2.email3.password(加密)剩下就是尋找加密函數了,搜索token后看到頁面加密的位置,encryptPass('emailPwdInp'),那麽接下來搜索 encryptPass找到加密函數了 function encrypt (str) { const key = CryptoJS.enc.Utf8.parse("idcsmart.finance") const iv = CryptoJS.enc.Utf8.parse("9311019310287172") var encrypted = CryptoJS.AES.encrypt(str, key, { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, iv: iv, }).toString() return encrypted } function encryptPass (id) { le