{"id":13798135,"url":"https://github.com/Sentinel-One/brick","last_synced_at":"2025-05-13T05:31:38.426Z","repository":{"id":45918217,"uuid":"374822898","full_name":"Sentinel-One/brick","owner":"Sentinel-One","description":null,"archived":false,"fork":false,"pushed_at":"2024-06-18T14:35:08.000Z","size":5041,"stargazers_count":92,"open_issues_count":3,"forks_count":14,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-03-17T14:51:16.520Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sentinel-One.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-07T23:12:42.000Z","updated_at":"2025-01-26T07:28:00.000Z","dependencies_parsed_at":"2024-08-04T00:02:25.651Z","dependency_job_id":"4e70e72e-a970-4144-b842-dcea13b4668d","html_url":"https://github.com/Sentinel-One/brick","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sentinel-One%2Fbrick","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sentinel-One%2Fbrick/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sentinel-One%2Fbrick/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sentinel-One%2Fbrick/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sentinel-One","download_url":"https://codeload.github.com/Sentinel-One/brick/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253883110,"owners_count":21978610,"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":[],"created_at":"2024-08-04T00:00:39.403Z","updated_at":"2025-05-13T05:31:36.586Z","avatar_url":"https://github.com/Sentinel-One.png","language":"Python","funding_links":[],"categories":["Tools :hammer:"],"sub_categories":[],"readme":"# Brick\n\nBrick is a static vulnerability scanner used to pinpoint potentially vulnerable SMM modules within a UEFI firmware image. It is comprised out of a collection of modules (implemented as IDAPython scripts), each responsible for identifying a specific vulnerability/anti-pattern in SMM code.\n\n## Pre-requisites\n* IDA Pro version 7.7 or above. Older IDA versions might work as well but were not tested.\n* Python 3.10 or above.\n\n## Installation\n* Clone this repository:  \n`git clone --recursive https://github.com/Sentinel-One/brick.git`\n* Install necessary Python packages:\n`pip install -r requirements.txt`\n* Install the [Bip](https://github.com/synacktiv/bip) framework and other required IDA plugins:\n`python install.py`\n\n## Usage\n* Obtain a dump of the firmware image you wish to scan.\n![](images/SpiDump.jpg)\n* Run: `python brick.py \u003cuefi_rom\u003e [-o outdir]` and wait for the analysis to complete (can take up to an hour, depending on how many SMM modules are found in the UEFI firmware image).\n  \n![](images/BrickRun.jpg)\n* Open the HTML report and browse the results. Usually, further manual investigation is required to classify results as either true positives or false positives.\n\n![](images/BrickReport.jpg)\n\n## Detection Modules\n\n### efiXplorer\nIn addition to being the main analysis engine upon which `Brick` is built, `efiXplorer` also comes with its own set of heuristics that can detect a bunch of vulnerabilities such as SMM call-outs, buffer overflows, etc. During its operation, `Brick` propagates these finding so that they'll show up in the resulting output file as well.\n\n### Unsanitized nested pointers:\nIf the `CommBuffer` for the handler contains nested pointers, they must be sanitized by functions such as [SmmIsBufferOutsideSmmValid](https://github.com/tianocore/edk2/blob/master/MdePkg/Library/SmmMemLib/SmmMemLib.c) to make sure user-controllable arguments do not overlap with SMRAM.\nFailure to do so might lead to what is commonly known as a [confused-deputy attack](https://en.wikipedia.org/wiki/Confused_deputy_problem) in which the highly privileged SMI handler is tricked by lower privileged code to overwrite or leak out SMRAM contents.\n![](images/CommBuffer.jpg)\n\n### Low SMRAM corruption\nSome SMI handler write to the `CommBuffer` without first validating its size. Attackers can exploit this by placing the `CommBuffer` in a memory location just below SMRAM. When the handler will try to write to the `CommBuffer`, it will uninteionally corrupt the low portion of SMRAM.\n![](images/LowSmram.png)\n\n### TOCTOU attacks\nThe `CommBuffer` itself lives outside of SMRAM, and so DMA attacks can change its contents while an SMI handler is executing. Because of that, double-fetches from the `CommBuffer` are dangerious because they do not necessarily yield the same values.\n\n![](images/TOCTOU.jpg)\n\n### CSEG-only aware handlers\nSome SMI handlers only check caller-provided pointers against the address range of the *Compatibility SMRAM segment* (0xA0000-0xBFFFF). Since other SMRAM regions that might be active are not protected by these SMI handlers, `Brick` flags them as potentially vulnerable.\n![](images/CSEG.jpg)\n\n### Leaking out SMRAM contents via NVRAM variables\nA common anti-pattern in firmware code is as follows:\n![](images/SetVariable.jpg)\n\nBasically, the code uses the `GetVariable` service to retrieve the contents and size of some NVRAM variable. It then processes it in memory and finally writes it back by calling the  `SetVariable` service. The problem with the piece of code above is that the call to `SetVariable` is made using a *hardcoded size* rather than the actual size that was retrieved by `GetVariable`. If an attacker is able to set this NVRAM variable from the OS, he/she can make it much shorter than anticipated. As a consequence, the call to `GetVariable` will leave a large portion of the Data buffer uninitialized. These uninitialized bytes will be manifested eventually to NVRAM while processing the call to `SetVariable`, where they can be queried by attackers running only with OS-level privileges.\n\n## Contribution\nSince `Brick` is a young project, bugs and missing features are likely to appear. Issues and pull requests are highly welcome.\n\nFor additional information and other inquiries, feel free to contact the author directly:\n\nTwitter: [@assaf_carlsbad](https://twitter.com/assaf_carlsbad)  \nE-Mail: [carlsbad@sentinelone.com](mailto://carlsbad@sentinelone.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSentinel-One%2Fbrick","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSentinel-One%2Fbrick","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSentinel-One%2Fbrick/lists"}