贝壳app Authorization参数分析
嗯,2021年快結(jié)束了,學(xué)習(xí)忙碌一年了,年底了寫點(diǎn)文章,總結(jié)性學(xué)習(xí)成果吧!
今天我們要分析的app是貝殼 版本號:v2.66.0,小伙伴們可以去各大應(yīng)用商定自行下載,也是一個(gè)很好的逆向分析案例。
轉(zhuǎn)載文章,請注明出處,謝謝!https://blog.csdn.net/weixin_38819889/article/details/122058454
參考鏈接:https://core.vivcms.com/2021/10/25/637.html
同系列文章推薦下:
1.聚美app之 _sign參數(shù)分析
2.大潤發(fā)優(yōu)鮮app之paramsMD5參數(shù)分析
3.美圖秀秀 sig參數(shù)分析
4.貝殼app Authorization參數(shù)分析
5.豆瓣app sig參數(shù)分析
6.半次元app之data參數(shù)分析
1.抓包找參數(shù)
第一步,打開我們的charles直接抓包,發(fā)現(xiàn)這個(gè)時(shí)候沒有抓到對應(yīng)的包。好吧,那我們換一種vpn抓包的方式。先打開postern,然后再開啟charles,這個(gè)時(shí)候就成功的抓到數(shù)據(jù)包了,如下圖所示,Authorization 就是要分析研究的字段,經(jīng)過多次的測試,發(fā)現(xiàn)其他字段可以去掉,但唯獨(dú)這個(gè)字段是不能的。
2.反編譯和靜態(tài)分析
找到這個(gè)加密參數(shù) Authorization ,接下來就是反編譯apk,來把我們的貝殼app拖進(jìn)去jadx里面,看看加密邏輯是咋寫的。
搜索一波,感覺這里很像的樣子map2.put("Authorization", getSignString(str3, null)); ,點(diǎn)進(jìn)去看一看。然后我們來到這里了,可以看到(下圖)這里是調(diào)用一個(gè)getSignString()方法,并傳入?yún)?shù)str3 和null,然后計(jì)算出結(jié)果當(dāng)做Authorization 的值。
跟進(jìn)去看看 getSignString()方法是咋實(shí)現(xiàn)的,然后就來到了這里。
具體代碼如下,沒錯(cuò),可以大膽的猜測下,這就是最核心的加密方法。首先,我們先靜態(tài)分析一波邏輯,然后再用frida動(dòng)態(tài)調(diào)試下,驗(yàn)證下我們的猜想對不對。
public String getSignString(String str, Map<String, String> map2) {Map<String, String> urlParams = getUrlParams(str);HashMap hashMap = new HashMap();if (urlParams != null) {hashMap.putAll(urlParams);}if (map2 != null) {hashMap.putAll(map2);}ArrayList arrayList = new ArrayList(hashMap.entrySet());Collections.sort(arrayList, new Comparator<Map.Entry<String, String>>() { // from class: com.bk.base.netimpl.a.1public int compare(Map.Entry<String, String> entry, Map.Entry<String, String> entry2) {return entry.getKey().compareTo(entry2.getKey());}});String httpAppSecret = ModuleRouterApi.MainRouterApi.getHttpAppSecret();boolean notEmpty = Safe.C2266e.notEmpty(httpAppSecret);String str2 = BuildConfig.FLAVOR;if (!notEmpty) {try {httpAppSecret = JniClient.GetAppSecret(APPConfigHelper.getContext());} catch (Exception e) {e.printStackTrace();httpAppSecret = str2;}}String httpAppId = ModuleRouterApi.MainRouterApi.getHttpAppId();if (Safe.C2266e.notEmpty(httpAppId)) {str2 = httpAppId;} else {try {str2 = JniClient.GetAppId(APPConfigHelper.getContext());} catch (Exception e2) {e2.printStackTrace();}}StringBuilder sb = new StringBuilder(httpAppSecret);for (int i = 0; i < arrayList.size(); i++) {Map.Entry entry = (Map.Entry) arrayList.get(i);sb.append(((String) entry.getKey()) + "=" + ((String) entry.getValue()));}String str3 = TAG;LjLogUtil.m30128d(str3, "sign origin=" + ((Object) sb));String SHA1ToString = DeviceUtil.SHA1ToString(sb.toString());String encodeToString = Base64.encodeToString((str2 + ":" + SHA1ToString).getBytes(), 2);String str4 = TAG;LjLogUtil.m30128d(str4, "sign result=" + encodeToString);return encodeToString;}可以看到getSignString()方法傳入兩個(gè)參數(shù),一個(gè)是string字符串類型參數(shù),另外一個(gè)是hashmap類型參數(shù)。首先調(diào)用getUrlParams()方法,這個(gè)方法就是就是得到請求url后面那一堆參數(shù)的。
private Map<String, String> getUrlParams(String str) {if (str == null || str.length() == 0) {return null;}HashMap hashMap = new HashMap();Uri parse = Uri.parse(str);for (String str2 : parse.getQueryParameterNames()) {String str3 = str2.toString();hashMap.put(str3, parse.getQueryParameter(str3));}return hashMap;}接著尼就是聲明一個(gè)hashmap,分別把urlParams和 map2放進(jìn)去,然后又定義一個(gè)arrayList數(shù)組,并對數(shù)組排個(gè)序。之后又定義了兩個(gè)變量 httpAppSecret和httpAppId,具體是干嘛的,值到底是多少,沒事,目前不知道 不要緊 ,我們繼續(xù)往下看。
接著又定一個(gè)字符串sb,先把httpAppSecret加進(jìn)去,再接著把a(bǔ)rrayList數(shù)組里面的元素取出來,做一個(gè)拼接的操作。然后來到這個(gè)方法處DeviceUtil.SHA1ToString(sb.toString());,看關(guān)鍵詞就能夠大概的猜想到這一個(gè)sha1算法。
public static String SHA1ToString(String str) {try {MessageDigest instance = MessageDigest.getInstance("SHA-1");instance.update(str.getBytes());byte[] digest = instance.digest();StringBuffer stringBuffer = new StringBuffer();for (byte b : digest) {String hexString = Integer.toHexString(b & 255);if (hexString.length() < 2) {stringBuffer.append(0);}stringBuffer.append(hexString);}return stringBuffer.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return BuildConfig.FLAVOR;}}最后把sha1計(jì)算的結(jié)果和str2參數(shù)拼接(Base64.encodeToString((str2 + ":" + SHA1ToString).getBytes(), 2);),并做了一個(gè)base64操作,這個(gè)str2 就是之前 httpAppId,計(jì)算出來的值就是最后加密結(jié)果,也就是Authorization。
3.frida動(dòng)態(tài)調(diào)試
靜態(tài)分析已經(jīng)差不多了,是時(shí)候拿出我們的frida了,看看實(shí)際傳參和結(jié)果到底是個(gè)什么樣子的,以及 httpAppSecret和httpAppId到底是什么。
js代碼如下:
Java.perform(function(){var getSig = Java.use("com.bk.base.netimpl.a");getSig.getSignString.implementation = function (v1, v2) {console.log("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓");console.log("Sig參數(shù)1: " + v1);var it = v2.keySet().iterator();var result = "";while(it.hasNext()){var keystr = it.next().toString();var valuestr = v2.get(keystr).toString();result += keystr + valuestr + " ";}console.log("Sig參數(shù)2: " + result);var res = this.getSignString(v1,v2)console.log("Sig加密后的數(shù)據(jù):", res)console.log("↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑");return res;}var api = Java.use("com.bk.base.router.ModuleRouterApi");api.getHttpAppSecret = function (){console.log("getHttpAppSecret" + api.getHttpAppSecret());return api.getHttpAppSecret();}api.getHttpAppId = function () {console.log("getHttpAppId" + api.getHttpAppId());return api.getHttpAppId();}var jni = Java.use("com.homelinkndk.lib.JniClient");jni.GetAppId.implementation = function (v1) {var res = this.GetAppId(v1);console.log("appId Jni param1: " + v1);console.log("appId Jni: " + res);return res;}var log = Java.use("com.bk.base.util.bk.LjLogUtil");log.d.overload('java.lang.String', 'java.lang.String').implementation = function (v1,v2){console.log("Log.d(): " + "v1:", v1, "v2:", v2);}var encrypt = Java.use('com.bk.base.util.bk.DeviceUtil');encrypt.SHA1ToString.implementation = function(parm1){console.log("SHA1加密前參數(shù):", parm1)var res = this.SHA1ToString(parm1)console.log("SHA1加密后結(jié)果:", res)return res;} });httpAppId是一個(gè)固定值 20180111_android:,來源就是如下:
繼續(xù)分析httpAppSecret的來源,先看看sha1加密的過程:
可以看到在執(zhí)行sha1加密傳參之前,先拼接一個(gè)固定字符串d5e343d453aecca8b14b2dc687c381ca,然后是拼接請求的url后面的參數(shù),沒錯(cuò) 這個(gè)固定值 就是httpAppSecret。
然后說一說get和post 請求方式的不同。get請求的時(shí)候,hashmap為null,而post請求把請求的body參與計(jì)算。
然后分析就是到此結(jié)束了。
4 代碼還原:
具體代碼就不公布了,畢竟對別人不太友好??纯醋詈竽玫降臄?shù)據(jù)。有興趣的可以自己嘗試分析一波,肯定是會(huì)有很多收獲的。
總結(jié)
以上是生活随笔為你收集整理的贝壳app Authorization参数分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: scrapy使用cookie的三种方式
- 下一篇: 美图秀秀 sig参数分析