__csr 代表 Cross-Site Request,通常用于跨站点请求。

在请求接口的参数中,会看到一个叫做 __csr 的参数。

全局搜索的时候,找到一个 StaticSiteData 模块,__csr 对应的键名是 csr_key

这里找到了 csr_key 的赋值方式 d("CSRBitMap").toCompressedString()

把开头的 d 换成 require 调用 CSRBitMap 模块就能获取到 __csr 参数的结果了。

直接定位到 CSRBitMap 模块,分析一下是怎么实现的。这里的 h 变量是一个空数组,通过 a 函数将内容写入到 h 变量中,但是目前不知道 a 传入的是什么内容,所以在这里添加断点,然后刷新页面看看传入的是什么参数。

这里显示 a 传入了一个数字 16。点击右侧 「Call Stack」 中的 「handlePayload」继续往下跟踪。

刚才传入的数字 16 是从 csrUpgrade 这里来的,那么下次传入的结果就会是 1, 8, 73... 以此类推。

在页面上搜索 csrUpgrade 就找到来源了,使用下面的代码就可以获取到这段 csrUpgrade 并且格式化数组。

document.head.outerHTML.match(/(?<=csrUpgrade":":).*?(?=")/g).join(',').split(',')

那么跟着断点往下分析,传入这段 csrUpgrade 数据后 a 又传入了 303。点击右侧 「Call Stack」 中的 「U」继续往下跟踪。

刚才传入的数字 303 是从一个 css 中满足 c == 2 这个条件的 p 属性这里来的。

使用下面的代码就可以从 css 中过滤出 c 等于 2 的 p 属性的结果,并且格式化成数组。

document.body.outerHTML.match(/(?<=type":"css","src":"https.*?","c":2,"p":":).*?(?=")/g).join(',').split(',')

后面的分析方法类似,就不细节说明了,直接看结果。

这段 css 传入后,又传入了一段 csrUpgrade。不过这次是从 body 中获取到的。使用下面的代码就可以获取到这段 csrUpgrade 并且格式化数组。

document.body.outerHTML.match(/(?<=csrUpgrade":":).*?(?=")/g).join(',').split(',')

这里基本上可以得出是通过网页 head 和 body 中的 csrUpgrade 和 css 中 c 等于 2 的 p 属性通过 toCompressedString 生成出来的。toCompressedString 的实现方法参考:逆向 Facebook 接口 __dyn 参数

相关代码:Facebook-API-Params-Generator