PS:這是一個系列,坐等我慢慢填坑。
PS:不太會直接能跑的代碼,拋磚引玉。
PS:那些我也不太熟練的就不搞了,包括(破滑塊、驗證碼..)
PS: 反編譯搞Apk會有很長的幾個文章,稍后慢慢更。
最近,和某XX單位的網站gang上了。
他們家的網頁只允許在微信客戶端打開,抓包就跟蛋疼了。
不過,手上有Root后的Google Nexus5X,也有 whistle 跨平台抓包工具,
這個倒沒太折騰,抓包工具證書往手機系統根證書一扔,完事。
安卓7.0及以上用戶證書導入的問題 - entr0py - 博客園
抓到了包,下面蛋疼的事情開始了。
前言: body 加密
嗯?請求Body是這一串東西?
嗯?時隔三年,神奇海螺又出現了?

// json { "encryKey": "14a625eb2ec957f9b53412b01de37044e7e2aa6b4b911111c75091cba2a0315b", "data": "44bc0dab8db8017603586f40554742d14a0c23dd009e35cae5b5ac87dbf7962a311fae30070763d2b48b564d72191fd07a881ebcccfb7c0fdd33e4067bc5119cee5e2fa5eaac10da995c86c8a092dcc3", "sign": "cc3f924bbb6d57a15bd3e130230f51e55a04fa9e459d177440fbd10bce4b02d0", "timestamp": 1627224237000 }
很明顯,每個單詞我們都知道,每個字母和數值我們也懂。
但是....
除了timestamp我們可以生成,其他的明顯是加密后數據和簽名。
一點都不高能的預警
先說一下思路:
- 撈出核心JS文件
- 讀懂加密過程,撈出關鍵參數
- 用其他語言實現涉及到的加密函數
- 對比加密結果是否一致,嘗試去偽造請求
撈JS
首先這貨的微信瀏覽器的,所以沒辦法使用瀏覽器開發者工具。
不過,抓包上面不是搞掂了么?直接從抓包結果看HTML就完事。
乖乖一個個請求看,找到第一個返回HTML的響應體。
於是,找到了這個...

哦, 看到了....
<script src="/umi.a029b1fd.js"></script>
看到這貨,本寶寶小心臟有點亂跳了。
訪問一看。

害,看起來沒的那么簡單啊,明顯這貨是被webpack打包后的JS文件。
先下載回來再說...
umi.a029b1fd.js 下載到本地,一看1.5M。
打開一看,毫無疑問沒有格式化...
得嘞,大JS文件格式化,先打開我的Ubuntu機器再說。
哦,VS Code format崩;加大內存,繼續崩。
搜了一波,找到了神器 Online JavaScript beautifier
文件扔上去,再下載下來...
完事。


毫無疑問,這就是webpack打包后的東西了。
沒得事,全局搜一波上面的參數。

完美,看到這個,是不是答案已經出來了。
看看,每個參數怎么算的都告訴我了,還能做撒?還需要做撒?
於是,我午睡去了。
........
其實,最頭疼的東西就在這里了。
這時候,很多人會說,上AST 還原JS嘛。
AST抽象語法樹--最基礎的javascript重點知識,99%的人根本不了解 - SegmentFault 思否
嘖嘖嘖。
道理是這個道理,不過還有其他的思路嗎?
直接寫個index.html 引入這個JS也成的啊。
<html> <body> <h1>test</h1> </body> <script src="./app.js"></script> </html>
開始解JS
var O = Date.parse(new Date),
Y = Object(h["e"])(!1, 16),
j = Object(h["a"])(JSON.stringify({
data: b,
timestamp: O
}), Y),
P = Object(h["f"])(j, Y);
T = {
encryKey: Object(h["a"])(Y, h["b"]),
data: j,
sign: P,
timestamp: O
}
在代碼里面看到了一堆這種 h["a"] h["e"],然后跟着參數(j, Y)。
我們明顯知道,這是JavaScript的一個函數調用,h看起來是一個map或者是對象,
這里是在調用它的a方法,傳入了(j, Y)
在這里,我們最想知道的就是h["a"]的定義是什么樣的,
因為知道定義實現,也就能還原完整代碼邏輯。
跟一點代碼(VS Code跳轉定義功能),我們能看到h是什么?

h = n("jNxd"),
看到這里其實是很頭疼的,n是個什么玩意我們完全無從得知。
不過這里也能得到點信息,各種各樣的函數或者對象都是綁定在”n“上的,
我們只要拿到n,我們需要的h,h[a], h[b] 都知道是什么了。
怎么拿到n呢? 友情提示,善用debugger。
開始尋找n
剛剛我們已經完整把app.js(umi.a029b1fd.js格式化之后的文檔)導入我們的index.html
用瀏覽器打開看看頁面。

頁面沒什么問題,我們嘗試在app.js上面加點debugger吧。
加在哪呢?(目的只有一個,能獲取的到n)
....h附近前面可以嗎?

瀏覽器控制台打開,刷新頁面,切換到Console頁面。

試試這里能不能有n對象。

咦,看起來有戲。
試試 h = n("jNxd")

很好,很好,看起來這里是OK的,
h["a"]也是一個函數,符合我們上面看到的。
點擊一下上面h["a"]輸出的內容,可以跳轉到函數定義。
於是,我們來到了重頭戲。

s = (e, t) => { var n = i.a.enc.Utf8.parse(t), r = i.a.enc.Utf8.parse(t), o = i.a.enc.Utf8.parse(e), a = i.a.AES.encrypt(o, n, { iv: r, mode: i.a.mode.CBC, padding: i.a.pad.Pkcs7 }); return i.a.enc.Hex.stringify(a.ciphertext) }, u = (e, t) => { var n = i.a.enc.Utf8.parse(t), r = i.a.enc.Utf8.parse(t), o = i.a.enc.Hex.parse(e), a = i.a.enc.Base64.stringify(o), s = i.a.AES.decrypt(a, n, { iv: r, mode: i.a.mode.CBC, padding: i.a.pad.Pkcs7 }); return s.toString(i.a.enc.Utf8).toString() }, c = (e, t) => i.a.enc.Hex.