https://github.com/pietroborrello/CustomProcessingUnit Skip to content Sign up * Product + Features + Mobile + Actions + Codespaces + Copilot + Packages + Security + Code review + Issues + Discussions + Integrations + GitHub Sponsors + Customer stories * Team * Enterprise * Explore + Explore GitHub + Learn and contribute + Topics + Collections + Trending + Skills + GitHub Sponsors + Open source guides + Connect with others + The ReadME Project + Events + Community forum + GitHub Education + GitHub Stars program * Marketplace * Pricing + Plans + Compare plans + Contact Sales + Education [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} pietroborrello / CustomProcessingUnit Public * Notifications * Fork 5 * Star 93 The first dynamic analysis framework for CPU microcode 93 stars 5 forks Star Notifications * Code * Issues 0 * Pull requests 0 * Actions * Projects 0 * Wiki * Security * Insights More * Code * Issues * Pull requests * Actions * Projects * Wiki * Security * Insights pietroborrello/CustomProcessingUnit This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. master Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags 1 branch 0 tags Code * Clone HTTPS GitHub CLI [https://github.com/p] Use Git or checkout with SVN using the web URL. [gh repo clone pietro] Work fast with our official CLI. Learn more. * Open with GitHub Desktop * Download ZIP Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Launching Xcode If nothing happens, download Xcode and try again. Launching Visual Studio Code Your codespace will open once ready. There was a problem preparing your codespace, please try again. Latest commit @pietroborrello pietroborrello update slides ... 53d1496 Aug 12, 2022 update slides 53d1496 Git stats * 3 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time bios init Aug 11, 2022 images init Aug 11, 2022 uasm-lib init Aug 11, 2022 ucode_collection init Aug 11, 2022 .gitignore init Aug 11, 2022 Makefile init Aug 11, 2022 Notes.md init Aug 11, 2022 README.md add slides Aug 11, 2022 slides.pdf update slides Aug 12, 2022 View code [ ] Custom Processing Unit Prerequisites Setup Run Custom Processing Unit Simple instructions Complex actions Raw udbgrd and udbwr LDAT access Patch microcode Match & Patch Tracing microcode Secret memory dumpers Writing microcode patches Example README.md Custom Processing Unit [cpu_logo] Custom Processing Unit is the first dynamic analysis framework able to hook, patch and trace CPU microcode at the software level. It works by leveraging undocumented instructions in Intel CPUs that allow access to the CRBUS. Using our microcode decompiler we reverse engineered how the CPU uses the CRBUS and by replicating the interactions we have full control of the CPU. Find the static analysis framework at https://github.com/ pietroborrello/ghidra-atom-microcode. Check out our slides describing this work here. Note: Custom Processing Unit requires a Red-Unlocked CPU: currently, only Goldmont CPUs (GLM) have a public Red Unlock. We tested Gigabyte GB-BPCE-3350C with CPU stepping 0x9 and 0xa (cpuid 0x000506C9 and 0x000506CA). Custom Processing Unit is made up of a UEFI application and a few libraries. The UEFI application interacts with the GLM CPU, while the libraries provide different helpers to compile microcode into the UEFI application and analyze its output. Prerequisites 1. Follow the steps to red unlock your Goldmont CPU from https:// github.com/ptresearch/IntelTXE-PoC. 2. Create a bootable USB key with an EFI shell 3. Install gnu-efi on your main host Setup GNU_EFI_DIR= make This will build the source microcode files and the UEFI application into cpu.efi. Copy cpu.efi into the \EFI\ folder of the USB key, plug it in the GLM and boot into the EFI shell. Run map -r in the efi shell to identify the USB key device and : to mount it. Run Custom Processing Unit Run ./cpu.efi to print the help: Usage: patch: p patch & exec: x perf: f zero out m&p: z hook: h [m&p idx] [uop addr] [patch addr] template: m dump imms: di dump rom: dr dump msrs: dm dump SMM: ds [address] [size] cpuid: c [rax] [rcx] rdmsr: rm [msr] wrmsr: wm [msr] read: r [cmd] [addr] write: w [cmd] [addr] [value] invoke: i [addr] update ucode: u [size] ldat read: lr [port] [array] [bank] [idx] [addr] [optional size] ldat write: lw [port] [array] [bank] [idx] [addr] [value] Simple instructions cpu provides helpers to run simple instructions from the command line: * cpuid * rdmsr * wrmsr Complex actions cpu provides interfaces to complex CPU routines that are interesting to execute to study cpu behavior: * u: update the CPU ucode with the provided (signed) patch * f: collect performance counters while running microcode Raw udbgrd and udbwr cpu provides raw interfaces to the undocumented instructions udbrd and udbgwr. The most interesting commands they provide are: * 0x0: access CRBUS * 0x10: access UROM * 0x40: access stgbuf * 0xd8: invoke ucode routine from address LDAT access cpu exposes LDAT access routines to read and write. Specify the parameters [port] [array] [bank] [idx] [addr] to read or write there. Interesting ports are: * 0x6a0: microcode sequencer, which has access to the internal the ucode ROM and RAM * 0x120: load/store buffers * 0x3c0: instruction cache * 0x630: ITLB Please notice that accessing some of these internal components may cause the CPU to freeze. Patch microcode cpu provides functionalities to install patches in the microcode. 1. Write your microcode patch in bios/ucode_patches/ucode_patch.u (look at the other patches for examples) 2. Build the UEFI application 3. Execute cpu.efi p to install the patch at the address provided in .org. Notice that in the microcode, only the addresses between 0x7c00 and 0x7e00 are writable and meaningful to patch. Running cpu.efi x, it will also execute the microcode patched and print the rax, rbx, rcx, rdx registers as result. Match & Patch To automatically execute microcode at certain CPU events or microcode points, cpu leverages the Match and Patch. It defines a microcode address to hook and the microcode address to jump to when the hook is triggered. * z: resets all the match & patch. * h: installs an hook, given an index (0-0x20), an address to hook (0-0x7c00) and a target address to execute (0x7c00-0x7e00). Tracing microcode By installing multiple hooks and continuously executing an instruction, cpu is able to trace the microoperations performed by such an instruction, and dump them. To trace: 1. Write the instruction to be traced after the // [TRACED INSTRUCTION HERE] in get_trace_clock_at(). 2. Build the UEFI application. 3. Trace with: cpu.efi m. It will create a trace.txt file that contains all the addresses that have been hit. 4. Execute uasm-lib/uasm.py -t trace.txt > parsed_trace.txt. It will generate a full trace of the microcode executed during the instruction. Notice that uasm.py will leverage the ms_arrayX.txt files in its folder to generate a disassembly of the microinstructions executed. These are for GLM with stepping 0x9 (cpuid 0x000506C9). Please generate the proper arrays in case you have a different stepping. You can use the LDAT dump functionalities for this purpose. Secret memory dumpers The CPU has different inaccessible buffers from the architecture, for which we provide routines to dump: * smm: SMROM (or any other address while disabling SMM protection) * rom: internal ROM * imms: CPU hardcoded immediates * msrs: internal MSRs configurations Writing microcode patches We provide an assembler that generates header files to be compiled into the cpu.efi UEFI application. Look into the provided patches in bios/ucode_patches for the syntax. It supports simple operations and labels. Assemble a microcode patch with uasm.py -i ucode_patch.u -o ucode_patch.h. cpu.efi will be compiled and automatically include the microcode patch that you want to apply. Example file: code_patch.u .org 0x7c00 rax:= ZEROEXT_DSZ32(0x00001337) rbx:= ZEROEXT_DSZ32(0x00001337) rcx:= ZEROEXT_DSZ32(0x00001337) rdx:= ZEROEXT_DSZ32(0x00001337) recompile, then run in the GLM: cpu.efi z # zero out match & patch cpu.efi p # apply the patch cpu.efi h 0 0x0428 0x7c00 # rdrand entry point now every time rdrand is executed, it will return 0x1337 in the registers. About The first dynamic analysis framework for CPU microcode Resources Readme Stars 93 stars Watchers 7 watching Forks 5 forks Releases No releases published Packages 0 No packages published Languages * C 91.5% * Python 8.3% * Makefile 0.2% Footer (c) 2022 GitHub, Inc. Footer navigation * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.