1 00:00:09,029 --> 00:00:12,320 Herald: So, in this talk we will hear about 2 00:00:12,320 --> 00:00:15,730 what UEFI is, how it can be used, 3 00:00:15,730 --> 00:00:18,560 and how it can be executed in userspace, 4 00:00:18,560 --> 00:00:20,259 and our speaker is Jethro Beekman, 5 00:00:20,259 --> 00:00:25,749 and... the stage is yours. 6 00:00:25,749 --> 00:00:27,820 Jethro Beekman: Thank you for the introduction. 7 00:00:27,820 --> 00:00:32,499 *applause* 8 00:00:32,499 --> 00:00:34,790 Alright, thank you for the introduction. 9 00:00:34,790 --> 00:00:38,180 So, I'm a PhD student at UC Berkeley, 10 00:00:38,180 --> 00:00:40,070 and in my copious amounts of free time, 11 00:00:40,070 --> 00:00:43,440 I like to reverse-engineer things. 12 00:00:43,440 --> 00:00:45,270 In particular, this time, 13 00:00:45,270 --> 00:00:47,250 I reverse-engineered UEFI, 14 00:00:47,250 --> 00:00:49,620 which is the modern BIOS replacement. 15 00:00:49,620 --> 00:00:52,820 And, in this talk, I will discuss some tools 16 00:00:52,820 --> 00:00:55,030 that you can use - that you too can use 17 00:00:55,030 --> 00:00:57,140 to reverse-engineer UEFI, 18 00:00:57,140 --> 00:00:58,750 including some tools that I wrote, 19 00:00:58,750 --> 00:01:01,670 and tools that other people wrote. 20 00:01:01,670 --> 00:01:04,860 So, this whole project started 21 00:01:04,860 --> 00:01:08,040 when I bought a new SSD for my laptop 22 00:01:08,040 --> 00:01:10,670 and, as you might know, modern SSDs have 23 00:01:10,670 --> 00:01:13,510 built-in encryption capabilities, 24 00:01:13,510 --> 00:01:16,310 whether this is secure or not is a question, 25 00:01:16,310 --> 00:01:18,310 is a good question, but really, 26 00:01:18,310 --> 00:01:19,850 reverse-engineering SSD firmware 27 00:01:19,850 --> 00:01:23,300 is a talk for another day. 28 00:01:23,300 --> 00:01:27,810 So, I decided to use this encryption, 29 00:01:27,810 --> 00:01:31,460 and use it using the built-in 30 00:01:31,460 --> 00:01:32,990 hardware password option 31 00:01:32,990 --> 00:01:35,950 of my UEFI firmware. 32 00:01:35,950 --> 00:01:38,560 This is the password I chose, 64 characters, 33 00:01:38,560 --> 00:01:42,120 "correct horse battery staple galaxy piece position require house". 34 00:01:42,120 --> 00:01:47,520 It's very secure, obviously. 35 00:01:47,520 --> 00:01:49,790 So this all seemed to be working fine, 36 00:01:49,790 --> 00:01:51,390 and I was trusting that my hard drive 37 00:01:51,390 --> 00:01:53,880 was encrypted properly, 38 00:01:53,880 --> 00:01:54,909 but once you start to think about 39 00:01:54,909 --> 00:01:56,159 how it actually works, 40 00:01:56,159 --> 00:01:59,480 there's a small discrepancy, really, 41 00:01:59,480 --> 00:02:02,500 because the way this password's input 42 00:02:02,500 --> 00:02:04,720 to the hard drive is using 43 00:02:04,720 --> 00:02:06,970 the ATA security feature set, 44 00:02:06,970 --> 00:02:09,408 the security-unlock command. 45 00:02:09,408 --> 00:02:11,489 And if you look at the unlock command, 46 00:02:11,489 --> 00:02:12,930 you clearly see that the password 47 00:02:12,930 --> 00:02:16,889 is supposed to be 32 bytes. 48 00:02:16,889 --> 00:02:21,310 How are these 64 characters turned into 32 bytes? 49 00:02:21,310 --> 00:02:22,709 That is my question, 50 00:02:22,709 --> 00:02:25,450 because if my laptop dies 51 00:02:25,450 --> 00:02:28,310 but my SSD is still functional, 52 00:02:28,310 --> 00:02:29,650 I want to be able to take my SSD 53 00:02:29,650 --> 00:02:31,680 and put it into another computer 54 00:02:31,680 --> 00:02:34,430 to get access to my data. 55 00:02:34,430 --> 00:02:36,349 I tried all the standard things, 56 00:02:36,349 --> 00:02:40,629 like truncating it, or using a standard 57 00:02:40,629 --> 00:02:42,980 hash function like SHA-256 58 00:02:42,980 --> 00:02:44,909 that has 32-byte output, 59 00:02:44,909 --> 00:02:47,680 but these things all didn't work. 60 00:02:47,680 --> 00:02:49,540 So then I decided to, you know, 61 00:02:49,540 --> 00:02:52,989 really dive into the firmware 62 00:02:52,989 --> 00:02:54,609 to figure out how it works. 63 00:02:54,609 --> 00:02:56,249 So this talk will also be called 64 00:02:56,249 --> 00:03:00,480 "How to turn 64 characters into 32 bytes". 65 00:03:00,480 --> 00:03:06,759 *applause* 66 00:03:07,629 --> 00:03:09,120 So what are some challenges 67 00:03:09,120 --> 00:03:12,010 when reverse-engineering UEFI? 68 00:03:12,010 --> 00:03:14,109 So first of all, this is the first thing 69 00:03:14,109 --> 00:03:17,510 that runs when your computer is booted up. 70 00:03:17,510 --> 00:03:18,919 So that means you will not be able 71 00:03:18,919 --> 00:03:21,230 to use a standard debugger. 72 00:03:21,230 --> 00:03:24,200 Surely people who develop firmware for a living 73 00:03:24,200 --> 00:03:27,069 have some kind of hardware debugger 74 00:03:27,069 --> 00:03:30,510 but that's unlikely to work on a commodity system 75 00:03:30,510 --> 00:03:34,620 such as this laptop, which is all I got from the store. 76 00:03:34,620 --> 00:03:37,309 Maybe you think you can emulate the firmware 77 00:03:37,309 --> 00:03:39,340 using qemu or something like that, 78 00:03:39,340 --> 00:03:41,120 but the hardware that the firmware 79 00:03:41,120 --> 00:03:42,590 is designed to support 80 00:03:42,590 --> 00:03:45,999 is unlikely to be correctly emulated by qemu. 81 00:03:45,999 --> 00:03:50,309 So that is also probably not a viable way 82 00:03:50,309 --> 00:03:52,249 to debug this. 83 00:03:52,249 --> 00:03:57,629 Also, because UEFI is basically one big process, 84 00:03:57,629 --> 00:04:01,299 using one address space, 85 00:04:01,299 --> 00:04:02,329 there's no operating system 86 00:04:02,329 --> 00:04:04,849 so there's no system calls. 87 00:04:04,849 --> 00:04:07,089 Also there's no dynamic linker, 88 00:04:07,089 --> 00:04:09,029 so there's no dynamic symbols, 89 00:04:09,029 --> 00:04:10,439 there's no symbol table that you can use 90 00:04:10,439 --> 00:04:13,290 as a starting point in your reverse-engineering. 91 00:04:13,290 --> 00:04:16,478 You know, if you were reverse-engineering 92 00:04:16,478 --> 00:04:20,099 a standard password utility in userspace 93 00:04:20,099 --> 00:04:22,009 or something, you might start at 94 00:04:22,009 --> 00:04:24,190 the read system call for, 95 00:04:24,190 --> 00:04:26,900 that would be displayed to the user 96 00:04:26,900 --> 00:04:28,280 to enter the password. 97 00:04:28,280 --> 00:04:35,150 But in UEFI, no, that is not an option. 98 00:04:35,150 --> 00:04:36,930 And even though there's no dynamic linker, 99 00:04:36,930 --> 00:04:38,500 the whole firmware consists 100 00:04:38,500 --> 00:04:42,030 of 281 different modules, in my case, 101 00:04:42,030 --> 00:04:46,030 and it could be similar numbers on your UEFI laptop. 102 00:04:46,030 --> 00:04:50,589 And these modules all need to interact in some way. 103 00:04:50,589 --> 00:04:54,300 So, let's take a look at these different modules. 104 00:04:54,300 --> 00:04:56,680 There's a tool called UEFITool, 105 00:04:56,680 --> 00:04:58,729 written by Nikolaj Schlej, and 106 00:04:58,729 --> 00:05:00,300 this really should be in your bag of tricks 107 00:05:00,300 --> 00:05:01,840 if you're interested in doing anything 108 00:05:01,840 --> 00:05:05,389 with UEFI firmware. 109 00:05:05,389 --> 00:05:11,430 So, here I'll just go and use UEFIExtract, 110 00:05:11,430 --> 00:05:15,300 which is a command line utility 111 00:05:15,300 --> 00:05:17,020 included with UEFITool 112 00:05:17,020 --> 00:05:20,229 that allows you to extract a firmware blob, 113 00:05:20,229 --> 00:05:21,800 so in this case I took the firmware blob 114 00:05:21,800 --> 00:05:26,460 from the Lenovo firmware update CD 115 00:05:26,460 --> 00:05:29,949 and we're going to extract that. 116 00:05:29,949 --> 00:05:34,240 After extracting it, we get this nice directory structure 117 00:05:34,240 --> 00:05:37,979 with one subdirectory per module 118 00:05:37,979 --> 00:05:40,419 and as you can see, there's quite a few of them. 119 00:05:40,419 --> 00:05:44,720 Here's, there's system management mode control module, 120 00:05:44,720 --> 00:05:47,560 timer module, things like that. 121 00:05:47,560 --> 00:05:48,700 And as you can see, 122 00:05:48,700 --> 00:05:50,569 each module has a bunch of subdirectories 123 00:05:50,569 --> 00:05:51,589 for the different sections 124 00:05:51,589 --> 00:05:53,199 that are included in that module. 125 00:05:53,199 --> 00:05:57,060 And one that appears a lot is the PE32+ image. 126 00:05:57,060 --> 00:05:59,110 This is a portable execution image, 127 00:05:59,110 --> 00:06:02,580 this is a format that Windows uses for executables. 128 00:06:02,580 --> 00:06:05,840 So, you might think you might be able to run 129 00:06:05,840 --> 00:06:11,419 these modules, and that is true. 130 00:06:11,419 --> 00:06:14,110 But first, let's take a look at 131 00:06:14,110 --> 00:06:16,169 what happens when you run a module like that. 132 00:06:16,169 --> 00:06:19,639 Each module has an entry point, main, 133 00:06:19,639 --> 00:06:22,930 and the main function gets passed 134 00:06:22,930 --> 00:06:24,659 a pointer to the system table. 135 00:06:24,659 --> 00:06:26,860 The system table is just... 136 00:06:26,860 --> 00:06:30,050 contains more pointers to other structures. 137 00:06:30,050 --> 00:06:32,370 For example, for the terminals, 138 00:06:32,370 --> 00:06:34,639 cons in, cons out, standard error, 139 00:06:34,639 --> 00:06:38,099 the standard text inputs and outputs, 140 00:06:38,099 --> 00:06:41,259 and also the boot services structure. 141 00:06:41,259 --> 00:06:43,069 The boot services structure contains 142 00:06:43,069 --> 00:06:44,960 a bunch of function pointers, 143 00:06:44,960 --> 00:06:47,909 including these install protocol interface 144 00:06:47,909 --> 00:06:51,259 and locate protocol functions. 145 00:06:51,259 --> 00:06:53,060 The install protocol interface allows 146 00:06:53,060 --> 00:06:56,080 a module to install a protocol interface 147 00:06:56,080 --> 00:07:00,300 using, specified by a particular GUID 148 00:07:00,300 --> 00:07:03,169 and the interface is specified by just some pointer. 149 00:07:03,169 --> 00:07:05,719 Then, later, another module can call 150 00:07:05,719 --> 00:07:08,810 a locate protocol function with the same GUID 151 00:07:08,810 --> 00:07:10,840 and it will receive a pointer 152 00:07:10,840 --> 00:07:12,849 to this interface that was previously installed 153 00:07:12,849 --> 00:07:14,199 by the other modules. 154 00:07:14,199 --> 00:07:17,840 So, most modules in their main function 155 00:07:17,840 --> 00:07:20,759 start by loading a bunch of protocols 156 00:07:20,759 --> 00:07:24,389 and then, after that, installing one more 157 00:07:24,389 --> 00:07:28,050 of their own protocols. 158 00:07:28,050 --> 00:07:29,189 This is all done at runtime. 159 00:07:29,189 --> 00:07:31,129 So there's really no static way of 160 00:07:31,129 --> 00:07:32,650 viewing the dependencies 161 00:07:32,650 --> 00:07:34,749 between the different modules. 162 00:07:34,749 --> 00:07:36,290 Luckily, we might be able to 163 00:07:36,290 --> 00:07:37,349 execute these modules, 164 00:07:37,349 --> 00:07:40,810 as I was alluding to before. 165 00:07:40,810 --> 00:07:42,089 These modules, they're written 166 00:07:42,089 --> 00:07:44,280 for the hardware you're currently using, 167 00:07:44,280 --> 00:07:47,039 with your current operating system. 168 00:07:47,039 --> 00:07:49,060 So they have a compatible instruction set. 169 00:07:49,060 --> 00:07:50,259 So in order to execute them, 170 00:07:50,259 --> 00:07:51,539 you just need a compatible 171 00:07:51,539 --> 00:07:54,659 application binary interface, or ABI. 172 00:07:54,659 --> 00:07:55,860 This is what I've written, 173 00:07:55,860 --> 00:07:58,229 with the efiperun tool. 174 00:07:58,229 --> 00:08:01,909 You can think of efiperun as WINE for UEFI. 175 00:08:01,909 --> 00:08:03,889 Just like WINE allows you to run 176 00:08:03,889 --> 00:08:06,189 Windows applications on Linux, 177 00:08:06,189 --> 00:08:08,650 efiperun allows you to run EFI modules 178 00:08:08,650 --> 00:08:11,850 on Linux. 179 00:08:11,850 --> 00:08:19,310 *applause* 180 00:08:22,000 --> 00:08:24,990 So, efiperun has a bunch of features, 181 00:08:24,990 --> 00:08:29,129 it includes many of the standard EFI APIs 182 00:08:29,129 --> 00:08:31,609 and it's very easy to add implementations 183 00:08:31,609 --> 00:08:33,280 for missing APIs. 184 00:08:33,280 --> 00:08:35,919 Also, at runtime, a missing API 185 00:08:35,919 --> 00:08:37,380 will be generated automatically 186 00:08:37,380 --> 00:08:39,600 with some stub functions. 187 00:08:39,600 --> 00:08:41,309 It supports memory map annotations, 188 00:08:41,309 --> 00:08:45,570 so that you can see which parts of memory 189 00:08:45,570 --> 00:08:47,720 have been allocated by which module 190 00:08:47,720 --> 00:08:49,810 and you can all run these in your standard 191 00:08:49,810 --> 00:08:53,420 debugger environments, like gdb. 192 00:08:53,420 --> 00:08:55,450 Also, as an interesting aside, 193 00:08:55,450 --> 00:08:56,830 I think this the only project 194 00:08:56,830 --> 00:08:58,060 I could find online 195 00:08:58,060 --> 00:09:00,060 that uses the cross-stdarg header 196 00:09:00,060 --> 00:09:02,620 which is used for calling 197 00:09:02,620 --> 00:09:04,130 variable-argument functions 198 00:09:04,130 --> 00:09:07,310 across calling conventions. 199 00:09:07,310 --> 00:09:14,010 So, let's do a little demo of efiperun. 200 00:09:14,010 --> 00:09:15,970 In this demo, I will just 201 00:09:15,970 --> 00:09:20,970 run efiperun on each different module 202 00:09:20,970 --> 00:09:24,150 to see which other modules it interacts with. 203 00:09:33,740 --> 00:09:35,780 So, I just wrote this little Ruby script 204 00:09:35,780 --> 00:09:37,530 which traverses the directory tree 205 00:09:37,530 --> 00:09:41,710 that we just saw from the UEFIExtract utility 206 00:09:41,710 --> 00:09:44,270 and then it executes efiperun 207 00:09:44,270 --> 00:09:47,300 for each different module. 208 00:09:47,300 --> 00:09:48,040 Whee! 209 00:09:50,500 --> 00:09:52,400 Assertion error that I've never seen before, 210 00:09:52,400 --> 00:09:53,580 that's always fun. 211 00:09:53,580 --> 00:09:56,500 As you can see, 281 processes are launched, 212 00:09:56,500 --> 00:09:58,000 most modules return 213 00:09:58,000 --> 00:09:59,760 from the main function, normally, 214 00:09:59,760 --> 00:10:01,400 but some of them get stuck 215 00:10:01,400 --> 00:10:04,040 in an infinite loop, 216 00:10:04,040 --> 00:10:06,230 so efiperun will automatically terminate 217 00:10:06,230 --> 00:10:07,840 after 10 seconds in this case. 218 00:10:07,840 --> 00:10:10,100 Let's look at the output of 219 00:10:10,100 --> 00:10:13,980 all these different efiperun modules. 220 00:10:16,680 --> 00:10:18,430 You can see a bunch of them segfault, 221 00:10:18,430 --> 00:10:21,340 which, you know, can be, is understandable 222 00:10:21,340 --> 00:10:23,400 because they might be expecting 223 00:10:23,400 --> 00:10:26,410 some memory setup from the early boot 224 00:10:26,410 --> 00:10:28,810 that is not existent anymore, 225 00:10:28,810 --> 00:10:32,430 but there are a bunch of modules that do work 226 00:10:32,430 --> 00:10:36,770 such as system boot manager. 227 00:10:36,770 --> 00:10:40,480 You can see that it prints out a bunch of stuff, 228 00:10:40,480 --> 00:10:43,580 version information, copyright information, 229 00:10:43,580 --> 00:10:45,570 then it requests a protocol, 230 00:10:45,570 --> 00:10:48,060 this protocol has a GUID that is specified 231 00:10:48,060 --> 00:10:50,200 by the EFI specification, 232 00:10:50,200 --> 00:10:53,380 so we can interpret that GUID 233 00:10:53,380 --> 00:10:56,060 and then it calls some stub functions 234 00:10:56,060 --> 00:10:57,910 that we have not implemented 235 00:10:57,910 --> 00:10:58,930 and then afterwards, 236 00:10:58,930 --> 00:11:00,190 it installs its own protocol, 237 00:11:00,190 --> 00:11:02,190 which is also a protocol specified 238 00:11:02,190 --> 00:11:07,080 by the EFI specification. 239 00:11:07,080 --> 00:11:08,040 Another interesting module 240 00:11:08,040 --> 00:11:12,170 is the system splash module, 241 00:11:12,170 --> 00:11:15,630 which we see over here. 242 00:11:15,630 --> 00:11:18,760 As you can see, it actually requests 243 00:11:18,760 --> 00:11:21,480 a bunch of protocols that are not implemented 244 00:11:21,480 --> 00:11:22,910 by efiperun and you will see 245 00:11:22,910 --> 00:11:24,640 it will automatically generate 246 00:11:24,640 --> 00:11:27,950 a dummy interface for that purpose. 247 00:11:27,950 --> 00:11:30,560 And then you will see that it calls 248 00:11:30,560 --> 00:11:31,910 a function in this dummy interface 249 00:11:31,910 --> 00:11:34,360 that was created here, 250 00:11:34,360 --> 00:11:35,930 namely function number 2, 251 00:11:35,930 --> 00:11:39,760 and because we are unable to handle this function 252 00:11:39,760 --> 00:11:43,480 we just abort. 253 00:11:43,480 --> 00:11:46,480 Okay, so now that I've shown you 254 00:11:46,480 --> 00:11:48,680 that we can run these different modules, 255 00:11:48,680 --> 00:11:50,040 we really need to get started with 256 00:11:50,040 --> 00:11:51,930 the reverse-engineering of my BIOS 257 00:11:51,930 --> 00:11:54,210 to figure how to turn those 64 characters 258 00:11:54,210 --> 00:11:56,600 into 32 bytes. 259 00:11:56,600 --> 00:12:00,060 You might remember this picture from slide 2. 260 00:12:00,060 --> 00:12:01,620 You can see that there's a little graphic 261 00:12:01,620 --> 00:12:03,890 displayed in the password prompt. 262 00:12:03,890 --> 00:12:05,100 So this graphic needs to be stored 263 00:12:05,100 --> 00:12:05,940 somewhere in the BIOS, 264 00:12:05,940 --> 00:12:08,180 and it needs to be coded to display 265 00:12:08,180 --> 00:12:11,940 this graphic to the user at some point. 266 00:12:11,940 --> 00:12:13,690 So, let's take a look at the different modules 267 00:12:13,690 --> 00:12:15,200 that might have something to do with images 268 00:12:15,200 --> 00:12:17,810 and graphics and things like that. 269 00:12:17,810 --> 00:12:19,610 Turns out there's only 4 of the 281 270 00:12:19,610 --> 00:12:22,310 that have a file names that seems to correspond 271 00:12:22,310 --> 00:12:24,440 to something with graphics or images. 272 00:12:24,440 --> 00:12:28,350 And if this, the first module is called 273 00:12:28,350 --> 00:12:30,440 by another module, 274 00:12:30,440 --> 00:12:32,370 which is Lenovo prompt service. 275 00:12:32,370 --> 00:12:34,350 And Lenovo prompt service contains 276 00:12:34,350 --> 00:12:36,000 in one of its data sections, 277 00:12:36,000 --> 00:12:38,080 this image over here. 278 00:12:38,080 --> 00:12:40,070 So now we know that we've found something 279 00:12:40,070 --> 00:12:44,510 that has to do with the password prompt. 280 00:12:44,510 --> 00:12:47,040 This prompt module is called by only one 281 00:12:47,040 --> 00:12:47,980 other module, which is 282 00:12:47,980 --> 00:12:49,820 the Lenovo password CP module, 283 00:12:49,820 --> 00:12:51,130 which probably means something like 284 00:12:51,130 --> 00:12:55,550 password control panel or something like that. 285 00:12:55,550 --> 00:12:57,010 The password CP module also calls 286 00:12:57,010 --> 00:12:59,500 into 3 other modules, namely 287 00:12:59,500 --> 00:13:01,700 the sound service module, presumably to 288 00:13:01,700 --> 00:13:04,130 play beeps if the user does something wrong 289 00:13:04,130 --> 00:13:05,990 while entering the password, 290 00:13:05,990 --> 00:13:08,440 the translate service module, which is used 291 00:13:08,440 --> 00:13:10,340 to translate characters, 292 00:13:10,340 --> 00:13:11,880 which I've reverse-engineered, 293 00:13:11,880 --> 00:13:16,030 I've figured out that it's used to translate 294 00:13:16,030 --> 00:13:20,470 ascii characters back into keyboard scan codes. 295 00:13:20,470 --> 00:13:22,460 Keyboard scan codes are codes that are assigned 296 00:13:22,460 --> 00:13:24,450 to each different key on your keyboard. 297 00:13:24,450 --> 00:13:26,440 It's the way the hardware keyboard 298 00:13:26,440 --> 00:13:29,860 communicates with your computer. 299 00:13:29,860 --> 00:13:32,420 And then there's the Lenovo crypt service module, 300 00:13:32,420 --> 00:13:34,130 which turns out to be 301 00:13:34,130 --> 00:13:36,550 standard SHA-256 hash function. 302 00:13:40,400 --> 00:13:42,280 Right, so let's see and have a demo, 303 00:13:42,280 --> 00:13:43,830 in which we are going to call 304 00:13:43,830 --> 00:13:45,220 one of the functions in 305 00:13:45,220 --> 00:13:48,470 this Lenovo password CP module. 306 00:13:53,790 --> 00:13:58,130 So, efiperun allows you to write code 307 00:13:58,130 --> 00:14:00,030 to interact with the EFI modules 308 00:14:00,030 --> 00:14:02,930 that are loaded at runtime. 309 00:14:02,930 --> 00:14:04,700 Here I've written this Lenovo-specific 310 00:14:04,700 --> 00:14:07,420 debug module and you can specify 311 00:14:07,420 --> 00:14:09,810 two functions that will be called. 312 00:14:09,810 --> 00:14:11,500 The first function in it will be called 313 00:14:11,500 --> 00:14:14,980 before all the EFI modules are loaded, 314 00:14:14,980 --> 00:14:16,790 the second function will be called after 315 00:14:16,790 --> 00:14:18,710 all the EFI functions are loaded. 316 00:14:18,710 --> 00:14:20,260 So in this case, we'll first call 317 00:14:20,260 --> 00:14:21,950 the install something function, and then 318 00:14:21,950 --> 00:14:24,360 call, after loading the EFI modules, 319 00:14:24,360 --> 00:14:26,830 the call something function. 320 00:14:26,830 --> 00:14:30,760 The install function installs a stub 321 00:14:30,760 --> 00:14:34,060 Lenovo crypt service protocol. 322 00:14:34,060 --> 00:14:35,690 This is necessary because the standard 323 00:14:35,690 --> 00:14:37,390 Lenovo crypt service calls into system 324 00:14:37,390 --> 00:14:39,290 management mode to do the hashing, 325 00:14:39,290 --> 00:14:41,130 which is currently not possible from 326 00:14:41,130 --> 00:14:43,540 Linux userspace. 327 00:14:43,540 --> 00:14:48,390 The second function, call_LenovoPasswordCp_8cc, 328 00:14:48,390 --> 00:14:50,890 will determine the address of the function 329 00:14:50,890 --> 00:14:52,480 in the Lenovo password CP module 330 00:14:52,480 --> 00:14:55,100 at offset 8cc and then call it. 331 00:14:55,100 --> 00:14:57,480 It will take two parameters, in and out. 332 00:14:57,480 --> 00:15:01,490 In will use this unicode string, my password, 333 00:15:01,490 --> 00:15:02,470 and for the output, 334 00:15:02,470 --> 00:15:05,770 we'll just pass this array buffer. 335 00:15:06,970 --> 00:15:10,440 Then we'll just print the output 336 00:15:10,440 --> 00:15:13,150 of the buffer after calling the function. 337 00:15:29,510 --> 00:15:31,850 So, as you can see here, 338 00:15:31,850 --> 00:15:33,600 the Lenovo translate service module 339 00:15:33,600 --> 00:15:37,260 installs this protocol E3AB-etc. 340 00:15:37,260 --> 00:15:39,280 and then later Lenovo password CP module 341 00:15:39,280 --> 00:15:43,260 requests the same protocol E3AB-etc. 342 00:15:43,260 --> 00:15:46,100 Also, you will see that 343 00:15:46,100 --> 00:15:48,190 the Lenovo password CP module 344 00:15:48,190 --> 00:15:52,050 requests the protocol C73E4-etc. 345 00:15:52,050 --> 00:15:53,530 which is the Lenovo crypt service protocol 346 00:15:53,530 --> 00:15:55,800 that we installed earlier. 347 00:15:55,800 --> 00:15:57,780 Then it does a bunch of memory operations, 348 00:15:57,780 --> 00:15:59,550 and at the end, we get the output. 349 00:15:59,550 --> 00:16:02,340 So I reverse-engineered this function 350 00:16:02,340 --> 00:16:07,570 at offset 8cc, and it turns out that 351 00:16:07,570 --> 00:16:10,170 it is, in fact, the following function: 352 00:16:10,170 --> 00:16:12,660 it takes the input password and 353 00:16:12,660 --> 00:16:15,050 converts it into scan codes, 354 00:16:19,650 --> 00:16:25,560 and then it pads it to 64 characters, 355 00:16:25,560 --> 00:16:30,360 and then it takes a SHA-256 hash 356 00:16:30,360 --> 00:16:33,520 and then it displays the first half of that. 357 00:16:36,580 --> 00:16:40,390 Alright, here we go, so... 358 00:16:40,390 --> 00:16:46,250 *applause* 359 00:16:46,250 --> 00:16:47,450 We have reverse-engineered to 360 00:16:47,450 --> 00:16:51,470 the first half of the password algorithm. 361 00:16:51,470 --> 00:16:52,870 Took me about three weeks to decode 362 00:16:52,870 --> 00:16:54,840 the entire algorithm, 363 00:16:54,840 --> 00:16:57,530 and here it is. 364 00:16:57,530 --> 00:16:59,060 So this is the hash that we just saw 365 00:16:59,060 --> 00:17:01,580 of the password, and then this hash is 366 00:17:01,580 --> 00:17:03,740 concatenated with the serial number and 367 00:17:03,740 --> 00:17:06,050 model number of the hard drive. 368 00:17:06,050 --> 00:17:08,800 That all is then hashed again, 369 00:17:08,800 --> 00:17:12,300 and that is then passed to the SATA drive 370 00:17:12,300 --> 00:17:13,569 over the ATA protocol. 371 00:17:13,569 --> 00:17:15,349 Now this is actually quite a good idea 372 00:17:15,349 --> 00:17:17,770 because it means that if you sniff 373 00:17:17,770 --> 00:17:20,530 the password on the SATA bus 374 00:17:20,530 --> 00:17:22,569 you will only be able to then later 375 00:17:22,569 --> 00:17:24,449 unlock the same drive. 376 00:17:24,449 --> 00:17:25,480 Because other drives, even though 377 00:17:25,480 --> 00:17:26,900 they might be using the same password, 378 00:17:26,900 --> 00:17:28,050 will have a different serial number 379 00:17:28,050 --> 00:17:29,640 and model number. 380 00:17:29,640 --> 00:17:33,390 So this hash will not work for them. 381 00:17:33,390 --> 00:17:35,820 Unfortunately, the algorithm is 382 00:17:35,820 --> 00:17:40,750 a little more complex than this. 383 00:17:40,750 --> 00:17:43,490 The password hash, as I said, actually 384 00:17:43,490 --> 00:17:45,350 uses the scan codes of the password, which 385 00:17:45,350 --> 00:17:47,260 means that there is no distinguishing in 386 00:17:47,260 --> 00:17:49,030 case of the letters. 387 00:17:49,030 --> 00:17:51,980 Also, after hashing it, it truncates it 388 00:17:51,980 --> 00:17:54,150 to only 12 bytes. Which means that 389 00:17:54,150 --> 00:17:56,550 there's a maximum of 96 bits of entropy 390 00:17:56,550 --> 00:18:00,050 in this password hash. 391 00:18:00,050 --> 00:18:02,090 This is quite unfortunate. 392 00:18:02,090 --> 00:18:05,240 But most human passwords have less than 393 00:18:05,240 --> 00:18:08,100 96 bits of entropy to start with, 394 00:18:08,100 --> 00:18:11,550 so it's probably not that big of a deal. 395 00:18:11,550 --> 00:18:15,170 Okay, then again this part of the hash is 396 00:18:15,170 --> 00:18:17,050 concatenated with the serial number 397 00:18:17,050 --> 00:18:18,170 and the model number, 398 00:18:18,170 --> 00:18:19,490 except the bytes are swapped. 399 00:18:19,490 --> 00:18:21,720 And I really can't figure out why 400 00:18:21,720 --> 00:18:22,990 the bytes are swapped here. 401 00:18:22,990 --> 00:18:24,930 But it probably has to do something with 402 00:18:24,930 --> 00:18:27,510 the fact that the ATA protocol uses 403 00:18:27,510 --> 00:18:30,310 16-bit words while this model number and 404 00:18:30,310 --> 00:18:32,740 serial number are 8-bit character strings. 405 00:18:32,740 --> 00:18:35,240 So maybe they did some endianness mess-up 406 00:18:35,240 --> 00:18:36,990 or something like that. 407 00:18:36,990 --> 00:18:40,650 Alright, so in this talk, I've shown you 408 00:18:40,650 --> 00:18:43,760 how you too can reverse-engineer UEFI 409 00:18:43,760 --> 00:18:45,190 with some tools that you can use 410 00:18:45,190 --> 00:18:47,320 in this including the efiperun tool 411 00:18:47,320 --> 00:18:49,290 which allows you to run EFI modules 412 00:18:49,290 --> 00:18:50,860 in linux userspace. 413 00:18:50,860 --> 00:18:52,680 The code of this is of course available 414 00:18:52,680 --> 00:18:55,000 under GPL license on github, 415 00:18:55,000 --> 00:18:56,140 and if you want to read about 416 00:18:56,140 --> 00:18:58,010 the second part of reverse-engineering 417 00:18:58,010 --> 00:18:59,210 the algorithm, you can find more 418 00:18:59,210 --> 00:19:00,850 information on my blog. 419 00:19:00,850 --> 00:19:02,650 Thank you very much. 420 00:19:02,650 --> 00:19:11,980 *applause* 421 00:19:11,980 --> 00:19:14,560 H: So, thank you, Jethro, and we have 422 00:19:14,560 --> 00:19:17,240 more than ten minutes' time for Q&A. 423 00:19:17,240 --> 00:19:19,370 Is there a question from the Internet, 424 00:19:19,370 --> 00:19:21,340 signal angel? 425 00:19:21,340 --> 00:19:22,850 Signal: Not right now. 426 00:19:22,850 --> 00:19:23,950 H: And do we have questions 427 00:19:23,950 --> 00:19:25,210 from the audience? 428 00:19:25,210 --> 00:19:31,100 Please line up at the microphones. 429 00:19:31,100 --> 00:19:35,380 Then we'll start with microphone 2, please. 430 00:19:35,380 --> 00:19:37,520 Q: Thanks a lot for making your tools available, 431 00:19:37,520 --> 00:19:38,710 as someone else who does a lot of 432 00:19:38,710 --> 00:19:41,640 UEFI reversing, I've been through similar 433 00:19:41,640 --> 00:19:44,800 rabbit holes of trying to track this down. 434 00:19:44,800 --> 00:19:46,760 You mentioned that SMM is not supported 435 00:19:46,760 --> 00:19:48,670 and I assumed also the real mode 436 00:19:48,670 --> 00:19:50,980 in the transition into long mode 437 00:19:50,980 --> 00:19:51,850 is not supported. 438 00:19:51,850 --> 00:19:53,640 Is that on your roadmap or something, 439 00:19:53,640 --> 00:19:55,920 that you're interested in continuing 440 00:19:55,920 --> 00:19:57,340 development on? 441 00:19:57,340 --> 00:20:00,030 A: Yeah, I'm interested in it, but 442 00:20:00,030 --> 00:20:02,300 I'm not quite sure how to do it, 443 00:20:02,300 --> 00:20:05,840 especially calling into system management mode, 444 00:20:05,840 --> 00:20:07,180 protected mode should probably, 445 00:20:07,180 --> 00:20:08,540 you know, also be possible, 446 00:20:08,540 --> 00:20:11,250 but currently I'm also doing 64-bit mode 447 00:20:11,250 --> 00:20:15,070 but, yeah, if anyone wants to help me 448 00:20:15,070 --> 00:20:23,570 implement it, obviously I welcome your support. 449 00:20:23,570 --> 00:20:25,370 H: Okay, and from the Internet, please. 450 00:20:25,370 --> 00:20:27,059 Q: Yes. The Internet wants to know 451 00:20:27,059 --> 00:20:32,510 what is the advantage of UEFI compared to coreboot? 452 00:20:32,510 --> 00:20:33,470 A: I'm sorry, I didn't... 453 00:20:33,470 --> 00:20:35,300 Q: The Internet wants to know 454 00:20:35,300 --> 00:20:38,030 what is the advantage of UEFI compared 455 00:20:38,030 --> 00:20:40,110 with coreboot, for example? 456 00:20:40,110 --> 00:20:41,840 A: The advantage of UEFI compared to what? 457 00:20:41,840 --> 00:20:44,800 Q: To coreboot, coreboot, this open source 458 00:20:44,800 --> 00:20:46,030 BIOS replacement. 459 00:20:46,030 --> 00:20:48,160 A: Oh okay. coreboot is UEFI, 460 00:20:48,160 --> 00:20:49,780 coreboot is Intel's open source 461 00:20:49,780 --> 00:20:51,330 implementation of UEFI. 462 00:20:51,330 --> 00:20:53,800 Q: Actually, well, actually it's not. 463 00:20:53,800 --> 00:20:56,220 A: Oh, it's not, no, that's tianocore, 464 00:20:56,220 --> 00:20:59,940 you're right. 465 00:20:59,940 --> 00:21:03,430 The only advantage is, 466 00:21:03,430 --> 00:21:05,050 I don't know what the advantage is, 467 00:21:05,050 --> 00:21:06,910 this is just what's supported on my laptop. 468 00:21:06,910 --> 00:21:08,910 So that's what I was interested in. 469 00:21:08,910 --> 00:21:14,850 *laughter, applause* 470 00:21:14,850 --> 00:21:17,520 H: Okay. Microphone 3, please. 471 00:21:17,520 --> 00:21:19,620 Q: Hi. Thank you for your talk. 472 00:21:19,620 --> 00:21:20,980 Have you looked at any other firmware 473 00:21:20,980 --> 00:21:24,740 besides your Lenovo? 474 00:21:24,740 --> 00:21:27,550 A: I've not personally, but 475 00:21:27,550 --> 00:21:32,740 I know other people have. 476 00:21:32,740 --> 00:21:34,710 H: Okay. 4, please. 477 00:21:34,710 --> 00:21:37,059 Q: Thank you for the talk. How did you 478 00:21:37,059 --> 00:21:42,059 come out how to get the password, the hash 479 00:21:42,059 --> 00:21:47,680 with the combination of the serial number 480 00:21:47,680 --> 00:21:50,210 and the module number? 481 00:21:50,210 --> 00:21:53,200 A: So, the full details of this 482 00:21:53,200 --> 00:21:55,600 are in my blog post, but in short, 483 00:21:55,600 --> 00:21:58,880 there is a EFI protocol for talking 484 00:21:58,880 --> 00:22:01,180 to the hard drive, which is 485 00:22:01,180 --> 00:22:02,270 the ATA support protocol, 486 00:22:02,270 --> 00:22:04,430 if I remember correctly, 487 00:22:04,430 --> 00:22:05,630 there's a special module, 488 00:22:05,630 --> 00:22:06,640 there are only a few modules, 489 00:22:06,640 --> 00:22:08,650 that invoke this protocol, 490 00:22:08,650 --> 00:22:12,110 so I just disassembled those, and looked 491 00:22:12,110 --> 00:22:13,470 at what they did, and what commands 492 00:22:13,470 --> 00:22:15,220 they sent to the ATA drive. 493 00:22:15,220 --> 00:22:16,650 Q: Thank you. 494 00:22:16,650 --> 00:22:19,280 H: And there is another question from the chat. 495 00:22:19,280 --> 00:22:22,390 Q: Yes. The chat wants to know if you found 496 00:22:22,390 --> 00:22:24,790 any other unexpected bugs and 497 00:22:24,790 --> 00:22:28,510 if it is possible to check UEFI code, 498 00:22:28,510 --> 00:22:31,170 for example, when running it with valgrind 499 00:22:31,170 --> 00:22:34,520 or something. 500 00:22:34,520 --> 00:22:36,740 A: I've not really run into any other 501 00:22:36,740 --> 00:22:39,140 unexpected bugs, but I must say I also 502 00:22:39,140 --> 00:22:42,250 really wasn't looking for them. 503 00:22:42,250 --> 00:22:44,040 H: Okay. 2, please. 504 00:22:44,040 --> 00:22:48,600 Q: I have little understanding of EFI, but 505 00:22:48,600 --> 00:22:55,400 I had the idea to look into trying to get 506 00:22:55,400 --> 00:23:00,570 boot ROMs from PC graphic cards 507 00:23:00,570 --> 00:23:04,340 to be running on a MacOS computer, 508 00:23:04,340 --> 00:23:09,520 old Mac Pros when they still were having cards, 509 00:23:09,520 --> 00:23:12,320 and I was wondering, I wanted to figure out... 510 00:23:12,320 --> 00:23:15,870 these cards run, apparently, the old BIOS, 511 00:23:15,870 --> 00:23:19,020 real mode, and I wanted to figure out 512 00:23:19,020 --> 00:23:23,380 if I can write a stub that gets loaded 513 00:23:23,380 --> 00:23:27,050 by the EFI system and then that... 514 00:23:27,050 --> 00:23:31,000 my code would then invoke the initialization boot ROM 515 00:23:31,000 --> 00:23:33,940 for the graphics card and provide the functions. 516 00:23:33,940 --> 00:23:38,360 Would your toolset, would that help me in 517 00:23:38,360 --> 00:23:40,929 tracing that while my Mac is running, 518 00:23:40,929 --> 00:23:43,360 because I can't do it while it's booting? 519 00:23:43,360 --> 00:23:48,230 A: I don't... it sounds like a, quite a complex setup, 520 00:23:48,230 --> 00:23:49,890 I think it would be possible to write 521 00:23:49,890 --> 00:23:52,050 an EFI module to do what you're saying, 522 00:23:52,050 --> 00:23:53,179 but I'm not sure if you'll be able 523 00:23:53,179 --> 00:23:57,200 to run that while your operating system is also running. 524 00:23:57,200 --> 00:24:01,660 So... I'm not sure, I'll have to talk more 525 00:24:01,660 --> 00:24:05,560 offline to discuss your specific situation. 526 00:24:05,560 --> 00:24:07,920 H: Okay, and microphone 3, please. 527 00:24:07,920 --> 00:24:16,240 Q: Hi. Have you looked into using SerialICE for emulation of the UEFI 528 00:24:16,240 --> 00:24:22,850 which is essentially qemu but it has, does forward all of the hardware accesses 529 00:24:22,850 --> 00:24:25,770 to real hardware, so you can just trace it 530 00:24:25,770 --> 00:24:29,780 and run arbitrary BIOS or UEFI code in it? 531 00:24:29,780 --> 00:24:31,420 A: I've not looked into that, but that 532 00:24:31,420 --> 00:24:33,970 sounds a very interesting avenue to explore. 533 00:24:33,970 --> 00:24:36,009 Q: Thank you. 534 00:24:36,009 --> 00:24:37,909 H: Okay. I see no more questions. 535 00:24:37,909 --> 00:24:39,920 Thank you to our speaker. 536 00:24:39,920 --> 00:24:41,250 *applause*