遇到過很多次數據加密的情況。之前都是看到别人如何前端調試,然後逆向獲取密鑰解密流量,這一次,給大家實戰一下。
一、逆向式我們的目标是某信小程序。
首先還是來看看這個小程序的請求流量。當正常人一眼望去,絲毫理不清傳遞的是什麼,我們基本就可以斷定,其對流量進行了加密處理。
然後我們再看看返回請求——依然一頭霧水:
經過上面兩張圖,可以判斷這個小程序存在流量加密的情況。至于是全局的流量加密,還是部分流量加密,這個需要經過分析之後才能判斷。
如果隻是部分流量加密,那麼還可以測一測有沒有漏網之魚,如果是全局流量加密的話,就必須對小程序進行逆向獲取源代碼,再進行分析了。
對某信小程序的逆向采用某神仙模拟器加一個6.X版的某信。因為高版本的安卓和某信不再信任系統的證書,這會造成無法抓包的情況,所以使用安卓5加6.X版本的某信。
再參考網上的文章,從模拟器中脫到了小程序的wxapkg文件。這個文件在我的環境中位于:
/data/data/com.tencent.mm/MicroMsg/7e3e7c**********706/appbrand/pkg
因為小程序比較多,不知道哪一個才是目标文件。通過adb把這幾個wxapkg文件全部下載下來,然後就是從wxapkg文件中提取源代碼,這裡使用wxappUnpacker一鍵提取:
獲取到的目标小程序的源代碼文件結構如下,之後便是進入分析階段了。
【→所有資源關注我,私信回複“資料”獲取←】1、網絡安全學習路線2、電子書籍(白帽子)3、安全大廠内部視頻4、100份src文檔5、常見安全面試題6、ctf大賽經典題目解析7、全套工具包8、應急響應筆記
進入代碼審計環節,來分析前端的代碼算法。
上面的小程序經過逆向,獲取到的源代碼結構如下:
因為之前沒有分析過某信小程序,所以這裡首先學習了一下小程序的一些基本知識。重點有兩個,第一個是app.js,這個文件是整個項目的入口文件,通過App()方法來注冊一個小程序,并确定了整個程序的生命周期。
第二個便是module.exports,某信小程序的模塊化,個人理解就是對外暴露的方法,可以供其他方法調用這個模塊,類似于public方法。
了解完上面這兩個點,再回到項目的源代碼本身,通過浏覽整個文件結構,發現對于加密的方法定義都位于/utils文件下。
其中需要關注的是encrypt.js文件,裡面定義了關于流量的加解密方法。直接上代碼。
從上面的代碼中看到encrypt.js通過module.exports對外暴露了encrypt和decrypt兩個方法。這兩個應該就是用于對流量進行加密和解密的方法了。先來分析encrypt函數:
Encrypt函數傳遞兩個參數e和n,然後将參數n通過r函數處理之後賦值給s,其中r函數内容如下。為了安全裡面的字符串,截取長度均已經修改,與原程序不同:
r函數将傳遞的參數截取一段然後與字符串進行拼接,然後使用SHA256函數簽名,再截取中間一部分,将字母轉換成大寫之後返回。
再回到encrypt函數,變量i存儲的AES加密解密的密鑰,此處使用硬編碼的方式寫在代碼當中。然後變量u存儲格式化之後的s變量,變量c存儲格式化之後的參數e。
之後就是加密部分了。
先了解一下AES的加密。對于AES有不同的模式,本程序中使用了CBC的模式,這種模式是先将明文切分成若幹小段,然後每一小段與初始塊或者上一段的密文段進行異或運算後,再與密鑰進行加密。
在使用CBC模式進行加解密過程中,需要定義一個初始向量。初始向量用于随機數據加密,達到的效果是對相同的明文,傳遞相同的密鑰。不同的初始向量可以産生不同的密文。
再回到代碼本身。可以看到encrypt函數調用了AES模塊的encrypt方法進行加密,傳遞的參數,依次為c明文,i密鑰,然後變量u表示初始向量,采用CBC模式進行加密。
Encrypt函數分析完了,再看decrypt函數,上代碼:
Decrypt函數還是傳遞兩個參數e,s然後通過formatString函數将參數e處理一下,其中formString函數具體内容如下,對e參數進行去除換行空格的處理:
變量i還是存儲r函數處理後的參數s,變量u存儲的還是格式化的密鑰,變量c存儲格式化後的變量i,最後調用AES模塊的decrypt函數進行解密,結果存儲在變量o當中。
進行解密的參數傳遞,e密文,u密鑰,c初始化向量,采用CBC模式解密。這裡加密和解密的初始化向量都是由r函數進行處理的。
在上面分析中,加密解密傳遞的都是兩個參數,然後其中一個參數是用于生成初始向量的。因為在上面的過程中,這個參數不是固定的,所以需要分析這個參數的來源,這樣才能完整的對整個數據進行解密。
再回到項目本身,在app.js中引入了一個request.js文件,在這個文件當中封裝了http請求的方法,并對外暴露接口:
在第108行中,有一段代碼:
r=(0,n.encrypt)(JSON.stringify(r),d)
這段代碼應該就是調用加密函數對請求數據進行了加密。這裡傳遞了兩個參數,其中d參數就是加密過程中用于生成iv向量的參數,而在第103行最後可以看到,d參數的來源是函數getRandomUuid。接下來看看這個函數的内容:
這個函數的作用隻是生成一個随機的字符串然後返回。但是在上一張圖的第105行代碼将這個d賦值給了i.uuid,在我們最開始看請求數據包的時候,在http請求的請求體中就存在一個uuid的字段:
所以可以确認,這個uuid的字段就是用于生成iv向量的參數。
然後繼續跟進我們的代碼,在進行流量加密之後,會調用一個c函數,然後再return。所以我們需要看一下這個c函數的具體内容,因為解密的過程應該在這個c函數當中:
在第61行的位置發送一個http請求,如果請求成功進入回調函數,對數據進行解密,這個解密可以看到傳遞的參數c.uuid就是請求包中的uuid字段。
三、解密式整個小程序的分析到這裡基本就結束了,接下來隻需要根據上面的密鑰、iv向量生成、算法等等寫一個解密的腳本就可以了。
為了高(tou)效(lan)作(mo)業(yu),使用之前搞開發寫的PHP版AES解密腳本改了改,最後的效果如下:
輸入uuid參數和密文,點擊解密之後返回明文,将明文修改之後點擊加密,返回密文。
返回包的解密:
好了,這個小程序的流量加密分析到這就全部結束了。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!