記一次反編譯小程序尋找簽名函數并聯動bp插件自動化加簽
0x00 前言
日常滲透測試中,在進行數據包的重放或者是篡改數據包時,會碰到一些存在數據加密或加簽的站點,這時我們就得尋找加簽或者加密的算法,而這尋找過程往往有一定難度。
總的來講,對于數據解密或者加簽破解的難度:app>web≥wxapp,同時api接口都是相同的,為降低不必要的挖洞難度,可將目光放到微信小程序上。本次就是以一個微信小程序站點開展的測試。
0x01 拖取微信小程序包
這里簡單說下,目前微信小程序在pc端貌似已經有加密了,Mac(/Users/{系統用戶名}/Library/Containers/com.tencent.xinWeChat/Data/Library/Containers/com.tencent.xinWeChat/Data/Library/Caches/com.tencent.xinWeChat/{微信版本號}/{用戶ID}/WeApp/LocalCache/release/{小程序ID}/)、Windows(C:\Users\{系統用戶名}\Documents\WeChat Files\Applet\{小程序ID}\),而我們這邊可以去拖安卓端的小程序包。
這里需要提前準備好一個已經root過的安卓手機或者是一個安卓模擬器,先去/data/data/com.tencent.mm/MicroMsg/{一串16進制字符}/appbrand/pkg 這個目錄下將其他小程序包都刪除掉,然后再打開微信加載我們需要測試的目標小程序。
此處注意,一定要等小程序完全打開并且再點幾個功能,確保將所有包都運行,由于目前的小程序體量逐漸變大,可能會有多個子包的存在。


然后將相關子包拖出來。
0x02 反編譯小程序拿源碼
在將相關子包拖出來并放在我們指定的目錄,然后用wxappUnpacker工具將包反編譯出來。
node wuWxapkg.js ../20220323/debug_607957350_2_511127914.wxapkg
在原本存放小程序的目錄下會出現一個以小程序包名的子文件夾,反編譯出來的源碼就在里面。

用微信官方開發工具打開源碼項目:
1、選擇“導入項目”,“AppID”選擇測試號并導入
2、到“本地設置”模塊,勾選上“不校驗合法域名”功能


0x03 尋找簽名加密函數
案例背景環境
介紹一下本次示例案例的背景環境。
在這?通過抓包發現站點有使?簽名來鑒定提交數據的完整性, 經??測試,發現修改任意帶有值的參數,都會導致服務器端報錯提示"簽名錯誤”


這里簡單介紹一種快速定位JavaScript中關鍵加密函數的方法--關鍵字尋找
關鍵字尋找
1.1、在項目中全局搜索關鍵字
常見的通用關鍵字例如key、encrypt、iv、sign、password、rsa、aes等
1.2、搜索加簽加密接口名
例如此處接口名為/xxxxxxing1/f**dinfo/getfundranklist/1.0,可以搜其拆分的路由名稱:xxxxxxing1 f**dinfo getfundranklist
1.3、搜索相關涉及到加簽加密的參數名
例如此處則可以搜索oftype openapi_sign paramsDigest ordercol等
在介紹完背景和方法后,可以開始尋找加簽函數了。
定位加簽函數
在相關開發者工具中,全局搜索openapi

發現有兩個js存在,進入這兩個js繼續定位關鍵的位置。
發現openapi關鍵字都存在于同一個關鍵函數(說明:這里后面經過對比兩個js文件,發現內容大致相同而app-service.js不存在亂碼情況,故后面都以此js進行跟蹤分析)

openapi_sign參數存在于getSecretSign方法中,同時另外?個請求體里的參數paramsDigest也 在??,這根據這個命名?概推測該?法可能是?于簽名。

繼續搜索此方法名getSecretSign,看看該方法是否有被調用到,發現了關鍵形參:t.data、 r.secretkey。

繼續上下?搜索t.data,發現?個關鍵點,閱讀相關js代碼,發現??的 json字符串就是從數據包參數 ??獲取的,然后調?Object.assign?法將json串復制到t.data當中。

由于r.secretkey未能搜索到,故嘗試搜索secretkey關鍵字看看能不能找到些啥,發現剛好存在 ?個secretkey,至此可以?致判定我們最初找的getSecretSign為加簽?法。

0x04 編寫加簽函數
本地起一個js腳本,將0x03中找到的加簽函數寫入,提供必要的參數值,運行測試下。

結果報錯提示r對象未被定義,閱讀代碼發現,r對象只是用于提供它的hex()方法,返回項目源碼當中尋找hex()方法。

然后往上面跟代碼發現此處是引用了github上的一個MD5加密算法github。
這里直接將src目錄下的md5代碼復制下來,貼到我們測試的js文件當中。

