Update laps core function

main
mpgn 2021-10-17 11:50:29 -04:00
parent ef1e5d3fb1
commit fcddee656e
4 changed files with 194 additions and 41 deletions

View File

@ -90,8 +90,8 @@ class connection(object):
def proto_flow(self):
if self.create_conn_obj():
self.enum_host_info()
self.proto_logger()
self.enum_host_info()
self.print_host_info()
# because of null session
if self.login() or (self.username == '' and self.password == ''):

View File

@ -34,23 +34,7 @@ class KerberosAttacks:
self.nthash = self.hash
if self.password is None:
self.password = ''
def login_for_smb(username, password, domain):
# Create the baseDN
baseDN = ''
domainParts = domain.split('.')
for i in domainParts:
baseDN += 'dc=%s,' % i
# Remove last ','
baseDN = baseDN[:-1]
print(domain, baseDN, domain)
ldapConnection = ldap_impacket.LDAPConnection('ldap://%s' % domain, baseDN, domain)
print(username, password, domain)
ldapConnection.login(username, password, domain, '', '')
return ldapConnection
self.password = ''
def outputTGS(self, tgs, oldSessionKey, sessionKey, username, spn, fd=None):
decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

View File

@ -0,0 +1,169 @@
import logging
import random
from pyasn1.codec.der import decoder, encoder
from pyasn1.type.univ import noValue
from impacket.ntlm import compute_lmhash, compute_nthash
from impacket.ldap import ldap as ldap_impacket
from cme.logger import CMEAdapter
class LDAPConnect:
def __init__(self, host, port, hostname):
self.proto_logger(host, port, hostname)
def proto_logger(self, host, port, hostname):
self.logger = CMEAdapter(extra={
'protocol': 'LDAP',
'host': host,
'port': port,
'hostname': hostname
})
def plaintext_login(self, domain, username, password, ntlm_hash):
lmhash = ''
nthash = ''
#This checks to see if we didn't provide the LM Hash
if ntlm_hash and ntlm_hash.find(':') != -1:
lmhash, nthash = ntlm_hash.split(':')
elif ntlm_hash:
nthash = ntlm_hash
# Create the baseDN
baseDN = ''
domainParts = domain.split('.')
for i in domainParts:
baseDN += 'dc=%s,' % i
# Remove last ','
baseDN = baseDN[:-1]
try:
ldapConnection = ldap_impacket.LDAPConnection('ldap://%s' % domain, baseDN, domain)
ldapConnection.login(username, password, domain, lmhash, nthash)
# Connect to LDAP
out = u'{}{}:{}'.format('{}\\'.format(domain),
username,
password if password else ntlm_hash)
self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "389"
# self.logger.success(out)
return ldapConnection
except ldap_impacket.LDAPSessionError as e:
if str(e).find('strongerAuthRequired') >= 0:
# We need to try SSL
try:
ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % domain, baseDN, domain)
ldapConnection.login(username, password, domain, lmhash, nthash)
self.logger.extra['protocol'] = "LDAPS"
self.logger.extra['port'] = "636"
# self.logger.success(out)
return ldapConnection
except ldap_impacket.LDAPSessionError as e:
errorCode = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{}'.format(domain,
username,
password))
else:
errorCode = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{}'.format(domain,
username,
password))
return False
except OSError as e:
self.logger.error(u'{}\\{}:{} {}'.format(domain,
username,
password,
"Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller"))
return False
def hash_login(self, domain, username, ntlm_hash):
lmhash = ''
nthash = ''
#This checks to see if we didn't provide the LM Hash
if ntlm_hash.find(':') != -1:
lmhash, nthash = ntlm_hash.split(':')
else:
nthash = ntlm_hash
self.hash = ntlm_hash
if lmhash: self.lmhash = lmhash
if nthash: self.nthash = nthash
self.username = username
self.domain = domain
if self.kdcHost is not None:
target = self.kdcHost
else:
target = domain
self.kdcHost = domain
# Create the baseDN
self.baseDN = ''
domainParts = self.kdcHost.split('.')
for i in domainParts:
self.baseDN += 'dc=%s,' % i
# Remove last ','
self.baseDN = self.baseDN[:-1]
if self.hash == '' and self.args.asreproast:
hash_TGT = KerberosAttacks(self).getTGT_asroast(self.username)
if hash_TGT:
self.logger.highlight(u'{}'.format(hash_TGT))
with open(self.args.asreproast, 'a+') as hash_asreproast:
hash_asreproast.write(hash_TGT + '\n')
return False
# Connect to LDAP
try:
self.ldapConnection = ldap_impacket.LDAPConnection('ldap://%s' % target, self.baseDN, self.kdcHost)
self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash)
self.check_if_admin()
out = u'{}{}:{} {}'.format('{}\\'.format(domain),
username,
nthash,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
self.logger.extra['protocol'] = "LDAP"
self.logger.extra['port'] = "389"
# self.logger.success(out)
if not self.args.continue_on_success:
return True
except ldap_impacket.LDAPSessionError as e:
if str(e).find('strongerAuthRequired') >= 0:
try:
# We need to try SSL
self.ldapConnection = ldap_impacket.LDAPConnection('ldaps://%s' % target, self.baseDN, self.kdcHost)
self.ldapConnection.login(self.username, self.password, self.domain, self.lmhash, self.nthash)
self.logger.extra['protocol'] = "LDAPS"
self.logger.extra['port'] = "636"
# self.logger.success(out)
except ldap_impacket.LDAPSessionError as e:
errorCode = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain,
self.username,
self.password,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''),
color='magenta' if errorCode in ldap_error_status else 'red')
else:
errorCode = str(e).split()[-2][:-1]
self.logger.error(u'{}\\{}:{} {}'.format(self.domain,
self.username,
self.password,
ldap_error_status[errorCode] if errorCode in ldap_error_status else ''),
color='magenta' if errorCode in ldap_error_status else 'red')
return False
except OSError as e:
self.logger.error(u'{}\\{}:{} {}'.format(self.domain,
self.username,
self.nthash,
"Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller"))
return False

