WEBVTT 00:00:00.000 --> 00:00:19.152 36C3 preroll music 00:00:19.152 --> 00:00:22.520 Herald: The next talk is an intel management engine, deep dive. 00:00:22.520 --> 00:00:27.230 Understanding the ME at the OS and hardware level and it is by Peter Bos, 00:00:27.230 --> 00:00:31.089 Please welcome him with a great round of applause! 00:00:31.089 --> 00:00:38.780 Applause 00:00:38.780 --> 00:00:49.409 Peter Bosch: Right. So everybody. Harry. Nice. OK. So welcome. Well, this is me. 00:00:49.409 --> 00:00:59.510 I'm a student at Leiden University. Yeah, I've always been really interested in how 00:00:59.510 --> 00:01:04.610 stuff works. And when I got a new laptop, I was like, you know, how does this thing 00:01:04.610 --> 00:01:08.410 really boot? I knew everything from reset vector onwards. I wanted to know what 00:01:08.410 --> 00:01:15.221 happened before it. So first I started looking at the boot guard ACM. While 00:01:15.221 --> 00:01:21.420 looking through it, I realized that not everything was as it was supposed to be. 00:01:21.420 --> 00:01:26.280 That led to a later part in the boot process being vulnerable, which ended up 00:01:26.280 --> 00:01:34.249 being discovered by me. And I found out here last year that I wasn't the only one 00:01:34.249 --> 00:01:38.310 to find it. Trammell Hudson also found it, and we reported it together, presented it 00:01:38.310 --> 00:01:43.399 at Hack in the Box. And then at the same time, I was already also looking at the 00:01:43.399 --> 00:01:49.350 management engine. Well, there had been a lot of research done on that before. The 00:01:49.350 --> 00:01:58.140 public info was mostly on the file system and on specific vulnerabilities, which 00:01:58.140 --> 00:02:04.400 still made it pretty hard to get started on reverse-engineering it. So that's why I 00:02:04.400 --> 00:02:10.340 thought it might be useful for me to present this work here. It's basically 00:02:10.340 --> 00:02:16.910 broken up into three parts. The first bit is just a quick introduction into the 00:02:16.910 --> 00:02:22.250 operating system it runs. So if you want to work on this yourself, you're more 00:02:22.250 --> 00:02:28.690 easily able to understand whats in your face in your Disassembler. So and then 00:02:28.690 --> 00:02:37.950 after that, I'll go over its role in the boot process and then also how this 00:02:37.950 --> 00:02:45.780 information can be used to to start developing a new firmware for it or do 00:02:45.780 --> 00:02:49.730 more security research on it. So first of all, what exactly is the management 00:02:49.730 --> 00:02:57.280 engine? There's been a lot of fuss about it being a backdoor and everything, in 00:02:57.280 --> 00:03:05.000 reality, if it is or not depends on the software that it runs. It's basically a 00:03:05.000 --> 00:03:09.110 processor with his own RAM and his own IO and MMUs and everything's sitting inside 00:03:09.110 --> 00:03:16.049 your south ridge. It's not in the CPU, It's in its outreach. So when I say this 00:03:16.049 --> 00:03:24.010 is gonna be about the sixth and seventh generation of Intel chips, I mean, mostly 00:03:24.010 --> 00:03:28.489 motherboards from those generations. If you run a newer CPU on it, it will also 00:03:28.489 --> 00:03:39.584 work for that. So yeah. Bit more detail. CPU it runs is based on the 80486, which, 00:03:39.584 --> 00:03:43.510 you know, is funny. It's quite an old CPU you and it's still being used in almost 00:03:43.510 --> 00:03:51.079 every computer nowadays. So it has a little bit of its own RAM. It has quite a 00:03:51.079 --> 00:03:58.150 bit of built in ROM, has a hardware accelerated cryptographic unit and it has 00:03:58.150 --> 00:04:05.450 fuses which are right once memory is used to store security settings and keys and 00:04:05.450 --> 00:04:11.079 everything. Some of the more scary features it has: Bus bridges to all of the 00:04:11.079 --> 00:04:16.419 buses inside the south ridge, it can access the RAM on the CPU and it can 00:04:16.419 --> 00:04:21.359 access the network, which makes it really quite dangerous. If there is a 00:04:21.359 --> 00:04:28.409 vulnerability or if it runs anything nefarious and it's tasks nowadays include 00:04:28.409 --> 00:04:35.860 starting the computer as well as adding management features. This is mostly used 00:04:35.860 --> 00:04:41.190 in servers where it can serve as a board management controller, do like a remote 00:04:41.190 --> 00:04:49.001 keyboard and video and it does security boot guard, which is the signing of a 00:04:49.001 --> 00:04:54.830 firmware and verification of signatures. It implements a firmware TPM and there is 00:04:54.830 --> 00:05:02.590 also a SDK to use it as a general purpose secure enclave. So on the software side of 00:05:02.630 --> 00:05:12.650 it, it runs a custom operating system, parts of which are taken from MINIX, the 00:05:12.650 --> 00:05:17.250 teaching operating system by Andrew Tanenbaum. It's a micro kernel operating 00:05:17.250 --> 00:05:32.930 system. It runs binaries that are in a completely custom format. It's really 00:05:32.930 --> 00:05:36.030 quite high level system actually. If you look at it in terms of the operating 00:05:36.030 --> 00:05:40.681 system, it runs, it's mostly like Unix, which makes it kind of familiar, but it 00:05:40.681 --> 00:05:46.819 also has large custom parts. Like I said before in this talk, I'm going to be 00:05:46.819 --> 00:05:52.740 speaking about sixth and seventh generation Intel core chipsets, so that's 00:05:52.740 --> 00:05:58.949 Sunrise Point. Lewisburg, which is the server version of this and also the laptop 00:05:58.949 --> 00:06:04.410 system on a chip they're just called Intel core low power. They also include the 00:06:04.410 --> 00:06:08.360 chipset as a separate die. So it also applies to them. In fact, I've been 00:06:08.360 --> 00:06:11.979 testing most of this stuff. I'm going to tell you about on the laptop that's 00:06:11.979 --> 00:06:19.430 sitting right here, which is a Lenovo T 460. The version of the firmware I've been 00:06:19.430 --> 00:06:30.820 looking at is 11001205. Right. So I do need to put this up there. I'm not a part 00:06:30.820 --> 00:06:38.520 of Intel, nor have I signed any contracts to them. I've found everything in ways 00:06:38.520 --> 00:06:43.500 that you could also do. I didn't have any leaked NDA stuff or anything that you 00:06:43.500 --> 00:06:53.099 couldn't get your hands on. It's also a very wide subject area, so there might be 00:06:53.099 --> 00:07:00.580 some mistakes here or there, but generally it should be right. Well, if you want to 00:07:00.580 --> 00:07:04.220 get started working on an ME firmware, want to reverse-engineer it or modify it 00:07:04.220 --> 00:07:08.580 in some way first, you've got to deal with the image file. You've got your SPI flash. 00:07:08.580 --> 00:07:12.009 It's where most of its firmware lives in the same flash chip as your BIOS. So 00:07:12.009 --> 00:07:17.410 you've got that image. And then how do you get the code out? Well, there's tools for 00:07:17.410 --> 00:07:22.949 that. It's already been extensively documented, documented by other people. 00:07:22.949 --> 00:07:28.681 And you can basically just download a tool and run it against it. Which makes this 00:07:28.681 --> 00:07:31.690 really easy. This is also the reason why there hasn't been a lot of research done 00:07:31.690 --> 00:07:35.940 yet before these tools were around. You couldn't get to all of the code. The 00:07:35.940 --> 00:07:41.349 kernel was compressed using Huffman tables, which were stored in ROM. You 00:07:41.349 --> 00:07:45.360 couldn't get to the ROM without getting code execution on the thing. So there was 00:07:45.360 --> 00:07:52.639 basically no way of getting access to the kernel code. And I think also to see some 00:07:52.639 --> 00:07:55.800 library. But that's not a problem anymore. You can just download a tool and unpack 00:07:55.800 --> 00:08:02.520 it. Also, the intel tool to generate firmware images, which you can find in 00:08:02.520 --> 00:08:11.979 some open directories on the internet, has Qt resources, XML-files which basically have the 00:08:11.979 --> 00:08:18.330 description for all of the file formats used by these ME versions, including names 00:08:18.330 --> 00:08:26.050 and comments to go with those structured definitions. So that's really useful. So 00:08:26.050 --> 00:08:30.430 we look at one of these images. It has a couple of partitions, some of them overlap 00:08:30.430 --> 00:08:38.150 and some of them are storage, some are code. So there is the main partitions, 00:08:38.150 --> 00:08:45.709 FTPR and NFTP, which contain the programs it runs. There's MFS, which is the read-write 00:08:45.709 --> 00:08:51.980 file system it uses for persistent storage. And then there is a log to flash 00:08:51.980 --> 00:08:57.320 option, the possibility to embed a token that will tell the system to unlock all 00:08:57.320 --> 00:09:02.850 debug access which has to be signed by Intel so it's not really of any use to us. 00:09:02.850 --> 00:09:07.439 And then there is something interesting, ROM bypass. Like I said, you can't get 00:09:07.439 --> 00:09:13.160 access to the ROM without running code on it. And ROM is mask ROM. So it's internal 00:09:13.160 --> 00:09:17.540 to the chip, but Intel has to develop new ROM code and have to test it without 00:09:17.540 --> 00:09:23.270 respinning the die every time. So they have a possibility on a unlocked 00:09:23.270 --> 00:09:28.170 preproduction chipset to completely bypass the internal ROM and load even the early 00:09:28.170 --> 00:09:33.670 boot code from the flash chip. Some of these images have leaked and you can use 00:09:33.670 --> 00:09:39.250 them to get a look at the ROM code, even without being able to dump it. That's 00:09:39.250 --> 00:09:45.610 going to be really useful later on. So then you've got these code partitions and 00:09:45.610 --> 00:09:51.230 they contain a whole lot of files. So there is the binaries themselves which 00:09:51.230 --> 00:09:57.569 don't have any extension. There is the metadata files. So the binary format they 00:09:57.569 --> 00:10:05.350 use has no headers, nothing included. And all of that data is in the metadata file. 00:10:05.350 --> 00:10:12.000 And when you use the unME11 tool, you can actually, it'll convert those to text 00:10:12.000 --> 00:10:16.069 files for you so you can just get started without really understanding how they 00:10:16.069 --> 00:10:26.640 work. Yes. So the metadata. It's type- length-value structure, which contains a 00:10:26.640 --> 00:10:31.180 whole lot of information the operating system needs. It has the info on the 00:10:31.180 --> 00:10:35.820 module, whether it's data or code, where it should be loaded, what the privileges 00:10:35.820 --> 00:10:43.390 of the process should be, a SHA checksum for validating it and also some 00:10:43.390 --> 00:10:49.000 higher level stuff such as device file definitions if it's a device driver or any 00:10:49.000 --> 00:10:55.430 other kind of server. I've actually written some code that uses this, that's 00:10:55.430 --> 00:11:01.460 on GitHub, so if you want a closer look at it, some of the slides have a link to to 00:11:01.460 --> 00:11:09.780 get a file in there which contains the full definitions. Right. So all the code 00:11:09.780 --> 00:11:16.801 on the ME is signed and verified by Intel. So you can't just go and put in a new 00:11:16.801 --> 00:11:24.689 binary and say, hey, let's run this. The way they do this is in Intel's 00:11:24.689 --> 00:11:30.300 manufacture-time fuses, they have a hash of the public key that they use to sign 00:11:30.300 --> 00:11:36.070 it. And then on each flash partition, there is a manifest which is signed by the 00:11:36.070 --> 00:11:40.820 key and it contains the SHA hashes for all the metadata files, which then contain a 00:11:40.820 --> 00:11:47.150 SHA hash for the code files. It doesn't seem to be any major problems in verifying 00:11:47.150 --> 00:11:52.530 this, so it's useful to know, but it's you're not really gonna use this. And then 00:11:52.530 --> 00:12:00.300 the modules themself, as I've said, they're flat binaries. Mostly. The 00:12:00.300 --> 00:12:05.560 metadata contains all the info the kernel uses to reconstruct the actual program 00:12:05.560 --> 00:12:13.530 image in memory. And a curious thing here is that the actual base address for all 00:12:13.530 --> 00:12:17.459 the modules for old programs is the same across an image. So if you have a 00:12:17.459 --> 00:12:19.930 different version, it's going to be different. But if you have two programs 00:12:19.930 --> 00:12:25.949 from the same firmware it's gonna be loaded at the same virtual address. Right. 00:12:25.949 --> 00:12:32.820 So when you want to look at it, you're gonna load it in some disassembler, like 00:12:32.820 --> 00:12:39.540 for example IDA, and you'll see this, it disassembles fine, but it's gonna 00:12:39.540 --> 00:12:44.270 reference all kinds of memory that you don't have access to. So usually you'd 00:12:44.270 --> 00:12:49.459 think maybe I've loaded up a wrong address or or am I missing some library? Well, 00:12:49.459 --> 00:12:55.150 here you've loaded it correctly if you use that, the address from the metadata file. 00:12:55.150 --> 00:13:02.310 But you are in fact missing a lot of memory segments. And let's just take a 00:13:02.310 --> 00:13:09.829 look at each of these. It's calling and switching code. It's pushing a pointer 00:13:09.829 --> 00:13:15.890 there, which is data. And what's that? So it has shared libraries, even though it's 00:13:15.890 --> 00:13:19.920 flat binaries. It actually does use shared libraries because you only have 1.5 00:13:19.920 --> 00:13:24.319 megabyte of RAM. You don't want to link your C library into everything and 00:13:24.319 --> 00:13:32.800 waste what little memory you have. So there is the main system library which is 00:13:32.800 --> 00:13:39.270 like libc on a Linux system. It's in a flash partition, so you can actually just 00:13:39.270 --> 00:13:45.689 load it and take a look at it easily and it starts out with a jump table. So 00:13:45.689 --> 00:13:48.770 there's no symbols in the metadata file or anything. It doesn't do dynamic linking. 00:13:48.770 --> 00:13:56.549 It loads the pages for the shared library at a fixed address, which is also in the 00:13:56.549 --> 00:14:01.620 shared library's metadata. And then it's just there in the processor's memory and 00:14:01.620 --> 00:14:06.130 it's gonna jump there if it needs a function. And the functions themself are 00:14:06.130 --> 00:14:12.890 just using the normal System V, x86 calling conventions. So it's pretty easy 00:14:12.890 --> 00:14:17.980 to look at that using your normal tools. There's no weird register argument passing 00:14:17.980 --> 00:14:24.559 going on here. So, right. Now, shared libraries. There's two of them. And this 00:14:24.559 --> 00:14:28.160 is where it gets annoying. The system library, you've got access to that so you 00:14:28.160 --> 00:14:32.850 can just take your time and go through it and try to figure out, you know, oh, hey, 00:14:32.850 --> 00:14:39.880 is this open or is this read or what's this function doing? But then there's also 00:14:39.880 --> 00:14:49.150 another second really large library, which is in ROM. They have all the C library 00:14:49.150 --> 00:14:54.300 functions and some of their custom helper routines that don't interact with the 00:14:54.300 --> 00:15:00.920 kernel directly, such as strings functions. They live in ROM. So when 00:15:00.920 --> 00:15:04.700 you've got your code and this is basically where I was when I was here last year, 00:15:04.700 --> 00:15:07.040 you're looking through it and you're seeing calls to a function you don't have 00:15:07.040 --> 00:15:11.010 the code for all over the place. And you have to figure out by its signature what 00:15:11.010 --> 00:15:14.870 is it doing. And that works for some of the functions and it's really difficult 00:15:14.870 --> 00:15:20.610 for other ones. That really had me stopped for a while. Then I managed to find one of 00:15:20.610 --> 00:15:25.070 these ROM bypass images and I had the code for a very early development build of the 00:15:25.070 --> 00:15:29.370 ROM. This is where I got lucky. So the actual entry point addresses are fixed 00:15:29.370 --> 00:15:33.939 across a entire chipset family. So if you have an image for the server version of 00:15:33.939 --> 00:15:39.310 like 100 series chipset or for client version or for a desktop or laptop 00:15:39.310 --> 00:15:47.540 version, it's all gonna be the same ROM addresses. So even though the code might 00:15:47.540 --> 00:15:51.930 be different, you'll have the jump table, which means the addresses can say fixed. 00:15:51.930 --> 00:15:56.760 So this only needs to be done once. And in fact when I upload my slides later, there 00:15:56.760 --> 00:16:02.919 is a slide in there at the end that has the addresses for the most used functions. 00:16:02.919 --> 00:16:07.350 So you're not going to have to repeat that work, at least not for this chipset. So if 00:16:07.350 --> 00:16:15.160 you want to look at a simple module, you've loaded it, now you've applied the 00:16:15.160 --> 00:16:21.860 things I just said, and you still don't have the data sections. If I don't know 00:16:21.860 --> 00:16:26.669 what that function there is doing, but it's not very important. It actually 00:16:26.669 --> 00:16:33.230 returns a value, I think, that's not used anywhere, but it must have a purpose 00:16:33.230 --> 00:16:40.220 because it's there. Right. So then you look at the entry point and this is a lot 00:16:40.220 --> 00:16:44.660 of stuff. And the main thing that matters here is on the right half of the screen, 00:16:44.660 --> 00:16:50.189 there is a listing from a MINIX repository and on the left half there is a 00:16:50.189 --> 00:16:54.809 disassembly from an ME module. So it's mostly the same. There is one key 00:16:54.809 --> 00:16:58.419 difference, though. The ME module actually has a little bit of code that runs before 00:16:58.419 --> 00:17:06.230 its C library startup function. And that function actually does all the ME specific 00:17:06.230 --> 00:17:13.980 initialization, does a lot of stuff related to how C library data is kept 00:17:13.980 --> 00:17:21.520 because there is also no data segments for the C library being allocated by the 00:17:21.520 --> 00:17:25.820 kernel. So each process actually reserves a part of its own memory and tells the C 00:17:25.820 --> 00:17:31.290 library, like, any global variables you can store in there. But when you look at 00:17:31.290 --> 00:17:37.610 that function, one of the most important things that it calls is this function. 00:17:37.610 --> 00:17:41.510 It's very simple, it just copies a bunch of RAM. So they don't have support for 00:17:41.510 --> 00:17:46.650 initialized data sections. It's a flat binary. What they do is they they actually 00:17:46.650 --> 00:17:51.520 use the .bss segment, the zeroed segment at the end of the address space, and copy 00:17:51.520 --> 00:17:57.070 over a bunch of data in the program. The program itself is not aware of this. It's 00:17:57.070 --> 00:18:04.180 really in the initialization code and in linker script. So this is also something 00:18:04.180 --> 00:18:09.170 that's very important because you're going to need to also at that address in the 00:18:09.170 --> 00:18:13.310 data section, you're going to need to load the last bit of the of the binary. 00:18:13.310 --> 00:18:20.520 Otherwise you're missing constants or at least initialization values. Right. Then 00:18:20.520 --> 00:18:26.150 there is the full memory map to the processes themselves. It's a flat 32 bit 00:18:26.150 --> 00:18:31.970 address space. It's got everything you expect in there. It's got a stack and a 00:18:31.970 --> 00:18:39.500 heap and everything. There's a little bit of heap allocated right on initialization. 00:18:39.500 --> 00:18:44.690 This is this is basically how you derive the address space layout from the 00:18:44.690 --> 00:18:51.100 metadata, especially like the data segment, then, and the stack itself is 00:18:51.100 --> 00:18:56.180 like the address location varies a lot because of the number of threads that are 00:18:56.180 --> 00:19:03.380 in use or the size of data sections. And also those stack guards, they're not 00:19:03.380 --> 00:19:07.960 really stack guards. There is also metadata for each thread in there. But 00:19:07.960 --> 00:19:13.640 that's nothing that's relevant to the process itself, only to the kernel. And 00:19:13.640 --> 00:19:21.890 well, if you then skip forward a bit and you've done all these - you look at your 00:19:21.890 --> 00:19:28.790 simple driver like this. This is taken from a driver used to talk to the CPU, 00:19:28.790 --> 00:19:34.630 like, OK. So when I say CPU or host, by the way, I mean the CPU, like your big 00:19:34.630 --> 00:19:39.370 SkyLake, or KabyLake, or CoffeeLake, whatever your big CPU that runs your own 00:19:39.370 --> 00:19:46.070 operating system. Right. So this is used to to send messages there. But if you look 00:19:46.070 --> 00:19:51.680 at what's going on here, OK - think I had a problem with the animation here - it 00:19:51.680 --> 00:19:57.000 sets up some stuff and then it calls a library function that's in the main syslib 00:19:57.000 --> 00:20:01.270 library, which actually has a main loop for the program. That's because Intel was 00:20:01.270 --> 00:20:06.440 smart and they added a nice framework for device driver implementing programs, 00:20:06.440 --> 00:20:10.130 because it's a micro kernel, so device drivers are just usual programs, calling 00:20:10.130 --> 00:20:20.060 specific APIs. Then there's normal POSIX file I/O. No standard I/O, but it has all 00:20:20.060 --> 00:20:26.530 the normal open, and read, and ioctl and everything functions. And then there's 00:20:26.530 --> 00:20:30.170 more initialization for the srv library. And this is basically what all the simple 00:20:30.170 --> 00:20:38.890 drivers look like in it. And then there's this. Because they're so low a memory, 00:20:38.890 --> 00:20:50.040 they don't actually use standard I/O, or even printf itself to do most of the 00:20:50.040 --> 00:20:54.820 debugging. It uses a thing that's called "sven", I'll touch on that later. So there 00:20:54.820 --> 00:20:59.150 is the familiar APIs that I talked about. It even has POSIX threads, or at least a 00:20:59.150 --> 00:21:04.510 subset of it, and there is all the functions that you'd expect to find on 00:21:04.510 --> 00:21:08.700 some generic Unix machine. So that shouldn't be too much of a problem to do 00:21:08.700 --> 00:21:14.570 with, but then there's also their own tracing solution, sven. That's what Intel 00:21:14.570 --> 00:21:17.350 calls it. The name is in all the development tools that you can download 00:21:17.350 --> 00:21:23.370 from their site, and basically, they don't include format strings for a lot of the 00:21:23.370 --> 00:21:28.390 stuff. They just have a 32-bit identifier that is sent over debug port, and it 00:21:28.390 --> 00:21:34.270 refers to a format string in a dictionary that you don't have. There is one of the 00:21:34.270 --> 00:21:38.820 dictionaries for a server chip that's floating around the internet, but even 00:21:38.820 --> 00:21:45.940 that is incomplete. And the normal non-NDA version of the Intel developer tools has 00:21:45.940 --> 00:21:53.810 some 50 format strings for really common status messages it might output, but yeah, 00:21:53.810 --> 00:21:57.391 like, if you see these functions, just realize it's doing some debug print. There 00:21:57.391 --> 00:22:00.550 might be dumping some states or just telling it it's gonna do something else. 00:22:00.550 --> 00:22:12.020 It's no important logic actually happens in here. Right. So then for device files. 00:22:12.020 --> 00:22:16.190 They're actually defined in a manifest. When the kernel loads a program, and that 00:22:16.190 --> 00:22:20.830 program wants to expose some kind of interface to other programs its manifest 00:22:20.830 --> 00:22:27.780 will contai,n or it's metadata file will contain a special file producer entry, and 00:22:27.780 --> 00:22:33.120 that says, you know, you have these device files, with a name, and an access mode and 00:22:33.120 --> 00:22:39.210 the user, and group ID, and everything, and the minor numbers, and the kernel 00:22:39.210 --> 00:22:42.830 sends this to the- or not kernel- the program loader sends this to the virtual 00:22:42.830 --> 00:22:47.720 file system server and it automatically gets a device file, pointing to the right 00:22:47.720 --> 00:22:51.800 major or minor number. And then there's also a library, as I said, to provide a 00:22:51.800 --> 00:23:03.680 framework for a driver. And that looks like this. It's really easy to use. If you 00:23:03.680 --> 00:23:08.070 were a ME developer you just write some callbacks for open, and close, and 00:23:08.070 --> 00:23:11.000 everything, and it automatically calls them for you, when a message comes in, 00:23:11.000 --> 00:23:15.400 telling you that that happened, which also makes it really easy to reverse engineer, 00:23:15.400 --> 00:23:21.100 'cause if you look at a driver, it just loads some callbacks, and you can know, by 00:23:21.100 --> 00:23:27.510 their offset in a structure, what actual call they're implementing. Right, so then 00:23:27.510 --> 00:23:31.950 there is one of the more weird things that's going on here: How the actual 00:23:31.950 --> 00:23:37.470 userland programs get access to memory map registers. There's a lot of this going on. 00:23:37.470 --> 00:23:42.830 Calls to a couple of functions that have some magic arguments. The second one you 00:23:42.830 --> 00:23:50.640 can easily tell is the offset, because it has- it increases in very nice power-of- 00:23:50.640 --> 00:23:54.670 two steps, so it's probably the register offsets, and then what comes after it 00:23:54.670 --> 00:24:00.160 looks like a value. And then the first bit seems to be a magic number. Well, it's 00:24:00.160 --> 00:24:05.479 not. There is also an extension in the metadata, saying these are the memory 00:24:05.479 --> 00:24:12.170 mapped I/O ranges, and those ranges, they'd each list a physical base address, 00:24:12.170 --> 00:24:19.360 and a size, and permissions for them. Then the index in that list does not directly 00:24:19.360 --> 00:24:23.150 correspond to the magic value. The magic value actually you need to do a little 00:24:23.150 --> 00:24:27.680 computation on the offset, and you can access it through those functions. The 00:24:27.680 --> 00:24:38.600 computation itself might be familiar. Yeah, so these are the functions. The 00:24:38.600 --> 00:24:44.610 value is a segment selector. So they use them. Actually, don't use paging for inter 00:24:44.610 --> 00:24:51.820 process isolation, they use segments like x86 Protected Mode segments. And for each 00:24:51.820 --> 00:24:56.610 memory mapped I/O range there is a separate segments, and you manually specify 00:24:56.610 --> 00:25:04.280 that, which is just weird to me, like, why would you use x86 segmenting on a modern 00:25:04.280 --> 00:25:10.610 system? Minix does it, but, yeah, to extent that even to this? Luckily, normal 00:25:10.610 --> 00:25:16.130 address space is flat, like, to the process, not to the kernel. Right, so now 00:25:16.130 --> 00:25:24.870 we can access memory mapped I/O. That's all the, like the really high level stuff. 00:25:24.870 --> 00:25:28.700 So what's going on under there? It's got all the basic microkernel stuff, so 00:25:28.700 --> 00:25:33.020 message passing, and then some optimizations to actually make it perform 00:25:33.020 --> 00:25:40.140 well on a really slow CPU. The basics are, you can send a message, you can receive a 00:25:40.140 --> 00:25:46.160 message, and you can send and receive a message, where you basically say "Send a 00:25:46.160 --> 00:25:50.930 message, wait till a response comes in, then continue", which is used to wrap 00:25:50.930 --> 00:25:58.400 function calls. This is mostly the same as in Minix. There's some subtle changes, 00:25:58.400 --> 00:26:08.230 which I'll get to later. And then memory grants are something that only appeared in 00:26:08.230 --> 00:26:13.080 Minix really recently. It's a way for a process to basically create a new name for 00:26:13.080 --> 00:26:16.690 a piece of memory it has, and give a different process access to it, just by 00:26:16.690 --> 00:26:21.630 sharing the number. These are referred to by the process ID and a number of that 00:26:21.630 --> 00:26:28.470 range. So the process IDs are actually local per process, so to uniquely identify 00:26:28.470 --> 00:26:35.461 one you need to say process ID plus that number, and they're only granted to a 00:26:35.461 --> 00:26:38.300 single process. So when a process creates one of these, it can't even access it 00:26:38.300 --> 00:26:42.490 itself, unless it creates a grant for itself, which is not really that useful, 00:26:42.490 --> 00:26:51.880 usually. These grants are used to prevent having to copy over all the data inside 00:26:51.880 --> 00:26:57.500 the IPC message used to implement a system call. Yeah, these are the basic operations 00:26:57.500 --> 00:27:03.190 on it. You can create one, you can copy into and from it. So, you can't actually 00:27:03.190 --> 00:27:07.010 map it. A process that receives one of these has to say to the kernel, using a 00:27:07.010 --> 00:27:12.721 system call, "please write this data into that area of memory that belongs to a 00:27:12.721 --> 00:27:17.930 different process." And then there's also indirect grants, because, you know, in 00:27:17.930 --> 00:27:25.309 Minix they do have this, but also only recently, and usually if you have a 00:27:25.309 --> 00:27:30.360 microkernel system, you would have to copy your buffer for a read call first to the 00:27:30.360 --> 00:27:36.540 file system server and then back to, like, either the hard disk driver, or the device 00:27:36.540 --> 00:27:40.620 driver that's implementing a device file. So the ME actually allows you to create a 00:27:40.620 --> 00:27:45.860 grant, pointing to a grant, that was given to you by someone else. And then that 00:27:45.860 --> 00:27:52.820 grant will inherit the privileges of the process that creates it, combined with 00:27:52.820 --> 00:27:57.530 those that it assignes to it. So if the process has a read/write grant it can 00:27:57.530 --> 00:28:01.340 create a read-only or write-only grant, but it cannot, if it only has a read 00:28:01.340 --> 00:28:08.860 grant, it cannot add write rights to it for a different process, obviously. So 00:28:08.860 --> 00:28:12.880 then there is also some big differences from MINIX. In MINIX you address a process 00:28:12.880 --> 00:28:18.080 by its process ID or thread ID with a generation number attached to it. In the 00:28:18.080 --> 00:28:25.440 ME you can actually address IPC to a file descriptor. Kernel doesn't actually know a 00:28:25.440 --> 00:28:28.610 lot about file descriptors, it just implements the basic thing where you have 00:28:28.610 --> 00:28:32.350 a list of files and each process has a list of file descriptors assigning integer 00:28:32.350 --> 00:28:39.320 numbers to those files to refer to them by. And this is used so you can as a 00:28:39.320 --> 00:28:43.040 process, you can actually directly talk to a device driver without knowing what is 00:28:43.040 --> 00:28:47.110 process ID is. So you don't send it to the file system server, you send it to the 00:28:47.110 --> 00:28:51.740 file descriptor or the Kernel just magically corrects it for you. And they 00:28:51.740 --> 00:28:55.550 moved select into the kernel so you can tell the kernel: "Hey, I want to wait till 00:28:55.550 --> 00:28:59.720 the file system server tells me that it has not available or till a message comes 00:28:59.720 --> 00:29:05.440 in." This is one of the most complicated system calls the ME offers that's used in 00:29:05.440 --> 00:29:12.010 a normal program. You can mostly ignore it and just look like: "Hey, those arguments 00:29:12.010 --> 00:29:16.760 sort of define a file descriptor set as a bit field." And then there's the message 00:29:16.760 --> 00:29:21.040 that might have been received and there's DMA locks because you don't just want to 00:29:21.040 --> 00:29:24.790 write to registers. You actually might want to do the direct memory access from 00:29:24.790 --> 00:29:30.720 hardware so you you can actually tell the kernel to lock one of these memory grounds 00:29:30.720 --> 00:29:38.260 in RAM for you, it won't be swapped out anymore. And yeah, it will even tell you 00:29:38.260 --> 00:29:42.020 the physical address so you can just load that into a register and it's not really 00:29:42.020 --> 00:29:46.760 that complicated. Just lock it, get a physical access, write into the register 00:29:46.760 --> 00:29:53.580 and continue. Well, that's the most important stuff about the operating 00:29:53.580 --> 00:29:58.929 system. The hardware itself is a lot more complicated because the operating system, 00:29:58.929 --> 00:30:03.300 once you have the code, you can just reverse engineer it and get to know it. 00:30:03.300 --> 00:30:11.010 The hardware. Well, let's just say it's a real pain to have to reverse engineer a 00:30:11.010 --> 00:30:16.179 piece of hardware together with its driver. Like if you've got the driver 00:30:16.179 --> 00:30:18.450 code, but you don't know what the registers do. So you don't know what a lot 00:30:18.450 --> 00:30:24.440 of logic does. And you're trying to both figure out what the logic is and what the 00:30:24.440 --> 00:30:30.050 actual registers do. Right. So first you want to know which physical address goes 00:30:30.050 --> 00:30:39.881 where? The metadata listings I showed you actually have names in there. Those are 00:30:39.881 --> 00:30:47.940 not in the metadata files themself, I annotated those. So you just see the 00:30:47.940 --> 00:30:56.680 physical address and size. But there is one module, the bus driver module and the 00:30:56.680 --> 00:31:04.230 bus driver is normal user process, but it implements stuff like PCI configuration 00:31:04.230 --> 00:31:09.550 space accesses and those things. And it has a nice table in it with names for 00:31:09.550 --> 00:31:17.049 devices. So if you just run strings on it, you'll see these things. When I saw this, 00:31:17.049 --> 00:31:20.960 I was was pretty glad because at least I could make sense what device was being 00:31:20.960 --> 00:31:26.680 talked to in a in a certain program. So the bus driver does all these things. It 00:31:26.680 --> 00:31:30.990 manages power getting to devices, it manages configuration space access, it 00:31:30.990 --> 00:31:35.960 manages the different kinds of buses and IOMU that are on the system. And it makes 00:31:35.960 --> 00:31:39.500 sure that the normal driver never has to know any of these details. It just asked 00:31:39.500 --> 00:31:45.520 it for a device by a number assigned to it a build time. And then the bus driver 00:31:45.520 --> 00:31:50.360 says, OK, here's a range of physical address space you can now write to. So 00:31:50.360 --> 00:31:56.640 that's a really nice abstraction and also gives us a lot of information because the 00:31:56.640 --> 00:32:01.640 really old builds for sunrise point actually have a hell of a lot of debug 00:32:01.640 --> 00:32:07.021 strings in there as printf format strings, not as catalogue ID. It's 00:32:07.021 --> 00:32:11.910 one of the only pieces of code for the ME that does this, so that already tells you 00:32:11.910 --> 00:32:15.480 a lot. And then there's also the table that I just talked about that has the 00:32:15.480 --> 00:32:23.760 actual info on the devices and names. So I generated some DocuWiki content from this 00:32:23.760 --> 00:32:28.570 that I use myself and this is what's in the table, part of it. So it tells you 00:32:28.570 --> 00:32:33.070 what address PCI configuration space lives at. That tells you to do the bus device 00:32:33.070 --> 00:32:38.130 function for it through that. It tells you on what chipset SKU they're present using 00:32:38.130 --> 00:32:44.640 a bitfield. And it tells you their names in different fields. It also contains the 00:32:44.640 --> 00:32:48.540 values that are used to write the base address registers for PCI. So also their 00:32:48.540 --> 00:32:54.190 normal memory ranges. And there's even more devices. So the ME has access to a 00:32:54.190 --> 00:32:58.860 lot of stuff. A lot of it is private to it. A lot of it is components that also 00:32:58.860 --> 00:33:06.110 exist in the rest of the computer. And there's not a lot of information. A lot of 00:33:06.110 --> 00:33:11.410 these are basically all the things that are out there together with conference 00:33:11.410 --> 00:33:15.140 slides published by other people who have done research on the ME. I didn't have 00:33:15.140 --> 00:33:21.980 time to add links to those, but they're easy to find on Google. I'll get later to 00:33:21.980 --> 00:33:28.230 this, I actually wrote a emulator for the ME, a partial emulator to be able to run 00:33:28.230 --> 00:33:34.230 ME code and analyze it, which obviously needs to know a bit about the hardware so 00:33:34.230 --> 00:33:41.030 you can look at the app. There is some files in Intel's debugger package, 00:33:41.030 --> 00:33:46.150 specific versions of that that have really detailed info on some of the devices, also 00:33:46.150 --> 00:33:51.460 not all of it. And I wrote some tool to parse some of the files. It's really rough 00:33:51.460 --> 00:33:57.040 code. I published it because people wanted to see what I was doing. It doesn't work 00:33:57.040 --> 00:34:04.080 out of the box. And there is a nice talk on this by Mark Ermolov and Maxim 00:34:04.080 --> 00:34:06.870 Goryachy.. Actually I don't know if I'm pronouncing that correctly, but they've 00:34:06.870 --> 00:34:12.049 done a lot of work on the ME and this particular talk by them is really useful. 00:34:12.049 --> 00:34:16.339 And then there's also something else. There is a second ME on server chipsets, 00:34:16.339 --> 00:34:21.299 the innovation engine. It's basically a copy paste of the ME to provide a ME that 00:34:21.299 --> 00:34:24.760 the vendor can write code for. Don't think it's used a lot. I've only been able to 00:34:24.760 --> 00:34:31.639 find HP software that actually targets it and that has some more debug strings, but 00:34:31.639 --> 00:34:36.639 also not a lot, it mostly has a table containing register names, but they're 00:34:36.639 --> 00:34:41.869 really abbreviated and for a really small subset of the devices, there is 00:34:41.869 --> 00:34:48.280 documentation out there in a Pentium N and J series datasheet. It's seems like they 00:34:48.280 --> 00:34:52.409 compile their a lot of code or whatever with the wrong defines because it doesn't 00:34:52.409 --> 00:35:00.350 actually fit into the manual that well, it's just a section that has like some 20 00:35:00.350 --> 00:35:08.640 tables that shouldn't be in there. So this is from that talk I just referenced and 00:35:08.640 --> 00:35:12.609 it's a overview of the innovation engine and the bus bridges and everything in 00:35:12.609 --> 00:35:20.070 there. This isn't very precise. So based on some of those files from System Studio, 00:35:20.070 --> 00:35:24.500 I try to get a better understanding of this, which is this. This is the entire 00:35:24.500 --> 00:35:29.760 chipset. The little DMA block in the top left corner is what connects to your CPU. 00:35:29.760 --> 00:35:36.570 And all of the big blocks with a lot of ports are our bus bridges or switches for 00:35:36.570 --> 00:35:45.470 PCIexpress-like fabric. So there's a lot going on. The highlighted area is the 00:35:45.470 --> 00:35:59.081 management engine memory space and the rest of it is like the global chipset. The 00:35:59.081 --> 00:36:02.840 things I've highlighted in green hair are on the primary PCI bus. So there's this 00:36:02.840 --> 00:36:08.210 weird thing going on where there seems to be two PCI hierarchies, at least 00:36:08.210 --> 00:36:13.741 logically. So in reality it's not even PCI, but on intel systems, there's a lot 00:36:13.741 --> 00:36:19.600 of stuff that behaves as if it is PCI. So it has like a bus device function and 00:36:19.600 --> 00:36:28.650 numbers, PCI configuration space registers and they have two different roots for the 00:36:28.650 --> 00:36:32.310 configuration space. So even though the configuration space address includes a bus 00:36:32.310 --> 00:36:36.480 number, they have two completely different things with each. Each of which has its 00:36:36.480 --> 00:36:41.290 own bus zero. So that's that's weird also because they don't make sense when you 00:36:41.290 --> 00:36:45.680 look at how the hardware is laid out. So this is stuff that's on the primary PCI 00:36:45.680 --> 00:36:50.780 configuration space that's directly accessed by the EM, by the north bridge on 00:36:50.780 --> 00:36:55.260 the ME CPU. So that's the minute I A system agent. System agent is what Intel 00:36:55.260 --> 00:37:00.619 calls a Northbridge nowadays, now that it's not a separate chip anymore. It's 00:37:00.619 --> 00:37:07.530 basically just a Northbridge and a crypto unit that's on there and the stuff that's 00:37:07.530 --> 00:37:12.530 directly attached to Northbridge being the ROM and the RAM. So the processor itself 00:37:12.530 --> 00:37:16.960 is, as I said, derived from a 486, but it does actually have some more modern 00:37:16.960 --> 00:37:21.830 features that it does CPU ID, at least on my systems. Some other researchers said 00:37:21.830 --> 00:37:29.369 theirs didn't. It's basically the core that's in the quark MCU, which is really 00:37:29.369 --> 00:37:33.260 great because it's one of the only cores made by Intel that has public 00:37:33.260 --> 00:37:39.800 documentation on how to do run control. So breakpoints and accessing registers and 00:37:39.800 --> 00:37:44.420 everything over JTAG. Intel doesn't publish this stuff except for the quark 00:37:44.420 --> 00:37:50.920 MCU, because they were targeted makers. But they reused that in here, which is 00:37:50.920 --> 00:37:58.200 really useful. It even has an official port to the OpenOCD debugger, which I have 00:37:58.200 --> 00:38:03.100 not gotten to test because I don't have a JTAG probe, which is compatible with Intel 00:38:03.100 --> 00:38:11.000 voltage levels and supported by OpenOCD and also has like a set CPU ID and MSRs. 00:38:11.000 --> 00:38:21.170 It has some really fancy features like branch tracing and some more strict paging 00:38:21.170 --> 00:38:30.480 permission enforcement stuff. They don't use the interrupt pins on this. So it's an 00:38:30.480 --> 00:38:34.710 IP block but if there are some files out there, that's where it is this screenshot 00:38:34.710 --> 00:38:40.601 is from, that actually are used by a built in logic analyzer Intel has on the 00:38:40.601 --> 00:38:46.680 chipset and you can select different signals on the chip to to watch, which is 00:38:46.680 --> 00:38:50.900 a really great source of information on how the IP blocks are laid out and what 00:38:50.900 --> 00:38:54.200 signals are in there, because you basically get a tree view of the IP blocks 00:38:54.200 --> 00:39:00.800 and chip and some of their signals. They don't use the legacy interrupt system, 00:39:00.800 --> 00:39:07.920 they only use message based interrupts by what a device writes a value into a 00:39:07.920 --> 00:39:13.050 register on the interrupt controller instead of asserting a pin. And then there 00:39:13.050 --> 00:39:21.700 is the Northbridge. It's partially documented in that data sheet I mentioned, 00:39:21.700 --> 00:39:29.020 it does support x86 IO address space, but it's never used. Everything in the ME is 00:39:29.020 --> 00:39:36.600 in memory space or expose as memory space through bridges, in the Northbridge 00:39:36.600 --> 00:39:43.070 implements access to the ROM,RAM, it has a IOMMU which is only used for transactions 00:39:43.070 --> 00:39:48.750 coming from the rest of the system and it's always initialized to, at least in 00:39:48.750 --> 00:39:51.660 the firmware I looked up, it's always initialized to the inverse of the page 00:39:51.660 --> 00:40:00.200 table, so linear addresses can be used for memory maps, sorry, for DMA. It also does 00:40:00.200 --> 00:40:06.270 PCI configuration space access to the primary PCI bus. And it has a firewall 00:40:06.270 --> 00:40:15.080 that allows the operating system to deny any IP block in the chipset from sending a 00:40:15.080 --> 00:40:18.890 completion on the bus request. So it can actually say: "Hey, I want to read some 00:40:18.890 --> 00:40:25.040 register and only these devices are allowed to send me value for it." So 00:40:25.040 --> 00:40:29.570 they've actually thought about security here, which is great. Then there is one of 00:40:29.570 --> 00:40:38.190 the most important blocks in the ME, which is the crypto engine. It does some sort of 00:40:38.190 --> 00:40:47.100 more well-known crypto algorithms. AES, SHA hashes, RSA and it has a secure key 00:40:47.100 --> 00:40:56.330 store, which I'm not gonna [audio dropped] ... all about it in their ME talk at 00:40:56.330 --> 00:41:04.250 Blackhat. And a lot of these things have DMA engines, which all seem to be the 00:41:04.250 --> 00:41:09.500 same. And there is no other DM agents ... engines in ME, so this is also used from 00:41:09.500 --> 00:41:23.170 memory to memory copy or DMA into other devices. So that's used in a lot of 00:41:23.170 --> 00:41:27.400 things. This is actually a diagram which I don't have the vector for anymore. So 00:41:27.400 --> 00:41:35.260 that's why the libre office background is in there. I'm sorry. So this is basically 00:41:35.260 --> 00:41:39.020 what that crypto engine looks like when you look at that signal tree that I was 00:41:39.020 --> 00:41:44.910 talking about earlier. The DMA engines are both able to do memory to memory copies 00:41:44.910 --> 00:41:52.570 until directly targets the crypto unit they're part of. Basically, when you, I 00:41:52.570 --> 00:41:57.490 don't know about the control bits that go with this, but when you set the target 00:41:57.490 --> 00:42:02.150 address to zero and the right control bits, it will copy into the buffer that's 00:42:02.150 --> 00:42:11.960 used for the encryption. So that is how it accelerates memory access for crypto. And 00:42:11.960 --> 00:42:15.590 these are the actual register offsets. They're the same for all of the DMA 00:42:15.590 --> 00:42:21.580 engines in there relative to the base address of the subunit they're in. And 00:42:21.580 --> 00:42:27.290 then there's the second PCI bus or bus hierarchy, which is like in some places 00:42:27.290 --> 00:42:33.540 called the PCI fixed bus. I'm actually not entirely sure whether this is actually 00:42:33.540 --> 00:42:38.840 implemented as a PCI bus as I've drawn it here, but this is what it behaves like. So 00:42:38.840 --> 00:42:43.920 it has all the ME private stuff, that's not a part of the normal chipset. So it's 00:42:43.920 --> 00:42:51.310 timers for the ME, it has the implementation of the secure enclave 00:42:51.310 --> 00:42:58.010 stuff, that the firmware TPM registers. And it has the gen device which I've 00:42:58.010 --> 00:43:01.780 mostly ignored because it's only used the boot time. It's only used by the actual 00:43:01.780 --> 00:43:10.869 boot ROM for the ME mostly. It is what the ME uses to get the fuses Intel burns. So 00:43:10.869 --> 00:43:15.420 that's the intel public key, whether it's a production or pre-production part, but 00:43:15.420 --> 00:43:20.260 it's pretty much a black box. It's not used that much, fortunately. There is the 00:43:20.260 --> 00:43:24.340 IPC block which allows the ME to talk to the sensor hub, which is a different CPU 00:43:24.340 --> 00:43:28.190 in the chipset. It allows it to talk to power management controller and all kinds 00:43:28.190 --> 00:43:34.180 of other embedded CPUs. So it's inter processor communication not interprocess. 00:43:34.180 --> 00:43:39.090 Confused me for a bit. And here's the host embedded controller interface, which is 00:43:39.090 --> 00:43:44.320 how the ME talks to the rest of the computer when it wants the computer to 00:43:44.320 --> 00:43:47.960 know that it's talking so it can directly access a lot of stuff. But when it wants 00:43:47.960 --> 00:43:54.250 to send a message to the EFI or to Windows or Linux, it'll use this. And it also has 00:43:54.250 --> 00:43:59.080 status registers, which are really simple things where the ME writes in a value. And 00:43:59.080 --> 00:44:05.290 even if the ME crashes, the host can still read the value, which is how you can see 00:44:05.290 --> 00:44:11.160 whether the ME is running, whether it's disabled, whether it fully booted, or 00:44:11.160 --> 00:44:15.400 whether it crashed halfway through. But at a point where it could still get the rest 00:44:15.400 --> 00:44:21.230 of the computer running and there is some corporate code to to read it. I've also 00:44:21.230 --> 00:44:27.080 implemented some decoding for it on the emulator because it's useful to see what 00:44:27.080 --> 00:44:33.210 those values mean. So then there's something really interesting, the primary 00:44:33.210 --> 00:44:37.240 adverse translation table, which is the bus bridge that allows the ME to actually 00:44:37.240 --> 00:44:44.200 access the PCIexpress fabric of the computer. For a lot of the, what in this 00:44:44.200 --> 00:44:50.010 table call ME peripherals, that are actually outside the ME domain and the 00:44:50.010 --> 00:45:00.320 chipset, it uses this to access it. It also uses it to access the UMA, which is 00:45:00.320 --> 00:45:04.960 an area of host RAM that's used as a swap device for the ME and to Trace Hub, which is 00:45:04.960 --> 00:45:11.190 the debug port, but also has a couple of windows which allow the ME to access any 00:45:11.190 --> 00:45:19.060 random area of host RAM, which is the most scary bit because UMA is specified by 00:45:19.060 --> 00:45:24.650 host, but the host DRAM area is where you can just point it anywhere. You can read 00:45:24.650 --> 00:45:28.750 or write any value that that Windows or Linux or whatever you're running has 00:45:28.750 --> 00:45:37.460 sitting there. So that's scary to me. So and then there's the rest of it, the rest 00:45:37.460 --> 00:45:46.490 of the devices which are behind the primary ATT. And that's a lot of stuff, 00:45:46.490 --> 00:45:53.450 that's debug, that's also the older normal peripherals that your P.C. has, but it 00:45:53.450 --> 00:45:56.200 also includes things like the power management controller, which actually 00:45:56.200 --> 00:45:59.789 turns on and off all the different parts of your computer. It controls clocks and 00:45:59.789 --> 00:46:07.680 resets. So this is really important. There is a concept that you'll come across where 00:46:07.680 --> 00:46:14.261 you're reading Intel manuals or ME related stuff that's root spaces besides your 00:46:14.261 --> 00:46:20.320 normal addressing information for a PCI device, it also has a root space number, 00:46:20.320 --> 00:46:24.980 which is basically how you have a single PCI device exposing two completely 00:46:24.980 --> 00:46:31.151 different address spaces. And it's 0 for the host, it's one for the ME. Some 00:46:31.151 --> 00:46:34.940 devices expose the same information on there. Other ones behave completely 00:46:34.940 --> 00:46:43.370 different. That's something you don't usually see. And then there's the side 00:46:43.370 --> 00:46:48.560 band fabric. So besides all this stuff they just covered, which is PCI like at 00:46:48.560 --> 00:46:52.880 least. There is also something completely different, side band fabric, which is a 00:46:52.880 --> 00:47:00.990 completely packet switched network, where you don't use any memory mapping by 00:47:00.990 --> 00:47:06.370 default. You just have a one byte address for a device and some other addressing 00:47:06.370 --> 00:47:09.590 fields and you're just sending a message saying: "Hey, I want to read configuration 00:47:09.590 --> 00:47:14.320 or data or memory." And there is actually a lot of information out there on this, 00:47:14.320 --> 00:47:18.480 because Intel, it seems like I just copy pasted their internal specification into a 00:47:18.480 --> 00:47:26.860 patent. This is how you address it. This is all devices on there, which is quite a 00:47:26.860 --> 00:47:32.590 lot. It's also what you, if any of you are kernel developers, and you've had to deal 00:47:32.590 --> 00:47:40.110 with GPIO on Intel SoCs. There's this P2SB device that you have to use. That's what 00:47:40.110 --> 00:47:48.240 the host uses to access this. Their documentation on it is really, really bad. 00:47:48.240 --> 00:47:52.420 This was all done using static analysis. But then I wanted to figure out how some 00:47:52.420 --> 00:47:57.410 of the logic actually works and it was really complicated to play around with the 00:47:57.410 --> 00:48:07.310 ME. There was this nice talk by Ermolov and Goryachy, where they said: "You know, 00:48:07.310 --> 00:48:11.790 we found a an exploit that gives you code execution and you can you can get JTAG 00:48:11.790 --> 00:48:18.813 access to." It sounds really nice. It's actually not that easy. So arbitrary code 00:48:18.813 --> 00:48:23.359 execution in the BUP module, they actually describe their exploit and how you should 00:48:23.359 --> 00:48:30.270 use it. But they didn't describe anything that's needed to actually implement that. 00:48:30.270 --> 00:48:35.690 So if you want to do that, what you need to do to figure out where to stack lives, 00:48:35.690 --> 00:48:40.230 you need to know where you need to write a payload that will actually get it from a 00:48:40.230 --> 00:48:44.640 buffer overflow on a stack that, by the way, uses stack cookies. So you can't just 00:48:44.640 --> 00:48:51.369 overwrite the return address to turn that into an arbitrary write. And you need to 00:48:51.369 --> 00:48:56.369 find out what the return pointer address is so you can overwrite it and find ROP 00:48:56.369 --> 00:49:03.320 gadgets because the stack is not executable. And then when you've done 00:49:03.320 --> 00:49:09.920 that, you can just turn on debug access or change to custom firmware or whatever. So 00:49:09.920 --> 00:49:13.660 what I did is I had a bit of trouble getting that running and in order to test 00:49:13.660 --> 00:49:17.720 your payload, you have to flash it into the system and it takes a while and then 00:49:17.720 --> 00:49:20.880 the system just doesn't power on if the ME's not working, if you're crashing it 00:49:20.880 --> 00:49:24.580 instead of getting code execution. So it's not really valuable to to develop it that 00:49:24.580 --> 00:49:32.910 way, I think. Some people did. I respect that because it's really, really hard. And 00:49:32.910 --> 00:49:38.790 then I wrote this ME Loader, it's called Loader because at first I started out like 00:49:38.790 --> 00:49:42.849 writing it as a sort of a wine thing where you where you would just mmap the right 00:49:42.849 --> 00:49:47.380 ranges at the right place and jump into it, execute it, patch some system calls. 00:49:47.380 --> 00:49:51.849 But because the ME is a micro kernel system in almost every user space program 00:49:51.849 --> 00:49:57.480 accesses hardware directly, it ended up implementing like a good part of the 00:49:57.480 --> 00:50:08.080 chipset, at least as stubs or enough logic to get the code running. And I later on 00:50:08.080 --> 00:50:14.510 added some features that actually allowed to talk to the hardware. I can use it as a 00:50:14.510 --> 00:50:18.530 debugger, but just because it's actually running the ME firmware or parts of it 00:50:18.530 --> 00:50:26.200 inside a normal Linux process, I can just use gdb to debug it. And back in April 00:50:26.200 --> 00:50:30.320 last year, I got that working to the point where I could run the bootstrap process, 00:50:30.320 --> 00:50:38.580 which is where the vulnerability is. And then you just develop the exploit against 00:50:38.580 --> 00:50:43.960 it, which I did. And then I made a mistake cleaning up some old change root 00:50:43.960 --> 00:50:52.010 environments for close source software. And I nuked my home dir. Yeah. I hadn't 00:50:52.010 --> 00:50:56.599 yet pushed everything to GitHub. So I stuck with an old version and I decided, 00:50:56.599 --> 00:51:00.160 you know, let's refactor this and turn it into something that might actually at some 00:51:00.160 --> 00:51:03.930 point be published, which by the way I did last summer. This is all public code. The 00:51:03.930 --> 00:51:09.790 ME Loader thing. It's on GitHub. And someone else beat me to it and replicated 00:51:09.790 --> 00:51:15.250 that exploit by the Russian guys. Which up to then they have produced a proof of concept 00:51:15.250 --> 00:51:22.760 thing for Apollo like chipsets, which were completely different for from what you had 00:51:22.760 --> 00:51:33.690 to do for normal ME. I was a bit disappointed by that one, not being the 00:51:33.690 --> 00:51:38.580 first one to actually replicate this. But then I did about a week later, I got it 00:51:38.580 --> 00:51:44.270 got my loader back to the point where I could actually get to the vulnerable code 00:51:44.270 --> 00:51:51.120 and develop that exploit and got it working not too long after. And here's the 00:51:51.120 --> 00:51:54.720 great thing. Then I went to the hacker space. I flash it into my laptop. The 00:51:54.720 --> 00:51:59.040 image that I had just been using only on the emulator. I didn't change it. I flash. 00:51:59.040 --> 00:52:05.280 I was like, this is never gonna work on it. It works. some laughter And I've still got an image 00:52:05.280 --> 00:52:08.480 on a flash ship with me because that's what I used to actually turn on the 00:52:08.480 --> 00:52:14.490 debugger. And then you need a debug probe because that USB based debugging stuff 00:52:14.490 --> 00:52:18.810 that's mentioned here only works pretty late in boot. Which is also why I only 00:52:18.810 --> 00:52:21.880 really see Apollo Lake stuff because on those chipsets you can actually use this 00:52:21.880 --> 00:52:33.010 for the ME. And then you need this thing because there's a second channel, that is 00:52:33.010 --> 00:52:36.360 using the USB plug, but it's a completely different physical layer and you need an 00:52:36.360 --> 00:52:40.911 adapter for it, which I don't think was intended to be publicly available. Because 00:52:40.911 --> 00:52:44.859 if you go to Intel site to say, I want to buy this, they say, here's the C-NDA, 00:52:44.859 --> 00:52:54.460 please sign it. But it appeared on mouser. And luckily I knew some people, who had 00:52:54.460 --> 00:52:59.120 done some other stuff, got a nice bounty for it and bought it and I let me use it. 00:52:59.120 --> 00:53:05.430 Thanks to them. It's expensive, but you can buy it if it's still up there. Haven't 00:53:05.430 --> 00:53:11.520 checked. That's the Link. So I'm a bit late, so I'm gonna use the time for 00:53:11.520 --> 00:53:15.760 questions as well. So the main thing the ME does that you cannot replace is the 00:53:15.760 --> 00:53:21.250 boot process. It's not just breaking the system. If you don't turn it on, it 00:53:21.250 --> 00:53:25.240 actually does stuff that has to be done. So you gonna have to use the ME anyway if 00:53:25.240 --> 00:53:30.730 you want to boot a computer. I don't necessarily have to use Intel's firmware. 00:53:30.730 --> 00:53:35.810 The ME itself boots is like a micro kernel system, so it has a process which 00:53:35.810 --> 00:53:39.859 implements a lot of the servers that will allow it to get to a point where it can 00:53:39.859 --> 00:53:44.710 start those servers. This process has very high privileges in older versions, which 00:53:44.710 --> 00:53:49.160 is what is being used on these chipsets. And if you exploit that, you're still ring 00:53:49.160 --> 00:53:55.680 3, but you can turn on debugger and you can use the debugger to become ring 0. So 00:53:55.680 --> 00:53:59.171 this is what normal boot process for a computer looks like. And this is what 00:53:59.171 --> 00:54:02.050 happens when you use Boot Guard. There's a bit of code that runs even before the 00:54:02.050 --> 00:54:07.170 reset vector, and that's started by micro code initialization, of course. And this 00:54:07.170 --> 00:54:12.120 is what actually happens. The ME loads a new firmware into a power management 00:54:12.120 --> 00:54:16.390 controller, it then ready some stuff in a chipset and it tells the power mentioning 00:54:16.390 --> 00:54:23.660 controller like please stop pulling that CPU reset pin low and the CPU will start. 00:54:23.660 --> 00:54:28.160 Power managment controller is a completely independent thing I say 8051 derived 00:54:28.160 --> 00:54:32.690 microcontroller that runs a real time operating system from the 90s. This is the 00:54:32.690 --> 00:54:38.690 only string in the firmware by the way, that's quoted there. And depending on the 00:54:38.690 --> 00:54:42.410 chipsset that you have, it's either loaded with a patch or with a complete binary 00:54:42.410 --> 00:54:46.690 from the ME, and it does a lot of important stuff. No documentation on it 00:54:46.690 --> 00:54:52.120 besides ACPI interface, which is not really any useful. The ME has to do these 00:54:52.120 --> 00:54:58.710 things. It needs to load the keys for the Boot Guard process needs to set up clock 00:54:58.710 --> 00:55:06.550 controllers and then tell the PMC to turn on the power to to the CPU. It needs to 00:55:06.550 --> 00:55:15.240 configure PCI express fabric and reset - like get the CPU to come out of reset. 00:55:15.240 --> 00:55:18.290 There's a lot of code involved in this, so I really didn't want to do this all 00:55:18.290 --> 00:55:22.150 statically. What I did is I added hardware support, hardware passthrough support to 00:55:22.150 --> 00:55:28.500 the emulator and booted my laptop that way. Actually had a video of this, but I 00:55:28.500 --> 00:55:33.970 don't have the time to show it, which is a pity. But this is what I - the bring up 00:55:33.970 --> 00:55:38.030 process from the ME running in a Linux process, sending whatever hardware access 00:55:38.030 --> 00:55:43.340 as it was trying to do that are important for boot to the debugger. And then that 00:55:43.340 --> 00:55:49.880 was using a ME in real hardware that was halted to actually do to register accesses 00:55:49.880 --> 00:55:56.520 and it works. It's not going to show this. It actually booted the computer reliably. 00:55:56.520 --> 00:56:02.410 Then Boot Guard configuration is fun because you know where they say they fuse 00:56:02.410 --> 00:56:10.990 in the keys. Well yeah. But the ME loads them from fuses and then manually loads 00:56:10.990 --> 00:56:14.530 them into registers. So if you have code execution on the ME before it does this, 00:56:14.530 --> 00:56:18.000 you can just load your own values and you can run core boot even on a machine that 00:56:18.000 --> 00:56:24.190 has Boot Guard. Yeah. So I'm gonna go through this really quickly. This is, by 00:56:24.190 --> 00:56:29.570 the way, these are the registers that configure what security model the CPU is 00:56:29.570 --> 00:56:34.579 gonna enforce for the firmware. I'm going to release this code after my talk. It's 00:56:34.579 --> 00:56:39.810 part of a Python script that I wrote that uses the debugger to start the CPU without 00:56:39.810 --> 00:56:45.670 ME firmware. I traced all the of the ME firmware did. And I now have a Python 00:56:45.670 --> 00:56:51.470 script that can just start a computer without Intel's code. If you translate 00:56:51.470 --> 00:56:55.920 this into a rough sequence or even into binary for the ME, you can start a 00:56:55.920 --> 00:57:02.850 computer without the ME itself or at least without it running the operating system. 00:57:02.850 --> 00:57:12.710 applause So, yeah, future goals. I really do want 00:57:12.710 --> 00:57:20.420 to share this because if there is a way to escalate, to ring 0 fruit, a rope chain, 00:57:20.420 --> 00:57:24.359 then you could just start your own kernel in the ME and have custom firmware, at 00:57:24.359 --> 00:57:29.600 least from the vulnerability on. But you could also build a mod chip that uses the 00:57:29.600 --> 00:57:34.829 debugger interface to load a new firmware. There's lots of stuff still needs to be 00:57:34.829 --> 00:57:41.210 discovered, but I'm gonna hang out at the open source firmware village later, at 00:57:41.210 --> 00:57:46.690 least part of the week here. So because I really want to get started on open source 00:57:46.690 --> 00:57:55.250 ME firmware using this. Right. And there's a lot of people that's played a role in 00:57:55.250 --> 00:58:00.700 getting me to this point. Also would like to thank the guy from Hague hacker space, 00:58:00.700 --> 00:58:07.680 BinoAlpha, who basically allowed me to use his laptop to prepare the demo, which I 00:58:07.680 --> 00:58:14.660 ended up not being able to show, but. Right. I was gonna ask what are the 00:58:14.660 --> 00:58:17.380 worrying questions? But I don't think there's really any time for any more. 00:58:17.380 --> 00:58:22.570 Herald: Peter, thank you so much. Applause Unfortunately, we don't have any more time 00:58:22.570 --> 00:58:30.720 left. Peter: I'll be around. I'll be around. 00:58:30.720 --> 00:58:35.660 Herald: I think it's very, very interesting because I hope that your talk 00:58:35.660 --> 00:58:41.119 will inspire many people to keep looking into how the management engine works and 00:58:41.119 --> 00:58:46.930 hopefully uncover even more stuff. I think we have time for just one single question. 00:58:46.930 --> 00:58:51.040 I don't know, do we? How one from the Internet. Thank you so much. 00:58:51.040 --> 00:58:56.790 Signal Angel: OK. First off, I have to tell you. Your shirt is nice. Chat wanted 00:58:56.790 --> 00:59:05.000 me to say this. And they asked how reliable this exploit is and does it work 00:59:05.000 --> 00:59:09.160 on every boot? Peter: Right, Yeah. That's actually 00:59:09.160 --> 00:59:14.960 something really important that I forgot to mention. So they patch a vulnerability, 00:59:14.960 --> 00:59:17.339 but they didn't provide downgrade protection. If you could flash a 00:59:17.339 --> 00:59:24.170 vulnerable image with an exploit in it, it'll just boot every time on these chips 00:59:24.170 --> 00:59:27.850 that's so six or seven generation chips that's put in that image and it will 00:59:27.850 --> 00:59:31.230 reliably turn on the debugger every time you turn on the computer. applause 00:59:31.230 --> 00:59:36.650 Herald: Thank you so much for the question. And Peter Bosch thank you so 00:59:36.650 --> 00:59:39.160 much. Please give him a great round of applause. 00:59:39.160 --> 00:59:43.625 applause 00:59:43.625 --> 01:00:08.000 subtitles created by c3subtitles.de in the year 20??. Join, and help us!