现有 PT 站漏洞分析及作弊方法

本文假设你已经对什么是 BT(BitTorrent) 以及 PT(Private Tracker) 有基本了解.


0x00 前言(回忆&废话)

遥想十几年前, 我还在小学低年级的时候家里没有宽带, 只能用 3G 无线上网卡上网, 网速不超过 5Mbps. 在线看优酷都只能看低分辨率版本的.

那时候也用 BT 种子和硕鼠 flv 下载器之类的方法囤积过一些视频 (那时候下载的电影都还是 rmvb / flv 格式的), 晚上开着电脑下载一些资源, 第二天就能流畅观看了.

后来没几年, 家里就办了宽带(我至今记得第一次看到下载速度 1MB/s 的震撼), 又随着国内”提速降费”, 家里的网速很快就能支持流畅观看一切流媒体了, 就再也没有了下载一堆视频的需求, 之前下载的视频也全被我扬了.

直到大学才又通过同学了解到一些校园网 PT, 注册了北邮人和北洋园, 但因为我对电影,日漫和某些站点的日本动作片都没什么兴趣, 也没找到对我有价值的资源.

还是和同学聊天时突发奇想, 发现了 PT 站的各类机制存在一些明显的漏洞, 花了些时间仔细探索了下协议, 发明了一些网络上不常提到的新作弊方法, 写成此文.

0x01 BT 现况与 PT

2024 年, 已经很少有正规资源通过 BT 网络发布, 就连大多盗版影视分享站都已经使用自己的服务器或使用网盘(百度网盘/阿里云盘/GDrive)分享, 很多种子已经名存实亡, 没人做种根本下不动.

相反的是, PT 站的邀请注册制度以及考核/等级制度让大家喜欢”刷上传”, 各种购置硬件和宽带做种, 客观上让 PT 的活种更多下载更快了, 这也限制了下载者需要做种一段时间, 贡献一定的上传量, 而不能下完就跑…….吗?

实际上, PT (Private Tracker) 并没有(也不能)对 BitTorrent 协议做任何修改, PT 使用的客户端就是一直以来使用的 BT 客户端. 而 BitTorrent 协议也从来不是为 PT 用途设计的, 其中必然存在着诸多逻辑漏洞.

加之现在 PT 主要以传播盗版影视资源为生, 并没有足够多开发者愿意在这种灰色领域投入大量时间精力, 导致很多 PT 站还在用年久失修的 NexusPHP, 也就更不可能在没有统一标准的情况下去开发 PT 的专有客户端(只能用存在问题的 BT 客户端).

0x02 传统作弊

如果你对 BitTorrent 协议还不熟悉的话, 推荐以下两篇资料:

BitTorrentSpecification

BitTorrent协议分析

为了更好的理解这篇文章的剩下内容, 你应该先了解 BEncode 编码, BT 文件格式(info_hash), peerId, Tracker协议Peer协议

Tracker 协议

Tracker 协议是 BT 客户端与 PT 站点交换数据所用的协议, 这是 BT 客户端与 PT 站点交换数据使用的唯一方式.

一个抓包得到的典型 Tracker 请求&响应如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /announce.php?passkey=xxxx&info_hash=%f5%ea%60Mn%3b%ce%fc%fd%93%96%f9%d5%b2f%c0%24*%a34&peer_id=-qB4630-u-OFvmi_~fo9&port=12866&uploaded=0&downloaded=0&left=123456&corrupt=0&key=2F750FC7&event=started&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0 HTTP/1.1
Host: byr.pt
User-Agent: qBittorrent/4.6.3
Accept-Encoding: gzip
Connection: close

---
HTTP/2.0 200 OK
Connection: close
Content-Encoding: gzip
Content-Type: text/plain; charset=utf-8
Date: Sat, 23 Mar 2024 17:01:14 GMT
Pragma: no-cache
Server: nginx
X-Powered-By: PHP/8.2.8

