反爬解決方案:七麥請求加密參數(shù)以及壓縮混淆Js的逆向分析

前言:

因?yàn)樽罱ぷ餍枰廊?code>APP應(yīng)用的信息躺坟,考慮到目前市場上比較成熟的應(yīng)用市場整合網(wǎng)站,因此選擇了七麥來下手和二,也由此發(fā)現(xiàn)了七麥的反爬策略趾牧,所以這次我們來分析一下七麥網(wǎng)站的接口的參數(shù)的由來。

開始:

我們首先來看看七麥的接口傀广,如下圖所示:

正常請求

正常響應(yīng)

我們可以看到這是正常情況下的請求颁独,看到了一個很有趣的參數(shù)。
參數(shù)構(gòu)成是這樣的:

analysis: IRIdEVEIChkIDF1USWkOFkofB0YADVNoWVQYCHZCBgBQAgRaAlNRAFQiGgA=

打眼一看伪冰,這個加密的值有點(diǎn)像Base64加密之后的效果誓酒,并且我們間隔一段時間使用這個相同的值我們會發(fā)現(xiàn),返回的響應(yīng)是如下這樣:

{'code': 10602, 'msg': 'Access Error'}

因此贮聂,我們可以斷定這個應(yīng)該是加了時間部分的Salt靠柑,我們直接去尋找相關(guān)的加密方法。
我們一般會通過每個請求后面的Initiator部分來跳轉(zhuǎn)吓懈,如下圖所示:

Initiator部分

跳轉(zhuǎn)之后

不過這樣的意義不是很大歼冰,因?yàn)槲覀冎苯舆M(jìn)入了一個產(chǎn)生這個請求的Js部分,讓人看的一臉蒙耻警,所以我這里推薦使用XHR Breakpoints打斷點(diǎn)去攔截請求隔嫡,這樣我們就可以看到一個完整的調(diào)用棧CallBack Stack,此處填入 URL 包含的關(guān)鍵詞 indexPlus甘穿。
增加了斷點(diǎn)之后我們重新刷新頁面腮恩,此時會卡在Debug的位置,如圖:

XHR斷點(diǎn)位置

我們可以通過右邊的Watch機(jī)制查看到這里的h是一個XHR對象
watch h對象

我們大致翻閱這段代碼温兼,發(fā)現(xiàn)這里面的代碼大致上都是很混亂的名字秸滴,猜想應(yīng)該是經(jīng)過代碼混淆了,我們來觀察下面這段代碼募判,也就是我們斷點(diǎn)位置的下面幾行荡含。

"7O1s": function(t, e, n) {
    var r = n("DIVP")
        , i = n("XSOZ")
        , o = n("kkCw")("species");
    t.exports = function(t, e) {
        var n, a = r(t).constructor;
        return void 0 === a || void 0 == (n = r(a)[o]) ? e : i(n)
    }
},
"7UMu": function(t, e, n) {
    var r = n("R9M2");
    t.exports = Array.isArray || function(t) {
        return "Array" == r(t)
    }
},
"7gX0": function(t, e) {
    var n = t.exports = {
        version: "2.5.5"
    };
    "number" == typeof __e && (__e = n)
},

雖然這段代碼經(jīng)過了一定程度的混淆,但是我們還是大致能看出來一點(diǎn)規(guī)律届垫,比如類似701s的隨機(jī)字符應(yīng)該是某個方法的名稱释液,而 var r = n("DIVP") 即引入模塊,正常的寫法可能是import a from 'b'或者 const a = require('b')敦腔。
這里發(fā)起 Ajax 請求的函數(shù)很可能只是一個被封裝了的模塊供整個項(xiàng)目調(diào)用均澳,粗略看一下函數(shù)代碼也沒有發(fā)現(xiàn)計算加密的部分。針對這種模塊化開發(fā)符衔,一個逆向的思路是找前,只要查看該模塊被引用的情況,不斷向上追溯判族,總能找到最初發(fā)起請求和加密的函數(shù)躺盛。
PS: 插一嘴,在如今前端開發(fā)也是大部分基于一些成熟的框架進(jìn)行模塊化的開發(fā)形帮,并有一整套完整的打包發(fā)布槽惫、壓縮混淆工具,這同時意味著他們的請求一般都會封裝起來辩撑,因此我們在逆向的時候只有不斷前溯界斜,就能夠發(fā)現(xiàn)模塊的根源。

我們在這里檢索斷點(diǎn)所在的模塊名 7GwW合冀,如圖:

