Bloqueando anúncios do YouTube na Apple TV por meio de descriptografia e adulteração de Protobuf
(ericdraken.com)- Para bloquear, no nível da rede, os anúncios do YouTube na Apple TV e no iPhone, foram feitos testes que passaram por pfSense, bloqueio de DNS, roteamento por VPN, Squid, MITMProxy e chegaram até a adulteração de respostas Protobuf
- Como os anúncios do YouTube são entregues a partir dos mesmos domínios dos vídeos comuns, era difícil separar com estabilidade conteúdo e anúncios usando apenas bloqueio de DNS como Pi-hole e pfBlockerNG
- Após descriptografar o tráfego TLS com o MITMProxy, os campos de anúncios em JSON do YouTube web foram removidos e, no app do iOS, as estruturas de anúncio dentro de respostas application/x-protobuf foram localizadas e modificadas diretamente
- A decodificação completa de Protobuf com Python levava cerca de 23 segundos no roteador pfSense, mas, com uma varredura linear ao redor de
/pagead/, até um payload de 1.8MiB passou a poder ser processado em tempo real - Esse método exige a instalação de uma CA confiável e CPU com desempenho suficiente e, embora tenha permitido bloquear anúncios em dispositivos Apple conectados à rede, depois acabou levando até a considerar pagar pelo YouTube Premium
Roteador pfSense e segmentação da rede
- O objetivo era montar um roteador baseado em FreeBSD·pfSense para bloquear, em toda a rede, os anúncios pre-roll, mid-roll e end-roll do YouTube na Apple TV e no iPhone
- O hardware usado foi um mini PC J4125 com conjunto de instruções AES-NI, RAM DDR4, SSD mSATA e um pendrive para instalar o pfSense
- Um exemplo de configuração era 32GiB de RAM e SSD mSATA de 128GB
- Considerava-se que 128GB de armazenamento eram úteis para logs, redução de desgaste do SSD, captura de pacotes e espaço para edge cache
- Após instalar o pfSense, a LAN 1 foi configurada com o IP estático
192.168.1.3, fora da faixa DHCP existente, e o acesso ao portal web administrativo foi feito com a contaadmin/pfsense - Depois de confirmar no dashboard do pfSense a indicação
AES-NI CPU Crypto: Yes (inactive), o AES-NI foi ativado manualmente em System › Advanced › Miscellaneous - Aproveitando os 32GiB de RAM, foi alocado bastante espaço de RAM disk para
/vare/tmp, com backups do RAM disk configurados para ocorrer a cada hora
Bloqueio de DNS e separação física da rede
- No lugar do Pi-hole existente, foi instalado o pacote do pfSense pfBlockerNG-devel para configurar bloqueio de anúncios·conteúdo malicioso e bloqueio geográfico
- O tamanho da instalação acrescentava cerca de 20MiB
- Caso o serviço
pfb_dnsblnão iniciasse ou aparecesse[ Missing CRON task ], a recomendação era tentar apagar o arquivo vazio/var/run/booting
- As 3 portas Gigabit do roteador pfSense foram usadas para separação física de LAN, em vez de VLAN
- Dispositivos que “ligam para casa”, como Alexa e Apple TV, foram colocados em uma LAN de hardware separada
- A intenção era separar a LAN importante dos dispositivos smart e dispositivos Wi‑Fi para proteger aparelhos usados para banco, negociação de ações e uso de crypto wallet
- A rede dos dispositivos smart foi separada em
172.31.1.0/24, enquanto a LAN mais confiável foi mantida em192.168/16- Considerava-se que, sem rotas entre as redes, também se reduzia parte do impacto de regras de iptables mal configuradas
- Era necessário ativar o DHCP resolver na NIC física para que novos dispositivos da rede recebessem endereços
- O AC1200 Archer C5 foi descartado por não ter AP mode, por problemas de acesso remoto, firmware stock antigo e falta de suporte do chipset Broadcom a OpenWRT/DD-WRT/Tomato
- Depois, um Nighthawk R7000 foi usado como AP para Apple/Amazon/TV e como AP para a Trusted Wireless Network
- Na Trusted Wireless Network, decidiu-se desligar o 2.4GHz e usar apenas 5GHz
- Considerava-se que 5GHz é mais facilmente bloqueado por paredes e concreto, o que ajudaria a evitar snooping a média distância
Forçando todo o DNS a passar pelo pfSense
- Foram adicionadas regras de NAT para que todos os clientes atrás do pfSense usassem o servidor local de Unbound DNS
- O objetivo era impedir que apps e assistentes domésticos contornassem isso usando seus próprios servidores DNS ou DNS hardcoded
- Para que o pfBlockerNG pudesse intervir nas requisições DNS, era preciso bloquear DNS over TLS
- As regras de NAT inicialmente foram criadas em cada interface, exceto WAN, mas depois isso foi simplificado com o alias de firewall
Non_WAN- Tanto em IPv4 quanto em IPv6, consultas DNS locais na porta 53 eram redirecionadas para localhost
- Era necessário desativar NAT reflection para impedir acesso ao servidor DNS local a partir da internet externa
- Em Services › DNS Resolver › Display Custom Options, foi adicionado
server: log-queries: yespara registrar em log as requisições DNS interceptadas - Nos logs de DNS, apareceu uma requisição do Windows tentando acessar o Google Tag Manager, e essa requisição foi tratada por blackhole para o IP inexistente
10.10.10.1
Tentativa de contornar o direcionamento de anúncios do YouTube com VPN
- Como os anúncios do YouTube vinham dos mesmos domínios dos vídeos comuns, era difícil selecionar apenas os anúncios com bloqueadores por domínio como pfBlockerNG ou Pi-hole
- Considerava-se que bloquear
googleadservices.comsó teria utilidade depois de assistir ao vídeo do anúncio e clicar no anúncio - No navegador, o uBlock Origin pode interferir no JavaScript, mas acreditava-se que, no app do YouTube no iPhone, era difícil limitar anúncios sem jailbreak
- Considerava-se que bloquear
- Em vez de bloquear os anúncios diretamente, foi feito um experimento para levar o algoritmo de anúncios do YouTube a considerar o usuário um alvo menos atraente
- A ideia era enviar o tráfego da Apple TV por uma VPN e usar um endpoint de VPN em uma região com poucos espectadores do YouTube
- O objetivo era fazer o usuário parecer um homem de 70 anos morando na Itália
- Foi configurado WireGuard no pfSense, importando a private key do NordLynx/WireGuard a partir de uma VM Linux
- Ao inserir o endereço do túnel como
1.0.0.0com subnet mask0, a UI passava a mostrar o resultado como0.0.0.0/0
- Ao inserir o endereço do túnel como
- Ao enviar todo o tráfego da Apple TV pela VPN, o YouTube passou a aparecer em italiano e a quantidade de anúncios diminuiu, mas surgiram problemas no Netflix e no Amazon Prime
- Parecia que arquivos de CSS ou font estavam sendo bloqueados e que thumbnails não carregavam
- Havia o alerta de que Netflix e Prime fazem geofencing de provedores de VPN com eficiência
- Depois, tentou-se rotear pela VPN apenas os FQDNs relacionados ao YouTube, usando como candidatos
www.youtube.com,youtube.com,googlevideo.com,accounts.google.com,googleapis.com,gstatic.come outros- Após a configuração, o YouTube via o usuário como estando em Milão, enquanto Netflix e Prime Video o viam como estando no Canadá
- Os anúncios ficaram raros e, quando apareciam, eram em italiano
Condição de corrida de DNS e problema de domínio curinga
- Um dia depois, foi descoberta uma condição de corrida de DNS em que o alias de hostname do pfSense e o cache DNS do cliente viam conjuntos diferentes de IPs do YouTube
- O intervalo padrão de resolução do alias de hostname do pfSense é de 300 segundos
- O TTL de DNS do YouTube foi observado em 1.440 segundos
- Se o IP resolvido pelo Alias Daemon para o FQDN não corresponder ao IP que a Apple TV recebeu depois, o tráfego pode não entrar no túnel VPN
- A mitigação é fazer o pfSense ignorar o TTL do destino e manter em cache a entrada de alias por mais tempo
- Os subdomínios variantes de
googlevideo.comexigiam roteamento curinga, mas as regras de NAT e firewall operam com base em IP e não conseguem lidar diretamente com hostname curinga - Foi escrito um PoC usando o módulo Python do Unbound e a API REST do pfSense para capturar os IPs das respostas DNS e adicioná-los dinamicamente ao alias
VPN_wildcards- O TTL de
VPN_wildcardsfoi definido como 1 hora, com capacidade de 500 - Registros A são analisados como
ipaddress.IPv4Address, e registros AAAA comoipaddress.IPv6Address
- O TTL de
- Na verificação da manhã, o Unbound DNS Resolver estava em estado de segfault, e como cada adição de IP exigia recarregar as regras do pfSense, o pfSense ficou muito lento
Descriptografia de HTTPS com Squid e MITMProxy
- O novo objetivo era instalar um proxy semelhante ao Squid e adicionar ao dispositivo um certificado de CA falso, mas confiável, para realizar a descriptografia do tráfego TLS
- O Squid foi instalado como pacote do pfSense e até o smoke test de SSL Filtering teve sucesso, mas acabou sendo abandonado
- O desempenho era muito lento
- A configuração de ACL era trabalhosa
- Havia um problema relacionado a
https://http/* - A atualização da lista de filtros de URL do SquidGuard demorava muito
- A UI do Squid foi considerada insuficiente
- Depois disso, foi escolhido o MITMProxy
- Foi considerado extensível para o bloqueio de anúncios do YouTube, por ter scripting em Python e UI
- O tarball Linux do mitmproxy 7.0.4 não rodava no FreeBSD por causa de
ELF interpreter /lib64/ld-linux-x86-64.so.2 not founde bibliotecas ausentes
- Ele foi instalado no ambiente jail FreeBSD do pfSense com
pkg install mitmproxy- Foram 50 pacotes para instalar, 206MiB de espaço adicional e 33MiB de download
- Ao executar
mitmproxydentro do jail, a UI abria
- Para experimentar o MITMProxy, foi adicionado no pfSense um IP virtual
127.0.1.1ao localhost, e uma regra de NAT encaminhava[Private IPs]:8080para127.0.1.1:8080- Quando o proxy de um notebook de teste foi configurado como
192.168.20.1:8080, as requisições do navegador apareceram no log da UI do MITMProxy
- Quando o proxy de um notebook de teste foi configurado como
- O arquivo PEM da CA do MITMProxy fica em
~/.mitmproxy/mitmproxy-ca-cert.pem- Um servidor web em Python 3 foi usado para servir
cert.pem - O MITMProxy também fornece o mesmo certificado de CA em
mitm.it - O certificado foi adicionado a um notebook limpo e a um iPhone
- Um servidor web em Python 3 foi usado para servir
Operação do MITMProxy e resposta a certificate pinning
- No roteador, o
mitmproxyconsumia muita CPU mesmo ocioso, e isso foi atribuído à geração sob demanda de certificados TLS para cada requisição e ao excesso de logs da UI - O
mitmdumpfoi considerado menos pesado para a CPU por dispensar a UI e o logging extremo- Na execução, foram usados
--anticomp,--mode regular,--listen-port 8080,--listen-host 127.0.1.1etc.
- Na execução, foram usados
- Certificate Pinning é uma técnica em que o servidor ou o cliente já conhece antecipadamente a fingerprint esperada do certificado, de modo que a falsificação de certificado do MITMProxy não funciona
- Como alternativa, foi usado
--ignore-hostspara fazer hosts comoapple.com:443eicloud.com:443ignorarem o proxy
- Como alternativa, foi usado
- No Transparent Proxy Mode, foi aplicado um patch em
next_layer.pydo MITMProxy 7.0.4 para que--allowed-hostsfuncionasse melhor com base em SNI- Antes, em muitos casos, parecia que apenas o IP do servidor era usado na correspondência
- O patch adiciona
server.snicomo candidato de hostname além deserver.address[0]
- Após o patch, alguns hosts puderam ser interceptados com estabilidade, enquanto os demais apenas passavam
Remoção de anúncios em JSON no YouTube web
- No smoke test do MITMProxy, URLs de anúncios e rastreamento do YouTube foram bloqueadas com um pequeno script
- Em
youtube.com, foram bloqueados/pagead/,/log_event?,/stats/ads,/stats/qoe?,/ptracking?,/generate_204,el=adunit,adformat=,/activeview?etc. - Em
google.comegoogle.ca, foi bloqueado/pagead/
- Em
- Nos testes iniciais, as requisições marcadas para bloqueio realmente eram bloqueadas também no painel Network do DevTools
- Itens
(failed)eram gerados pelo script - As falhas
502foram atribuídas ao pfBlockerNG tratando a requisição como black-hole - O HTTP/2 foi desativado para impedir que requisições subsequentes no mesmo canal passassem
- Itens
- O simples bloqueio de URL não eliminou completamente os anúncios, então, observando o HTML/JavaScript do YouTube e os filtros do uBlock Origin, foi investigada a possibilidade de as informações de anúncio estarem no corpo das respostas JSON
- Nas respostas JSON capturadas pelo MITMProxy, foram confirmadas informações de anúncios e rastreamento nas estruturas
playerAdseplaybackTrackingplayerAdsincluiplayerLegacyDesktopWatchAdsRenderer,playerAdParams,gutParams.tag,showCompanion,showInstream,useGutetc.playbackTrackingincluivideostatsPlaybackUrl,ptrackingUrl,qoeUrl,atrUrletc.youtubeRemarketingUrltinha o formatowww.youtube.com/pagead/viewthroughconversion/...
- No YouTube web, foi possível eliminar os anúncios web via roteador removendo as informações de anúncio do payload JSON
Análise do YouTube para iOS e do Protobuf
- O app do YouTube para iOS usa dados no formato Protocol Buffer (Protobuf) em chamadas de API parecidas com as da versão web, em vez de JSON
- No Protobuf, as chaves são numéricas e podem mudar, então é difícil encontrar a seção de anúncios com uma abordagem no estilo JSONPath
- No payload, foram vistas strings de anúncios como “Telus”, “Samsung TV”, “Boxing Week” e “Buy now”
- O tráfego de rede do YouTube no iOS era diferente do tráfego web
- Na versão web, dá para estimar em certa medida os candidatos a anúncio pelos parâmetros
rangeouclendos chunks de vídeo - O protocolo do iOS não usa o parâmetro de query
rangenem o cabeçalhoRange, e usa contadores como&nr=2e&nr=3
- Na versão web, dá para estimar em certa medida os candidatos a anúncio pelos parâmetros
- Ao decodificar respostas Protobuf para análise offline, foram encontrados itens como
has_unlimited_entitlement: Falseehas_premium_lite_entitlement: False- Alterar esses valores pareceu uma forma de “trapacear”, então a abordagem heurística foi retomada
- Experimentos de bloqueio de URLs de anúncios causaram loop infinito, erros de UI e crash no app do iOS
200com body vazio,404,503, body de resposta truncado e tratar parte do vídeo do anúncio como null faziam o app ficar lento ou quebrado até crashar- O endpoint de reporte de erros
/error_204/indica “dev assertion failed” e foi bloqueado
- Os anúncios parecem ser registrados em slots dentro de um vídeo específico
- Os tipos de slot incluem pre-roll, mid-roll, end-roll, full-page e ad pod
- Se apenas a URL do anúncio for bloqueada, ocorre um erro do tipo “um anúncio inexistente reservou o slot”, e a UI entra em estado de pânico
Problemas de desempenho do Protobuf e o blackboxprotobuf
- Decodificar cerca de 500 KiB de Protobuf bruto para texto legível apenas com Python era muito lento
- Em um desktop com CPU i7-6700, levava cerca de 2,06 a 2,11 segundos
- Em um roteador pfSense, levava cerca de 22,8 a 24,2 segundos
- O C++
protoc --decode_rawera muito mais rápido- Em um desktop com CPU i7-6700, levava cerca de 0,017 a 0,022 segundo
- Em um roteador pfSense, ficava na faixa de 0,12 a 0,14 segundo
- Como o decoding bruto não é suportado em Python, foi escolhida uma abordagem de comunicação direta com o binário C++
protocviasubprocess.Popen - O
blackboxprotobufpara Burp Suite consegue decodificar mensagens wire raw de Protobuf, injetar valores e depois reencodá-las- Recomenda-se usar a versão original do Burp Suite, e não um fork do PyPI
- Alguns forks podem causar stack overflow por recursão profunda
- Definir
os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "cpp"antes de importarprotobuffaz com que a implementação em C++ delibprotobuf.soseja usada quando possível
- O
protobuf_to_json(data)doblackboxprotobufpode gerar um schema.protopor tentativa de inferência, mas o resultado é muito grande, profundamente aninhado e imperfeito- O dump de schema em Python tinha mais de 250.000 caracteres
- Isso foi considerado suficiente para extrair os detalhes dos anúncios
Desativando a seção de anúncios com a alteração de 1 byte
- O formato wire do Protobuf pode mudar de encoding ao fazer decode/edit/re-encode sem o schema original
- Entre as causas citadas estão o uso ou não de codificação ZigZag, a impossibilidade de identificar o tipo numérico e a não determinismo na ordem dos campos de objeto
- A solução foi usar a compatibilidade retroativa do Protobuf para fazer a seção de anúncios parecer um campo desconhecido
- Isso aproveita o comportamento de softwares antigos que ignoram campos desconhecidos ao ler fields novos
- Ao alterar 1 byte em um ponto crítico, a seção profundamente aninhada passa a parecer pertencer a uma versão futura do schema, e o Protobuf a ignora
- A chave do campo de destino
49399797precisou ser encontrada por varredura de tag varint, e não por simples busca de string- O wire type era
2, indicando string ou mensagem aninhada com length-delimited - A tag de destino foi calculada como
AA FF B8 BC 01 - Ao deslocar para fora os 3 bits do wire type, a chave do campo
49399797é restaurada
- O wire type era
- A busca real funcionava localizando primeiro uma assinatura de URL de anúncio como
/pagead/nos bytes brutos do Protobuf e, nas proximidades, recuando para encontrar a tag do campo-alvo e a chave do campo- Um alvo de interceptação de exemplo era
POST youtubei.googleapis.com:443/youtubei/v1/browse?key=... - A resposta era
200,application/x-protobuf,1.87m - No log de exemplo,
49399797foi encontrado na posição4465e50195462na posição4477
- Um alvo de interceptação de exemplo era
- Em um smoke test O(n), a remoção de anúncios funcionou com uma única varredura de 1,8 MiB de dados Protobuf, sem memória adicional
- O alvo foi encontrado no byte
30.593 - Cerca de 600 bytes de backtracking foram usados para encontrar a chave do campo a ser corrompida
- Não é mais necessário bloquear URLs contendo
*.googleadservices.comou/pagead/, porque essa requisição deixa de ser gerada desde o início
- O alvo foi encontrado no byte
Estrutura do addon do MITMProxy
- O script PoC é salvo como
youtube.pye executado commitmdump --listen-port 8080 --listen-host 127.0.0.1 -s "youtube.py"- Como pré-requisitos no FreeBSD, são indicados
pkg install protobuf,pkg install py38-pipepip install jsonpath-ng
- Como pré-requisitos no FreeBSD, são indicados
- O script é composto pelas classes
Logger,trunc,KilledError,JSONPathReplacement,ProtobufDebugParsereYouTubeAdBlocker - O regex de host alvo de interceptação de
YouTubeAdBlockeré\.youtube\.com|google\.(com|ca)|googleapis\.com|googleadservices\.com|googlevideo\.com- A string de busca de URL de anúncio em Protobuf é
b"/pagead/" - O limite de busca é
80_000 - A tag do campo alvo é
50195462
- A string de busca de URL de anúncio em Protobuf é
- A regra de bloqueio de requisições verifica strings parciais de URL por host e encerra o flow
- Para
youtube.com, incluipagead/,log_event?,stats/ads,stats/qoe?,ptracking?,generate_204,error_204,adformat=,activeview?,_ad_,ai?,sw.jsetc. - Em
sw.js, há um comentário dizendo que service workers são recusados
- Para
- Em respostas JSON, vários replacements de JSONPath são aplicados
$.responseContext.serviceTrackingParams[*].params[?(@.key == 'yt_ad')].valueé alterado para"0"$..adPlacementsé alterado para[]$..adPlacementRenderer,$..adPlacementConfig,$..playerAdParams,$..gutParamssão alterados para{}$..adVideoIdé alterado para string vazia$..showCompanion,$..showInstream,$..useGutsão alterados paraFalse
- Em respostas Protobuf, quando o content type contém
protobuf, o body é convertido embytearraye/pagead/é procurado nos primeiros 80.000 bytesTagBytes(self.target_field_tag, WIRETYPE_LENGTH_DELIMITED)cria os bytes da tag alvo, e novos bytes são gerados paratarget_field_tag - 1- Faz-se uma busca reversa até imediatamente antes da posição de
/pagead/para encontrar os bytes da tag alvo - Se encontrados, esses bytes são sobrescritos pelos novos bytes e
flow.response.set_content(bytes(body))substitui o corpo da resposta
- Pelos comentários, este PoC bloqueia 90% dos anúncios
- Outras seções também têm outras chaves de campo, e pode haver várias seções de anúncio que precisam ser corrompidas
Escopo de aplicação e limitações
- Essa técnica é resumida como uma técnica altamente especializada para bloquear anúncios do YouTube em dispositivos Apple ou tráfego de rastreamento de Instagram, WhatsApp e Facebook
- Considera-se que a exigência de CPU para descriptografar/recriptografar tráfego HTTPS excede em muito o que um Raspberry Pi consegue suportar
- A avaliação é que, após fazer jailbreak na Apple TV e adicionar o certificado raiz do pfSense, o gateway pfSense pode descriptografar o tráfego da Apple TV e bloquear anúncios inspecionando o hostname de publicidade nos headers das requisições
- Ainda assim, isso não se aplicaria a anúncios no iPhone, e fazer jailbreak no iPhone é mais difícil, além de apps bancários poderem detectar isso e deixar de funcionar
- O próprio jailbreak é considerado extremo demais
- Se uma CA confiável falsa for possível, dá para descriptografar os pacotes TLS em texto puro e aplicar bloqueio por URL
- Como exemplos de URLs bloqueadas, são citados os caminhos
/pagead/viewthroughconversion/...e/pagead/conversion/...do YouTube
- Como exemplos de URLs bloqueadas, são citados os caminhos
- Por fim, o autor configurou um roteador de hardware do zero, dividiu a LAN em zonas confiável e não confiável, adicionou bloqueio de anúncios por DNS e um proxy MITM transparente e, então, bloqueou com bom desempenho os anúncios do YouTube em dispositivos Apple conectados à rede
YouTube Premium e apoio aos criadores
- Depois de bloquear anúncios do YouTube por alguns meses, o autor passou a pagar o YouTube Premium por querer apoiar os criadores de conteúdo
- Acrescenta a ressalva de que “só porque você pode, não significa que deve”
- O preço do YouTube Premium é mencionado como CAD
$9.99/mopassando para$11.99/mo, cerca de$13.43/mocom impostos - No experimento assistindo a anúncios, o autor usou um notebook limpo e navegação privada para assistir ao YouTube de forma intermitente por um dia
- O registro mostra 10 vídeos assistidos
- Houve exposição a 8 anúncios, dos quais apenas 2 podiam ser pulados
- Assumindo um CPV de USD
$0.15, o custo diário de anúncios seria$1.20, e a extrapolação mensal daria cerca de USD$36/mo - Em outro cálculo com números da Statista, anunciantes dos EUA gastaram
$15.1 billionno YouTube em 2019, e residentes nos EUA assistiram916 billionvídeos, resultando em uma média de USD$0.0165por visualização- Aplicando esse cálculo, o custo diário seria de cerca de USD
$0.13, e a extrapolação mensal seria de aproximadamente USD$3.96 - Considera-se que esse valor não chega perto dos USD
$10do Premium
- Aplicando esse cálculo, o custo diário seria de cerca de USD
- Se houver uma reivindicação via DMCA, a receita de anúncios pode ir não para o criador, mas para o reclamante, como Sony ou Viacom
- Por isso, é possível acabar sem dar nada aos canais de que se gosta sem sequer perceber
- O autor avalia que não é surpreendente que muitos criadores migrem para o Patreon
2 comentários
O texto original é muito longo, mas o processo é interessante; o ponto principal é que, no fim, o autor acabou simplesmente assinando o YouTube Premium e usando assim.
Opiniões no Hacker News
No geral, é um hack bacana, mas algumas afirmações sobre Protobuf soam estranhas
O que foi feito foi corromper de propósito a tag de um determinado campo no Protobuf, mas ignorar números de tag desconhecidos não é uma “falha”; é um princípio central de design para extensibilidade
1,87 MiB também não é um tamanho tão grande, e provavelmente essas mensagens não ficam sendo transmitidas em streaming continuamente, então a explicação de que isso seria uma barreira de desempenho também não convence muito
A codificação do Protobuf não foi projetada para tornar a decodificação cara; pelo contrário, foi projetada para ser decodificada com eficiência, e mesmo sem o esquema
.protooriginal é possível decodificar diretamente comUnknownFieldSetUm método melhor talvez fosse usar um esquema
.protofalso contendo apenas o campo que se quer remover. A abordagem de varrer strings é mais propensa a erros, porque a mesma sequência de bytes pode aparecer por acaso em outros dadosSe a ordem dos campos mudar, os bytes resultantes da recodificação podem ser diferentes, mas o receptor deve tratar aquilo como a mesma mensagem, e parece pouco provável que o app do YouTube detecte uma mudança na ordem dos campos
Do ponto de vista de alguém que já trabalhou com Protobuf, parece que o autor entendeu mal essa parte
Vivi a maior parte da vida em áreas rurais e, quando não estou no meu Wi‑Fi, isso ainda é um download grande na prática. No celular talvez existam formas de contornar, mas o Wi‑Fi rural ainda sofre com a arquitetura da Web 2.0 e muitas vezes é usado em velocidades de 2G a 4G
Em áreas urbanas, onde há população suficiente para sustentar a infraestrutura, 1,87 MB em geral virou um arquivo pequeno, mas por volta das 18h, quando todo mundo ligado ao cabo está fazendo streaming, isso pode ser uma exceção
without the C++ source proto files: criei um projeto chamado protodump, que gera arquivos.protode origem a partir de um binárioEle recria as definições de mensagens e campos, incluindo os nomes originais; basta extrair o binário da caixa Apple TV
https://github.com/arkadiyt/protodump
Protobuf foi a tecnologia que me apresentou a IDLs e, na época, parecia uma ideia mágica. Fiquei ainda mais impressionado depois de criar minha própria IDL mal-ajambrada e então descobrir o Protobuf
Se você não quiser puxar a dependência inteira do
protoc, pode escrever por conta própria um decodificador Protobuf simples, de algumas centenas de linhas: https://github.com/kubernetes/test-infra/blob/master/guberna... https://github.com/kubernetes/test-infra/blob/master/guberna...Desde que descobri The Proxomitron, mais de 20 anos atrás, venho passando o tráfego por um proxy man-in-the-middle para remover anúncios e reescrever páginas com coisas como CSS do usuário
Lugares como a CloudFlare tendem a me classificar como “bot”, mas também há formas de contornar isso, embora não sejam simples. Casos assim também mostram por que a atestação remota é perigosa para a liberdade do usuário
Parece haver vários projetos “sucessores”, e também fico curioso se ele é exclusivo do Windows. Eu estava procurando, sem muita intensidade, um proxy simples capaz de inserir links locais em conteúdo remoto
No momento, até desliguei o pi-hole que rodava no Pi 4. Passei horas tentando fazê-lo funcionar corretamente junto com vários serviços, mas acabei desistindo; não valia o tempo para uma rede doméstica
O que realmente funciona bem são bloqueadores de anúncios baseados no navegador e patchers de apps como o ReVanced. Conforme minhas economias aumentam, fico mais inclinado a simplesmente pagar por serviços sem anúncios, como YouTube Premium, Hulu, Netflix e Max, nos casos em que esses dois não resolvem
Nunca o usei para o caso mencionado aqui, mas ele era ótimo como proxy atrás do firewall da empresa. Antigamente, o firewall exigia credenciais de login para conexões externas, então muitos programas não conseguiam acessar a internet
Lembrei do Privaxy, empacotado em Docker. É um proxy intermediário compatível com as listas de bloqueio do UBlock Origin.
É surpreendente ver a quantidade de anúncios e scripts de rastreamento em produtos inteligentes, especialmente TVs. Pelo que testei até agora, o tráfego desnecessário passou de 40%, e foi bem divertido experimentar remover anúncios de apps de smart TV.
https://github.com/deetungsten/webui-privaxy é um fork dockerizado de https://github.com/Barre/privaxy
Eu queria alterar o fork para que o frontend não usasse o endereço
0.0.0.0hardcoded, permitindo isolar de verdade o contêiner Docker, mas a vida aconteceu. Você chegou a testar na Apple TV?https://github.com/AdguardTeam/urlfilter
Este texto é uma ótima resposta à pergunta recorrente: “como devo aprender para virar hacker?”
Ele mostra muito bem o processo de raciocínio e o trabalho persistente por trás de qualquer exploit.
Há uma parte que diz “vamos usar WireGuard — há o conjunto de instruções de criptografia Intel AES-NI”, mas, até onde sei, WireGuard não usa AES.
No geral, o autor parece superestimar um pouco os requisitos de CPU da criptografia TLS, ou subestimar o desempenho de computadores de placa única modernos.
Também acho estranha a explicação de que os requisitos de CPU para descriptografar e recriptografar tráfego HTTPS em um Raspberry Pi seriam muito excedidos. Eu ficaria bem surpreso se MITM de TLS fosse realmente inviável em um RPi 4, mesmo usando RSA puramente em software.
Entre os celulares Android ainda em uso, há aparelhos com CPUs mais fracas que a do RPi 4, e eles também usam TLS.
Se um celular Android fraco só consegue processar tráfego TLS a 50 Mb/s, isso pode não ser um grande problema no uso real. Celulares lentos normalmente estão conectados a redes lentas.
Por outro lado, se você tem internet gigabit em casa e um dispositivo fraco entre todos os seus computadores e a internet cria um gargalo de 50 Mb/s, aí isso vira um problemão.
Os requisitos de CPU do TLS dependem muito da largura de banda alvo. Em larguras de banda mais altas, descarregar para aceleradores acaba se tornando praticamente obrigatório. O custo do handshake também não é desprezível e pode limitar o número de conexões por segundo. Em um único dispositivo isso raramente é um problema, mas pode ficar maior em uma rede inteira de dispositivos.
Texto excelente. Eu esperava um método para fazer MITM em dispositivos que não permitem instalar uma CA personalizada.
Tenho um dispositivo IoT que não expõe uma API local e só mostra dados pela nuvem, e queria capturar o tráfego entre o dispositivo e a nuvem.
No fim, será que não há outro jeito além de despejar a memória flash, trocar a CA e gravar de volta?
Há um bom texto com abordagens para tentar interceptar dispositivos IoT sem mexer em hardware ou firmware:
https://robertheaton.com/2019/11/21/how-to-man-in-the-middle...
Se for possível, você estará dependendo de falhas de implementação.
Sinceramente, acho que mesmo alguns dispositivos que hoje permitem instalar certificados confiáveis próprios não continuarão assim por muito tempo.
Sempre surgem novos métodos para bloquear anúncios no YouTube ou em qualquer plataforma, mas alguns meses depois eles mudam e aquilo deixa de funcionar.
Em vez disso, que tal atacar os anunciantes? YouTube/Google parece rastrear apenas “cliques”, mas será que acompanha compras reais?
Em tese, se uma quantidade suficiente de bots falsos e usuários reais clicasse em anúncios sem comprar nada, daria para queimar o orçamento de publicidade. Com o tempo, o departamento de marketing veria que, em certa plataforma, o número de cliques está no maior nível histórico, mas a taxa de conversão em relação a cliques ou impressões é baixíssima, e poderia acabar saindo dela.
Texto impressionante. Assim que vi a etapa de patch de MITM, imaginei que seria algo especial, e realmente foi.
O item do sumário “Novo objetivo: fazer o YouTube acreditar que sou um homem de 70 anos que mora na Itália” me chamou a atenção.
Um tempo atrás, não sei como, o direcionamento de anúncios passou a acreditar que eu era alguém querendo comprar um pijama de seda lavável de 500 dólares para a minha namorada.
Os anúncios em si eram ótimos, mas fico curioso para saber quanto estavam pagando por impressão.
Depois que mudei para a Apple TV, geralmente recebo anúncios locais com segmentação regional errada. Em média, talvez isso até seja melhor.
Isso não é uma “falha” do Protobuf. O fato de, ao modificar bytes, eles serem decodificados como campos em outras posições é algo que funciona conforme o esperado
O Protobuf, desde o início, é um protocolo baseado em números de campo e prefixos de comprimento, parte da suposição razoável de que os bytes não mudam durante a transmissão e deixa a integridade a cargo de quem lê
Mesmo que fosse uma falha, seria uma falha do app do YouTube para iOS, não do Protobuf; e, na prática, nem é uma falha, então é difícil chamar de “exploit”. A menos que estejam falando do fato de que, na troca Protobuf do app do YouTube para iOS, o hash do payload retornado não é verificado
Depois deste texto, provavelmente eles passem a verificar
Não é uma falha, é algo que funciona conforme o design
A parte que diz que “o Google torna computacionalmente caro decodificar, modificar e recodificar sem os arquivos proto de código-fonte em C++” também é estranha. Com código Python não otimizado, pode ser caro, mas em C ou em outra linguagem compilada, varrer um Protobuf de 1,8 MB é algo trivial, com ou sem os arquivos-fonte proto
Não parece que dificultar a decodificação de arquivos Protobuf sem os fontes tenha sido um objetivo de design. Se esse era o objetivo, foi executado de forma bem ruim