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,649
and... the stage is yours.
6
00:00:25,649 --> 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
537
00:24:41,250 --> 00:24:53,000
subtitles created by c3subtitles.de
Join, and help us!