# 以下内容已经经过 gzip 解压缩
d8:completei53e10:downloadedi69e10:incompletei3e8:intervali1800e12:min intervali30e5:peersld2:ip39:2600:1700:2e30:656f:9209:d0ff:fe00:70d97:peer_id20:-TR2930-ue5o9dvps3p94:porti16881eed2:ip34:2001:da8:204:1921:0:7582:b3e3:c4c47:peer_id20:-UT2040-�Y�\����;��4:porti11826eed2:ip38:2400:dd01:103a:1012:3151:a2b:4b44:93877:peer_id20:-qB4630-)_~cP.FFpu2.4:porti25101eed2:ip37:2001:da8:215:3c0a:4f50:2d58:3633:26387:peer_id20:-TR3000-btgt831w3aqc4:porti51413eed2:ip22:2401:de00:1:2238::92137:peer_id20:-UT2040-�Y�$�\�q��_4:porti28606eed2:ip27:2001:da8:204:1481::977:f5987:peer_id20:-UT2040-�Y{g�����4:porti49461eed2:ip35:2402:f000:2:5001:4a0:ebdd:c27f:6c5c7:peer_id20:-qB4180-(QLI0Q8NjjF-4:porti8999eed2:ip23:2408:8244:420:272::10017:peer_id20:-qB4630-
# 之后还有些内容省略了, 都是类似的 IP 地址

可以观察到, 对 Tracker 的请求是一个简单的 HTTP GET 请求, 响应是 Bencode 编码的内容.

请求中比较重要的参数有:

  1. passkey(你在 PT 站的身份标识)

  2. info_hash(你想下载的种子hash)

  3. peer_id(你自己的ID, 由客户端字符串+随机串组成, 每个下载任务不同)

  4. uploaded(该种子上传量)

  5. downloaded(该种子下载量)

  6. left(该种子仍需下载的字节数)

其余参数在此处不是很重要, 如 key 是 BT Tracker 辨别身份使用的一个客户端生成的随机 32-bit 串(PT 不看这个), port 是自己监听的端口等等…

服务器返回的响应解码后可以得到 complete, downloaded, incomplete, interval 还有 peers(所有正在做种的对端 IP + 端口 + 可选的 peerId)

这时候敏锐的你肯定已经发现了最明显的问题… 每个种子的上传量都是自己上报的, 那就是想报多少报多少…

这就是传统时代最常见的 PT 作弊, 直接构造请求向 Tracker 汇报虚假的上传量, 更多信息可以参考: PT作弊与反作弊 这篇文章

但其实这种作弊也相对容易被发现: 你多上报上传量, 但其他用户没有上报对应的下载量, 对所有异常种子(上传-下载>阈值)的所有做种用户取交集, 很快就能发现是谁在作假.

0x03 更多作弊方法

虽然市面上常见的 PT 作弊软件仅仅是修改了上报的上传/下载量 (无论是模仿客户端还是直接 MITM 修改), 但实际上 PT 存在的问题远远不止这些.

假装保种骗魔力值

上传量造假还算是有据可循, 但保种量造假就更难被发现了: 我向 Tracker 上报我正在做xx种子, 但实际上我根本不需要持有这个种子的内容, 也不需要真实监听在端口上, 我只需要写个脚本定期向 Tracker 发送 announce 请求就行了, 内存和储存的占用率几乎可以忽略不计, 随便找台机器挂着就能刷魔力值.

对于一些相对冷门的种子, 长时间没有人下载或因为连通性差而无法下载是非常正常的情况, PT 站点也很难因为没有上传判断某个人是不是在做假种. 也可以配合真正的客户端, 做一小部分真种子刷一些上传, 做一部分假种, 使做假种更加隐蔽.

对于 TJUPT 这样的按做种时间考核的站点, 更是直接 Hit & Run 毫无压力.

免费下载(吸血)

上述方法都在关注于怎么刷上传量/魔力值, 但我们要意识到, PT 不是 PCDN, 上传再多也不给钱. 实际上我们上传的目的是为了下载更多资源而不是花钱做慈善.

如果我们有一种免费下载的方法, 我们也不是那么需要上传量. 那么…有吗?

我们来看看现在很多作弊方法没有关注到的部分: Peer协议.

Peer 协议

Peer 协议基于 TCP, 我们会主动向 Tracker 给我们的 peer IP:port 发起 TCP连接, 正在做种的对方也会主动向我们的 IP:port 发起 TCP 连接. 任意一个方向连接成功后双方开始握手.

握手包有以下几个部分:

  1. 20 bytes 固定的包头 \x13BitTorrent protocol
  2. 8 bytes reserved, 可以全置为 \x00
  3. 20 bytes 的 info_hash
  4. 20 bytes 的自己的 peer_id

对方收到握手包后, 返回同样的前 20+8+20 bytes + 自己的 20 bytes peer_id, 双方即握手完成, 之后两者就可以开始自由地发送消息交换文件了. (当然这里就意味着我们作为下载者可以开始下载文件了.)

理论上, peer 可以将我们发送的 peerId 和从 Tracker 获取的 peerId 进行对比, 拒绝不在 Tracker 列表中的对端. 但现在所有的主流客户端(例: libtorrent代码)都没有进行这个校验. 我推测有几个可能的原因 (其实无论原因为何, 现在的局面下, 要大规模修改客户端也不现实):

  1. 在 BT 中检查完全不必要, 并且协议也没有要求
  2. Tracker 更新延迟或宕机会导致 peer 更新不及时, 显著降低连接性, 也过于中心化, 丧失 P2P 优势
  3. 部分客户端实现上已经使用了 no_peer_id 请求 Tracker 不要返回 peerId, 其中标准和实现混乱, 也不一定所有 Tracker 都会返回下载者 peerId
  4. peerId 实际上是公开的, 向 Tracker 也能请求到其他人的 peerId, 就算校验了也能冒用他人 peerId, 校验意义不大
  5. qBittorrent 的匿名模式会在连接 Tracker 和 peer 时会使用不同的随机 peerId, 直接导致这种检查方式失效

所以, 对端不检查 peerId 意味着我们只要拥有 peer 的 IP:port + 种子 hash 就能下载这个种子.

很容易想到, 我们可以先向真正的 PT 站 Tracker 请求到 peer 列表之后, 直接使用这个 peer 列表就能下载到整个文件. 我们还可以在请求过 peer 列表后过一段时间再实际开始下载(降低我们的嫌疑).

传统的篡改客户端不上报下载量的方法仍然会一直连接 Tracker, 而我们实际上可以缓存得到的 peer 列表, 直接返回给客户端进行下载.

当然… 在 PT 站一直下载种子并访问 Tracker 但不产生实际流量还是看起来比较可疑,

还有种更好更安全的实现方法: 我们大量正常下载做种人数多的免费种子, 收集其中所有的做种 peer (特别是某些 seedbox). 当想要下载付费种子时, 直接向这些所有 peer 发起请求下载文件(使用磁力链接+自定义的作弊Tracker). 这种方法就完全绕过了 PT 站 Tracker, 在 PT 站看来我们的行为是 100% 正常的, 但我们能免费下载到付费种子.

唯一有可能的反作弊方法是给每个用户返回的 peer 列表中插入蜜罐, 但这实现和部署都比较困难, 可以认为几乎不可能遇到, 真有 PT 站实现蜜罐的话也有一些有效的反蜜罐方法, 不过限于篇幅不再赘述.

Ban 别人的账号

利用 peer 协议的特性, 我们还能直接恶意刷他人的流量. 比如我今天看用户 A 不爽, 我就先进他个人资料获取他所有正在做种的种子, 随便通过一到两个种子我就能确定 A 的 IP 和端口. 我直接连接到 A 向其发起大量下载请求, 此时 A 会产生大量可疑的上行 (比如对一个 2G 的种子上传了 1000G), 但 PT 站却没有发现任何正在下载的用户. PT 站很有可能会认为 A 在作弊虚假上报上传量, 从而封禁 A 的账号.

其他

由于 BitTorrent 协议本身不安全的属性, PT 站的反作弊几乎只能通过统计方法进行. 这也给了我们非常多可操作的空间.

例如我们先对大量热门/ RSS 中的种子进行吸血下载, 然后再伪装成被吸血的一员直接虚报上传量, 用下载骗上传.

例如我们得到某个热门种子的 Peer List, 然后可以把他改造成 BT 种子分享给他人(自建 Tracker 返回 PT 站的 peer).

0x04 代码实现

以下代码仅为概念验证 (PoC), 很多细节不完善, 并可能被 PT 站检测并封号, 也可能导致你的邀请人被连坐, 后果自负.

我使用 Golang 实现了一个比较简陋的实验性代码. 只写了缓存 Peer List 免费下载刷某个 peer 的上行流量这两个功能.

感兴趣的话你也可以试着改造成中间人截获免费种 Peer List 的方法, 可以实现接近 100% 的防检测, 不过我自己偷懒没写.

一些防止被检测的注意点有:

  1. 使用和代码中伪装版本相同的客户端(qBit/4.6.3), 如果后续有更新记得更新代码
  2. 别光偷流量, 也同时正常下载/上传一些其他种子
  3. 选择下载人数相对多的种子吸血或获取 Peer List 后过一段时间再吸血更难被发现

开源在 GitHub: https://github.com/lyc8503/PTHackPoC

0x05 小结&个人观点

开始只是突发奇想, 没想到最后写的代码量和本篇博客的长度远超我的预期. 虽然部分实现了 PT 下载自由, 但其实也没找到什么想下的资源, 最近可能会多下几个文件测试测试, 最后还是让账号吃灰.

至于 BT 和 PT 本身, 如果你看完了全文应该不难发现其处处充满着互联网初期野蛮发展的痕迹: 盗版侵权(当然, 你也可以认为是”共享精神”)以及简陋粗糙不安全的协议设计. 很多 PT 站能带着这一堆历史包袱走到今天也实属不易, 多少 NAS 爱好者事实上就是在用自己实名的宽带明文传播非法内容.

至于在 PT 站作弊是否道德, 我个人认为虽然 PT 通过一堆根本不可靠的方法表面上提高了作弊的难度, 使得作弊人数减少, 但技术上其实完全没有解决 BT 中吸血的问题. 众所周知, Security through obscurity 在现代计算机安全中是完全错误的, 就是掩耳盗铃, 现有 PT 站的模式只会让少数吸血者吸血吸的更爽. 与其逃避问题, 不如面对问题.

再者, 即使不作弊, PT 封闭的生态和 ratio 机制也只会让大家想尽办法刷上传量(或是给站长送钱), 用 RSS 订阅一堆谁也不需要的免费种子刷上传完全就是对公共网络带宽的浪费, 只会造成不必要的网络拥塞; 或是买 Seedbox 刷一堆上传之后就开始吸血, 实则也没有起到长期保种的目的.

虽然现实情况下 PT 站还能继续苟, 维持一种脆弱的现状, 再过一段时间才能完全被历史淘汰. 但也许, 早日开始使用一些更现代的 P2P 方案(比如 Resilio Sync)才是真正解决问题的方法. 又或许, 在这个流媒体和云存储的时代, P2P 模式的资源分发已经完成了它的历史使命? 毕竟, 与其花钱去买硬盘或者 Seedbox, 为什么不去花钱支持一下作者和正版版权方呢?


打赏支持
“请我吃糖果~o(*^ω^*)o”
现有 PT 站漏洞分析及作弊方法
https://blog.lyc8503.site/post/pt-hack/
作者
lyc8503
发布于
2024年3月27日
许可协议