追溯7GwW

我們?nèi)炙阉?code>7GwW這個模塊各薇,發(fā)現(xiàn)它只存在一個Js文件當(dāng)中,我們接著在這個Js文件當(dāng)中尋找7GwW君躺,發(fā)現(xiàn)它是被KCLY這個模塊所引用峭判,同理,繼續(xù)全局找棕叫,如圖:

尋找KCLY

我們可以發(fā)現(xiàn)林螃,有三個模塊引用了它,沒事俺泣,我們一個個分析:

我們先分析XmWM疗认,這個模塊是有tIFN引入的,如圖:

尋找XmWM

接著我們再順著tIFN伏钠,接著找侮邀,找到了mtWM模塊,然后繼續(xù)引入贝润,最終找到了gXmS绊茧,如圖所示:

gXmS

我們可以看到了在這個模塊請求被打包,封裝打掘。
至此华畏,我們費(fèi)勁腦子終于找到了封裝請求的模塊,不過倒是很費(fèi)時尊蚁,但這只是為了讓人理解模塊化的代碼的含義亡笑,真正我們在分析一個請求的時候,我們是可以使用一個更簡單的方法横朋,Callback Stack調(diào)用棧仑乌,
我們可以分析出,這個請求是發(fā)送的get請求,那我們就可以認(rèn)為get這個部分是調(diào)用的模塊晰甚,如圖:
get

分析的方法其實(shí)和之前的都是差不多的衙传,我們看Callback Stack調(diào)用棧每個調(diào)用方法的細(xì)節(jié)就能找到。

我們可以深挖這個加密的流程厕九,也就是整個請求組裝的過程蓖捶,如圖:

d.a.interceptors.request.use(function(a) {
            try {
                if (void 0 == g.difftime && !v) {
                    var e = Object(l.f)("synct");
                    g.difftime = -Object(l.f)("syncd") || +new Date - 1e3 * e
                }
                var n = Object(l.h)(Object(l.a)("ElhBGlwHD1c="));
                n = n.split("").reverse().join("");
                var t = +new Date - (g.difftime ? g.difftime : 0) - 1515125653845
                  , r = ""
                  , o = [];
                return void 0 === a.params && (a.params = {}),
                p()(a.params).forEach(function(e) {
                    if (e == n)
                        return !1;
                    a.params.hasOwnProperty(e) && o.push(a.params[e])
                }),
                o = o.sort().join(""),
                o = Object(l.d)(o),
                o += "@#" + a.url.replace(a.baseURL, ""),
                o += "@#" + t,
                o += "@#1",
                r = Object(l.d)(Object(l.h)(o)),
                -1 == a.url.indexOf(n) && (a.url += (-1 != a.url.indexOf("?") ? "&" : "?") + n + "=" + encodeURIComponent(r)),
                a
            } catch (a) {}
        }, function(a) {
            return m.a.reject(a)
        }),

我們加上斷點(diǎn)來試試,如圖:


分析
分析

其實(shí)我們發(fā)現(xiàn)整個加密過程無非是兩個加密函數(shù)比較重要扁远,l.dl.h俊鱼,我們看看這兩個函數(shù)的方法,如圖:

l.d

l.h

接下來就沒有什么難度了畅买,就是自定義一些加密算法并闲,可以打斷點(diǎn)看出來尖淘,比如如圖:


i的值

base64加密的l.d方法

至此齿税,一個完整的分析就是這樣出來,我們可以看到我們整個的分析流程就是根據(jù)每個包追溯上層包一個個追溯過來的话速,惡心的就是代碼被混淆讓人看的煩洒宝,不過其實(shí)掌握好規(guī)律之后就會發(fā)現(xiàn)原理還是很容易的购公。

話不多說,上代碼

我們按照組裝的步驟:

  1. 設(shè)置一個時間差變量
  2. 提取查詢參數(shù)值(除了 analysis)
  3. 排序拼接參數(shù)值字符串并 Base64 編碼
  4. 拼接自定義字符串
  5. 自定義加密后再 Base64 編碼
  6. 拼接 URL
# -*- coding: utf-8 -*-

'''
------------------------------------------------------------
File Name: qimai.py
Description : 
Project: test
Last Modified: Friday, 25th January 2019 8:55:39 am
-------------------------------------------------------------
'''


import time
from urllib.parse import urlencode
import json
import base64

import requests


