起因
过年期间,宅在家里闲来无事,我在网上找各种资源。终于通过自己的不懈努力,找到了一套非常优质的资源:画面高清,中文字幕,每日定期更新十部。
但是,仔细思考一下,我感觉十分奇怪。是什么样的人每天都能找到十部电影?什么样的人能够按时为这十部电影添加中文字幕?所以,被自己强烈的好奇心驱使,我开始了针对这一 BT 资源组的溯源之路。
基本思路
我们都知道,BT 是一种 P2P 的下载协议,当一个人想要通过 BT 下载文件时,可能会通过多个对等 (Peer) 节点进行下载,在这些 Peer 节点中,可能会包含当前资源的发布者,但是也可能不包含。这是因为当网络中有一部分节点完成下载时,初始的发布者即使下线也可以保证新的节点完成下载。因此,想要找一组 BT 资源的发布者,直接通过流量监听筛选当前Peer节点的方法并不准确。但是,如果是在资源刚发布时对资源的 Peer 节点进行收集分析,并及时监控每个 Peer 节点的完成状态,就有可能找到资源的发布者(第一个做种节点)。比如,如果某个 Peer 节点在资源刚刚发布时就已经下载完成了资源的所有内容,而其他节点都是刚刚开始下载,我们就可以认为这个节点是资源的发布者。根据统计,每个资源的大小约在 17G 左右,因此按照4M/s的速度下载,发布资源 第一个做种节点 传递给其他节点至少需要 1 小时 12 分钟。理论上,只要在这段时间内观测到下载完资源的Peer节点,都有可能是发布资源的做种节点。 具体可以分为以下四个步骤:
步骤一:监控资源发布
这一部分的功能是监控每日种子资源的发布,确保在资源发布后第一时间进行追踪分析。我直接通过 python 的 requests 库直接对种子搜索网站发送关键字请求,判断今日的新的资源是否已经发布。如果已经发布,就从网站上把种子下载下来,如果有的种子搜索网站没有下载种子文件的方法,也可以磁力链接转化为种子文件。另外,在这里我也直接从网页中获取相应资源的 info-hash,这样在后面就不需要重新计算了。
步骤二:解析种子文件
BT 的种子文件是通过 Bencode 编码进行组织的。因此,拿到 BT 种子文件后,通过bencode编码对文件进行解码,可以提取出以下信息:
虽然我们可以从 [ info]publisher-url 字段中提取出 http://yb1233.vip/ 的域名,但是仍然无法确定这个域名与做种者是否真的有关联关系,这个域名是一个网络**网站,与色情没什么关系,很有可能只是购买了做种者的推广服务。因此,我继续从 announce 和 announce-list 字段中提取种子的 tracker 列表,以便于通过 tracker 获取当前时间的peer节点。
步骤三:收集Peer节点
解析得到资源的 tracker 后,通过资源的 info-hash 获取当前正在下载的 peer 节点。在这组案例中,提取出来的 tracker 支持 HTTP 协议与 UDP 协议, 如 http://sukebei.tracker.wf:8888/announce, udp://9.rarbg.com:2710/announce等。如果想要向 http 协议的 tracker 请求 peer 节点,需要构造一个 GET 请求,发送给目标tracker。在构造的 GET 请求中,需要携带固定的 info_hash, peer_id, port, uploaded, downloaded, left, compact, numwant, event 等字段,并将字段编码到 URL 中,生成的 URL 与下面类似。
http://tracker2.itzmx.com:6961/announce?info_hash=%D43D%B0%E7o%5D%87%DE%B3%943%3Fz%D3%B0%2FZ%CE%28&peer_id=%BB%7D%AD%A9%D0%DB7%FE%01%27%09%8Ba%A1%16%8F%CD%F63%D9&port=34707&uploaded=0&downloaded=0&left=431102370&compact=1&numwant=1000&event=started
Tracker 回应的内容也是通过 bencode 编码的,通过 bencode 解码,可以在 peers 字段中解析出请求到的 peer 地址。UDP 的 tracker 与 http 的 tracker 类似,只不过把上述的参数拼接成一个字节串发送过去,就可以收到 tracker 的回复。
步骤四:评估Peer节点完成状态
按照协议,当客户端从 tracker 获取到新的 peer 节点时,就可以向该 peer 节点建立连接,并进行下载了。但是,在进行下载之前,客户端为了实现对资源的分片请求,需要知道远程的 peer 节点拥有该资源的哪些片段(piece)。这个步骤是通过 peer 节点之间的 handshake 与 bitField 命令实现的。客户端首先与 peer 节点建立连接,并发送 handshake 数据包。数据包的格式如下。 向 peer 节点发送 handshake 包后,客户端也会收到 peer 节点的 handshake 数据包。此外,随后还会收到一个 bitField 数据包,数据包的格式如下返回的 bitField 数据包的内容字段中,包含了一个 bitarray 的结构,标记了该 peer 节点对资源的每个片段(piece)的拥有情况。如果全部都为1,则代表该Peer已经完成了资源的下载。
结果分析
借助以上思路,我在1月26日到30日对这组资源进行了跟踪分析。通过分析Peer的下载完成度,发现在26-27日使用了 1.160.61.90 进行发布做种,但是在 28-30 日换成了 1.160.60.3 进行发布。通过IP地址可以查到发布的服务器位于台湾,并且是个人地址的可能性较大。其实这次的溯源主要利用的优势是资源的发布时可预测,周期性的。因此我们可以在每次资源刚刚发布时进行监控分析。如果是正常情况下,当我们拿到资源的种子时,当初的发布者很可能早就下线了。另外,BT 协议是不能够隐藏信息发布者的身份的,因此利用 BT 进行资源的发布一般都没有匿名性的需求。如果大家有这方面的需求,可以考虑一下 IPFS。
参考资料
-Torrent文件结构解析-https://blog.csdn.net/mergerly/article/details/8013694
*本文原创作者:TBDChen,本文属于FreeBuf原创奖励计划,未经许可禁止转载