app:B站, 版本:随便搞了个最新版
目标:分析sign算法
本文第一次发布2021-10-26,时隔两个月,感觉这篇文章写的似乎并不是很清晰,于是做了一篇重制版发在了公众号里。如果感觉本文看着不清晰可以看看公众号里的重制版,写的会比较详细,地址:初识OLLVM控制流平坦化(重制篇)
如果对md5不了解或者想要md5源码(公众号里有c++版和py版的源码)可以到公众号回复 md5 获取。
1. 算法定位
B站的java层定位并不难找,直接搜索大法即可定位到生成sign的native函数。native函数s通过frida发现传入参数是请求的url的params的sortmap,输出的是signedQuery对象,frida打印则是完整的url,包含了sign。
然后看下so文件的内容。ida打开bili.so,在导出函数搜索java发现为空。是动态注册,直接看JNI_Onload。
发现是混淆的控制流平坦化,这里可以用某大佬开源的hook_RegisterNatives直接定位到s函数的偏移地址(git上搜hook art就能找到,这里看了一下大佬的源码,是hook了art,进行筛选,最后拿到了所有的RegisterNatives)。
2. 算法分析
ida看函数有三个参数,前两个是jni相关的,先不用管,第三个参数是我们传进来的sortmap,标记一下,然后看下引用。
只在10090函数做了引用,所以主要看10090,其它混淆的代码就不要看。
这里看到调用了sortmap的函数有三个,在六处调用,hook了三个函数,并没有看出什么有用的信息。可以尝试看一下有返回值的几处在后续的流程中,返回值是如何被使用的。有三个函数有返回值,先看一下v64
通过追溯v64(看到之前截图才发现原来是v63,不知道为啥又变成v64了…),hook到函数12720,发现s就是拼接好的加密字符串,函数的返回值v73就是我们最终想要的sign的值。手动将传入的字符串做md5加密发现和结果并不一样。所以还要进一步来分析,是否做了魔改或者加了盐。
到函数12720,可以看到只有B474被调用,通过hook发现B474被调用了7次,而最后一次的结果就是我们想要的的sign值,与java层hook到的结果一致。
进入函数B474就可以看到关键函数BBE8,BBE8函数的代码特征很明显和MD5相似。
hook BBE8函数就可以看到盐值,560c52ccd288fed045859ed188bffd973
通过测试,MD5(params + “560c52ccd288fed045859ed188bffd973”)与抓包得到的sign值相同。
总结,B站的sign其实就是一个加了盐的MD5,关键点就是hook到url参数的拼接规则和盐值。native层做了ollvm控制流平坦化,但是这个算法并不复杂,所以就算混淆完的代码也并不是很多。
最后欢迎各位老司机进群交流:546452230