├── LICENSE ├── readme.md ├── scripts ├── makesh └── mkrelease └── src └── nl └── peterbjornx └── intelme ├── entry ├── ConfigTool.java ├── MFSTool.java ├── RegionTool.java └── TestMain.java ├── io ├── ByteBufTools.java └── XmlTools.java ├── model ├── MERegion.java ├── MERegionHeader.java ├── cfg │ ├── ConfigArchive.java │ ├── ConfigFile.java │ └── ConfigRecord.java ├── fpt │ ├── FPTEntry.java │ └── FPTHeader.java ├── man │ ├── CryptoBlock.java │ ├── Manifest.java │ ├── ManifestExtension.java │ └── ManifestHeader.java ├── mfs │ ├── MFSBackingStore.java │ ├── MFSFileBacking.java │ ├── MFSVolume.java │ ├── MFSVolumeHeader.java │ ├── chunk │ │ └── MFSChunkStore.java │ └── page │ │ ├── MFSDataPage.java │ │ ├── MFSPageInfo.java │ │ └── MFSSystemPage.java └── parts │ ├── Partition.java │ └── code │ ├── CPDEntry.java │ ├── CPDHeader.java │ ├── CodePartition.java │ ├── CodePartitionDirectory.java │ ├── MFSPartition.java │ └── file │ ├── CodeFile.java │ └── ManifestFile.java └── util ├── CrcUtil.java ├── MEFormatException.java └── MFSException.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Peter Bosch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Intel Management Engine Image Tool 2 | ================================== 3 | This set of tools allow to extract and create firmware images for the ME, 4 | and was created by Peter Bosch for personal use. The code was not written 5 | with quality in mind, and as such there 6 | are little to no comments and no unit tests. As they say at my hackerspace: 7 | Patches welcome. 8 | 9 | The images produced by these tools are not yet verified against real 10 | hardware but do load in Intel FIT. 11 | 12 | Credits 13 | ------- 14 | 15 | The information required to implement the tool was gathered from original 16 | research and the following resources: 17 | * ME Analyzer (https://github.com/platomav/MEAnalyzer) by Plato Mavropoulos 18 | * unME11 (https://github.com/ptresearch/unME11) by Dmitry Sklyarov (@_Dmit) 19 | * parseMFS (https://github.com/ptresearch/parseMFS) by Dmitry Sklyarov (@_Dmit) 20 | * Intel ME: Flash Filesystem Explained (https://www.blackhat.com/eu-17/briefings.html#intel-me-flash-file-system-explained) by Dmitry Sklyarov (@_Dmit) 21 | * Various information from Igor Skochinsky 22 | 23 | It currently consists of three tools: 24 | 25 | ME Region Tool 26 | -------------- 27 | 28 | The ME region tool allows extracting a ME region into its constituent partitions. 29 | It produces an XML file containing the information contained within the Flash 30 | Partition Table that cannot be inferred from the files. 31 | 32 | MFS Tool 33 | -------- 34 | 35 | The MFS tools allows extracting MFS volumes on the FAT level, MFS directories 36 | are not yet supported. The tool can also add files to volumes, but not overwrite them. 37 | 38 | ME Config Tool 39 | -------------- 40 | The ME config tool can convert `intel.cfg` and `fitc.cfg` format archives into 41 | their contents and reconstruct them. Metadata and file lists are stored in an 42 | XML archive and as such the tool does not require the host filesystem to support 43 | UNIX permissions. 44 | 45 | 46 | -------------------------------------------------------------------------------- /scripts/makesh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | INJARPATH="$1" 3 | OUTFLPATH="$3" 4 | MAINCLASS="$2" 5 | TEMPLATE=""" 6 | #!/bin/bash 7 | \nJARPATH=\"\`which \"\$0\"\`\"\nMAINCLASS=$MAINCLASS\n\nexec java -cp \"\$JARPATH\" \$MAINCLASS \"\$@\"\n 8 | """ 9 | echo -e $TEMPLATE > "$OUTFLPATH" 10 | cat "$INJARPATH" >> "$OUTFLPATH" 11 | chmod +x "$OUTFLPATH" -------------------------------------------------------------------------------- /scripts/mkrelease: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | RELEASEDIR="out/meimagetool-$1" 3 | mkdir -p "$RELEASEDIR" 4 | scripts/makesh out/meimagetool.jar nl.peterbjornx.intelme.entry.RegionTool "$RELEASEDIR/meregiontool" 5 | scripts/makesh out/meimagetool.jar nl.peterbjornx.intelme.entry.MFSTool "$RELEASEDIR/mfstool" 6 | scripts/makesh out/meimagetool.jar nl.peterbjornx.intelme.entry.ConfigTool "$RELEASEDIR/meconfigtool" 7 | cp LICENSE readme.md "$RELEASEDIR/" 8 | cd out 9 | tar czf "meimagetool-$1.tar.gz" "meimagetool-$1" 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/nl/peterbjornx/intelme/entry/ConfigTool.java: -------------------------------------------------------------------------------- 1 | package nl.peterbjornx.intelme.entry; 2 | 3 | import nl.peterbjornx.intelme.io.ByteBufTools; 4 | import nl.peterbjornx.intelme.model.cfg.ConfigArchive; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | public class ConfigTool { 10 | 11 | public static void main(String[] args) throws IOException { 12 | if ( args.length == 1 && (args[0].equals("-h") || 13 | args[0].equals("--help") || 14 | args[0].equals("/?")) ) { 15 | usage(""); 16 | } else if ( args.length != 3 ) { 17 | usage("Not enough arguments"); 18 | } 19 | 20 | File bin = new File(args[1]); 21 | File dir = new File(args[2]); 22 | 23 | ConfigArchive region; 24 | 25 | switch (args[0]) { 26 | case "x": 27 | region = new ConfigArchive(ByteBufTools.ReadToByteBuffer(bin.getPath())); 28 | break; 29 | case "c": 30 | region = new ConfigArchive(dir); 31 | break; 32 | default: 33 | usage("Invalid mode"); 34 | return; 35 | } 36 | 37 | switch (args[0]) { 38 | case "x": 39 | region.export(dir); 40 | break; 41 | case "c": 42 | region.compile(bin); 43 | break; 44 | } 45 | 46 | } 47 | 48 | private static void usage(String reason) { 49 | System.err.println(reason); 50 | System.err.println("Usage: meconfigtool [x|c] "); 51 | System.err.println(" meconfigtool --help"); 52 | System.err.println(" meconfigtool -h"); 53 | System.err.println(" meconfigtool /?"); 54 | System.err.println(); 55 | System.err.println("The config archive tool allows compiling and extracting ME config files"); 56 | System.err.println(" The format used by the tool consists of a directory containing a metadata XML"); 57 | System.err.println(" and a separate binary for each file. The names of these binaries must"); 58 | System.err.println(" match the short partition name as configured in the metadata."); 59 | System.err.println(); 60 | System.err.println(" The modes of operation supported by the tool are:"); 61 | System.err.println(" x - Extract a archive to its constituent files and metadata."); 62 | System.err.println(" c - Create a archive from its constituent files and metadata."); 63 | System.err.println(" -h - Displays this message."); 64 | System.err.println(" /? - Displays this message."); 65 | System.err.println(" --help - Displays this message."); 66 | System.exit(255); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/nl/peterbjornx/intelme/entry/MFSTool.java: -------------------------------------------------------------------------------- 1 | package nl.peterbjornx.intelme.entry; 2 | 3 | import nl.peterbjornx.intelme.io.ByteBufTools; 4 | import nl.peterbjornx.intelme.model.mfs.MFSFileBacking; 5 | import nl.peterbjornx.intelme.model.mfs.MFSVolume; 6 | import nl.peterbjornx.intelme.util.MFSException; 7 | 8 | import java.io.File; 9 | import java.io.FileNotFoundException; 10 | import java.io.IOException; 11 | import java.nio.file.Files; 12 | import java.nio.file.Paths; 13 | 14 | public class MFSTool { 15 | 16 | private static String[] names = {null, null, null, null, null, null, "intel.cfg", "fitc.cfg" }; 17 | 18 | private static String getFileName( int i ) { 19 | if ( i >= 0 && i < names.length && names[i] != null ) 20 | return names[i]; 21 | return Integer.toString(i); 22 | } 23 | 24 | private static int getFileNumber( String str ) { 25 | for ( int i = 0; i < names.length; i++ ) 26 | if ( names[i] != null && names[i].equals(str) ) 27 | return i; 28 | return Integer.parseInt(str); 29 | } 30 | 31 | private static void createMFS(File template, File part) throws IOException { 32 | Files.copy(Paths.get(template.getAbsolutePath()),Paths.get(part.getAbsolutePath())); 33 | } 34 | 35 | private static MFSVolume mountImage( File part ) throws FileNotFoundException, MFSException { 36 | MFSFileBacking f = new MFSFileBacking(part); 37 | return new MFSVolume(0, f.Size(), f); 38 | } 39 | 40 | private static void appendFiles(MFSVolume vol, File directory) throws IOException, MFSException { 41 | File[] files = directory.listFiles(); 42 | assert files != null; 43 | for ( File f : files ) { 44 | if ( f.isDirectory() ) 45 | continue; 46 | int num = getFileNumber(f.getName()); 47 | vol.CreateFile( num, ByteBufTools.ReadToByteBuffer(f.getPath()).array() ); 48 | } 49 | vol.SyncMetadata(); 50 | } 51 | 52 | private static void extractFiles(MFSVolume vol, File directory) throws MFSException, IOException { 53 | directory.mkdir(); 54 | for ( int i = 0; i < vol.getFileCount(); i++ ) { 55 | if (!vol.FileExists(i)) 56 | continue; 57 | File f = new File(directory,getFileName(i)); 58 | byte[] buf = new byte[vol.getFileSize(i)]; 59 | vol.ReadFile(i,0,buf,0,buf.length); 60 | Files.write(Paths.get(f.getAbsolutePath()),buf); 61 | } 62 | } 63 | 64 | private static void mainCreate(String[] args) throws IOException, MFSException { 65 | if ( args.length != 4 ) 66 | usage("Not enough arguments"); 67 | File bin = new File(args[1]); 68 | File tmp = new File(args[2]); 69 | File dir = new File(args[3]); 70 | 71 | createMFS(tmp, bin); 72 | appendFiles(mountImage(bin), dir); 73 | } 74 | 75 | private static void mainExtract(String[] args) throws IOException, MFSException { 76 | if ( args.length != 3 ) 77 | usage("Not enough arguments"); 78 | File bin = new File(args[1]); 79 | File dir = new File(args[2]); 80 | 81 | extractFiles(mountImage(bin), dir); 82 | } 83 | 84 | public static void main(String[] args) throws IOException, MFSException { 85 | if ( args.length == 1 && (args[0].equals("-h") || 86 | args[0].equals("--help") || 87 | args[0].equals("/?")) ) { 88 | usage(""); 89 | } 90 | 91 | if ( args.length == 0) 92 | usage("No mode specified"); 93 | 94 | switch (args[0]) { 95 | case "x": 96 | mainExtract(args); 97 | break; 98 | case "c": 99 | mainCreate(args); 100 | break; 101 | default: 102 | usage("Invalid mode"); 103 | } 104 | } 105 | 106 | private static void usage(String reason) { 107 | System.err.println(reason); 108 | System.err.println("Usage: mfstool x "); 109 | System.err.println(" mfstool c