headers = {
    "Accept": "application/json, text/plain, */*",
    "Referer": "https://www.qimai.cn/rank",
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/59.0"
}

params = {
    "brand": "all",
    "country": "cn",
    "date": "2019-01-20",
    "device": "iphone",
    "genre": "36",
    "page": 1
}


# 自定義加密函數(shù)
def encrypt(
    a: str,
    n="a12c0fa6ab9119bc90e4ac7700796a53"
) -> str:
    s, n = list(a), list(n)
    sl, nl = len(s), len(n)
    for i in range(0, sl):
        s[i] = chr(ord(s[i]) ^ ord(n[i % nl]))
    return "".join(s)


def main() -> None:
    # iPhone 免費(fèi)榜單

    # 步驟一:時間差
    t = str(int((time.time() * 1000 - 1515125653845)))
    # 步驟二:提取查詢參數(shù)值并排序
    s = "".join(sorted([str(v) for v in params.values()]))
    # 步驟三:Base64 Encode
    s = base64.b64encode(bytes(s, encoding="ascii"))
    # 步驟四:拼接自定義字符串
    s = "@#".join([s.decode(), "/rank/indexPlus/brand_id/1", t, "1"])
    # 步驟五:自定義加密 & Base64 Encode
    s = base64.b64encode(bytes(encrypt(s), encoding="ascii"))
    # 步驟六:拼接 URL
    params["analysis"] = s.decode()
    url = "https://api.qimai.cn/rank/indexPlus/brand_id/1?{}".format(
        urlencode(params))
    # 測試:發(fā)起請求
    res = requests.get(url, headers=headers)
    rsp = json.loads(res.text)
    print(rsp)


if __name__ == '__main__':
    main()

PS: 大家感興趣的可以來我的github看源碼雁歌,希望大家可以Star一波哦哦宏浩!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市靠瞎,隨后出現(xiàn)的幾起案子比庄,更是在濱河造成了極大的恐慌,老刑警劉巖乏盐,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佳窑,死亡現(xiàn)場離奇詭異,居然都是意外死亡父能,警方通過查閱死者的電腦和手機(jī)神凑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來何吝,“玉大人溉委,你說我怎么就攤上這事“牛” “怎么了瓣喊?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長黔酥。 經(jīng)常有香客問我藻三,道長洪橘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任棵帽,我火速辦了婚禮熄求,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘岖寞。我一直安慰自己抡四,他們只是感情好柜蜈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布仗谆。 她就那樣靜靜地躺著,像睡著了一般淑履。 火紅的嫁衣襯著肌膚如雪隶垮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天秘噪,我揣著相機(jī)與錄音狸吞,去河邊找鬼。 笑死指煎,一個胖子當(dāng)著我的面吹牛蹋偏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播至壤,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼威始,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了像街?” 一聲冷哼從身側(cè)響起黎棠,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镰绎,沒想到半個月后脓斩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畴栖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年随静,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吗讶。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡燎猛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出关翎,到底是詐尸還是另有隱情扛门,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布纵寝,位于F島的核電站论寨,受9級特大地震影響星立,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜葬凳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一绰垂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧火焰,春花似錦劲装、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纯赎,卻和暖如春谦疾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背犬金。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工念恍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晚顷。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓峰伙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親该默。 傳聞我的和親對象是個殘疾皇子瞳氓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,103評論 1 32
  • 這篇文章主要講述在Mobile BI(移動商務(wù)智能)開發(fā)過程中,在網(wǎng)絡(luò)通信权均、數(shù)據(jù)存儲顿膨、登錄驗(yàn)證這幾個方面涉及的加密...
    雨_樹閱讀 2,439評論 0 6
  • 背景 ? 隨著移動互聯(lián)網(wǎng)的普及,被越來越多的心懷不軌的人覬覦叽赊,也越來越多的安全問題暴露了出來恋沃。開發(fā)者開發(fā)出來的應(yīng)用...
    陵無山閱讀 3,032評論 1 13
  • 今天下午去學(xué)畫畫了,教室有點(diǎn)冷必指,棉襖都沒敢脫下來囊咏,但是我仍然很開心,因?yàn)槲蚁矚g畫畫塔橡。
    徐菡xh閱讀 135評論 0 0
  • 1 服飾整潔 得體大方 色彩搭配合理 2 正式場合 男士宜穿禮服或深色西裝 皮鞋和襪子 女士宜穿套裝 不穿空短透露...
    風(fēng)華禮堂閱讀 304評論 0 0