薅羊毛系列之蜘蛛網電影搶票分析
說明:以下內容從我的個人部落格 blog.zhouzhipeng.com 複製過來,兩邊同步釋出。
首先宣告一下,這裡並不是給蜘蛛網打廣告。自己平時也比較喜歡看電影,剛好蜘蛛網電影app上有一個週六建行5元搶票活動,由於活動很火爆,幾乎很少能搶到! 所以想借用程式手段,自動提交搶票介面,來試圖能搶到5元電影票。
雖然沒有技術含量的東西,主要是想記錄一下,方便自己日後來回憶一下,同時也是一個思路的整理。
好了,廢話不多說,下面開始hack之旅!
前言
和所有電影app一樣,在經過選電影-> 選場次-> 選桌位 之後,來到了確認提交頁面,如下:
可以看到上圖中活動優惠有很多,我想”破”的就是龍卡星期六 5元看電影
理想情況是,你選好要看的電影只有進來這個頁面,剛好上午10點整的時候,5元
這個活動就可以開始搶了! 現實情況是到了9:59 分快到10點差不多的時候,進來這個頁面你會發現被
告知已經”搶完了”!
現實很殘酷,考驗網速和手速以及運氣! 但是身為一名小碼農,怎能像一般人一樣也在哪裡拼手氣呢!(?)
第一步:抓包分析
不出意外的話,它的這個訂單提交頁面應該是http(s) 請求的,既然如此,當時就是先來抓包分析下http請求咯!
因為我的用的是mac電腦,所以用的Charles
來抓包,略過配置步驟,直接貼一下抓包的請求:
經過初步的分析和體驗(我自己選了一個其他可用的活動提交了一個真實訂單), 發現最終提交訂單的介面的是
https://film.spider.com.cn/huayins/lockSeatList.html?insBirthday=&insId=&token=455FBE5EF0A0ED9545231547BB3050C6&userId=5da71497b4160d20c806c0568e535e07&hallId=17&feePrice=2.0%257C2.0&cinemaId=31070901¤tVersion=4.9.0&channelId=sfVivo&appVersion=460 &version=410&activityId=101511&showId=0170100000000000060598689&userName=xxxxxxxxxxx&partnerPrice=59.00&sign=e3277328f9fa9434efcec30e8259ad23&filetype=json&mobile=13080669828&insName=&filmId=201709909870&fpCount=&parorderId=610024803&seatId=6%253A9%257C6%253A8&key=huayins&fpId=
其中真實的userName
已被我和諧掉了。
用postman
工具把引數展開看一下:
憑藉這多年的web開發經驗(? 裝下b), 會發現破案的難點在於上圖紅框中的兩個引數token
sign
, 一般而已token
是登陸用的,而sign
則為請求合法性的校驗值 (一般sign是多個引數值按照一定順序拼接之後再用md5加密得來. ? 對的,一般是)
簡化問題
上面的lockSeatList
連結中,有很多引數都是相對固定的,像什麼活動優惠5元看電影
這個activityId
很容從其他抓包得到的查詢介面中獲取,在此不一一追溯.
而關鍵引數token
通過我刷了幾次介面會發現,它在一段時間內也是不會變的,暫時不考慮其生成方式。
那麼剩下的最後一個難點問題在於我們怎麼能知道sign
的生成演算法呢?!
對的,靠猜! (☺️) 開玩笑啦,當時是通過反編譯看程式碼!!
第二步:反編譯apk
沒錯,我們先假設蜘蛛網電影安卓app沒有很變態的加固、混淆之類的。 (如果有的話,就直接放棄得了,太花時間了。。。)
先到蜘蛛網官網弄一個apk檔案(這個很容易!) 這裡我不會貼任何下載連結,需要的實踐的朋友請自己去找。
拿到apk之後,不要慌張,善於利用一些大牛弄的反編譯工具,這裡給大家介紹一個 ,真的挺不錯的 javadecompilers.com (國外的網站,開啟可能有點慢)
進去之後,基本上傻瓜式的操作,直接上傳apk檔案,點一下Upload and Decompile
按鈕,剩下的就是等待了幾分鐘了。直接可以下載反編譯之後的原始碼檔案!
得到原始碼之後,剩下的事情就是分析程式碼,找出sign的生成演算法了!!
第三步:分析程式碼
用你熟悉的工具代開原始碼資料夾,這裡我用的是Intellij IDEA
,開啟之後如下所示:
有沒有。。。。 很懵逼的感覺!!! 特麼這麼多的檔案,從哪找起啊!!!
尋找入口很重要
在做任何事情都不能太盲目,我們要淡定、從容(? )。 先回憶下第一步:抓包分析
中發現的url https://film.spider.com.cn/huayins/lockSeatList.html?xxxx
是的,它就是入口!
找到發起該url請求的地方必定是我們要的,而這裡的關鍵字串lockSeatList.html
如果不出意外的話肯定是在程式碼中某個地方寫死的!
好的,我們先搜尋一下lockSeatList.html
在哪裡出現:
如上圖所示,一共有三處地方,我們一個個的試一下。 先接著搜尋第一處 ae
或 C4767f.ae
靜態欄位出現的地方:
出現了很多處,但是經過簡單的分析判斷,它並不是我們要的, “第一處” 排除.
接著,看下”第二處”:
恩,很高階的樣子,android界出了很多類似這種retrofit的框架,把http呼叫弄得用註解搞一下就完成了。。 鑑於有點複雜,可以先放一放這個,後面如果”第三處”也不是我們
要的,再回頭來分析下這個方法的呼叫方。
是的 ,直接突擊”第三處”疑似點:
接著再搜尋f7910W
出現的地方:
剛好只有一處地方出現(第二個是它自己本身,不算),注意看上圖紅框的地方,是不是有點像! 估計就是它了!!
水落石出
好的,我們進去看一看:
注意我標的紅箭頭的地方,這些並不是直接字串,還得一個個的去搜索這些變數的字串是個啥!
為了節省點大家的閱讀時間,這裡就不一一上搜索的截圖了,搜尋變數的方法與上面類似,直接晒一下我們最終要找的sign
欄位的面貌:
不難發現,正如我們一開始猜想的,sign
就是多個引數值拼接起來再加密的! 重點是下面的stringBuffer2
StringBuffer stringBuffer2 = new StringBuffer();
stringBuffer2.append(str).append(str2).append(str3).append(str4).append(k).append(m).append(str5).append(str6).append(stringBuffer).append(str7).append(q).append(str8).append(str9).append(str10).append(str11).append(str13).append(str14).append(str15).append("huayins").append("0779257096").append(v);
好的,接下來的事情就很簡單了,按照上面append
的順序,它其實是每個url上的引數的值。 最終sign
的拼接順序為:
showId cinemaId hallId filmId userName userId mobile urldecode(seatId) urldecode(feePrice) parorderId channelId partnerPrice activityId insName insBirthday insId fpId fpCount "huayins" "0779257096" token
模擬請求
有了以上過程後,我們只需要在原來的url引數上,對需要變更的activityId
活動編號等做以下更新,動態算出對應的sign
值介面。 我自己用
python
實現了一版,在此可能不方便直接公開貼出,需要的小夥伴可以 fork 一份:https://git.io/vNbMh