The Pirate Bay un-SSL


Recently, the world saw The Pirate Bay offering SSL encryption on their server. This means that your ISP won't know anymore which torrent you are downloading, right? Wrong.
HTTPS is quite useless for protecting static and public content. By static, I do mean the .torrent file itself. It is always the same. By public, I do mean than one doesn't need any kind of authentication to pick up the content. It's always the same, for everyone. For crawlers, too.
So, one could easily index (a portion of) The Pirate Bay torrent database by the Content-Length. Then, one could intercept some encrypted traffic between some machine(s) within his/her network and the server. Knowing both (encrypted) request and response lengths, it is possible to get a quite reliable list of matches from the previously indexed torrent list.


Don't try this at work, or you might hurt yourself Eye-wink

  1. Use Wireshark to capture some torrent downloads. Torrents are hosted on a separate server, which makes the task easier yet. Just use the following capture filter: "tcp and port 443 and host"
  2. Now, just go with the stream Smiling ("Follow TCP Stream" for the packet you suspect belongs to the torrent download. This will create another filter, just like "(ip.addr eq and ip.addr eq and (tcp.port eq 2157 and tcp.port eq 443)")
  3. Just save the displayed stream anywhere else (pcap1.pcap sounds nice)
  4. Now, use my quick&dirty Perl script to get the request/response lengths:
    perl pcap1.pcap
    Yeah, I know, it is nasty. It only supports the TLS cypher. And it simply calls the tshark (the command line version of Wireshark) to parse it's output.
  5. Now, just paste the REQ and RES values below Laughing out loud
    (note that the REQ value is optional, setting it to 0 simply ignores the request size for matching)
Note that you are able to fine-tune the maximum and minimum header sizes. For the response, the headers are almost the same all the time. The only thing that varies is the decimal representation of the file length and age. (Un)fortuately, the request headers do vary for different browsers and referring pages. However, knowing the request size still helps a bit, specially if the torrent's filename was huge Smiling


The following size distribution chart was generated using the database with ~165K torrents:

torrent size distribution

The most common torrent size is ~14 KB, and it's easy to figure out that such torrents represent the shared 700 MB files Smiling
There's also a major peak for the 454 bytes torrents. However, bigger torrents are less common, thus, the size detection technique becomes more precise. Now, the average "distance" between torrent sizes is ~44 bytes (at least for the sample I've collected). So, adding a cookie with the random size up to 128 bytes will disrupt the size matching detection a lot. The request size disruption is even easier: the largest torrent URI I've found was 150 bytes-wide. Thus, padding every request URI to match 150 characters is enough to make the requests completely indistinguishable. Joining the pieces (the padding add-on strings are bold):
GET /4319199/[a4e]Ghost_in_the_Shell_TV_01-26.4319199.TPB.torrent?nVM2UGfcG533un4ym70eT2
HTTP/1.1 Host: User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/2008070208
Firefox/3.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: Cookie: language=pt_BR; country=BR; PHPSESSID=ad6cb7e414c8dc88e0c2444f6215165a
HTTP/1.1 200 OK Content-Type: application/x-bittorrent Etag: "2198642509" Last-Modified: Mon, 28 Jul 2008 22:28:59 GMT Server: lighttpd Content-Length: 91601 Date: Mon, 28 Jul 2008 22:37:56 GMT X-Varnish: 108010229 107999438 Age: 253 Via: 1.1 varnish Connection: keep-alive Set-Cookie: p=68eOfxOC7JwBYcMe1RJWC4Z5PV/lJzqJORW8KROPMH9zQhszSjFnRp2tsNWEoyabWAloneUaoz
MxYtx4hoM9MZUKE/7wGzC3ZKLEZdppG4og3W; expires=Mon, 28-Jul-2008 22:37:56 GMT; path=/;
(binary torrent data)


  1. Use a constant padding in the .torrent files. This messes things a bit, but stills ineffective. The only advantage is not messing up with the server Sad
  2. Patch the lighttpd server so it sends a non-lasting cookie with a random size.


Encrypted session data

SSL size:
Min header length:
Max header length:

Possible matches

The Pirate Bay URL strlen(URI) torrent size
0 matches
Torrents indexed: 1580345


stas's picture
stas » July 31, 2008 » 11:05
database » hack » music » network » perl » php » video » web

Formulário CEP/CPF/CNPJ

(tente preencher os campos acima; a informação é atualizada instantaneamente)

Este projeto é o sucessor do CEP-2-City. É um formulário online que:

  • Verifica a validade do número CPF
  • Verifica a validade do número CNPJ
  • A partir do CEP, deduz o endereço completo (Cidade/Estado/Bairro/Rua)
  • A partir do CEP, deduz o código DDD da região Eye-wink

O banco de dados utilizado é compilado a partir de diversas fontes. Se não constar a informação da rua, então somente a cidade é retornada. A interface com o banco de dados foi implementada usando Perl e PHP, e pode ser acessada via CGI, Flash ou AJAX. O sistema de busca é extremamente eficiente, e não necessita de MySQL. O tamanho do banco de dados é cerca de 60 MB, e a performance chega a milhares de consultas por segundo.

Portanto, eis uma solução bastante símples, flexível e eficaz para o cadastro de clientes. Já utilizei este sistema numa pesquisa que conduzi, e asseguro que me poupou bastante tempo. Para realizar as consultas, basta acessar a seguinte URL (com a devida substituição do CEP):, e processar a string retornada com a função parse_str() (em PHP).

Se tiver interesse no banco de dados em si, entre em contato!


stas's picture
stas » August 15, 2007 » 20:31
XML feed