├── LICENSE ├── README.md ├── bin └── win32 │ └── mmdetect.exe └── mmdetect.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Positive Technologies 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6 | 7 | 8 | Copyright (c) 2017 Positive Technologies 9 | 10 | Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий: 11 | 12 | Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения. 13 | 14 | ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Intel ME Manufacturing Mode Detection Tools 2 | ===== 3 | This repository contains Python 2.7 scripts for checking the state of the Intel ME Manufacturing Mode. 4 | 5 | ## Manufacturing Mode 6 | 7 | Intel ME has a Manufacturing Mode designed to be used exclusively by motherboard manufacturers. This mode provides some additional opportunities that an attacker can take advantage of. When Manufacturing Mode is enabled, Intel ME allows execution of the command which makes the ME region writable via the SPI controller built into the motherboard. The ability to run code and send commands to Intel ME on the attacked system allows the attacker to rewrite the Intel ME firmware onto another version. So the attacker is able to deploy the firmware ([full disclosure][9]) which is vulnerable to [INTEL-SA-00086][7] and execute arbitrary code on Intel ME even if the system is patched. 8 | 9 | ## Usage 10 | 11 | mmdetect.py [-h] [--path PATH] 12 | 13 | Manufacturing mode detection tool. 14 | 15 | optional arguments: 16 | -h, --help show this help message and exit 17 | --path PATH path to lspci binary 18 | 19 | ## Limitations 20 | 21 | 1. Tools work only if HECI device isn't hidden. 22 | 2. 'pciutils' library ([WIN][6], [LIN][5]) is required. 23 | 3. 'requests' library is needed for installing 'pciutils' on Windows. 24 | 25 | pip install requests 26 | 27 | 28 | ## Related URLs: 29 | 30 | [How to Hack a Turned-Off Computer or Running Unsigned Code in Intel Management Engine][1] 31 | 32 | [CVE-2018-4251 (MacOS High Sierra 10.13.5, Security Update)][8] 33 | 34 | [Intel ME Manufacturing Mode: obscured dangers and their relationship to Apple MacBook vulnerability CVE-2018-4251][9] 35 | 36 | ## Author 37 | 38 | Maxim Goryachy ([@h0t_max][3]) 39 | 40 | ## Research Team 41 | 42 | Mark Ermolov ([@\_markel___][2]) 43 | 44 | Maxim Goryachy ([@h0t_max][3]) 45 | 46 | Dmitry Sklyarov ([@_Dmit][4]) 47 | 48 | ## License 49 | This software is provided under a custom License. See the accompanying LICENSE file for more information. 50 | 51 | [1]: https://www.blackhat.com/eu-17/briefings.html#how-to-hack-a-turned-off-computer-or-running-unsigned-code-in-intel-management-engine 52 | [2]: https://twitter.com/_markel___ 53 | [3]: https://twitter.com/h0t_max 54 | [4]: https://twitter.com/_Dmit 55 | [5]: https://github.com/pciutils/pciutils 56 | [6]: https://eternallybored.org/misc/pciutils/ 57 | [7]: https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00086.html 58 | [8]: https://support.apple.com/en-ca/HT208849 59 | [9]: http://blog.ptsecurity.com/2018/10/intel-me-manufacturing-mode-macbook.html 60 | -------------------------------------------------------------------------------- /bin/win32/mmdetect.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ptresearch/mmdetect/ec4c1852c92c6f5c46220030eb2cd4141b02899b/bin/win32/mmdetect.exe -------------------------------------------------------------------------------- /mmdetect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Intel ME Manufacturing Mode Detection Tools (Positive Technologies) 3 | # https://github.com/ptresearch/mmdetect 4 | 5 | import os, platform, sys 6 | import argparse, subprocess, tempfile 7 | import re, shutil 8 | import requests 9 | import zipfile 10 | 11 | PCIUTILSVER = "3.5.5" 12 | PCIUTILSFILENAME = "pciutils-" + PCIUTILSVER + "-win32" 13 | PCIUTILSFILENAMEEX = PCIUTILSFILENAME+".zip" 14 | LSPCIURL = "https://eternallybored.org/misc/pciutils/releases/" 15 | FULLURL = LSPCIURL + PCIUTILSFILENAMEEX 16 | 17 | def GetPCIUtils(): 18 | pciUtilsReq = requests.get(FULLURL) 19 | if pciUtilsReq.status_code != requests.codes.ok: 20 | print("[-] Error: Cannot download PCIUtils") 21 | sys.exit(-1) 22 | print("[+] PCIUtils downloaded successfully") 23 | return pciUtilsReq.content 24 | 25 | def FindMEDevice(fileName): 26 | PCIREGEX = r'(?P[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F])\ (?P[\w+\ \&\[\]\:\(\)\&\-\/]+)\: (?P[\w+\ \&\[\]\:\(\)\&\-\/]+)' 27 | try: 28 | lspci = subprocess.Popen([fileName], stdout=subprocess.PIPE) 29 | except OSError(e): 30 | print("[-] Error: lspci not found") 31 | sys.exit(-1) 32 | output = lspci.communicate()[0] 33 | if lspci.returncode != 0: 34 | print("[-] Error: Couldn't run lspci (try again as admin)") 35 | sys.exit(-1) 36 | param = output.splitlines() 37 | pciRegExp = re.compile(PCIREGEX) 38 | for i in param: 39 | pciDevDesc = pciRegExp.search(str(i)) 40 | if pciDevDesc.group("pci_class") == "Communication controller": 41 | if pciDevDesc.group("pci_name").find("ME Interface")!=-1 or (pciDevDesc.group("pci_name").find("HECI")!=-1 ): 42 | return pciDevDesc.group("pci_bdf") 43 | return "" 44 | 45 | def MeGetStatus(bdf, fileName): 46 | PCIREGEX = r'40\:\ (?P[0-9a-fA-F]{2})' 47 | lspci = subprocess.Popen([fileName, "-s", bdf, "-xxx"], stdout=subprocess.PIPE) 48 | output = lspci.communicate()[0] 49 | if lspci.returncode != 0: 50 | print("[-] Error: Couldn't run lspci") 51 | sys.exit(-1) 52 | pciRegExp = re.compile(PCIREGEX) 53 | regexp = pciRegExp.search(str(output)) 54 | if (regexp == None): 55 | print("[-] Error: Couldn't get extended register (try again as root)") 56 | sys.exit(-1) 57 | val = regexp.group("me_fwsts1") 58 | return (int(val, 16) & 1 << 4) != 0 59 | 60 | def ParseArguments(): 61 | parser = argparse.ArgumentParser(description='Manufecturing mode detection tool.') 62 | parser.add_argument('--path', metavar='PATH', help='path to lspci binary', type=str, default="") 63 | return parser.parse_args().path; 64 | 65 | lspciName = { 66 | "Windows": ["lspci.exe"], 67 | "Linux": ["lspci"], 68 | } 69 | 70 | def CheckPlatform(): 71 | osType = platform.system() 72 | if not osType in lspciName: 73 | print("[-] Error: Sorry, your platform isn't supported (%s)" % osType) 74 | sys.exit(-1) 75 | return osType 76 | 77 | def InstallPCIUtils(): 78 | if os.path.isfile(lspciName["Windows"][0]): 79 | print("[+] PCIUtils found") 80 | return "." 81 | print("[!] PCIUtils not found. Do you want install automatically (Y/N) [N]") 82 | ans = sys.stdin.read(1) 83 | if ans!="Y" and ans!="y": 84 | print("[!] Please install PCIUtils manually and try again") 85 | sys.exit(-1) 86 | pciUtilsZip = GetPCIUtils() 87 | pciUtilsDir =tempfile.mkdtemp() 88 | pciUtilsFileName = os.path.join(pciUtilsDir,"pciutils.zip") 89 | pciUtilsFile = open(pciUtilsFileName, "wb") 90 | pciUtilsFile.write(pciUtilsZip) 91 | pciUtilsFile.close() 92 | 93 | pciUtilsArch = zipfile.ZipFile(pciUtilsFileName) 94 | pciUtilsArch.extractall(path=pciUtilsDir) 95 | pciUtilsArch.close() 96 | 97 | os.remove(pciUtilsFileName) 98 | 99 | print("[+] PCIUtils extracted successfully") 100 | return os.path.join(pciUtilsDir,PCIUTILSFILENAME) 101 | 102 | def main(): 103 | lspciPath = ParseArguments() 104 | osType = CheckPlatform() 105 | if osType == "Windows": 106 | lspciPath = InstallPCIUtils() 107 | 108 | lspciBin = lspciName[osType][0] 109 | 110 | if lspciPath!="": 111 | lspciBin = os.path.join(lspciPath,lspciBin) 112 | 113 | meBDF = FindMEDevice(lspciBin) 114 | if meBDF == "": 115 | print("[-] Error: ME device not found (hidden)") 116 | sys.exit(-1) 117 | 118 | print("[+] Intel ME device found: %s\n" % meBDF) 119 | 120 | if MeGetStatus(meBDF, lspciBin): 121 | print("[!] THIS SYSTEM IS VULNERABLE!!!") 122 | else: 123 | print("[+] This system isn't vulnerable.") 124 | 125 | if __name__=="__main__": 126 | main() 127 | --------------------------------------------------------------------------------