Forense, Redes e MCUs – TCPDump com filtros e expressões

IMG_20160107_225143

Mesmo que você já tenha usado tcpdump, talvez não tenha ido além do essencial. Cito isso porque o essencial muitas vezes é o suficiente para diversas necessidades. Quando fazendo análise em tempo real, é necessário expandir ao máximo as possibilidades e filtros podem omitir informações cruciais e daí se torna ainda mais compreensível a utilização do sniffer com o mínimo possível de filtros. No caso de dados coletados para perícia, pode-se abusar desses filtros e fazer diversas análises diferentes, inclusive para auxiliar na documentação (laudo ou parecer), deixando a informação tão sucinta quanto possível.

Após alguns exemplos e talvez até dicas que você não conhecia, vamos ver um pouco de interceptação utilizando um dispositivo TAP para fazer a escuta do fluxo sem que haja manifestação na rede, então analisar o tráfego gerado entre uma comunicação com um Arduino utilizando ethernet shield e melhorar a comunicação baseando-se nessa análise. Se você ainda não conheceu o produto, poderá ver uma interceptação de um um ethernet shield com Arduino nesse post.

Se tiver interesse no produto, olhe aqui as características e se apaixone.

Trata-se de um dispositivo de escuta de rede multi-propósito e, o propósito depende da área de aplicação. Nesse post vou utilizar o mesmo sketch da interceptação do Arduino, mas vou dar uma simplificada nele para abordar alguns conceitos de rede.

Vou iniciar o assunto pela coleta pericial que é a parte menos complicada por ser a fase inicial. Vamos desde os primeiros conceitos para evitar a nulidade da Cadeia de Custódia.

Concluo afirmando que esse tutorial serve para qualquer sistema operacional que rode tcpdump, bastando mudar o parâmetro da interface, mas para os comandos bash e script recomendo a instalação do cygwin no Windows. Se tiver dúvidas quanto ao nome da interface, use o parâmetro ‘-D’ para identificá-las. Mais abaixo coloquei um exemplo detalhado, você não terá desculpa para não usar essa ferramenta!

Prólogo – Procedimento de coleta pericial

Antecedendo “à peça”, o perito normalmente tem que juntar todas as informações circunstanciais para montar uma linha do tempo em seu parecer ou laudo (dependendo se assistente técnico ou perito sob qualquer designação). Portanto nesse primeiro momento deve-se descrever tudo:

– confirmar a data/hora do computador que fará a coleta (FUNDAMENTAL, senão, adeus perícia)
– data/hora do inicio das operações.
– computador que será utilizado para a coleta (sistema, foto, serial).
– meio (fotos de cabos, conexões, TAP).
– descrição da ferramenta empregada (isso faz-se no momento da composição do documento final).

Todo o processo deve ser gravado SEM MOSTRAR O ROSTO. Antes de iniciar qualquer passo, deve-se dizer em alto e bom som o que será executado:

– “Estou iniciando a interconexão do dispositivo TAP à estrutura de rede”
– “Estou interconectando esse computador ao coletor forense”

Se possível, inicie a gravação do desktop previamente ao inicio do processo:
– “Vou digitar o comando para iniciar a gravação do desktop de forma auxiliar a essa gravação”
– “Vou migrar a aba do terminal para digitar o comando e iniciar a coleta”

Anota-se então a hora do ENTER para o início da coleta.

Antes de seguir, quero recomendar a leitura desse post onde relato um processo bastante agradável e robusto de fazer a gravação do desktop da maneira ideal. Isso é chamado “screencast”. Da forma que exemplifico nesse post, o material ficará rico, por favor, leia-o.

Apenas para concluir essa primeira etapa, gostaria de citar a possibilidade de fazer uma ata notarial, de forma que a coleta venha a ter fé pública certificada por um tabelião. Você pode chamar o tabelião de qualquer cartório para acompanhar o processo descrito e depois ele certifica a autenticidade do processo, mas os detalhes desse procedimento vou deixar para um post escrito pelo Ilmo. Perito Diego Souza.

