<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Red Team on fr0sttt</title><link>https://fr0sttt.dev/tags/red-team/</link><description>Recent content in Red Team on fr0sttt</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://fr0sttt.dev/tags/red-team/index.xml" rel="self" type="application/rss+xml"/><item><title>A detecção é inevitável. O que importa é o que você mostra quando ela acontece.</title><link>https://fr0sttt.dev/p/a-detec%C3%A7%C3%A3o-%C3%A9-inevit%C3%A1vel.-o-que-importa-%C3%A9-o-que-voc%C3%AA-mostra-quando-ela-acontece./</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fr0sttt.dev/p/a-detec%C3%A7%C3%A3o-%C3%A9-inevit%C3%A1vel.-o-que-importa-%C3%A9-o-que-voc%C3%AA-mostra-quando-ela-acontece./</guid><description>&lt;h1 id="o-objetivo-errado"&gt;O objetivo errado
&lt;/h1&gt;&lt;p&gt;Existe um modelo mental que a maioria das pessoas carrega quando começa a desenvolver ferramentas ofensivas: a ideia de que sucesso significa invisibilidade. O implant bom é o implant que ninguém vê. A evasão boa é aquela que o antivírus não detecta. O payload bom é o que passa pelo EDR sem disparar nenhum alerta.&lt;/p&gt;
&lt;p&gt;Esse modelo está errado. E construir ferramentas com base nele é a razão pela qual a maioria das ferramentas amadoras falha quando encontra um ambiente com defesa real.&lt;/p&gt;
&lt;p&gt;A invisibilidade é uma fantasia operacional. Em qualquer ambiente com telemetria decente, alguma coisa vai observar o que você está fazendo. ETW captura eventos do kernel. EDRs colocam hooks em user-mode. Scanners de memória rodam periodicamente. Tráfego de rede passa por proxies que inspecionam payload. A superfície de observação é grande demais para garantir que nada vai te ver. E quanto mais você tenta garantir isso, mais energia gasta num objetivo que é, na prática, inalcançável.&lt;/p&gt;
&lt;p&gt;A pergunta certa não é &amp;ldquo;como não ser visto?&amp;rdquo;. A pergunta certa é &amp;ldquo;quando eu for visto, o que o analista vai encontrar?&amp;rdquo;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="o-shift-de-mentalidade"&gt;O shift de mentalidade
&lt;/h2&gt;&lt;p&gt;Implants maduros — os que aparecem em operações de threat actors relevantes, nos relatórios de red teams sérios, nas pesquisas de C2 frameworks modernos — partem de uma premissa diferente: &lt;strong&gt;a análise é inevitável, então o que precisa ser controlado é o que está visível no momento em que ela acontece.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Isso muda fundamentalmente como você projeta cada componente da ferramenta. Você deixa de pensar em &amp;ldquo;como esconder isso&amp;rdquo; e passa a pensar em &amp;ldquo;se alguém olhar para isso agora, o que vai ver?&amp;rdquo; E a resposta que você quer é sempre a mesma: algo benigno, algo plausível, algo que não justifica investigação adicional.&lt;/p&gt;
&lt;p&gt;Irrelevância, não invisibilidade.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="como-esse-princípio-se-manifesta-na-prática"&gt;Como esse princípio se manifesta na prática
&lt;/h2&gt;&lt;p&gt;O sleep masking é o exemplo mais didático porque torna o princípio explícito.&lt;/p&gt;
&lt;p&gt;Um implant que beacona periodicamente passa a maior parte do seu tempo dormindo entre conexões. Esse intervalo é o momento de maior exposição: o processo existe, está em memória, e um scanner que passar nesse janela vai encontrar o implant inteiro carregado e executável. A abordagem ingênua não faz nada a respeito disso e torce para que nenhum scanner passe no momento errado.&lt;/p&gt;
&lt;p&gt;A abordagem madura parte da premissa oposta: o scanner vai passar. Então antes de dormir, o implant encripta a si mesmo em memória — o shellcode, as strings, as configurações, o heap. O que fica visível para qualquer ferramenta de análise durante o sono não é um implant. É lixo criptográfico sem assinatura, sem padrão reconhecível, sem nada que justifique um alerta. Quando o timer dispara, o implant se desencripta, executa, e volta a dormir. O ciclo se repete.&lt;/p&gt;
&lt;p&gt;O implant foi visto. Foi analisado. E foi considerado irrelevante.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;O mesmo princípio aparece em camadas diferentes, com implementações diferentes.&lt;/p&gt;
&lt;p&gt;Em disco, a de-otimização de código de máquina garante que o binário não corresponde a nenhuma assinatura conhecida e que sua estrutura parece plausível — não anômala, não gerada por um packer reconhecível, apenas diferente. Se um analista examinar o arquivo, vai encontrar código válido que não dispara nenhuma regra. Irrelevante.&lt;/p&gt;
&lt;p&gt;Em comportamento, syscalls diretas removem os hooks que EDRs colocam em user-mode para interceptar chamadas de sistema suspeitas. O processo continua fazendo o que precisa fazer, mas os observadores que dependiam daqueles hooks não recebem mais os eventos. O que chega na telemetria é um processo que existe e não faz nada de especial. Irrelevante.&lt;/p&gt;
&lt;p&gt;Em atribuição, técnicas como PPID spoofing fazem com que o processo filho do implant apareça como filho de um processo pai legítimo — um browser, um processo de sistema. Se um analista olhar a árvore de processos, vai ver uma relação que parece normal. Nada que justifique aprofundamento. Irrelevante.&lt;/p&gt;
&lt;p&gt;Em tráfego, malleable C2 profiles fazem com que a comunicação com o servidor de comando e controle imite o padrão de software legítimo: os mesmos headers HTTP, os mesmos intervalos de timing, os mesmos tamanhos de payload de uma aplicação conhecida. Um proxy que inspecionar o tráfego vai ver o que parece ser tráfego normal de um software normal. Irrelevante.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="a-lógica-por-trás-do-padrão"&gt;A lógica por trás do padrão
&lt;/h2&gt;&lt;p&gt;O fio condutor de todas essas técnicas é o mesmo: elas não tentam eliminar a observação. Elas controlam o que é observado.&lt;/p&gt;
&lt;p&gt;É uma distinção que parece sutil mas que tem consequências práticas profundas no desenvolvimento. Quando você projeta para invisibilidade, você tenta cobrir todos os vetores de detecção — e inevitavelmente falha em algum, porque a superfície de observação é grande demais. Quando você projeta para irrelevância, você pensa do ponto de vista do analista: o que vai aparecer na tela dele quando ele olhar para o que eu deixei? E você garante que a resposta seja &amp;ldquo;nada que valha o tempo de investigar&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Defesa funciona por triagem. Alertas são gerados o tempo todo, e equipes de segurança precisam priorizar o que investigar. Um implant que gera alertas de baixa fidelidade — ou que não gera alerta nenhum, mas cujos artefatos, quando examinados, não revelam nada de interesse — passa pela triagem não porque foi invisível, mas porque foi considerado não prioritário.&lt;/p&gt;
&lt;p&gt;É, em essência, o princípio da esteganografia aplicado à cadeia operacional inteira. Não esconder que algo existe. Esconder que o que existe é relevante.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="o-que-isso-significa-para-quem-desenvolve-ferramentas"&gt;O que isso significa para quem desenvolve ferramentas
&lt;/h2&gt;&lt;p&gt;A implicação prática é que cada componente de um implant precisa ser pensado com uma pergunta específica em mente: &lt;strong&gt;se esse componente for analisado isoladamente, agora, o que o analista vai concluir?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Para o binário em disco: parece código legítimo ou parece output de um packer?&lt;/p&gt;
&lt;p&gt;Para a memória durante o sleep: parece shellcode ou parece dado sem estrutura reconhecível?&lt;/p&gt;
&lt;p&gt;Para as chamadas de sistema: parecem o comportamento de um processo legítimo ou parecem a sequência clássica de injeção?&lt;/p&gt;
&lt;p&gt;Para o tráfego de rede: parece comunicação de software comum ou parece beacon com padrão de timing regular?&lt;/p&gt;
&lt;p&gt;Para a árvore de processos: parece uma relação pai-filho plausível ou parece um processo órfão sem contexto?&lt;/p&gt;
&lt;p&gt;Cada uma dessas perguntas tem uma resposta técnica específica. E a soma dessas respostas é o que determina se a operação sobrevive ao contato com defesa real — não se o EDR foi bypassado na entrada, não se o antivírus não detectou na hora do upload, mas se o implant continua operacional depois que alguém decidiu olhar mais de perto.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Invisibilidade é um objetivo binário e frágil: ou você é invisível ou não é, e basta um vetor descoberto para que tudo caia. Irrelevância é um objetivo gradual e resiliente: quanto mais componentes parecem benignos quando examinados, maior o custo da investigação, e maior a chance de que o analista decida que há coisas mais urgentes para investigar.&lt;/p&gt;
&lt;p&gt;Ferramentas amadoras perseguem o primeiro. Ferramentas maduras constroem o segundo.&lt;/p&gt;</description></item><item><title>Evasão por de-otimização: quando o código se disfarça de si mesmo</title><link>https://fr0sttt.dev/p/evas%C3%A3o-por-de-otimiza%C3%A7%C3%A3o-quando-o-c%C3%B3digo-se-disfar%C3%A7a-de-si-mesmo/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fr0sttt.dev/p/evas%C3%A3o-por-de-otimiza%C3%A7%C3%A3o-quando-o-c%C3%B3digo-se-disfar%C3%A7a-de-si-mesmo/</guid><description>&lt;h1 id="o-problema-com-a-solução-que-todo-mundo-usa"&gt;O problema com a solução que todo mundo usa
&lt;/h1&gt;&lt;p&gt;A maioria das ferramentas de evasão de antivírus resolve o problema da mesma forma: esconde o payload dentro de uma casca, e essa casca o descriptografa em memória na hora da execução. Packers, shellcode encoders, obfuscators — todos trabalham com alguma variação desse modelo. O resultado é um binário que parece inofensivo no disco mas que, em algum momento, escreve o código real numa região de memória e pula para ela.&lt;/p&gt;
&lt;p&gt;Esse padrão tem um nome no mundo de detecção: self-modifying code em regiões RWE. E ele ficou velho.&lt;/p&gt;
&lt;p&gt;Ferramentas como Moneta e PE-sieve são construídas exatamente para caçar esse comportamento. Elas varrem a memória do processo em tempo de execução, procuram regiões com permissões de leitura, escrita e execução simultaneamente, e analisam o que está dentro delas. Se o código que está sendo executado não corresponde ao que foi carregado do disco, o jogo acabou. A detecção não depende de assinatura, não depende de heurística de comportamento — ela depende de uma contradição matemática que o próprio processo cria ao rodar.&lt;/p&gt;
&lt;p&gt;O problema não é que a técnica seja fraca. É que ela é estruturalmente detectável. Não importa quão sofisticado seja o packer, o momento em que ele escreve o payload descriptografado numa região executável, ele cria uma evidência que não pode ser apagada sem desfazer o próprio trabalho.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="a-pergunta-que-muda-o-enquadramento"&gt;A pergunta que muda o enquadramento
&lt;/h2&gt;&lt;p&gt;Se o problema é o código que se modifica em tempo de execução, a solução óbvia é: e se o código não precisar se modificar?&lt;/p&gt;
&lt;p&gt;É aí que a de-otimização de código de máquina entra como abordagem. A ideia não é esconder o payload dentro de outra coisa. É transformar o próprio payload de forma que ele permaneça semanticamente idêntico, mas estruturalmente irreconhecível — e fazer isso de forma estática, antes da execução, sem criar nenhuma região RWE, sem nenhuma escrita em memória em runtime.&lt;/p&gt;
&lt;p&gt;O binário que vai para o disco já é o binário final. Não há descriptografia, não há automodificação. Há apenas instruções de máquina que fazem exatamente o que sempre fizeram, escritas de uma forma que nenhuma ferramenta de análise estática vai reconhecer como familiar.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="como-a-transformação-funciona"&gt;Como a transformação funciona
&lt;/h2&gt;&lt;p&gt;O código de máquina não é uma linguagem com uma única forma de expressar cada operação. A arquitetura x86, em particular, tem redundância suficiente para representar o mesmo cálculo de dezenas de formas diferentes, todas igualmente válidas para o processador. A de-otimização explora isso de forma sistemática, usando transformações matemáticas que preservam o resultado mas destroem qualquer padrão reconhecível.&lt;/p&gt;
&lt;p&gt;A primeira técnica é o particionamento aritmético. Uma instrução simples como &lt;code&gt;ADD RAX, 5&lt;/code&gt; pode ser substituída por uma sequência que calcula o mesmo valor através de operações intermediárias: &lt;code&gt;ADD RAX, 3&lt;/code&gt;, seguido de &lt;code&gt;ADD RAX, 2&lt;/code&gt;. O resultado é idêntico. Os bytes no binário são completamente diferentes. E a sequência pode ser particionada de formas diferentes a cada execução da transformação, garantindo que o mesmo payload nunca produza o mesmo padrão de bytes duas vezes.&lt;/p&gt;
&lt;p&gt;A segunda é a transformação polinomial. Constantes numéricas, em vez de aparecerem diretamente como valores imediatos nas instruções, são representadas como resultados de expressões polinomiais que o processador calcula em tempo de execução. O valor &lt;code&gt;0x1337&lt;/code&gt;, por exemplo, pode ser derivado de &lt;code&gt;(x² + 3x - 7)&lt;/code&gt; para algum &lt;code&gt;x&lt;/code&gt; escolhido em tempo de transformação. O processador chega no mesmo lugar, mas o padrão de bytes que chegou lá não tem nenhuma relação visual com o destino.&lt;/p&gt;
&lt;p&gt;A terceira é o inverso lógico, fundamentado nas leis de De Morgan. Operações como &lt;code&gt;AND&lt;/code&gt; e &lt;code&gt;OR&lt;/code&gt; podem ser reescritas usando suas equivalências lógicas invertidas: &lt;code&gt;NOT (NOT A OR NOT B)&lt;/code&gt; é matematicamente idêntico a &lt;code&gt;A AND B&lt;/code&gt;. Em código de máquina, isso se traduz em substituir instruções lógicas por sequências de instruções que o processador executa de forma diferente mas que produzem o mesmo estado nos registradores ao final.&lt;/p&gt;
&lt;p&gt;A quarta é o particionamento lógico, que divide operações de máscara e manipulação de bits em sequências menores que preservam o efeito combinado. Uma máscara aplicada em uma instrução pode ser decomposta em duas ou três operações intermediárias, nenhuma das quais se parece com a original.&lt;/p&gt;
&lt;p&gt;Combinadas, essas transformações são capazes de reescrever até 95% das instruções de um binário sem alterar seu comportamento. O binário resultante passa por análise estática como se fosse código gerado por um compilador diferente — porque, de certa forma, é.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="por-que-isso-é-diferente-do-que-já-existe"&gt;Por que isso é diferente do que já existe
&lt;/h2&gt;&lt;p&gt;Obfuscação de código de máquina não é nova. O que diferencia essa abordagem é a ausência de padrões reconhecíveis na própria transformação.&lt;/p&gt;
&lt;p&gt;Técnicas tradicionais de obfuscação inserem NOPs, jumps inúteis ou chamadas de função que não fazem nada. Isso cria um padrão diferente, mas ainda detectável: ferramentas de análise aprenderam a reconhecer sequências de instrução que não fazem sentido para um compilador normal. O código parece estranho de uma forma específica, e essa estranheza específica virou assinatura.&lt;/p&gt;
&lt;p&gt;A de-otimização por transformações matemáticas não cria código estranho. Cria código que parece simplesmente diferente — como se tivesse sido compilado com flags de otimização diferentes, ou gerado por um compilador menos comum. As sequências resultantes são semanticamente corretas, sintaticamente válidas e estruturalmente plausíveis. Não há nada para um analisador estático apontar como anômalo, porque nada é anômalo. É apenas código fazendo o que código faz.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="onde-a-técnica-tem-limite"&gt;Onde a técnica tem limite
&lt;/h2&gt;&lt;p&gt;Honestidade técnica exige dizer que isso resolve um problema específico dentro de um problema maior.&lt;/p&gt;
&lt;p&gt;A de-otimização ataca a camada estática da detecção: assinaturas de bytes, análise de padrões no binário, fingerprinting de compiladores. Ela não faz nada pela camada dinâmica, que é onde EDRs modernos como CrowdStrike, SentinelOne e Microsoft Defender for Endpoint colocam a maior parte do seu peso.&lt;/p&gt;
&lt;p&gt;Um payload que sobrevive à análise estática ainda vai ser observado em tempo de execução. Se ele faz &lt;code&gt;VirtualAlloc&lt;/code&gt; seguido de escrita de shellcode seguido de criação de thread, o EDR vai detectar o comportamento independente de como o código que gerou esses syscalls estava escrito no disco. A telemetria via ETW e os hooks em user-mode capturam o que o processo faz, não como ele parece.&lt;/p&gt;
&lt;p&gt;Isso não invalida a técnica. Significa que ela pertence a uma cadeia de evasão, não é a cadeia inteira. Em alvos sem EDR maduro — que ainda representam a maioria dos ambientes em engagements reais — a de-otimização sozinha já representa uma superfície de detecção estática praticamente nula. Em alvos com EDR de última geração, ela precisa ser combinada com evasão de comportamento: syscalls diretas para evitar hooks em user-mode, sleep masking para esconder o payload em memória entre operações, e técnicas como module stomping para eliminar a dicotomia entre o que está no disco e o que está em memória.&lt;/p&gt;
&lt;p&gt;A de-otimização resolve o problema para o qual ela foi projetada. O trabalho de um operador ofensivo competente é entender exatamente qual problema está sendo resolvido em cada camada — e não confundir uma peça do puzzle com o puzzle inteiro.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Ferramentas de detecção evoluem ao encontrar padrões. A de-otimização por transformações matemáticas ataca justamente a capacidade de formar padrões: cada transformação é parametrizada diferente, cada binário produzido é único, e a diversidade do output não é acidental — é o produto de escolhas matemáticas deliberadas. Isso não garante invisibilidade eterna. Garante que o custo de criar assinaturas para esse tipo de evasão sobe de forma desproporcional ao custo de aplicar as transformações. Em segurança, esse tipo de assimetria importa.&lt;/p&gt;</description></item></channel></rss>