The PC's BIOS among many other functions also provides a simple routine to read data in from the keyboard. Information about the keys pressed are stored in a ring buffer that provides space for about 16 characters. As Jonathan Brossard has shown in a paper and presented at DEFCON 16, the buffer's contents may be availlable for a while after it has been read by the BIOS. Chances are that passwords of the BIOS or disk encryption software can be recovered.
Jonathan Brossard paper provides a detailed description and several examples. Therefore I restrict myself to the recovery of the BIOS startup password. In order to create the following scenario, I enabled the BIOS protection and set a password of "1234supe". I then rebooted the machine, entered the password to unlock it and created a memory dump. Information about the position and status of the keyboard buffer is readily available from the BIOS data area. You can also spot the password:
At a closer look most characters are represented by two bytes: the character's ASCII code and a scan code that identifies the pressed key. The character "1", for instance, is represented by an ASCII code of 0x31 and its scan code 0x02. Of course there are a few exceptions. There's only the scan code but no ASCII value for the return key, for instance. Also, the BIOS does not translate keys to national character sets, but leaves this task to the operating system.
Unfortunately the BIOS data area is not a part of every memory dump. Crash dumps and dumps obtained through LiveKd do not contain page zero. Win32dd by Matthieu Suiche needs a special option "-t 1" to include page zero with the BIOS data area.
The plugin is rather primitive. It just dumps the keyboard buffer, but does not decode it. Actually this is the first Volatility plugin that I wrote and it helped me to get accustomed to the framework.
python volatility keyboardbuffer -f BIOS_password.dd Buffer start: 0x1e Buffer end : 0x3e Next char : 0x2e Last read : 0x2e Buffer : 0x1e: 0x31 0x1f: 0x02 0x20: 0x32 0x21: 0x03 0x22: 0x33 0x23: 0x04 0x24: 0x34 0x25: 0x05 0x26: 0x73 0x27: 0x1f 0x28: 0x75 0x29: 0x16 0x2a: 0x70 0x2b: 0x19 0x2c: 0x65 0x2d: 0x12 0x2e: 0x00 <-- Next/Last 0x2f: 0x00 0x30: 0x00 0x31: 0x00 0x32: 0x00 0x33: 0x00 0x34: 0x00 0x35: 0x00 0x36: 0x00 0x37: 0x00 0x38: 0x00 0x39: 0x00 0x3a: 0x00 0x3b: 0x00 0x3c: 0x00 0x3d: 0x00