Daqui em diante o procedimento serve para todos os demais casos.

A coleta deve ser feita em formato bruto

Conhecido tradicionalmente por “modo raw” (ou “crú”, na tradução direta de “raw”), esse formato é obrigatório para que se possa apresentar qualquer dado, evitando assim que haja possibilidade de argumentação quanto a manipulação dos dados coletados, ou insinuações de tendenciosidade que levem a anular a validade dos artefatos coletados em rede.

Especificar interface de rede já seria uma forma de manipulação, mas para não coletar manifestação da interface de loopback, não há problema em excluí-la. Desse modo, o primeiro formato básico do comando tcpdump pode ser:

Isso exibirá todo o conteúdo diretamente na tela (que é conhecido por stdout ou, “saída padrão” de comandos). Mas esse comando não serve para coleta de dados. Você poderia utilizá-lo previamente para verificar se há algum fluxo na rede, ou para certificar se está na máquina correta, mas esses procedimentos já não são ideais.

Para iniciar uma coleta em modo raw, voce pode utilizar o comando:

Utilizando a hora que estou escrevendo esse post por exemplo, resultaria em um arquivo com o seguinte formato:

Isso certamente casará com o horário da filmagem e gravação do desktop.

Como ou quando finalizar o processo de coleta?

Você deverá ter em mente o quanto de dados basta. Se quer coletar por tamanho, por pacotes ou por tempo. Assim, vou exemplificar todas essas formas de fazê-lo.

Coleta por número de pacotes

Você pode determinar um número de pacotes na coleta simplesmente passando o parâmetro ‘-c’:

Após coletar 50 pacotes, o programa se encerra automaticamente.

Tamanho de pacote

Se quiser determinar a coleta por tamanho de pacote, um script shell pode auxiliá-lo a interromper o processo:

– Crie o arquivo tcpdumpMon.sh
– Adicione o seguinte código:

– mude as permissões:

Inicie o tcpdump e esse script em seguida, passando o nome do arquivo como parâmetro. Se a captura de pacotes for muito curta, você pode iniciar o script primeiro colocando um sleep na primeira linha e então:

Se quiser limitar o tamanho do arquivo para que não exceda ao tamanho pretendido, você pode utilizar o parâmetro ‘-C’, assim qualquer valor excedente será escrito para um novo arquivo, que você poderá descartar.

Esse parâmetro tem o propósito de separar em arquivos de tamanho específico, para facilitar a leitura posterior no caso de a captura ser muito grande, o modo de utilização sugerido é paleativo em relação a um limitador de tamanho para um único pacote de dados pretendido.

A libpcap é a responsável pelos recursos contidos nos programas TCPDump e Wireshark. Essa lib oferece uma quantidade realmente considerável de recursos, não vai dar pra exemplificar tudo em um post, mas vou citar os que considero mais importante.

Ctrl+C

O Ctrl+C no shell interrompe o programa imediatamente. Se quiser interromper o programa da maneira mais simples, aí está.

Interrupção por tempo

Suponhamos que queira capturar X segundos ou minutos de dados. Uma maneira simples de fazê-lo é digitar isso em um segundo shell após iniciar o tcpdump (com exemplo de 10 segundos):

Interfaces disponíveis

Logo pensa-se em interfaces ethernet, mas a libpcap oferece captura de dados de outros tipos também. Para ver as disponíveis no sistema, utilize o parâmetro ‘-D’. Esse tutorial está sendo composto utilizando Linux como plataforma base, mas serve para qualquer outro sistema, bastando mudar o parâmetro de interface, cujo nome você identifica com esse parâmetro.

Exibir interfaces
Exibir interfaces

Como você pode ver, dá pra capturar pacotes inclusive do bluetooth. Utilizando o parâmetro ‘-i’ você pode especificar a interface a ser escutada:

