EFIPW is a tool that can be used to decode and modify Apple EFI firmware passwords via the command line. It is designed after the non open source OFPW utility and is designed to work on Intel machines running Leopard or newer. Useful for lab deployments (setting the firmware password of machines as a post install item) and pen tests (recovering the EFI firmware password).
83fe779b6bcdb2cbbb4da3359a7a5d0e75ca7ff27c8901c902ff4d15ec0f684b
#!/usr/bin/env python
"""
EFIPW (C) 2010 by Paul Makowski (my.hndl@gmail.com)
http://code.google.com/p/efipw/
http://paulmakowski.wordpress.com/
License:
GPLv3
Warranty:
Unless otherwise stated, this software is distributed
in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THERE IS
NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS PROVIDE THE SOFTWARE "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD
THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO
USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
About:
EFIPW is a tool to modify and/or decode firmware passwords stored on EFI-based Apple
computers in nvram. It may be useful for both lab administrators and pen testers.
It was inspired by the OPFW tool. Requires root permissions.
If you find this software useful, I would appreciate it if you let me know, but
you're certainly not required to.
Usage:
./efipy.py -h
Modes:
none: Firmware password is ignored, all boot actions allowed (single user, boot off external, etc). This is the default.
command: Firmware password enforced if user requests to boot off another device by holding down 'alt' during boot.
Single user, target disk mode, etc disabled. This is the default when passwords are set.
full: All actions are disallowed, unless correct password is entered (including normal boot to blessed drive).
Changelog:
0.1: initial release
0.1a: re-release (i put the wrong binary in the .zip file)
0.2: complete rewrite in Python (for simplicity, maintainability & 10.6 support)
0.2a: if new password is set and mode is not, default mode to "command"
"""
from optparse import OptionParser
import os
import binascii
parser = OptionParser(version="%prog 0.2a")
if os.geteuid(): parser.error("Must be run as root. (e.g. sudo ./efipw.py [options])")
parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="suppress confirmation messages")
parser.add_option("-d", "--decode", action="store_true", dest="decode", default=False, help="decode current EFI password")
parser.add_option("-p", "--password", dest="newPassword", metavar="PASSWORD", type="string", help="set new EFI password")
parser.add_option("-m", "--mode", dest="newMode", metavar="MODE", type="string", help="set new EFI mode [none, command, full]")
(options, args) = parser.parse_args()
# lolCrypt: Apple's lolzy encryption function
def lolCrypt(input):
output = ""
for i in range(0, len(input)): output += (chr(ord(input[i]) ^ 170)) # 170 in decimal is 10101010 in binary; this is the key...don't tell anyone ;)
return output
def splitLen(seq, length): return [seq[i:i+length] for i in range(0, len(seq), length)]
# REVEAL CURRENT PASSWORD
if options.decode:
# get the current (encoded) password
p = os.popen('nvram -p | grep security-password',"r")
curPassword = p.readline().strip()
print lolCrypt(binascii.unhexlify(curPassword[curPassword.find('%'):].replace('%', '')))
# SET NEW PASSWORD
if options.newPassword:
# set mode to command if not specified
if not options.newMode: options.newMode = "command"
if len(options.newPassword) > 48: print "Password cannot be longer than 48 characters; new password not set."
# set new password
else:
# prep the password
newPassword = splitLen(binascii.hexlify(lolCrypt(options.newPassword)), 2)
for i in range(len(newPassword)): newPassword[i] = '%' + newPassword[i]
newPassword = ''.join(newPassword)
# set the password
p = os.popen('nvram security-password=' + newPassword,"r")
if not options.quiet: print 'EFI password set.'
# SET NEW MODE
if options.newMode:
# validate mode
if options.newMode not in ["none", "command", "full"]: print "Invalid mode '" + options.newMode + "' specified; mode not set."
else:
p = os.popen('nvram security-mode=' + options.newMode,"r")
if not options.quiet: print 'EFI mode set.'