執行js腳本文件,無報錯。同時對?發現簽名?致。?此相關加簽函數已找到并能成功調?運?。


0x05 聯動burp插件
加簽算法已破解,為了能更提高實際滲透測試過程中的效率,可以聯動burp插件,使得當我們篡改數據時能自動化的運行加簽算法,直接得到相關簽名。
在這里我首先嘗試了burpCrypto插件,但調試js階段發現一直有報錯,同時在插件上未找到詳細錯誤信息,而jsencrypter會將錯誤信息直接地拋出在命令行頁面上,更有利于代碼調試,故此處選擇的是jsencrypter插件。
簡單介紹一下jsencrypter插件:

jsencrypter使用phantomjs啟動前端加密函數對數據進行加密,方便對加密數據輸入點進行fuzz,比如可以使用于前端加密傳輸爆破等場景。工具本身提供了幾種常見加密算法,可以直接引用,當加密加簽算法為非常規時,也可以引用我們自定義算法進行破解。
phantomjs是已停產的無頭瀏覽器,用于自動進行網頁交互。PhantomJS提供了一個JavaScript API,可實現自動導航,屏幕截圖,用戶行為和斷言,使其成為在無頭系統(如持續集成環境)中運行基于瀏覽器的單元測試的常用工具。
Jsencrypter的使用
按照插件的說明,復制了一份原來的phantomJS調用模板,按照文檔注釋說明,修改了引用的js文件,以及后續調用的方法。

在?于加簽的js中,將在0x04章節中成功加簽的js代碼復制過來,并在后面給其設置一個get方法,用于返回簽名。
function get(pass){ var pass1 = eval("("+pass+")"); var call = test(pass1,t); var str = 'paramsDigest:'+call.paramsDigest+'-------'+'openapi_sign:'+call.openapi_sign; return str; }
命令行中敲入命令,運行phantomjs
>phantomjs js1.js[*] load js successful[!] ^_^[*] jsEncrypterJS start![+] address: http://127.0.0.1:1664
然后bp上點擊test發送數據,可以看到相關的sign值完全正確。(此處sign值與前面圖對應)

自動化改進
原先js腳本,只是回顯了sign,但實際過程中,我們還是需要cv?法將openapi_sign paramsDigest以及我們篡改后的數據串值重新丟?repeater中,其實可以通過js正則,進?修改輸出,省去這?步。
首先定義一個unchange方法,用于將json串轉成參數串。
function unchange(b){ var str = b,p1; p1 = str.split(':"').join('='); p1 = p1.split('",').join('&'); p1 = p1.replace('{',''); p1 = p1.replace('"}',''); return p1;}
然后連接符+縫合起來
var str = unchange(pass)+'?msDigest='+call.paramsDigest+'&openapi_sign='+call.openapi_sign; return str;
看看實際效果

可以直接在插件上篡改參數值,然后復制結果到repeater中進行安全測試。

自動化改進2
但是這個地方,我們還是需要將數據先轉化成非標準的json字符串。這里我嘗試了在插件里面的js中進行修改,但是由于相關數據本身就包括了xxx&xxx1&xxx2,而&在HTTP請求中會當做一個分割參數符,這會導致參數傳到server端中時,只剩下一個xxx參數,其余的都被丟棄了。
這里本想先將數據base編碼,再傳輸過去,但思考下其實多此一舉,在調用插件前還需要編碼,加密前還需要先解碼,這更復雜,還不如直接寫個js,將數據轉成json字符串后再丟給插件。
故使用曲線救國的方式,寫了一個js,用于自動化生成json串。
function change(b){ var str = b,p1; p1 = str.split('=').join(':"'); p1 = p1.split('&').join('",'); p1 = p1.replace(/^/,'{'); p1 = p1.replace(/$/,'"}'); return p1;}
var str = 'secuid=JY208740&udid=&sysVer=5.7.7&appName=&systemInfo=%2C%2C%2C&softName=WXIN_O&tradeClient=H5Trade&device_model=&deviceVers=&hwID=&conn_style=2.460.01.0.0&mip=&mac=&imsi=&iccid=&rNetAddr=&packtm=&reqtime=&operway=W&operorg=&netAddr=13888888888&session=12f4530351a3********7b6d8dec3c36f60dce1e83e03329d42fc269&userCode=334507******1792&pkg=H_117292&fundid='; console.log(change(str));

至此,除了需要手動執行轉化數據串為json串外,勉強實現了自動化修改數據(不是
0x06 涉及到的工具下載方式
以上工具可到原文中下載:https://zone.huoxian.cn/d/1052-bp
包含以下工具:
- wxappUnpacker(模塊已經安裝好直接用)
- wxappUnpacker(github版)
- jsencrypter
第一次寫文章,有什么不對的地方還請各位師傅斧正。