1. 程式人生 > 其它 >JS逆向之5173分析加密password

JS逆向之5173分析加密password

篇幅有限

完整內容及原始碼關注公眾號:ReverseCode,傳送

抓包

登入URL:

POST https://passport.5173.com/?returnUrl=http%3A//www.5173.com/

引數:

smsLogin: 0
userName: 15806204095
password: 6a771c7ecf7ebe2c3d4c0075cdb96ae5
mobileNo: 
smsCaptcha: 
category: 
passpod: 
__validationToken__: 1680e6a3947c43aea45d83e69b0d7291
__validationDna__: 

分析

password

password有32位,有可能是md5

搜尋password,出現的地方太多了,懶得看,放棄。

點選登入按鈕,肯定觸發事件傳送請求,搜尋submit-btn無效結果。

搜尋tnSubmit加上斷點,點選登入按鈕時,果然斷在了這個function中,不過此刻Network面板的請求包已經發送出去了,gg了,沒能攔截到https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f請求傳送前的時間點。

再一次嘗試,在加密password時肯定要獲取該輸入框的值,通過id獲取元素的話,我們搜尋#txtPass在所出現的位置都打上斷點

點選登入時檢視Network已經攔截在了ValidateSlide請求,還沒有到登入請求

檢視斷點時列印o為aec712a02d8c835b92369e5d7e5494cf,並直接跳到return $[["ajax"]]處,檢視此時提交的data中的a[["serialize"]]()"smsLogin=0&userName=15806204095&password=aec712a02d8c835b92369e5d7e5494cf&mobileNo=&smsCaptcha=&category=&passpod=&__validationToken__=31004cd552c94687ba27d1c7258576f7&__validationDna__="

,其中的password就是之前列印的o引數。

由於password=o,現在只需要追蹤這個o引數來源即可。往上追溯是onsubmit: function(f, o)中作為第二個引數o傳遞進來的,通過呼叫的堆疊檢視上一級呼叫方法submitHandle。

submitHandler這段程式碼返回a.onsubmit(a, c),其中c就是onsubmit: function(f, o) 中的o=password。由於a.usingTpm || a.passwordHash是true,那麼這個c就是通過a.getPassword(a.pkey)獲取。

進入getPassword後,this.ready && this.activeTpm && this.usingTpm為false,必然進入的是else中的c = hex_md5(hex_md5(c).substr(8, 16) + a);實現加密。

(c = b("#" + this.passwordControlId).val()) && this.passwordHash賦值必然是true,其中(c = b("#" + this.passwordControlId).val())的結果為123456,即我們輸入的密碼,由於傳入的a為42m2gl,所以加密邏輯整理為c = hex_md5(hex_md5("123456").substr(8, 16) + "42m2gl")

那麼問題來了,傳入的a是哪裡來的,通過搜尋42m2gl,原來每次頁面生成的時候頁面會載入PasswordKey,通過PasswordKey和SecurityToken等key實現相互驗證進行校驗。

__validationToken__

__validationToken__這個欄位6b16902a6b134dc9a2c333b965c9405f在請求裡面無法搜到是因為頁面已經重新整理,通過fiddler抓包https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f歷史可以看到首頁載入時傳入該引數

爬蟲實現

首次先請求https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f

獲取頁面中的PasswordKey的值和SecurityToken的值,通過兩次md5密碼hex_md5(hex_md5("123456").substr(8, 16) + "42m2gl")拿到password加密結果,發起請求。

def hex_md5(s):
    m = hashlib.md5()
    m.update(str(s).encode("utf-8"))
    return m.hexdigest()

headers = {
    'Host': 'passport.5173.com',
    'Origin': 'https://passport.5173.com',
    'Pragma': 'no-cache',
    'Referer': 'https://passport.5173.com/?returnUrl=http%3A//www.5173.com/',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
}
login_url = 'https://passport.5173.com/?returnUrl=http%3A//www.5173.com/'
html = requests.get(login_url).text
# print(html)
securityToken = re.findall('SecurityToken:"(.*?)",', html, re.M | re.S)[0]
passwordKey = re.findall('PasswordKey:"(.*?)",', html, re.M | re.S)[0]
print(passwordKey)
print(securityToken)


# 滑塊 'https://passport.5173.com/Sso/ValidateSlide?token={}'.format(securityToken)
# hex_md5(hex_md5("123456").substr(8, 16) + "42m2gl")
password = hex_md5(hex_md5("123456")[8:8 + 16] + passwordKey)
userName = '15806204096'

data = {
    'smsLogin': '0',
    'userName': userName,
    'password': password,
    'mobileNo': '',
    'smsCaptcha': '',
    'category': '',
    'passpod': '',
    '__validationToken__': securityToken,
    '__validationDna__': ''
}
r = requests.post(login_url, data, headers=headers)
print(r.text)

雖然password邏輯已經破解,不過登入時還需要驗證碼滑塊的校驗,以後有時間再寫吧。。。

本文由部落格一文多發平臺 OpenWrite 釋出!