Ir para conteúdo
  • Cadastre-se
  • Entre para seguir isso  

    Artigos


    Fernando Mercês
    Saudações, leitores do Mente Binária! Hoje me deu vontade de falar sobre uma tarefa que eventualmente preciso fazer na empresa onde trabalho, que é a de verificar as diferenças entre arquivos executáveis, normalmente de Windows, também conhecidos por executáveis PE.
    Há vários usos ao comparar binários. É possível avaliar o que mudou na versão atual de um software em relação à anterior, descobrir o que muda em cada sample diferente de uma mesma família de malware, etc. Esses dias mesmo me foi pedido que verificasse a diferença entre 6 arquivos maliciosos, que compartilho abaixo como fiz.
    Reconhecimento básico
    Os arquivos que recebi tinham seu hash SHA-256 como nome. A primeira coisa que fiz foi checar seu tipo (usando comandos do macOS, mas o Linux tem comandos similares):
    $ file * fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04: PE32 executable (GUI) Intel 80386, for MS Windows fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9: PE32 executable (GUI) Intel 80386, for MS Windows fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05: PE32 executable (GUI) Intel 80386, for MS Windows ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd: PE32 executable (GUI) Intel 80386, for MS Windows ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640: PE32 executable (GUI) Intel 80386, for MS Windows ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e: PE32 executable (GUI) Intel 80386, for MS Windows Só para garantir, também chequei o SHA-256 deles e realmente bateu com o nome, o que era esperado:
    $ shasum -a256 * fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e PS.: No Linux o comando seria sha256sum ao invés de shasum -a256.
    O próximo passo foi checar o tamanho deles:
    $ wc -c * 396973 fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 396973 fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 396973 fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 396973 ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd 396973 ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 396973 ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e 2381838 total Aqui apresentou-se um caso atípico: os binários possuem exatamente o mesmo tamanho! Já pensei que havia grandes chances de as diferenças entre eles serem mínimas: provavelmente algo usado pelo autor do malware só para "mudar o hash" na tentativa de evitar que os antivírus detectem os arquivos idênticos, por exemplo. Essa tentativa é na verdade frustrada visto que, ao contrário do que muitos pensam, os antivírus não detectam malware por hash normalmente, já que isso seria muito custoso do ponto de vista do desempenho (seria preciso ler todos os bytes do arquivo!) e também seria muito fácil tornar um novo arquivo indetectável - bastaria alterar um único byte para um hash final completamente diferente.
    Comparação de estrutura
    Se estivéssemos tratando arquivos de texto, poderia simplesmente usar o comando diff, mas o assunto aqui é PE, então algo interessante de verificar é sua estrutura, que consiste basicamente em cabeçalhos, localizados antes das seções. Se você não sabe do que estou falando, recomendo os seguintes recursos:
    Posts do @Leandro Fróes sobre o formato PE e suas referências. Capítulo sobre PE do livro Fundamentos de Engenharia Reversa. Aulas 5 e 6 do CERO, nosso Curso de Engenharia Reversa Online em vídeo. Digitar "PE executable" no Google ler o que curtir. Depois dessa imersão no mundo dos executáveis PE, não tenho dúvidas de que você vai se apaixonar por eles também! 😍
    Voltando à comparação, o que eu quero dizer com estrutura? Bem, os valores dos campos dos cabeçalhos. Por exemplo, para ver o cabeçalho COFF de um arquivo PE, usei o readpe, parte do kit de ferramentas pev:
    $ readpe -h coff fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 COFF/File header Machine: 0x14c IMAGE_FILE_MACHINE_I386 Number of sections: 5 Date/time stamp: 1401620468 (Sun, 01 Jun 2014 11:01:08 UTC) Symbol Table offset: 0 Number of symbols: 0 Size of optional header: 0xe0 Characteristics: 0x102 Characteristics names IMAGE_FILE_EXECUTABLE_IMAGE IMAGE_FILE_32BIT_MACHINE Mas não, não usei o pev por saudosismo! A ideia de ter uma saída em texto da estrutura desses binários é depois usar o comando diff para compará-las. A primeira coisa que precisei então foi gerar um .txt contendo toda a estrutura, e não só o cabeçalho COFF, para cada um dos arquivos. Uma repetição em bash dá conta do recado:
    $ ls -1 readpe_output_* readpe_output_fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04.txt readpe_output_fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9.txt readpe_output_fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05.txt readpe_output_ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd.txt readpe_output_ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640.txt readpe_output_ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e.txt Eu usei o readpe sem nenhuma opção, assim ele imprime todos os cabeçalhos, incluindo os de seções. Só pra começar fiz um diff do primeiro para o segundo e não houve qualquer saída, ou seja, a estrutura dos arquivos eram idênticas! E eram mesmo:
    $ wc -c readpe_output_* 21627 readpe_output_fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04.txt 21627 readpe_output_fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9.txt 21627 readpe_output_fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05.txt 21627 readpe_output_ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd.txt 21627 readpe_output_ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640.txt 21627 readpe_output_ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e.txt 129762 total $ md5 !$ md5 readpe_output_* MD5 (readpe_output_fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640.txt) = 05b36b89b1165b3d619bee16f8a1d7f7 MD5 (readpe_output_ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e.txt) = 05b36b89b1165b3d619bee16f8a1d7f7
    Os hashes MD5 da saída em texto da estrutura de todos os arquivos batem. Eles são mesmo iguais estruturalmente!
    Passado o choque, percebi que teria que comparar o conteúdo das seções (código, dados, talvez resources, etc). Aí fui obrigado a inicializar minha VM do Janelas mesmo...
    Comparação do conteúdo das seções
    Existem alguns softwares que trabalham com PE e possuem funções de comparação de dois executáveis. Eu costumava usar o Cold Fusion (um antigo gerador de patch) pra isso, mas ele tem alguns bugs que me impediram. Achei a mesma função no Stud_PE, mas ele localiza arquivos por extensão na janela de comparação, então renomeei o primeiro e o segundo arquivo que tinha para a.exe e b.exe respectivamente.
    Ao abrir o a.exe no Stud_PE, usei o botão "File Compare", selecionei o método "Binary", setei o "Starting from" pra "Raw" e cliquei em "Compare":

    Se você não entendeu por que fiz isso, volte uma casa ou leia os tutorias de PE que indiquei. Ou pergunte que eu falo. 😍
    Bem, entre esses dois caras então havia 9 bytes que o diferenciavam e eu já tinha os offsets a partir do início do arquivo. Agora é descobrir em que seção eles estavam no PE, o que são, o que comem e como eles vivem. 😎
    Descobrindo como as diferenças são usadas
    Abri o executável no x64dbg (na verdade no x32dbg, já que este binário é de 32-bits) mas percebi que o entrypoint estava no endereço 013706AA. Como o ImageBase deste binário é 00400000, percebi que o ASLR estava habilitado e, antes de continuar , desabilitei-o com o DIE, como mostro neste vídeo rápido no canal Papo Binário:
    Antes de reabrir o binário no x32dbg, convém lembrar que eu tinha um offset e precisava convertê-lo para endereço virtual (VA). Isso é feito com o que alguns analisadores de PE chamam de FLC (File Location Calculator). O DIE tem, o Stud_PE tem e o pev também tem, com a ferramenta ofs2rva:
    $ ofs2rva 0x4c451 a.exe 0x4dc51 Mas pra não você não me acusar de saudosismo de novo, vou mostrar no Stud_PE 😄

    Percebe que o Stud_PE já diz que este byte pertence à seção .rdata, o que à esta altura você já sabe, caso tenha feito o trabalho de casa de estudo do PE, que é provavelmente uma seção de dados somente-leitura, então há grandes chances de nossa sequência diferentona pertencer à uma string constante, por exemplo. Fui ver no debugger como é que tava a festa. Abri o a.exe lá e dei um Ctrl+G no Dump pra ir pro endereço 44DC51:

    De fato tinha uma string lá: zuk0KRrGrP, mas ela na verdade começava em 44DC44 e pra saber quando ela era usada no malware, coloquei um breakpoint de hardware no acesso ao byte, que é o primeiro da string e cheguei à conclusão de que, como o nome sugere, é realmente uma string de identificação da campanha do malware, sempre no mesmo offset (calculei de novo usando FLC).  Agora foi só ver a dos outros e novamente recorri à uma ferramenta do pev (💚), a pestr:
    $ for i in *; do echo $i; pestr -so $i | grep 0x4c444; echo; done fdba340bb35635934aa43b4bddd11df31f2204e73394b59756931aa2f7f59e04 0x4c444 .rdata identifierStrzuk0KRrGrP fdf3060eb9c39b1a2be168b1ac52c2f80171394e73fe03c4e0c57911cb9358a9 0x4c444 .rdata identifierStrAR0U4hr1wW fedf9d9815b3d0ad28e62f99d5dcf92ec0f5fcb90135b4bdc30bb5709ab9ff05 0x4c444 .rdata identifierStrswEYVkFWeg ff2f1be6f64c91fa0a144cbc3c49f1970ba8107599d5c66d494ffb5550b0f7fd 0x4c444 .rdata identifierStrKXaUzlBDIj ff53c7ba285ffdc2c29683bb79bb239ea59b3532f8b146523adf24d6d61fc640 0x4c444 .rdata identifierStrv91TJ5c3Lr ffee504e292a9f3ae6c439736881ebb314c05eac8b73d8b9c7a5a33605be658e 0x4c444 .rdata identifierStrOzJnvFQy2U Bom, daí o céu é o limite. Dá pra criar assinatura, criar um script pra extrair esse ID da campanha, enfim, missão cumprida.

    FAQ
    1. Por que você não utilizou só um comparador de arquivos qualquer, que compara os bytes em hexadecimal?
    Eu queria saber exatamente onde estavam as diferenças entre os arquivos, se na estrutura ou não. Em caso negativo, é código? Se sim, que código? Que faz o que? São dados? Usados onde? Em qual seção? Um editor hexadecimal ignorantão não me daria isso. Além disso, se os arquivos fossem diferente estruturalmente, ou em tamanho, eu queria saber antes, pra não perder tempo analisando diferenças de bytes hexa que eu não sei o que é.
    2. Existem softwares para comparar binários PE muito mais poderosos, como o BinDiff. Por que caralhas você não o usou?
    O BinDiff é pra comparar código. Minha diferença estava nos dados. Além disso, o BinDiff e seus amigos traduzem o Assembly original do binário para uma linguagem intermediária própria e comparam lógica, não instruções. É bem fodão, mas não me atendia neste caso, afinal eu já sabia que os binários eram idênticos em funcionalidade. Só queria saber onde estava a diferença exata.
    3. Percebi pela screenshot do Stud_PE que ele também compara a estrutura dos arquivos PE, então todo aquele processo com o readpe foi à toa?
    Sim, foi só pra Inglês ver. Não, brincadeira! O Stud_PE compara os cabeçalhos COFF, Optional e os diretórios de dados somente. O readpe imprime todos os cabeçalhos, incluindo todas as seções mais os imports. É outro nível, moleque! 😏

    4. E quanto à executáveis ELF?
    O título não fala somente de PE propositalmente, já que a mesma técnica pode ser usada para arquivos ELF, só mudando os programas (readelf, etc).
    Por hora é só. Se você deixar sua análise abaixo ou quiser fazer um comentário/pergunta, ficarei muito grato. Considera apoiar a gente também vai. 💚

    Leandro Fróes
    Após ver sobre o comando find no nosso canal Papo Binário decidi estudar um pouco mais sobre o mesmo. Revisando estas anotações pensei que seria interessante compartilhá-las, tendo em vista que o find é um comando extremamente poderoso. Alguns dos parâmetros já foram abordados no vídeo, mas vou repassar alguns aqui, não custa nada, não é mesmo?!
    Este comando pode ser útil para diversas tarefas, dentre elas investigação, administração ou mesmo aprendizado sobre o sistema.
    Indo direto ao ponto, o find é um comando para procurar itens no filesystem (arquivos, links, diretórios, etc). O que o difere de outros programas que fazem isto é a quantidade de opções que a ferramenta possui e o fato de não depender da variável $PATH para encontrar um binário. O comando leva como principal parâmetro um path, ou seja, um caminho para procurar algo. Se não passarmos nada ele entenderá que o path é o diretório atual:
    find find /etc Se não especificarmos exatamente o que queremos buscar o find simplesmente nos mostra tudo o que achar pois ele varre o filesystem recursivamente na hora de procurar algo, mas não queremos isso tudo, até porque não seria muito útil. 🙄
    Vamos tentar entender alguns filtros interessantes... Imagine que você é um administrador e precisa verificar todos os arquivos que pertencem a um usuário em específico:
    find / -type f -user leandro O que fizemos aqui? Utilizamos 2 tipos de filtros, um deles foi o -user, que busca arquivos que pertencem apenas à aquele usuário. O -type filtra pelo tipo de item no filesystem e suporta os seguintes tipos:
    d -> diretório f -> arquivo regular l -> link simbólico s -> socket     Procurando por arquivos perdidos:   Imagine agora que seu sistema está uma bagunça e você não faz ideia onde está um arquivo em específico, pense que você tem no mínimo 8 subdiretórios lotados de arquivos e você não lembra onde está o que você está procurando, só lembra que existe a palavra "mentebinaria" no nome dele. Além disso, você também sabe que não está nos primeiros 2 subdiretórios. Podemos resolver com: find . -mindepth 2 -name "*mentebinaria*" -type f A primeira coisa que fizemos foi utilizar a opção -mindepth, que especifica quantos níveis na hierarquia o find deve olhar no mínimo (a opção -maxdepth especifica o máximo). A outra opção foi a -name, que procura por um nome completo ou parte dele como fizemos no exemplo utilizando o wildcard * (asterisco) para bater com qualquer string antes de depois da palavra "mentebinaria".   Executando comandos:
    Na minha opinião uma das opções mais interessantes do find é a -exec, que praticamente executa comandos em cima do que o find encontrar. Não entendeu? Vamos lá... supondo que queiramos ver qual o tipo de arquivo de todos os arquivo que encontrarmos em um diretório em específico com o comando file:
    find . -type f -exec file {} \; Temos muita coisa pra entender nesta linha. Primeiro, o -exec trabalha com o conceito de targets (as chaves {} ) e isto significa: coloque tudo o que o find devolver no local da chave. Para cada arquivo que o find achar ele rodará o comando file naquele arquivo. Incrível, não?
    Sim, mas com isto estaremos executanto o mesmo comandos múltiplas vezes, por exemplo:
    leandro@teste:~$ find . -type f | wc -l 295 Imagine rodar isto 295 vezes, muita coisa, não? Se notarmos no primeiro exemplo do -exec vemos que no fim da linha tem um ponto de vírgula e este indica o fim do -exec para o find (e não para o shell). Temos que usar a contra barra para escapar e o shell não pensar que é para ele.
    Ok, mas até agora não vimos como melhorar isto. Concordam que o comando file aceita mais de um parâmetro?
    file arq1 arq2 arq3 E se pudéssemos pegar tudo que o find achar e, ao invés de rodar um comando do -exec por vez passamos tudo um atrás do outro? É exatamente isto o que o + faz e para ele não precisamos escapar:
    find . -type f -exec file {} + Este exemplo é a mesma coisa do anterior, mas de forma mais automatizada. Vamos medir a velocidade dos dois comandos:
    root@teste:~# time find / -type l -exec file {} \; ... real 0m15,127s user 0m0,336s sys 0m1,640s root@teste:~# time find / -type l -exec file {} + ... real 0m1,119s user 0m0,212s sys 0m0,396s Bem mais rápido com o +, não acham? 😉
     
    Investigando o sistema:
    Seu servidor foi atacado, você não sabe exatamente o que aconteceu e como aconteceu, só sabe que nem tudo está funcionando do jeito que deveria. Uma coisa interessante à se fazer é tentar olhar para o que exatamente foi alterado desde o ataque. Imagine que isto ocorreu à 2 dias: find / -mtime -2 Aqui estamos dizendo que a partir da hora que rodarmos o comando olhar para tudo que foi modificado 48 horas atrás. Podemos também verificar se algo foi acessado com -atime.
    E se você não sabe exatamente quando foi o ataque? A única coisa que você sabe é que a última coisa que você fez foi adicionar novas funcionalidades à um script que você tem. Podemos procurar por tudo que foi modificado após este arquivo com a opção -newer:
    find /etc -newer <arquivo_velho> Mas como isto? O Linux guarda um tipo de informação chamada MAC no inode de cada arquivo, resumindo é simplesmente a data da última modificação, acesso e criação do arquivo ao qual aquele inode se refere. Apenas como curiosidade, o comando stat lê essas informações também. 😋
     
    Mais algumas informações:
    Ok, agora você não teve nenhum problema, só quer algumas informações sobre os arquivos que o find encontrar. A opção -size <n> pode ajudar a procurar por arquivos maiores (+) ou menores (-) que o especificado:
    find /var -size +20k Podemos trabalhar com os seguintes formatos:
    c -> bytes k -> KB 0 ou -empty -> vazio find . -empty Não está satisfeito? Ok, a opção -ls ti da muito mais informações (praticamente aplica um ls -lids em cima de tudo que o find achar)
    find . -user leandro -type d -ls  
    Facilitando o parsing:
    Achou as opções de informações fracas? De fato a saída fica bem poluída. E se você precisasse todo dia monitorar informações específicas sobre arquivos específicos e criasse um script para isso, como você faria para obter estas informações? O find ti ajuda nisso também!!! Se você está familiarizado com a linguagem C (se não está veja isto) a função printf do C pode imprimir uma saída formatada de acordo com o que você escolher (string, inteiro, inteiro sem sinal, etc).
    Assim como em C, a opção -printf possui uma série de diretivas para formatarmos a saída do find como quisermos, algumas delas são:
    %f -> nome do arquivo %p -> path completo %i -> inode %M -> permissões %n -> número de hard links find / -type f -atime -1 -printf '%p %i %M \n' O único detalhe aqui é que por padrão o -printf não coloca um caractere de nova linha, devemos adicionar como no exemplo. Com isto a saída fica bem mais interesante para um script ler, não acham?! Aqui está o exemplo de uma saída:
    file1 262295 -rw-r--r-- file2 262283 -rw-r--r-- file3 262296 -rw-r--r-- Estas foram algumas dicas sobre o comando find. Com certeza informações mais completas podem ser encontradas no manual do comando, este tutorial tem como objetivo simplesmente compartilhar minhas anotações sobre o que acho bem interessante e usual sobre o comando find.
    Qualquer dúvida, crítica ou sugestão, por favor, sinta-se à vontade para comentar e obrigado! 😄

    barbieauglend
    No artigo anterior, discutimos como encontrar informações importantes para se comunicar com seu dispositivo. Neste, vamos falar sobre uma abordagem genérica antes de reverter o código do firmware de fato.
    Objetivos
    A coisa mais importante durante o processo a partir de agora  é saber quais perguntas você quer responder. Se você começa a querer entender tudo, sem focar, no final acaba perdido numa montanha de informações sem sentido.
    Dê uma de Jack, O Estripador clássico: entenda tudo, mas por partes. Eu normalmente começo procurando o protocolo de comunicação no caso dele não estar documentado. Após isso quero entender geralmente o algoritmo usado para autenticação ou o gerador de senhas ou algo que me dê acesso a dados interessantes que possam ser usados em outros $hardware iguais. Normalmente a segurança de sistemas embarcados não é muito boa nisso: todos os hardware precisam de alguma forma de identificação única presente no firmware. Como você solucionaria o problema pensando em larga escala?
    Conversando com o seu $sistema
    A melhor parte e o principal diferencial da análise de hardware é ter o bare metal (o equipamento físico) nas suas mãos. Ter acesso aos sinais eletrônicos, poder medir frequências e VER como o sistema trabalha (adicionar LEDs em todos os circuitos possíveis e adaptar a frequência por exemplo, sempre lindo!) são coisas que fazem o coração palpitar bem mais do que algumas linhas de código. Acredite 😉 Sem muita informação prévia e com alguns equipamentos baratos, é possível obter dados interessantes para a análise. Poderíamos começar a controlar o tráfego de dados usando o analisadores lógicos simples e ao mesmo tempo podemos usar equipamentos mais avançados para medir o consumo de energia no processo de inicialização do hardware com tanta precisão, que poderíamos deduzir possíveis valores de chaves privadas - é pura ciência, física 💚 - e claro que funciona em condições ideais, como aprendemos na escola.
    Fluxo de dados na PCB
    Não adianta muito ter dados se você não pode ler, escrever ou transferi-los de alguma maneira. Olhar a placa deve ser suficiente para entender como o fluxo de dados ocorre, simplesmente pensando na posição do CI (Circuito Integrado) e das marcas na PCB, ou seja, na placa. Outra coisa importante: quase todas as plaquinhas têm uma datasheet voando na !nternetz e acessível publicamente, contendo toda a informação técnica (da pinagem, voltagem e o PROTOCOLO DE COMUNICAÇÃO). Sempre vale a pena usar o DuckDuckGo antes de começar a ter dores de cabeça por algo que esta documentado, certo?
    Vamos começar sem gastar muito $$$:
    Procure a fonte!
    Quem esta começando agora pode não ter todas as ferramentas disponíveis ou não ter acesso a uma oficina / laboratório. Por isso, vamos dump o código direto do hardware e abrir mao do contexto - que teríamos no caso da leitura dos dados no hardware - mas economizaremos dinheiro e teremos acesso a toda informação possível do $device. 
    Acesso ao firmware e memória
    Dumpe o código do CI e o descomprima. Essa é a parte mais fácil e mais difícil de todo o processo, mas para isso você não precisa de nenhum equipamento e pode usar várias ferramentas de graça (algumas inclusive de código aberto).
    Como eu falei anteriormente, é possível achar na Internet os datasheets (documentação completa, normalmente em PDF) de quase todos os dispositivos. Ache a datasheet para o seu CI e assim não terá necessidade nem de identificar a pinagem nem de reverter o conjunto de instruções necessárias para a comunicação. Algo também importante é saber como parar a comunicação entre o seu CI e os outros pontos de comunicação da placa, pois isso pode interferir na leitura dos dados. Como interromper o fluxo de dados depende bastante do circuito que você esta analizando.
    Mas eu preciso desoldar?
    Esse seria o caminho mais óbvio certo? Não quer interferência, desconecte seu CI da placa e vai para o abraço. Esse método te dá controle total sobre o seu CI 🙂 O problema aqui é que esse processo requer experiencia e TEMPO.
    A ideia deste artigo é para ser algo mais simples e barato, então tente evitar essa situação e pense em ideias mais "criativas". Normalmente é possível conectar os dispositivos num osciloscópio ou voltímetro para monitorar e ter certeza que não há interferência dos sinais de cada pino do CI. Fique atento nos outros componentes, se algum tráfego de dados está ocorrendo (instale por exemplo um monitor na outra porta UART). Se algum tráfego ocorrer, daí não tem outro jeito a não ser desconectar o seu CI - use um fim de semana. 🙂
    Assim que o seu CI estiver isolado, conecte ele a qualquer aparelho que "fale" o mesmo protocolo e comece a ler a memória bloco por bloco. Isso pode demorar, por isso aconselho quando começar a leitura, vá a cozinha e faça um café! 🙂
    Dumping os dados
    Criar suas próprias ferramentas pode ser super divertido, mas custa tempo e é bem mais fácil quando você sabe o que está procurando. Por enquanto, podemos usar vários projetos de código aberto disponíveis:
    Para fazer o dump, flashrom é uma das ferramentas populares. É facil de usar, cheia de bugs mas tem suporte para várias arquiteturas diferentes. Funciona muito bem no Rasperry Pi. 🙂
    Normalmente vale a pena usar o comando file para ter uma ideia do tipo de arquivo que você esta lidando. Se ele não te ajudar em nada, tem o famoso binwalk.
    Os logs do binwalk the darão os endereços importantes. Então agora podemos usar o dd e dividir o seu binário em segmentos específicos. O comando dd precisa dos parâmetros bs (block size), do skip (offset) e o count (que aqui signifca quantos blocos você tem/quer copiar). Normalmente você terá pelo menos 3 blocos:
    O bootloader.bin: geralmente não esta criptografado pelo fato do microcontrolador não poder descriptografar. O mainkernel.bin: se você tiver sorte será algum kernel Linux. Esse é o firmware que controla o bare metal. 🙂 Geralmente o mais divertido de ler e várias vezes comprimido - use o file novamente para saber como descomprimir. O mainrootfs.bin: para quem entende um pouco de Linux e sistemas BSD, esse é o sistema de arquivos, contendo todos os arquivos com configurações, os binários do sistema, etc. Use novamente o file para verificar se está comprimido. No caso da imagem estar criptografada, é possível quebrá-la utilizando o fcrackzip. 
    No próximo artigo eu vou tentar entrar em detalhes desses três binários - vamos ver se eu acho algum hardware interessante. 🙂

    sfigueiredoit
    Ataques cibernéticos estão cada vez mais presentes no nosso dia-a-dia, sendo assim, as empresas devem fortalecer seus mecanismos de defesa e capacitar seus usuários para que informação privilegiada não caia nas mãos erradas.
    Depois do acesso remoto aberto para a internet, justificar o orçamento para diretoria é o problema mais comum de 9 a cada 10 profissionais da área de segurança. Essa dificuldade muitas vezes está relacionada à falta de um planejamento ou estratégia que justifique o projeto, a diretoria precisa enxergar retorno ou resultado palpável que aquela despesa vai trazer.
    Ai você se pergunta: Como eu vou construir defesas, se não tenho orçamento?
    O primeiro passo é entender que nem todo mecanismo de defesa consiste na aquisição de uma ferramenta ou despesa financeira. Uma mudança de processo e otimização no uso de recursos que já estão implementados, na maioria das vezes, trás um retorno bem legal.
    Para te ajudar nessa jornada, alguns frameworks foram desenvolvidos com estratégias para que você, como profissional de segurança da informação, possa elaborar um plano bem definido e endereçar de forma estruturada as demandas de sua companhia. Neste artigo, vou te apresentar três frameworks  que são amplamente utilizados pelo mercado e ao final compartilho minha experiência sobre a adoção destes modelos.
    Familia de normas ISO 27000 As normas da família ISO/IEC 27000, podendo citar como as mais conhecidas as ISO 27001 e ISO 27002, estão diretamente relacionadas à segurança de dados digitais e sistemas de armazenamento eletrônico.
    Como destaque, posso indicar a ISO/IEC 27032 que literalmente oferece um guia de como estruturar sua operação em quesitos como segurança da informação e segurança de redes.
    Nesta norma, você também encontra uma literatura bacana sobre o relacionamento da área de segurança com o restante dos setores da companhia e te apresenta dicas bacanas de como trazer a nossa matéria para realidade do restante da galera.
    Conteúdo complementar: http://abntcatalogo.com.br/norma.aspx?ID=91527
    NIST Cybersecurity Framework Este framework é bastante reconhecido nos Estados Unidos pela sua presença em empresas públicas e privadas. Para equipes pequenas, pode ser complicado implementar seus controles devido à complexidade considerada no momento de sua concepção.
    O core deste framework é organizados em etapas, executadas de forma sequencial para estabelecer um ciclo de vida para as operações relacionadas a segurança. As etapas são: Identificar, Proteger, Detectar, Responder e Recuperar.
    Conteúdo complementar:  https://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.04162018.pdf
    COBIT A Associação de Auditoria e Controle de Segurança da Informação (ISACA), produziu uma estrutura de controles para a tecnologia da Informação, o COBIT. Em sua revisão mais recente ele evoluiu para abordar as melhores práticas buscando alinhar funções, processos e tecnologia à estratégia de negócios.
    Apesar deste framework não ser diretamente ligado a segurança da informação, perceba o link entre o problema exposto na introdução deste artigo e o objetivo final do COBIT. Os investimentos de segurança só fazem sentido se minimizam riscos de negócio, independentemente se estão atrelados à correção de uma vulnerabilidade técnica ou conscientização de usuários. Estabelecer estes links é fundamental.
    Conteúdo complementar: http://www.isaca.org/COBIT/Pages/default.aspx
    Conclusão
    Logo de cara, depois de pesquisar um pouco melhor, você vai pensar.. Putz! É coisa para caramba.
    Quando estamos aprendendo assuntos de viés mais técnico, é um grande erro tentar atacar todos as materáis ou tecnologias de uma só vez, com gestão não é diferente.  
    No inicio é importante elaborar um plano de estudo e aos poucos entender qual é a função de cada um destes frameworks na estratégia de segurança.
    Não encare a documentação como uma receita de bolo, mas sim como um mapa que vai te ensinar percorrer o caminho de pedras.
    Ter um norte a seguir, facilita a caminhada.
    Grande abraço e até o próximo artigo!

    barbieauglend
    barbie's hardware 101
    Primeiro passo: Procure por portas de Debug
        
    Na verdade, esse deveria ser o passo zero, já que a primeira coisa que devemos fazer antes de começar qualquer outra coisa é dar uma boa olhada no hardware que você tem na mão.
    Nesse processo, faça uma lista das portas físicas que você tem acesso, conte os pinos que você vê, etc. O seu foco aqui é achar a porta de debug que geralmente é deixada na placa para reparos e suporte técnico.
    Essa porta está disponível em qualquer dispositivo (estamos falando de sistemas embarcados), ou seja, as queridas impressoras, câmeras de segurança, a torradeira no canto da cozinha, o roteador, etc. Outro fato importante: todo dispositivo mais complexo é um pouco mais fácil, pois estará provavelmente usando alguma versão do kernel Linux (que é open source :D). Se você não ver nenhuma porta de Debug diretamente, não desista. Muitas vezes elas estão um pouco escondidas e você terá que abrir o aparelho ou até romper algum lacre. 😉
    As portas de debug são normalmente do tipo serial, UART, possuem de 4 a 6 pinos, e são literalmente desenhadas na placa. Sim, na PCB (placa) geralmente há uma marcação para a porta de debug, contornada, esperando para ser achada. 🙂 Como elas são feitas para o suporte técnico usar, elas não são cobertas, não tem um plug bonitinho esperando por você... Os conectores ou as ilhas (os buraquinhos na placa onde os fios ou terminais de componentes são soldados) vão estar soltos, sem proteção e não estarão conectados a lugar nenhum no dispositivo.
    Aqui o exemplo da placa do roteador FritzBox 4020:

    Localize as ilhas/conectores que não estão em uso e solde os pinos. Se a sua placa tem mais do que um CI (Circuito integrado), procure pelo principal e solde os pinos na porta que esta conectada a ele (geralmente a parte mais interessante está rodando lá de qualquer maneira!). Eu prefiro sempre soldar pinos para que fique mais fácil o acesso.
    Continuando
    É importante entender como o protocolo de transmissão da porta funciona. O protocolo de comunicação UART (Universal Asymchtonous Receiver / Transmitter) difere de outros protocolos de comunicação como o I2C, basicamente por ser um circuito físico do microcontrolador com a única função de transmitir e receber dados de forma serial. A parte boa é que por não ser de propósito geral como o USB, é possível transmitir dados usando apenas dois cabos entre dois dispositivos. Esse tipo de comunicação pode ser chamada de comunicação direta.
    Os dados são transmitidos do pino Tx (transmissor) da origem para o pino Rx (receptor) do destino.
    +-------+                      +-------+
    |                |                       |                |
    |          Tx +--           --> Tx            |
    |                |     `   . .  '         |                |
    |         Rx +-- .  ' `  .  --> Rx            |
    |                |                       |                |
    |      GND +----------+ GND      |
    |                |                       |                |
    +-------+                      +-------+
    Como o próprio nome diz, a transmissão de dados usando o protocolo UART é assíncrona, o que significa que não existe um relógio (sinal de clock) que sincronize os dados de saída do UART de origem com o os dados recebidos pelo UART de destino. Ao invés disso, o UART de origem adiciona bits de sinalização de "início" e  "fim" em cada pacote de dados transmitido. Esses bits irão então definir o começo e o final de um pacote de dados de uma maneira que o UART de destino sabe onde começar e onde terminar a leitura.
    Quando o UART de destino recebe um "bit de início", ele começa a ler os dados recebidos na frequência chamada de baud rate (taxa de transferência). Essa frequência é a velocidade de transmissão de dados em bps (bits por segundo) e os dois UART devem estar operando na mesma frequência (ou com um erro de no máximo 10%) e a estrutura dos dados deve ser a mesma para que a comunicação ocorra sem problemas.
    Achando o output de cada pino:
    Até agora sabemos que as portas seriais possuem entre 4 e 6 pinos. Algo importante é saber que eles operam de acordo com a seguinte especificação ou "pinagem":
    Tx ou Transmitting: esse pino será conectado com o Rx do nosso leitor. Rx ou Receiving: esse pino será conectado com o Tx do nosso leitor. Vcc: POWER \o/ NÃO CONECTE! Geralmente 3.3V ou 5V. GND ou Ground (terra): esse será conectado com o GND do nosso leitor. (DTR e CTS) são dois pinos que não são obrigatórios e normalmente não são necessários. Talvez escreva mais sobre eles na próxima série! 🙂 Tx e Rx possuem o valor 1 / verdadeiro / ligado (por padrão). Proximo passo: Multímetro!
    Claro que você pode simplesmente olhar as conexões desenhadas na sua PCB e usar a técnica da "tentativa & erro", mas dependendo do dispositivo que você está analisando, pode acabar ficando caro 😉 Então o melhor é analisar um pouco mais a sua PCB antes de mandar sinais aleatórios e por fogo em tudo - been there, done that! not fun!
    E não é tão dificil assim 🙂 Geralmente um multímetro simples é o suficiente para nos oferecer a maioria das informações necessárias para dizer quem é quem na nossa plaquinha! Mas é claro que eu nunca direi não a um osciloscópio! 🙂
    O osciloscópio não só nos dá "informações suficientes para deduzir" quem é quem, mas nos mostra exatamente quem é quem, de acordo com as especificações esperadas:
    O pino com valor 0V constante é o GND. O pino com valores constantes 3.3V ou 5V deverá ser o Vcc. Um dos pinos com valor flutuante próximo de 0V deve ser o Rx (faz sentido? Não? Pensa assim, Rx esta "escutando" mas não está conectado a nada ainda!) Yay! Agora que sabemos qual pino é qual, só falta saber a nossa taxa de transferência (baud rate) para montar o nosso leitor. Para descobri-la, a maneira mais facil que conheço é usando um analisador lógico: Conecte seus pinos, ligue (acione) a opção "análise de protocolo" e vai na adivinhação, simplesmente mudando o baud rate até você ver texto na saída de dados serial.
    Tendo o layout dos pinos e a taxa de transferência, nós podemos começar a nos comunicar com o dispositivo. \o/

    l0gan
    Complementando os artigos criados sobre máquina virtual para ambiente Windows e Linux, este tutorial tem como finalidade auxiliar na criação de uma máquina virtual para análise de binários, possivelmente maliciosos, em ambiente macOS. 
    Configurações da Máquina Virtual
    2 processadores (cores). 2GB de RAM. Placa de rede em modo NAT (em casos aonde você realmente precisa de comunicação com um C&C). Placa de rede em modo Host-Only. Compartilhamento de Pastas desativado ou Host-Only (com host local). Aqui vem um ponto interessante: como tenho receio de malwares que detectam o ambiente de virtualização (ex: VMware Fusion) e tentam escapar do guest pro host, rodo sempre o SO guest num SO host diferente. No caso, rodo a máquina virtual com macOS mas o SO host é Linux.
    Sistema Operacional virtual
    10.10.1 (Yosemite) publicado em 2014 10.13.4 (High Sierra) Versão Atual Obs.:  As duas versões do macOS mencionados acima são para demonstrar a tela de configuração do Gatekeeper de cada versão. A importância das versões está nos diferentes tipos de malware  que podem se propagar em versões específicas. No entanto, basta escolher uma.
    O Gatekeeper é um componente de proteção para o macOS existente desde a edição Mountain Lion. A responsabilidade deste constituinte é encontrar a identificação do desenvolvedor (Developer ID, também conhecido como “assinatura de autenticidade”), que é fornecido pela própria Apple. Quando em conformidade, o Gatekeeper mantém-se adormecido até o momento do cujo arquivo executável ou instalador ser flagrado com a assinatura de autenticidade ausente ou por ser reconhecido pela semelhança de algum tipo de malware.
    Uma vez que você utiliza softwares baixados através da App Store e ou assinados pela Apple você já possui uma certa segurança. Tendo consciência que boa parte dos últimos malwares para macOS dependiam que este recurso estivesse desativado, consequentemente, permitindo o download e instalação de qualquer software não identificado.
    Desativando o Gatekeeper

    Imagem 1: versão Yosemite
     No macOS Sierra e posterior a opção “Anywhere” não aparece mais, agora o sistema operacional perguntará para o usuário se ele deseja permitir que o software realmente seja instalado / executado no sistema. Porém há maneira de desabilitar o Gatekeeper e voltar com a opção como mostra na Imagem 1, usando o spctl (SecAssessment system policy security), via Terminal:
    $ sudo spctl --master-disable
    Imagem 2: versão high-sierra
    Outro sistema de segurança é o SIP (System Integrity Protection). Eu ainda não vi nenhuma necessidade de desativar para rodar malware porem caso precisem:
    SIP (proteção de integridade do sistema)
    Clique no menu  Selecione Reiniciar ... Mantenha pressionado o ⌘comando-R para inicializar no sistema de recuperação. Clique no menu Utilitários e selecione Terminal. Digite csrutil disable e pressione Enter. Feche o aplicativo Terminal. Clique no menu  e selecione Reiniciar .... Ferramentas
    No macOS além da própria Apple Store (que com certeza neste caso não terá as principais ferramentas que precisamos), também temos algumas boas fontes de ferramentas. O MacPorts, sistema de pacotes muito utilizado, e também o Homebrew suprem muito bem nossas necessidades quanto aos pacotes.
    Abaixo deixei um lista de ferramentas tanto para análise estática quanto dinâmica, claro que em alguns casos a mesma ferramenta pode ser utilizada em ambos os tipos de análise.
     
    Analise Estática
    xxd                 -> Cria um dump a partir de um binário, parecido com o hexdump.
    strip               -> Remove e ou modifica a tabela de símbolos de um binario.
    hexEdit         -> Editor hexadecimal.
    lipo                 -> Cria ou modifica arquivos multi-arquitetura, na imagem 6 tempos um exemplo da sua funcionalidade.
    otool              -> Exibe informações sobre binários Mach-O (tipo um objdump).
    jtool                -> Versão melhoradas do otool.
    nm                   -> Exibe a tabela de símbolos.
    codesign       -> Usado para criar, verificar e exibir assinaturas de código.
    machOView -> Interface visual para edição de binários mach-o. 
    class-dump -> Usado para examinar informações em tempo de execução do Objective-C armazenadas em arquivos Mach-O.
    dtrace             -> Ferramenta usada para analisar comportamento do Sistema Operacional e dos programas em execução.
    fs_usage       -> Exibe informações sobre chamadas de sistemas, executa rastreamento do kernel e processos, tudo em real-time.
    xattr                 -> Usado para exibir, modificar e ou remover atributos(metadados) de arquivos, diretórios e links simbólicos.
    Analise Dinâmica
    xcode                         -> IDE de desenvolvimento de software oficial da apple, possui recursos internos para testes de perfomance de sistema.
    hopper                      -> Ferramenta usada para disassemble e decompile de arquivos mach-o 32/64bits.
    lldb                             -> Debugger utilizado para depurar programas C, C ++, Objective-C, Objective-C ++ e Swift.
    fseventer                 -> Ferramenta gráfica usada para verificar atividades em disco e execução de processos de forma visual.
    open snoop             -> Usado para rastrear acessos de arquivos, aplicativos, processos e também monitoramento do 
                                              filesystem, você pode utilizar ele em conjunto com o Dtrace.
    activity Monitor    -> Exibe processos que estão sendo executados no macOS.
    procexp                    -> Ferramenta exibe informações acessíveis pelo proc_info para exibição de processos, parecido com o top e htop.
    lsock                          -> Baseado no PF_SYSTEM o lsock e usado para visualização em real time das conexões (Sockets) no sistema, similar ao netstat.
    Por se tratar de máquina virtual para pesquisas em macOS, não poderia deixar de mencionar as ferramentas do pessoal da Objective-See. Vale a pena testar e acompanhar os artigos deles.
     
    Imagem 3: ferramentas objective-see
     Destaco três ferramentas especificas para quem estiver analisando binários do tipo Mach-O:

    Imagem 4: ferramenta otool exibindo o magic number do binário.

    Imagem 5: ferramenta jtool exibindo o endereço da função main() do binário Mach-O
     
    Imagem 6: ferramenta lipo extraindo o suporte a uma arquitetura especifica em binários do tipo fat.
    Considerações finais
    Criar um snapshot da instalação default; Ficar atento: Anti-Disasssembly Anti-Debugging Sistemas de Ofuscação Anti-VM Ficar atento às falhas publicadas  

    AndreAlves
    Um pouco depois das revelaçōes de Edward Snowden sobre monitoração generalizada da internet por entidades governamentais, a IETF (Internet Engineering Taskforce - uma comunidade de gente interessada na engenharia da internet) criou um grupo de trabalho para rever a privacidade do DNS e o nomeou "DPRIVE" - abreviação para DNS Privacy.
    Pensar em jeitos de tornar as resoluçōes deste protocolo tão fundamental menos manipuláveis e mais secretas sem perder muita velocidade é o abacaxi que foi dado a esse grupo, que tem trabalhado bastante e gerado alguns frutos.
    Mais recentemente um deles ficou mais conhecido entre nós quando a Cloudflare lançou um serviço de DNS focado em privacidade e rapidez e anunciou suporte a uma das propostas do IETF para DNS seguro-privado-rápido , o DOH (DNS over HTTPS), que dá nome à este artigo.
    A sacada do DOH é possibilitar queries (consultas) DNS criptografadas (tchau entidades governamentais tentando espionar 👻) que são difíceis de diferenciar de outros tráfegos criptofragados (tchau provedores tentando fazer bandwith throttling ou traffic shaping).
    Mas afinal, como isto funciona?
    Basicamente as queries DNS se tornam um request HTTP do tipo POST ou GET para uma URL definida pelo serviço de DNS. Essas requests são trafegadas dentro de uma sessão TLS e formatadas como JSONs codificados em base64. No JSON temos os campos definindo o tipo do registro a ser consultado (A, CNAME, AAA, etc).
    Para visualizar aqui vai um exemplo de solicitação de uma query para resolver o nome www.exemplo.com usando o método POST, tirado direto do rascunho da RFC:
    :method = POST :scheme = https :authority = dnsserver.example.net :path = /dns-query accept = application/dns-udpwireformat content-type = application/dns-udpwireformat content-length = 33 E o conteúdo de 33 bytes da query:
    00 00 01 00 00 01 00 00 00 00 00 00 03 77 77 77 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 Não é lindo? Sim é. Mas se você quiser usar por enquanto terá que se aventurar. Um dos poucos (único?) navegadores que suporta este recurso é o Firefox em sua versão Nightly (sai um novo release toda noite!). Para configurar, os passos são:
    Digite about:config na barra de endereços e pressione [ENTER]. Altere o valor dos seguintes parâmetros de acordo: netowrk.trr.bootstrapAddress: 1.1.1.1 network.trr.uri: https://mozilla.cloudflare-dns.com/dns-query network.trr.mode: 2 (usa DOH primariamente, mas faz fallback pro DNS atual) Outros projetos utilizando DOH estão surgindo no Github. O DNS-over-HTTPS proxy, por exemplo, cria um proxy de modo que as consultas DNS sejam redirecionadas para o serviço do Google que suporta DOH.
    O mais legal é que a preocupação com privacidade e liberdade individual continuará a resultar em mais projetos como este para salvar nossa internet de quem se acha dono dela. 🙂
    Se você ficou interessado, dá uma pesquisada nos outros candidatos a DNS seguro:
    DNS over TLS (RFC 7858) DNS over DTLS (RFC 8094) DNS over QUIC (ID-draft) DNS over DNSCrypt (independente) DNS over TOR (independente)

    gzn
    Caro leitor, você gosta de desafios? Neste artigo vou contar como resolvi um desafio de engenharia reversa do Shellterlabs, mas sem usar um disassembly!
    Para quem não é acostumado com o termo, de acordo com o grupo CTF-BR!, um CTF (Capture The Flag) nada mais é do que uma competição que envolve diversas áreas mas principalmente as áreas ligadas à segurança da informação. No Papo Binário também há um vídeo sobre o assunto.
    O desafio em questão é o Shellter Hacking Express Acidentalmente. Em sua descrição, há a seguinte frase: Acidentalmente codificamos a chave.
    Isso não diz muita coisa mas ao baixar o binário, percebemos que há dois arquivos:
    tar tf ~/Downloads/e74a74b5-86cf-4cb3-a5bb-18a36ef067cf.tgz RevEng400/ RevEng400/encoder RevEng400/key.enc Usando o comando file, verifiquei de que tipo são os arquivos extraídos:
    cd RevEng400/ $ file * encoder: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.2.5, stripped key.enc: data Ao ver que o encoder é um binário ELF, fui direto analisar seu código num disassembler usando objdump e gdb, mas percebi que o binário não continha os símbolos, o que torna sua análise um pouco mais difícil.
    Sendo iniciante em engenharia reversa e depois de horas analisando a função de cifragem, confesso que fiquei sem saber para onde ir (já viu algum apressadinho tentando aprender a tocar guitarra? Pois é, já quer ir lá tocar aquele solo, e na velocidade Steve Vai, aí não dá né? rs) e desisti, mas não por muito tempo (ei crianças, nunca desistam dos seus sonhos viu! rs), e procurei o nosso querido prof. @Fernando Mercês lá no servidor do Discord, que me deu umas dicas. Segue trecho da conversa:
    > @fernandom @gzn sei que vc ta treinando ER, mas nem precisa disassemblar esse binario pra esse desafio nego > se vc olhar bem, vai ver que a saída do encoder tem o tamanho da string de entrada + o byte 0x03 no final > olhando a chave encodada (key.enc), é razoável admitir que ela tenha 16 caracteres então > você só precisa encontrar qual deles é o 0xef .. um loop com bash mata > supondo que seja o 'A'... então 'A' -> 0xef, aí você vai precisar da letra que gera o 0xf9 e assim sucessivamente, até chegar em 16 Já ouviu a expressão "pensar fora da caixa"? Pois é! Por que eu fui direto disassemblar? Esse é um dos problemas quando nós estamos começando: às vezes a gente acha que o método mais difícil deve ser o único ou o melhor para se resolver problemas, mas nem sempre é assim. Daí pensei: se o Mercês falou que não é muito difícil, vamos ao menos tentar não é?
    Bem, a primeira coisa que fiz foi ver uma maneira de imprimir o conteúdo do binário em hexadecimal. Para isso criei um pequeno script que usa o hexdump para me dar uma saída somente com os bytes em hexadecimal do parâmetro que receber. Chamei o script de hexdump.sh e depois dei permissão de execução nele (chmod +x). Seu conteúdo é o seguinte:
    #!/bin/sh hexdump -v -e '/1 "%02X "' $1 Então comecei os testes:
    for letra in 0 A a; do echo -n "$letra "; ./encoder $letra | ./hexdump.sh; echo; done 0 7F 01 A F7 02 a F7 03 Parece que nem sempre o final é 0x03... Bem, fui verificar o conteúdo do arquivo key.enc e encontrei isso:
    ./hexdump.sh < key.enc EF F9 42 09 A3 1A 43 F7 8C 8B BB 22 2A C2 A3 14 03  Pela lógica, já que essa é a chave codificada, se eu passar a chave correta original em texto como parâmetro para o binário encode ele terá que gerar a sequência acima. Seguindo a dica do Mercês, usei o próprio bash para tentar quebrar o desafio, primeiro mostrando o conteúdo em hexadecimal da chave codificada, depois iterando pelos caracteres possíveis e filtrando pelo primeiro byte dela:
    hexdump.sh < key.enc; echo for ((i=32;i<=126;i++)); do > l=$(printf "\x$(printf "%x" $i)") > echo -n "$l " > ./encoder "$l" | ./hexdump.sh > echo done | grep 'EF' Este código basicamente faz:
    Mostra os bytes em hexadecimal da chave a cada vez que executarmos esse comando (só pra saber qual byte é o próximo). Itera por todos caracteres imprimíveis da tabela ASCII (faixa de 32 à 126 em decimal). Imprime o caractere na tela sem a quebra de linha. Passa essa letra para como argumento para o binário encode e imprime a saída dele em hexadecimal. Por fim, usa o grep para encontrar uma combinação que tenha o próximo byte da chave. Partindo para um exemplo prático, fui tentar encontrar a primeira letra dessa chave, sabendo que sua versão codificada deve resultar no byte 0xEF:
    ./hexdump.sh < key.enc; echo EF F9 42 09 A3 1A 43 F7 8C 8B BB 22 2A C2 A3 14 03  for ((i=32;i<=126;i++)); do > caractere=$(printf "\x$(printf "%x" $i)") > echo -n "$caractere ";./encoder "$l" | ./hexdump > echo done | grep 'EF' " EF 01  B EF 02  b EF 03 Conforme pode ver acima, encontrei três caracteres diferentes que, quando encodados pelo encoder, geram o byte 0xEF: ", B, e b. Escolhi seguir com o B, prefixando-o na chave para dar sequência ao script e ver se encontramos o caractere que resulta no próximo byte da chave codificada (0xF9):
    ./hexdump.sh < key.enc; echo EF F9 42 09 A3 1A 43 F7 8C 8B BB 22 2A C2 A3 14 03  for ((i=32;i<=126;i++)); do > caractere=$(printf "\x$(printf "%x" $i)") > echo -n "B${caractere} " > ./encoder "B$l" | ./hexdump > echo done | grep 'EF F9' % EF F9 01  E EF F9 02  e EF F9 03  Mais uma vez encontrei três opções. Foi só continuar este processo até encontrar a chave que gera os exatos 16 bytes do arquivo key.enc.
    Aproveitei e automatizei um brute forcer com Python:
    #!/usr/bin/env python3 # -*- coding: utf-8 -*- import subprocess def encode(arg): result = subprocess.run(['./encoder', arg], stdout=subprocess.PIPE) return result.stdout def loadKey(): key_enc = [] with open('./key.enc', 'rb') as file: while True: byte = file.read(1) if byte: # a ordem dos bytes aqui não importa (porque trata-se apenas de 1 byte), mas é necessário especificar key_enc.append(int.from_bytes(byte, byteorder='little')) else: break return key_enc def permutations(key='', key_enc=loadKey(), key_i=0): if key_i == len(key_enc) - 1: print(key) return for char in (chr(i) for i in range(32, 127)): result = encode(key + char) if result[key_i] == key_enc[key_i] and key_i < len(key_enc): permutations(key=key + char, key_enc=key_enc, key_i=key_i + 1) def main(): permutations() if __name__ == "__main__": main() Saída codificada em base64 (pra não estragar a brincadeira de quem vai tentar resolver o desafio por conta própria):
    QmV3aXRjaGluZyBTZXh0LwpCZXdpdGNoaW5nIFNleHRPCkJld2l0Y2hpbmcgU2V4dG8K Segue vídeo do canal com a explicação do algortimo de encoding desse desafio: 
     

    Fernando Mercês
    Você gosta de software de código aberto? Gosta quando encontra um programa bem feito, que atende a sua necessidade, sem custo, é atualizado, os desenvolvedores colocam novos recursos, você pode até opinar, sugerir mudanças e várias são aceitas? Saiba que por trás destes milhares de programas livres há um mundo de pessoas que dedicam seu tempo (muitas vezes seu tempo livre) para entregar software de qualidade pra você sem nem te conhecer. Isso é muito louvável. Agora mesmo estou usando o WordPress para escrever este artigo, um software de código aberto. Não paguei nada por ele e ainda modifico da maneira que eu quiser, respeitando sua licença. Não é fantástico isso? Para este artigo motivei-me dos vários programas de código aberto que já vi nascerem e morrerem por falta de apoio, então resolvi escrever um manual de como ajudar a manter os programas que você gosta no ar. Preparado?
    O primeiro passo é entender o que é de código aberto (ou open source). Eu poderia tentar explicar com minhas palavras, mas há um vídeo que literalmente desenhou e explicou com LEGO. Incrível, não? E com legendas em Português do Brasil. Por favor assista, mesmo que você pense que já saiba o que é:

    Se você usa algum software de código aberto (e eu tenho certeza que sim), você pode ajudar com:
    Tradução - Nem todo mundo fala inglês no mundo. É importante que um software socialmente viável seja acessível e você pode contribuir com isso ajudando a traduzir as novas versões para sua língua nativa.
    Divulgação
    - Publicar no seu site, seu Twitter, Facebook ou qualquer outra rede social sobre sua experiência com o software, estimulando outras pessoas a o utilizarem.
    Reconhecimento
    - Enviar um e-mail de agradecimento aos desenvolvedores.
    - Publicar na sua rede social, ou na dos desenvolvedores (se houver) um depoimento sobre sua experiência com o software.
    - Se o software está no Github e você tem uma conta de usuário lá, é só ir na página dele e começar a segui-lo (follow) e dar uma estrelinha (star) também.
    - Se o software está no SourceForge você pode dar uma estrelinha (star), avaliar o software (rating) e também dar seu comentário (user reviews).
    Preferência
    - Mesmo que haja um software proprietário equivalente, estimular o uso de software de código aberto é muito importante. Ele é socialmente mais justo e depois de ver o vídeo do item 1 você já deve saber o motivo.
    Documentação
    - Se você já domina algum recurso do software, é legal escrever algo no seu blog ou gravar um vídeo no YouTube ensinando outras pessoas a fazê-lo. Isso faz com que mais e mais usuários sejam beneficiados e aumenta as chances de adesão do software em questão.
    - Ajudar a escrever a documentação oficial do software, coisa que te faz aprender muito e toma muito tempo dos desenvolvedores. Tempo este que eles poderiam dedicar a corrigir problemas e adicionar novos recursos. Só depende de você.
    Suporte
    - Se cadastrar nos fórums e listas de discussão sobre o software para ajudar outros usuários te faz estudar muito, ajudar muito e contribuir muito com o ecossistema que mantém o software vivo!
    Código
    - Claro que se você conhecer a linguagem de programação utilizada no software você pode – e deve – contribuir via código. Só tome cuidado com o egocentrismo aqui. Não é porque você fez um patch que ele tem que ser aceito. O software de código aberto é democrático e não serve pra você tentar provar pra ninguém que é bom. Basta querer ajudar e atender ao pedido de todos, não do seu ego.
    - Se você é programador e costuma desenvolver software freeware por exemplo, considera transformar em código aberto. Ele vai crescer muito mais e ter muito mais adeptos. Você pode se espantar com o tamanho que o projeto pode assumir quando se tem a colaboração da comunidade open source.
    Reportar problemas
    - Se você acreditar que encontrou um problema no software (bug), avise aos desenvolvedores. Normalmente isso é feito por um sistema de bug tracking ou issue tracking. Com certeza no site do desenvolvedor você terá mais informações sobre como fazê-lo. Pode ser que te peçam logs e outras informações para que eles possam reproduzir o erro e corrigir, mas vale a pena continuar e ir até o fim. Você vai ajudar muita gente no final.
    Doações
    - Muitas equipes que desenvolvem software de código aberto precisam de dinheiro para comprarem hardware, aluguel de  infraestrutura ou mesmo para promoverem eventos entre os desenvolvedores para alinharem o futuro do software. Doando você pode ajudar nisso. Se você tiver condições, apoie.
    Se informar
    - Empresas como Microsoft, Apple, Red Hat, dentre outras são grandes contribuidoras com projetos de código aberto, inclusive com o Linux.
    - Software livre e software de código aberto são diferentes. O primeiro movimento é criado pelo Richard Stallman, que explica as diferenças aqui.
    Essa lista não é definitiva e naturalmente deve haver várias outras formas de ajudar, mas escolhi escrever sobre as mais simples, que estão somente há alguns cliques de distância de você.
    Nos anos que venho dedicando a apoiar os projetos de código aberto, inclusive criando alguns, fiquei muito surpreso com as colaborações que meus projetos receberam e também tive a oportunidade de contribuir com muitos outros. Isso significa ajuda efetiva para pessoas e projetos. De verdade. As empresas também gostam disso (afinal são pessoas que trabalham nelas né!?) e várias propostas de emprego já surgiram através do Github. Não fica de fora dessa. O mundo open source precisa de você. E as pessoas também.

    Fernando Mercês
    É raro termos um artigo não técnico aqui no Mente Binária, mas este tema merece, creio. A proposta aqui é criarmos uma lista de filmes, séries e documentários que envolvam especificamente o tema informática (não vale tecnologia em geral, pois do contrário a lista ficaria gigante!) organizados por ano de lançamento. Preparado? Então pega a pipoca!
    2017
    Ghost in the Shell (A Vigilante do Amanhã: Ghost in the Shell) 2016
    Hackers Hacker (Anonymous) Cyberwar ZeroDays 2015
    Terminal F/Chasing Edward Snowden (Snowdens store flugt) Mr. Robot Hacker's Game Deep Web Blackhat (Hacker) 2014
    Who Am I - Invasores: Nenhum Sistema Está Salvo The Internet's Own Boy: The Story of Aaron Swartz (O Menino da Internet: A História de Aaron Swartz) The Hackers Wars Citizenfour Algorithm Sillicon Valley Halt and Catch Fire 2013
    We Steal Secrets: The Story of WikiLeaks Terms and Conditions May Apply TPB AFK: The Pirate Bay Away from Keyboard Her (Ela) Downloaded DEFCON 2012
    We Are Legion: The Story of the Hacktivists 2011
    Black Mirror 2010
    Tron: Legacy (Tron: O Legado) 2008
    Hackers Are People Too 2007
    Live Free or Die Hard (Duro de Matar 4.0) 2006
    Steal This Film 2005
    Hard Candy (Menina Má.Com) 2001
    The Code Revolution OS Antitrust (Ameaça Virtual) Artificial Intelligence: AI (A.I.: Inteligência Artificial) 2000
    Takedown (Caçada Virtual) 1999
    The Matrix (Matrix) Pirates of Silicon Valley (Piratas da Informática: Piratas do Vale do Silício) 1996
    Lawnmower Man 2: Beyond Cyberspace (O Passageiro do Futuro 2) 1995
    Ghost in the Shell (O Fantasma do Futuro) The Net (A Rede) Johnny Mnemonic (Johnny Mnemonic: O Cyborg do Futuro) Hackers - Piratas de Computador 1992
    The Lawnmower Man (O Passageiro do Futuro) 1984
    Triumph of The Nerds Hackers: Wizards of the Electronic Age 1983
    Wargames 1982
    Tron (Tron: Uma Odisséia Eletrônica) Esqueci de algum? Sugere aí nos comentários que adiciono! No canal Papo Binário já falei sobre algum destes títulos também. 🙂

×