Utilizando o parâmetro ‘-e’, você coloca no topo da mensagem o MAC do dispositivo, o que pode ser bastante útil para diversos propósitos. Se estiver querendo monitorar WiFi, é fundamental, mas a vez que salvou minha pele em rede ethernet foi em um CPD em 2006 mais ou menos. Aquela época estava tendo uma epidemia de hardwares utilizando o mesmo MAC e aconteceu justamente de um servidor em uma das redes estar com MAC repetido. Foi a condição mais inesperada, foi necessário análise da camada 7 do modelo OSI e ir descendo até desconfiar de spoofing, mas o caso não podia ser realmente chamado de spoofing, era porquice do fornecedor mesmo. O que acontecia é que os IPs eram diferentes por se tratar de servidores diferentes, mas quando os switches renovavam a tabela ARP a manifestação mais recente entrava na lista e então o outro servidor se tornava indisponível. Analisar pelo MAC ajudou a identificar os IPs que disputavam um espaço na tabela ARP dos switches.

Ver o que está sendo capturado

Não serve para captura forense, mas se estiver coletando dados para qualquer outro tipo de análise que não seja para aplicação judicial, você pode gravar em arquivo enquanto captura com o parâmetro -l:

Selecionar a direção do fluxo

Agora vamos começar a entrar em filtros. Você pode selecionar a direção a escutar utilizando o parâmetro ‘-P’. Mas isso tem mais de uma maneira de fazer. Suponhamos que queira escutar o fluxo de saída do host 172.0.0.15:

Se é fluxo de saída, então quer dizer que a origem é 172.0.0.15. Esse filtro poderia ser aplicado da seguinte maneira:

O mesmo se aplica para ‘-P in’ e ‘dst host’. Também é possível fazer a negativa de uma condição. Olhe que interessante, parece programação em Python:

A expressão é bastante clara, nao é coisa de se decorar, apenas basta entender e não sairá mais de sua memória.

Ler dados gravados do tcpdump

O resultado da gravação em arquivo não é texto plano, portanto para lê-lo você também precisará do tcpdump, mas dessa vez utilizando o parâmetro ‘-r’. O bom de ler a partir de pacotes de dados gravados é que você pode aplicar diferentes tipos de filtros para analisar diferentes situações. Em uma leitura do tráfego em tempo real você fica limitado ao filtro aplicado portanto, sempre que possível, grave os dados em arquivo e faça a análise posteriormente.

Nível de verbosidade

Quanto mais verboso, mais informação se torna disponível. No caso do tcpdump você pode utilizar 3 níveis de verbosidade; de ‘-v’ à ‘-vvv’.

Exibir dados dos pacotes

Para exibir os dados dos pacotes, você tem diversas combinações possíveis (man tcpdump). Eu uso sempre um modo que exibe o valor em hexa e em ASCII. Quando surge alguma dúvida no formato ASCII (por exemplo, um espaço após o último byte legível), eu confiro o valor pelo hexa (à esquerda). Adicionalmente, defino o tamanho da mensagem a ser exibida no pacote. Inicio com um valor cabalístico de 4192 bytes, mas você pode variar para mais ou para menos, a gosto. Para exibir os dados, utilizo ‘-XX’ e para definir o tamanho, utilizo ‘-s4192’.

Sniffing
Sniffing

Expressões

Já mostrei mais acima alguma coisa com expressão. Dá pra ir muito, muito além. Por exemplo, um servidor se comunica com vários outros em um CPD e você está interceptando esse servidor a partir do switch dos servers. O servidor se chama BANANA e você deseja analisar apenas a comunicação dele com PERA e UVA. Você pode compor de várias maneiras, mas vou exemplificar apenas a que parece mais simples:

Perceba que é fácil errar no filtro e o melhor é utilizá-lo a partir da leitura de um arquivo de captura. Isso porque invés de escrever o filtro como acima, você poderia escrever:

Mas nesse caso casariam duas condições diferentes. Uma seria a comunicaçao de BANANA com PERA __ou__ a segunda, apenas tráfego de UVA.