View File

@ -3,6 +3,7 @@
import socket
import os
import ntpath
import hashlib,binascii
from io import StringIO
from impacket.smbconnection import SMBConnection, SessionError
from impacket.smb import SMB_DIALECT
@ -26,8 +27,7 @@ from cme.protocols.smb.mmcexec import MMCEXEC
from cme.protocols.smb.smbspider import SMBSpider
from cme.protocols.smb.passpol import PassPolDump
from cme.protocols.smb.samruser import UserSamrDump
from cme.protocols.ldap.kerberos import KerberosAttacks
from impacket.ldap import ldapasn1 as ldapasn1_impacket
from cme.protocols.ldap.smbldap import LDAPConnect
from cme.helpers.logger import highlight
from cme.helpers.misc import *
from cme.helpers.powershell import create_ps_command
@ -260,15 +260,9 @@ class smb(connection):
if self.args.local_auth:
self.domain = self.hostname
if self.args.laps:
print("laps auth")
print(self.args.username)
self.laps_search(self.args.username, self.args.password, self.domain)
def laps_search(self, username, password, domain):
print("ldap connection")
connection = KerberosAttacks.login_for_smb(username[0], password[0], domain)
print("ldap connection end", self.hostname)
def laps_search(self, username, password, ntlm_hash, domain):
ldapco = LDAPConnect(self.domain, "389", self.domain)
connection = ldapco.plaintext_login(domain, username[0] if username else '', password[0] if password else '', ntlm_hash[0] if ntlm_hash else '' )
searchFilter = '(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(name='+ self.hostname +'))'
attributes = ['ms-MCS-AdmPwd','samAccountname']
@ -286,10 +280,13 @@ class smb(connection):
sAMAccountName = str(computer['vals'][0])
else:
msMCSAdmPwd = str(computer['vals'][0])
context.log.highlight("Computer: {:<20} Password: {}".format(sAMAccountName, msMCSAdmPwd))
logging.debug("Computer: {:<20} Password: {} {}".format(sAMAccountName, msMCSAdmPwd, self.hostname))
self.username = "administrator"
self.password = "October2021"
self.password = msMCSAdmPwd
if ntlm_hash:
hash_ntlm = hashlib.new('md4', msMCSAdmPwd.encode('utf-16le')).digest()
self.args.hash = [binascii.hexlify(hash_ntlm).decode()]
self.domain = self.hostname
def print_host_info(self):
self.logger.info(u"{}{} (name:{}) (domain:{}) (signing:{}) (SMBv1:{})".format(self.server_os,
@ -298,6 +295,9 @@ class smb(connection):
self.domain,
self.signing,
self.smbv1))
if self.args.laps:
self.laps_search(self.args.username, self.args.password, self.args.hash, self.domain)
def kerberos_login(self, aesKey, kdcHost):
#Re-connect since we logged off
self.create_conn_obj()
@ -394,19 +394,19 @@ class smb(connection):
self.hash = ntlm_hash
if lmhash: self.lmhash = lmhash
if nthash: self.nthash = nthash
self.username = username
if not self.args.laps:
self.username = username
self.domain = domain
self.conn.login(username, '', domain, lmhash, nthash)
self.conn.login(self.username, '', domain, lmhash, nthash)
self.check_if_admin()
self.db.add_credential('hash', domain, username, ntlm_hash)
self.db.add_credential('hash', domain, self.username, ntlm_hash)
if self.admin_privs:
self.db.add_admin_user('hash', domain, username, ntlm_hash, self.host)
self.db.add_admin_user('hash', domain, self.username, ntlm_hash, self.host)
out = u'{}\\{} {} {}'.format(domain,
username,
out = u'{}\\{}:{} {}'.format(domain,
self.username,
ntlm_hash,
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
@ -423,14 +423,14 @@ class smb(connection):
except (SessionError, NetBIOSTimeout) as e:
error, desc = e.getErrorString()
self.logger.error(u'{}\\{}:{} {} {}'.format(domain,
username,
self.username,
ntlm_hash,
error,
'({})'.format(desc) if self.args.verbose else ''),
color='magenta' if error in smb_error_status else 'red')
if error not in smb_error_status:
self.inc_failed_login(username)
self.inc_failed_login(self.username)
return False
if not self.args.continue_on_success:
return True