Detectando o Blue Pill

All non-trivial abstractions, to some degree, are leaky. - Joel Spolsky, The Law of Leaky Abstractions

Joel Spolsky define como uma "abstração" como sendo a simplificação de uma coisa muito mais complexa que acontece em um nível mais baixo. O protocolo TCP por exemplo fornece para as aplicações a abstração de meio de comunicação confiável, que simplifica o protocolo não confiável IP sobre o qual ele é implementado. Um banco de dados SQL fornece uma abstração de tabelas e relacionamentos que esconde a complexidade dos bytes e arquivos sobre o qual ele é implementado. Uma linguagem de programação de alto nível é uma abstração para o código de máquina que é efetivamente executado pelo processador. Toda a ciência da computação é feita de um número cumulativo de abstrações.

Máquinas virtuais também são abstrações, e das mais complexas. A máquina virtual Java é um computador abstrato que roda programas Java, implementada sobre as mais diversas plataformas. Em sistemas de virtualização como o Virtual Server, uma máquina virtual é um computador x86 abstrato implementado em cima do computador x86 real. Sistemas operacionais e aplicativos utilizam a máquina virtual como se estivesse usando uma máquina real, da mesma forma que utilizam o TCP como se fosse um protocolo confiável, sem tomar conhecimento da complexidade que está ocorrendo abaixo.

Este é o princípio de funcionamento de rookits baseados em hypervisor como o Blue Pill. O rootkit cria uma máquina virtual onde são executados o sistema operacional e as aplicações, sem que eles percebam. A máquina virtual é uma abstração tão perfeita da máquina real que os programas não teriam como saber que estão sendo virtualizados, e que levou Joanna Rutskowska, criadora do rootkit, a declarar que o Blue Pill seria "100% indetectável".

E seria mesmo - enquanto a abstração for perfeita. Mas para azar da Joanna, nenhuma abstração não-trivial é perfeita de acordo com a lei das abstrações do Joel Spolsky. Em determinadas situações a abstração irá "vazar" (leak), e a complexidade existente abaixo irá mostrar sua cara. No caso do TCP, por exemplo, se o primeiro pacote IP com ACK enviado pelo cliente evetualmente se perder, a conexão fica travada e não consegue se recuperar (ou se o link tiver com latência alta a velocidade será limitada pelo receive window) . A abstração falha e o TCP revela que embaixo dele está na verdade o protocolo não confiável IP. No caso de uma abstração complexa como o computador x86 criado pelo Blue Pill, é inevitável que vazamentos como esse serão encontrados: situações onde a máquina virtual revela que é somente uma abstração.

(No caso do filme "Matrix", os vazamentos seriam os déjà vu)

Detectar o Blue Pill é então encontrar estes "vazamentos" - descobrir onde a máquna virtual abstrata criada pelo rootkit não se comporta como uma máquina real. Esta é na verdade proposta do desafio feito pelo pessoal da Matasano, que estão apresentando o seu trabalho essa semana na Black Hat. E isto é também o que está por trás da apresentação feita pelo Edgar Barbosa na Syscan deste ano em Cingapura. Ao contrário da Matasano, o Edgar tem acesso ao código do Blue Pill (ele trabalha para a COSEINC, empresa para a qual a Joanna desenvolveu o rootkit), o que torna a sua apresentação ainda mais interessante.

O "vazamento" trivial para detectar um hypervisor é a performance da máquina, já que por mais leve que seja o hypervisor sempre vai criar uma carga adicional no sistema. O problema é que o hypervisor controla também o tempo na máquina virtual e pode mascarar esse efeito. A detecção precisa ser feito usando então algo que não esteja sob o controle do hypervisor, e o Edgar identifica na apresentação três recursos: a TLB, o recurso de branch prediction e o multiprocessamento (SMP). Os dois primeiros são estruturas internas de cache do processador (TLB de memória, branch prediction de instruções) que são afetados pelas instruções executadas pelo hypervisor, o que causa uma pequena mudança de performance que este não consegue mascarar.

O SMP é método mais interessante. Se o Blue Pill consegue mascarar o tempo em um processador, a solução é criar o seu próprio contador, usando um outro processador do sistema que não esteja executando o código do Blue Pill. Este contador serve como fonte de tempo para detectar que algo está rodando e consumindo CPU naquele processador, indicando a presença de um hypervisor.

Outra forma de detectar o Blue Pill é encontrar um bug no processador que só se manifeste na presença de um hypervisor. Na apresentação Edgar aponta um bug destes no processador AMD, uma instrução que trava a máquina somente se um hypervisor estiver rodando. Edgar diz que isso não teria muito uso fora de ambiente de testes por causa do travamento, mas eu discordo - a maior parte das organizações que eu conheço preferem que o sistema caia a que ele continue rodando com um rootkit, e na verdade várias das ferramentas de detecção de rootkits que usamos internamente são "destrutivas" desta forma. Assim, espero que a AMD não conserte o bug!

A Joanna certamente conhece esses mecanismos, tanto que colocou como condições para aceitar o desafio que a detecção não envolvesse alto uso de CPU (inviabilizando o método de SMP) e não travasse o sistema (inviabilizando o uso de bugs no processador). As condições no entanto sepultam na prática a história do "100% indetectável". Rootkits usando hypervisors são detectáveis e sempre vão ser - assim diz a lei.

UPDATE: Joanna Rutkowksa fez a sua apresentação na Black Hat 2007 e divulgou o fonte do novo Blue Pill. Meus comentários aqui.