Diversos protocolos diferentes podem estar trafegando e você pode querer apenas tratar protocolo IP. Então basta informar ao tcpdump que o que lhe interessa é apenas pacotes IP:

Se deseja interpretar apenas tráfego através do gateway (supondo final .1), voce pode fazê-lo especificando o gateway e se desejar, as portas pretendidas:

Você pode desejar exibir o tráfego externo, excluindo qualquer comunicação que esteja ocorrendo na rede local. Para tanto:

Ou pode omitir redes paralelas se comunicando através de firewalls, basta utilizar o parâmetro ‘not net’ seguido da rede que deseja excluir da escuta.

Filtrar flags TCP

Você pode querer filtrar por exemplo o início e fim de de uma comunicação (flags SYN e FIN). O comando é um pouco mais elaborado nesse caso, mas não deixa de ser claro:

Ou seja, você informa que quer as flags TCP da escuta e dessas flags o tcpdump deve exibir SYN ou FIN cujo valor da flag seja diferente de 0.

Especificar protocolo TCP ou UDP

Você pode ter hosts diferentes utilizando a mesma porta mas um utiliza TCP e outro UDP. Pra piorar, esses hosts passam por um gateway que faz mascaramento NAT, portanto ambos chegam à escuta com o mesmo IP. Sabendo que seu desejo é escutar a porta 8888 UDP, o comando seria algo como:

Capturar pacotes determinando um tamanho mínimo ou máximo de bytes

Suponhamos que você tenha uma comunicação que envolva diversos pacotes no handshake, mas te interessa especificamente o pacote maior (200 bytes por exemplo), que carrega toda a transação de um determinado evento. Você pode capturar apenas esse tipo de pacote definindo o tamanho pretendido, da seguinte maneira:

A porção ‘ip[2:2]’ se refere ao header do protocolo IP:
headerIPv4-show

Trata-se do Total Lenght, que é o tamanho total do pacote, incluindo o header do protocolo IP.

Exibir comunicação ICMP que não seja do tipo 0 e 8

O comando ping (echo request) utiliza o ICMP tipo 8. Existem diversos tipos no protocolo ICMP e voce pode querer filtrar qualquer comunicação ICMP que não seja ping. Para tal:

Só pra deixar um pouco mais claro, caso você não seja programador; icmp[icmptype] é o valor do tipo ICMP que está trafegando e ‘!= icmp-echo and icmp[icmptype] != icmp-echoreply’ significa que esse valor deve ser diferente do tipo 0 e 8 (echo reply e echo request).

Os 8 bits do header TCP

Você não precisa ser especialista em redes de computadores se não for sua área, mas não é nada mal ao menos conhecer o header do protocolo TCP. Esses 8 bits representam as flags da comunicação

Quando você lê os dados de uma linha da escuta, lá estará a respectiva flag:

dobitaobyte sniffing
dobitaobyte sniffing

Como você pode ver nessa mensagem, o inicio mostra o timestamp e indica TTL (Time To Live), a flag DF (Don’t Fragment), diz que é um protocolo TCP (6) e seu tamanho. Ou seja, no começo da linha já existem muitas informações importantes para identificar o comportamento da comunicação.

Já na segunda linha você vê a comunicação com origem 192.168.1.230 (com porta dinâmica estabelecedo comunicação HTTP com o host 186.202.183.65). A flag é [P.], ou, confirmação de PUSH, que significa dados sendo empurrados na comunicação. Veja a sequência, que vai de 1 a 1305, com ACK 1, ou seja, um pacote reconhecido como original. No final da linha o lenght indica o tamanho do pacote transferido: 1305 bytes, ou seja, a sequência inteira.

Depois disso está a mensagem, que inicia em 0x0000 e então o resto é interpretação.

Header TCP

Não ache que esse conhecimento é exclusivo de administradores de rede; Peritos necessitam dessa informação para análise e desenvolvedores conseguem desenvolver uma aplicativo de rede melhor se souberem o comportamento da comunicação. Do que discorri até esse ponto, todos os ítens podem ser encontrados no header TCP. Preferi pegar o modelo especificado no manual do TCPDump, mas você acha mais riqueza de detalhes no google, se lhe interessar:

header-tcp4

Esse é o header de um pacote TCP IPv4 (32 bits).

Ler os campos do header TCP

Pode parecer que estamos entrando no primeiro nível da loucura fazendo um filtro assim:

Mas se você der uma olhada a seguir, entenderá a linha. Todos os conceitos foram vistos anteriormente e apenas os relacionados ao acesso dos campos do header através de expressões não foram explicados. Vamos agora aos conceitos.

No 13º octeto do header tem um octeto relacionado às flags. Aqui é bom que você saiba binário, mas vou dar uma explicada rápido de qualquer modo.

syn

Como você pode ver na imagem, estão dispostos os 8 bits relacionadas às flags TCP. Supondo que o filtro comtemple apenas a captura de pacotes que contenham a flag SYN, então deveriamos casar o segundo campo da direita para a esquerda. O valor desse campo portanto é 2¹, que é o valor binário 00000010, que representa o valor decimal 2. Por isso o exemplo ‘tcp[13] == 2’; dizemos aqui para casar o segundo bit do 13º octeto do header TCP.

Você pode especificar pelo nome da flag pretendida também. Para [P] (push) você poderia casar:

Nesse simples caso, o filtro sugere que apenas pacotes cuja flag PUSH esteja assinalada sejam capturados. Pode ser bastante útil se você deseja ignorar qualquer coisa que não sejam dados empurrado de um lado a outro, pois todas as demais flags são ignoradas. Obviamente esse comando tem o propósito de ler a mensagem.

Essas dicas são muito mais do que utilizo nesse video, onde mostro a mudança do comportamento TCP mudando código do sketch do Arduino sem mexer no conteúdo da mensagem, ou seja, vou mandar exatamente a mesma mensagem, modificando o modo que o programa o faz. Acredite, vale muito a pena assistir esse video.

Como você pode ver no video, a redução foi de 45 para 13 pacotes sem modificações na mensagem, uma economia considerável de thoughput e tempo. Se somarmos apenas os bytes do CABEÇALHO IP e devolvessemos os outros 4 sensores do sketch original, teriamos 45*20*5 ou, ~4.5KB a cada 5 segundos do refresh ou, ~54KB por minuto.

Suponhamos que você esteja oferecendo serviço de broker e você tem apenas 100 clientes mandando 10 informes por casa. Nesse caso o resultado seria 54*10*100!

O que acha de trafegar 54MB de dados por minuto? Será que precisa de muita banda? Ah! Precisa sim, muita, mas muita banda, porque se você reparar nesse exemplo hipotético, eu fiz as contas apenas com os bytes do cabeçalho IP; não considerei o cabeçalho TCP, não considerei os dados e não considerei as retransmissões (comum no protocolo TCP). Por isso, se for planejar um produto, tem que planejar a escalabilidade dele senão é fácil colapsar.

Pra finalizar, não seria trivial analisar o fluxo de dados sem uma ferramenta específica e o DWOS TAP realmente facilita essa tarefa sem necessitar de configurações especificas. Se você ainda não adquiriu, aproveite a segunda fase de vendas, ainda praticando o preço abaixo do pretendido até dia 24/01/2016. Acesse o anúncio no Mercado Livre e veja os comentários de quem já o recebeu!

Siga-nos no Do bit Ao Byte no Facebook para ter informações de outros artigos conforme publicados.

Prefere twitter? @DobitAoByte.

Inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Que tal seguir o perfil forense de DWOS no facebook?

Próximo post a caminho!

Comments

comments

Djames Suhanko

Djames Suhanko é Perito Forense Digital. Já atuou com deployer em sistemas de missão critica em diversos países pelo mundão. Programador Shell, Python, C, C++ e Qt, tendo contato com embarcados ( ora profissionalmente, ora por lazer ) desde 2009.

Deixe uma resposta