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*