某音x-bogus算法反编译
最近一段时间,小王比较热衷实用python
写一些小工具,比如下载某音视频、某手视频等等。在研究某音视频的途中,发现某音对参数使用了签名,当然这个点也不奇怪,像我们这种小厂都会进行各种客户端、服务器加密签名,更别提某音这种大厂了。
起因
如上,当我们想把某音上一些好看的视频内容下载下来的时候,经过浏览器网络工具,发现内容是使用某个接口的时候,放在
postman
中进行分析。除了大部分不变的固定参数和标记up主信息的参数之外,额外存在一个x-bogus
参数,这个参数当我们拿掉的时候,请求直接失败。无疑,这个参数就是某音的参数加密后的验证参数了。要想完整使用代码拿到参数,当务之急当然就是拿到这个参数了。
反编译破解流程
既然是对参数进行加密的操作,肯定x-bogus
这个参数就是在js
层面做的处理,我们应该就可以通过对js
进行断点反编译的形式拿到具体的调用实现逻辑。那么说干就干。
js断点+反编译
- 首先打开浏览器的开发者工具,在sources中添加一个新的断点
X-Bogus
。如下图所示:在添加断点之后,使用
F5
刷新网页,就可以被拦截进入断点。上面的图中,我们发现断点已经断到了我们想要的参数,只是这里参数已经被进行了加密操作。因此,我们需要通过调用栈,查找调用关系,找到他的进行参数加密的地方。 可以直接点击调用栈的上一级调用关系,也就是图片中的
_0x1218ef
调用栈信息。在新的断点处,打印参数内容发现,
_0xc26b5e
参数里面的url
内容,还没有携带X-Bogus
参数,可以从这里确定出来,加密处理逻辑就是通过这里实现的。因此我们需要对这里进行分析。可以在这个地方加一个断点,再次刷新页面,查看信息。 会发现这个断点会反复执行,而且很难定位具体内容。这里可以使用一个小技巧,我们既然已经之后,加密的X-Bogus
参数,就可以直接进行反推,这个参数的结果每次都是不同的,但是长度是固定的,因此,可以直接添加一个条件断点。判断如果_0x2458f0['apply'](_0xc26b5e, _0x1f1790).length == x-bogus.length
,这样就是我们要的正确的断点结果。说干就干,添加一个条件断点上去。添加条件断点很简单,直接在刚才的断点位置右键选择添加条件断点,添加进去断点条件即可。我们这里要添加的条件是_0x2458f0['apply'](_0xc26b5e, _0x1f1790).length == 28
。因为x-bogus
的长度就是28。 再次刷新页面。发现打印出来的内容正式我们需要的东西。 接着我们分析
_0x5a8f25
这个方法。可以看到这个方法的位置是在
webmssdk.es5.js
,直接点击到这个方法所在位置。查看这个方法的两个参数,发现第一个参数就是加密前url(没有携带x-bogus),第二个参数为
undefined
。尝试直接执行这个方法体内容,发现内容正确返回了,那么这个方法就是我们想要的方法了。 接下来,我们把这个js拷贝出来,尝试使用nodejs直接调用。碍于篇幅,不贴全部代码了,这个直接说核心点。 - 导出目标方法。
window = global
//省略代码
function _0x5a8f25(_0x48914f, _0xa771aa) {
//省略具体方法体
}
window.get_xb = _0x5a8f25
//省略代码
- 代码中存在许多浏览器对象,比如document、headers等等,需要进行补充。
Request = {}
Headers = {}
navigator = {}
navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
var document = {}
document.addEventListener = function(e){
}
//其他代码
至此对于
x-bogus
的反编译破解完成了。
额外加餐
如果使用python的话,调用js,可以使用execjs
库。如果是在windows电脑,需要指定使用nodejs环境,防止直接使用windows的jscript环境造成乱七八糟的问题。
执行实例代码
query = urllib.parse.urlparse(url).query
xbogus = execjs.compile(open('./X-Bogus.js').read()).call('get_xb', query, headers['user-agent'])
new_url = url + "&X-Bogus=" + xbogus
response = requests.request("GET", new_url, headers=headers, data=payload)
(⊙o⊙)…,至此全部内容完成了。
转载自:https://juejin.cn/post/7300036605099868214