The following guide details instructions on the creation of modified DMA (attack) Firmware based on pcileech-fpga version 4.13.
Additionally this is intended to be a build-off of garagedweller's Unknown Cheats thread guide in a more detailed way
Tip
Video going over steps 1-4: https://www.youtube.com/watch?v=qOPTxYYw63E&ab_channel=RakeshMonkee
I don't like that there are people intentionally being vague, keeping information secret, or even misleading people to drive them away from being able to make their own firmware so that they end up buying 100s of dollars worth of custom firmware from other providers with no way to guarantee quality (I've seen "custom" paid firmware where they've only changed basic IDs lol)
ACs : Anti Cheats
DMA : Direct Memory Access
TLP : Transaction Layer Packet
DSN : Device Serial Number
DW : Double Word | DWORD
Donor card : A card that will be used to get IDs and will not be used on your main PC (Eg. PCIE Wifi card)
-
(Don't expect this to work for Vanguard, Faceit or ESEA in the guide's current state.
-
This guide does not detail how to set up software or change computer settings to accommodate DMA cards)
-
It is assumed that the user following the guide has a basic understanding of custom firmware and so on...
-
If you don't understand a single part of this guide, this guide is not for you as you will likely brick your card. Your best and safest bet is to buy a paid CFW making sure at the very least they have TLP emulation and hope for the best it is a 1:1.
- Requirements
- Gathering the donor information
- Initial Customisation
- Vivado Project Customisation
- Other Config Space Changes
- TLP Emulation
- Building and Flashing
- Visual Studio
- Xilinx Vivado Will need to make an AMD account to download
- Pcileech-fpga Source code for custom firmware
- Arbor Will need to make an account to download the trial (14 days)
(Using a donor card will help us later on with TLP emulation to communicate with the device to start a driver for legitimacy)
Due to my limited testing and knowledge, I'll be using a network adapter for all examples continuing
(I welcome any contribution about utilising different hardware for this)
It is suggested to use a cheap piece of hardware to get the IDs and then throw it out. These are used to emulate the DMA card. So don't get the IDs of any existing hardware in your computer and plug them into the firmware. ACs will detect 2 of the same IDs and flag it
Go into Scan Options under the Local system tab and Press Scan/Rescan, the values selected by default are good enough for us. Go Into PCI Config and locate your network controller, scroll around in the decode section and take note of the following things:
- Device ID
- Vendor ID
- Revision ID (will show as RevID)
- BAR0 Sizing Value(1/2/3/4/5 too if you have them)
Click on the square it's in to see the sizing info
My size is 16kb so record that
- Subsystem ID
- DSN(listed as Serial Number Register)
Note
If the Device Serial Number Capability Structure is not shown for your device, make a randomized string of byte-valid characters or 0 it out completely, but that may look a bit suspicious (I believe as long as its not the hard code value PCIleech comes with you should be fine since that's what ACs would scan for, please correct me if I'm wrong though.)
Combine your lower and upper DSN registers for our DSN configuration in step 3
For example, these are my values:
Serial Number Register (Lower DW): 68 4C E0 00
Serial Number Register (Upper DW): 01 00 00 00
Combine yours in the same format:
Lower DW + Upper DW = 68 4C E0 00 01 00 00 00
- We will still need Arbor later for our 0x40 and 0x60 blocks but it'd be convoluting to explain it here so keep it open
Once again due to limited knowledge, I'll be focusing on the PCIeSquirrel section of pcileech at the moment, sorry to those using other firmware.
- Open Vivado and in the top menu, in the search query, search for tcl console and click on it.
The console should now open at the bottom of the application.
-
In the Tcl console, type in
pwd
to see the working directory. It should look something like thisC:/Users/user/AppData/Roaming/Xilinx/Vivado
-
cd back a few times and then cd to the PCIeSquirrel folder in the pcileech-fpga-4.13 project folder. It should look something like this
C:\Users\user\Desktop\pcileech-fpga-4.13\PCIeSquirrel
. (Desktop is where my project folder is) -
Once you have PCIeSquirrel dir open, in the Tcl console type in
source vivado_generate_project.tcl -notrace
and wait for it to finish -
Once the project has been generated, Vivado should automatically open the
pcileech_squirrel.xpr
file. Keep it open on the side for a bit.
- Open the PCIeSquirrel folder and head to this file
/PCIeSquirrel/src/pcileech_pcie_cfg_a7.sv
. Within this file use Ctrl+F and search the file forrw[20]
which should be on line 209 to find the master abort flag/auto-clear status register. Change the accompanying 0 to a 1 along with the accompanyingrw[21]
.
Before
After
Setting rw[21]
to a 1, allows the DMA card to access the CPU’s memory directly (DMA) or exchange TLPs with peer peripherals (to the extent that the switching entities support that)
- In the same file
pcileech_pcie_cfg_a7.sv
Ctrl+Frw[127:64]
which should be on line 215 to find your DSN field listed asrw[127:64] <= 64'h0000000101000A35; // cfg_dsn
, insert your Serial Number there as suchrw[127:64] <= 64'hXXXXXXXXXXXXXXXX; // cfg_dsn
preserving the 16-character length of the input field, if your DSN is shorter, insert zeroes as seen in the example image
Before
After
this being my DSN
if your donor card didn't have a DSN, yours should look like
rw[127:64] <= 64'h0000000000000000; // +008: cfg_dsn
- Go ahead and save all the changes you've made
- Once inside Vivado, navigate to the "sources" box and navigate as such
pcileech_squirrel_top
>i_pcileech_pcie_a7 : pcileech_pcie_a7
then double click on the file with the yellow square labelledi_pcie_7x_0 : pcie_7x_0
.
- You should now be in a window called "Re-customize IP", in there, press on the
IDs
tab and enter all the IDs you gathered from your donor board, also note that the "SubSystem Vendor ID" Is just the same as your Vendor ID. (If your donor board is different from a network adapter you may have to adjust some settings in the "Class Code" section below as well.)
To check the class code of your donor card go back to Arbor > scan if needed, else > PCI config > set PCI view to Linear. Your card should be highlighted in green. There will also be a column header called Class. Match that with your card.
- Also go into the "BARs" tab and set the size value you gathered in step 2, note that the Hex Value shown is not meant to be the same as your bar address. You cannot edit this value.
the size of my bar was 16kb so 16kb is what you set it as
If the size unit is different change the size unit to accommodate the unit of the bar size
- Press OK on the bottom right then hit "Generate" on the new window that pops up and wait for it to finish.
- We will lock the core so that when Vivado synthesises and/or builds our project it will not overwrite some things and allow us to edit some things manually we could only do through the interface before, to do this, navigate to the "Tcl Console" located in the top right of the bottom box and enter into there
set_property is_managed false [get_files pcie_7x_0.xci]
, (to unlock it in the future for any purposes useset_property is_managed true [get_files pcie_7x_0.xci]
.)
- Decide whether you want to modify your config space in the
configspace.coe
file, which:- Has a higher probability of (user) error
- Is less time-consuming
- or in the Vivado IP core, which:
- Requires more effort
- Is easier to grasp
I will first explain how to make the changes in the Vivado IP core editor. If you would instead like to make your changes in the configspace.coe file please scroll down to the appropriate section.
- In Vivado, navigate to
pcie_7x_0_core_top
as shown in the image, and use the magnifying glass in the top left of the text editor to search for these different lines to match them to your donor card
- Here is a list of variable names in the Vivado IP core config correlating to values we have seen changed when dumping paid CFW that you could change to match your donor cards. Not in any particular order, there is:
- 0x00
CLASS_CODE
(easier to do this one in the UI) - 0x40
PM_CAP_VERSION
,PM_CAP_D1SUPPORT
,PM_CAP_AUXCURRENT
,PM_CSR_NOSOFTRST
- 0x50
MSI_CAP_64_BIT_ADDR_CAPABLE
, - 0x60
PCIE_CAP_DEVICE_PORT_TYPE
,DEV_CAP_MAX_PAYLOAD_SUPPORTED
,DEV_CAP_EXT_TAG_SUPPORTED
,DEV_CAP_ENDPOINT_L0S_LATENCY
,DEV_CAP_ENDPOINT_L1_LATENCY
,LINK_CAP_ASPM_SUPPORT
,LINK_CAP_MAX_LINK_SPEED
,LINK_CAP_MAX_LINK_WIDTH
- 0x90
LINK_CTRL2_TARGET_LINK_SPEED
- 0x00
- Fields that can be changed in different files (don't know specifics yet)
- 0x40
cfg_pmcsr_powerstate
- 0x60
corr_err_reporting_en
,non_fatal_err_reporting_en
,fatal_err_reporting_en
,no_snoop_en
- 0x90
Link Status2: Current De-emphasis
(I have not been able to find a single reference to deemph in link status2, nor any other config for this structure, your best bet is modifying this one in the .coe file)
- 0x40
Important
You are matching the bytes by capability & structure, not by block, for example, Vendor ID is a structure, whereas MSI is a capability that is made up of many structures and can be located in different blocks on different pieces of hardware
- In Visual Studio, head to
/src/pcileech_fifo.sv
and Ctrl+Frw[203]
which should be on line 290 and change the1'b1;
to1;b0;
(This will allow us to change the config space bytes)
Before
After
- In comparison with a paid custom firmware versus pcileech default, we have recorded changes in the following bytes (grouped by dword, 1 indicates a change, 0 indicates no change)
- 0x00
SKIP-IDS 00000100 01100000 00000000
- 0x40
11110000 00000001 00000000 00000000
- 0x50
00100000 11111001 00000000 00000000
- 0x60
00100000 00000111 00000101 00001101
- 0x90
00010001 00000000 00000000 00000000
- 0x00
Making a guide for this might even need a repo of its own, for now, see ekknod's bar controller config from line 803 for an example
These instructions are not complete and final.
-
Edit the Xilinx PCIe core in Vivado. By default, there is one BAR, BAR0 which have 4kB of all-zero read/write memory assigned
-
In Visual Studio head to
pcileech_tlps128_bar_controller.sv
and follow the instructions in the file to implement custom BAR PIO memory regions
Notes to consider:
0x31 | 0x30 | 0x29 | 0x28 | 0x27 | 0x26 | 0x25 | 0x24 | 0x23 | 0x22 | 02x1 | 02x0 | 01x9 | 01x8 | 01x7 | 01x6 | 0x15 | 0x14 | 0x13 | 0x12 | 0x11 | 0x10 | 0x9 | 0x8 | 0x7 | 0x6 | 0x5 | 0x4 | 0x3 | 0x2 | 0x1 | 0x0 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DW 0 | R | Fmt | - | Type | - | - | - | - | R | TC | - | - | R | - | - | - | TD | EP | Attr | - | R | - | Length | - | - | - | - | - | - | - | - | - |
DW 1 | Requester ID | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | Tag | - | - | - | - | - | - | - | Last BE | - | - | - | 1st BE | - | - | - |
DW 2 | Addresses[31:2] | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | R | - |
DW 0:
- R: Reserved bit.
- Fmt: Format field.
- Type: Type field specifying it's a memory read request.
- TC: Traffic Class field.
- TD: TLP Digest bit.
- EP: Extended Payload bit.
- Attr: Attribute field.
- Length: Length field indicating the number of double words (DWs) to be read.
DW 1:
- Requester ID: Identifies the sender of the request.
- Tag: Tag field (may not be used in all cases).
- Last BE: Last Byte Enable field.
- 1st BE: First Byte Enable field.
DW 2:
- Addresses[31:2]: Address to read from.
- R: Reserved bit.
0x31 | 0x30 | 0x29 | 0x28 | 0x27 | 0x26 | 0x25 | 0x24 | 0x23 | 0x22 | 02x1 | 02x0 | 01x9 | 01x8 | 01x7 | 01x6 | 0x15 | 0x14 | 0x13 | 0x12 | 0x11 | 0x10 | 0x9 | 0x8 | 0x7 | 0x6 | 0x5 | 0x4 | 0x3 | 0x2 | 0x1 | 0x0 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DW 0 | R | Fmt | - | Type | - | - | - | - | R | TC | - | - | R | - | - | - | TD | EP | Attr | - | R | - | Length | - | - | - | - | - | - | - | - | - |
DW 1 | Requester ID | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | Tag | - | - | - | - | - | - | - | Last BE | - | - | - | 1st BE | - | - | - |
DW 2 | Addresses[31:2] | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | R | - |
DW 3 | DATA DW 0 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
DW 0:
- R: Reserved bit.
- Fmt: Format field.
- Type: Type field indicating it's a memory write request.
- TC: Traffic Class field.
- TD: TLP Digest bit.
- EP: Extended Payload bit.
- Attr: Attribute field.
- Length: Length field indicating the number of double words (DWs) of data being written.
DW 1:
- Requester ID: Identifies the sender of the request.
- Tag: Tag field (may not be used in all cases).
- Last BE: Last Byte Enable field.
- 1st BE: First Byte Enable field.
DW 2:
- Addresses[31:2]: Address where the data will be written.
DW 3:
- DATA DW 0: Contains the actual data to be written.
Caution
It is not our fault if you brick your computer / DMA card with bad firmware (It shouldn't happen anyway if you follow the steps correctly).
- Run
source vivado_build.tcl -notrace
in the tcl console to generate the file you'll need to flash onto your card - You'll find the file in
pcileech_squirrel/pcileech_squirrel.runs/impl_1
named "pchileech_squirrel_top.bin" - Follow the steps on the official LambdaConcept guide for flashing REMINDER: ONLY FOR SQUIRREL
If you mess up your CFW and your game PC won't fully "boot", be because of bios hang or other reasons, you may be able to flash new firmware onto it from your second computer if the card is still powered (indicated by the green lights). If your run a DMA card speed test on your second computer and the DMA card isn't recognised (doesn't matter if the rest of the speed test goes through or not), I'm 90% sure it's dead, if your first computer won't stay powered on, you have to buy a PCIe riser that will allow you to power your DMA card without it communicating (EXTREMELY NOT RECOMMENDED: if a riser is unavailable you can hotplug the dma card in after your computers fully booted then flash the card, be warned however as this can corrupt your motherboard's bios, and there's a chance you may not be able to repair it)
Ulf Frisk for pcileech
ekknod for his custom pcileech config(You could use this as a base to start off of as well!)